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
18 * This module is all original code
20 * Copyright 1993, Robert Nation
21 * You may use this code for any purpose, as long as the original
22 * copyright remains in the source code and all documentation
27 * The functions in this module *must not* assume that the geometries in the
28 * FvwmWindow structure reflect the desired geometry of the window or its
29 * parts. While the window is resized or shaded, they may hold the old
30 * geometry instead of the new one (but you can not rely on this). Therefore,
31 * these geometries must not be accessed directly or indirectly (by the
32 * functions from geometry,c). Use the geometries that are passed in via
33 * structure pointers, e.d. "td".
36 /* ---------------------------- included header files ---------------------- */
42 #include "libs/fvwmlib.h"
43 #include "libs/Parse.h"
44 #include "libs/Graphics.h"
45 #include "libs/Picture.h"
46 #include "libs/PictureGraphics.h"
47 #include "libs/FRenderInit.h"
48 #include "libs/charmap.h"
49 #include "libs/wcontext.h"
51 #include "execcontext.h"
61 /* ---------------------------- local definitions -------------------------- */
63 /* ---------------------------- local macros ------------------------------- */
65 #define SWAP_ARGS(f,a1,a2) (f)?(a2):(a1),(f)?(a1):(a2)
67 /* ---------------------------- imports ------------------------------------ */
69 extern Window PressedW
;
71 /* ---------------------------- included code files ------------------------ */
73 /* ---------------------------- local types -------------------------------- */
79 unsigned use_pixmap
: 1;
88 FvwmRenderAttributes fra
;
94 unsigned is_tiled
: 1;
95 unsigned is_stretched
: 1;
98 } pixmap_background_type
;
103 FvwmPicture
*mp_created_pic
;
114 } bar_bs_pixmaps
; /* for UseTitleStyle & Colorset */
119 bar_bs_pixmaps bar_pixmaps
[BS_MaxButtonState
];
120 } dynamic_common_decorations
;
130 int border_cs
; /* for UseBorderStyle */
131 int bg_border_cs
; /* for UseBorderStyle */
133 XSetWindowAttributes attributes
;
134 unsigned long valuemask
;
135 Pixmap texture_pixmap
;
136 int texture_pixmap_width
;
137 int texture_pixmap_height
;
138 XSetWindowAttributes notex_attributes
;
139 unsigned long notex_valuemask
;
140 dynamic_common_decorations dynamic_cd
;
141 } common_decorations_type
;
156 unsigned has_x_marks
: 1;
157 unsigned has_y_marks
: 1;
158 } border_marks_descr
;
171 unsigned is_flat
: 1;
172 } border_relief_size_descr
;
177 border_relief_size_descr relief
;
178 border_marks_descr marks
;
180 } border_relief_descr
;
184 unsigned pressed_bmask
: NUMBER_OF_TITLE_BUTTONS
;
185 unsigned lit_bmask
: NUMBER_OF_TITLE_BUTTONS
;
186 unsigned toggled_bmask
: NUMBER_OF_TITLE_BUTTONS
;
187 unsigned clear_bmask
: NUMBER_OF_TITLE_BUTTONS
;
188 unsigned draw_bmask
: NUMBER_OF_TITLE_BUTTONS
;
189 unsigned max_bmask
: NUMBER_OF_TITLE_BUTTONS
;
190 ButtonState bstate
[NUMBER_OF_TITLE_BUTTONS
];
191 unsigned is_title_pressed
: 1;
192 unsigned is_title_lit
: 1;
193 unsigned do_clear_title
: 1;
195 } border_titlebar_state
;
201 FlocaleWinString fstr
;
202 DecorFaceStyle
*tstyle
;
204 unsigned is_toggled
: 1;
209 common_decorations_type
*cd
;
211 rectangle bar_g
; /* titlebar geo vs the frame */
212 rectangle left_buttons_g
; /* vs the frame */
213 rectangle right_buttons_g
; /* vs the frame */
214 frame_title_layout_t layout
;
215 frame_title_layout_t old_layout
;
216 border_titlebar_state tbstate
;
217 int length
; /* text */
218 int offset
; /* text offset */
219 /* MultiPixmap Geometries */
220 rectangle under_text_g
; /* vs the titlebar */
221 rectangle left_main_g
; /* vs the titlebar */
222 rectangle right_main_g
; /* vs the titlebar */
223 rectangle full_left_main_g
; /* vs the frame */
224 rectangle full_right_main_g
; /* vs the frame */
226 int left_of_text_length
;
227 int right_end_length
;
228 int right_of_text_length
;
229 rotation_t draw_rotation
;
230 rotation_t restore_rotation
;
231 unsigned td_is_rotated
: 1;
232 unsigned has_been_saved
: 1;
233 unsigned has_vt
: 1; /* vertical title ? */
234 unsigned has_an_upsidedown_rotation
: 1; /* 270 || 180 */
237 /* ---------------------------- forward declarations ----------------------- */
238 /* forward declarations are not so good */
240 /* for grouping titlebar_descr computation */
241 static void border_rotate_titlebar_descr(FvwmWindow
*fw
, titlebar_descr
*td
);
243 /* for grouping the MultiPixmap stuff */
244 static Bool
border_mp_get_use_title_style_parts_and_geometry(
245 titlebar_descr
*td
, FvwmPicture
**pm
, FvwmAcs
*acs
,
246 unsigned short sf
, int is_left
, rectangle
*g
, int *part
);
248 /* ---------------------------- local variables ---------------------------- */
250 static const char ulgc
[] = { 1, 0, 0, 0x7f, 2, 1, 1 };
251 static const char brgc
[] = { 1, 1, 2, 0x7f, 0, 0, 3 };
253 /* ---------------------------- exported variables (globals) --------------- */
256 unsigned long Globalgcm
;
258 /* ---------------------------- local functions ---------------------------- */
260 static Bool
is_button_toggled(
261 FvwmWindow
*fw
, int button
)
265 if (!HAS_MWM_BUTTONS(fw
))
269 mf
= TB_MWM_DECOR_FLAGS(GetDecor(fw
, buttons
[button
]));
270 if ((mf
& MWM_DECOR_MAXIMIZE
) && IS_MAXIMIZED(fw
))
274 if ((mf
& MWM_DECOR_SHADE
) && IS_SHADED(fw
))
278 if ((mf
& MWM_DECOR_STICK
) &&
279 (IS_STICKY_ACROSS_PAGES(fw
) || IS_STICKY_ACROSS_DESKS(fw
)))
283 if (TB_FLAGS(fw
->decor
->buttons
[button
]).has_layer
&&
284 fw
->layer
== TB_LAYER(fw
->decor
->buttons
[button
]))
293 /* rules to get button state */
294 static ButtonState
border_flags_to_button_state(
295 int is_pressed
, int is_lit
, int is_toggled
)
297 if (!is_lit
&& Scr
.gs
.use_inactive_buttons
)
299 if (is_pressed
&& Scr
.gs
.use_inactive_down_buttons
)
301 return (is_toggled
) ?
302 BS_ToggledInactiveDown
: BS_InactiveDown
;
306 return (is_toggled
) ?
307 BS_ToggledInactiveUp
: BS_InactiveUp
;
312 if (is_pressed
&& Scr
.gs
.use_active_down_buttons
)
314 return (is_toggled
) ?
315 BS_ToggledActiveDown
: BS_ActiveDown
;
319 return (is_toggled
) ?
320 BS_ToggledActiveUp
: BS_ActiveUp
;
325 static void get_common_decorations(
326 common_decorations_type
*cd
, FvwmWindow
*t
,
327 window_parts draw_parts
, Bool has_focus
, Bool is_border
,
331 color_quad
*draw_colors
;
333 df
= border_get_border_style(t
, has_focus
);
334 cd
->bg_border_cs
= -1;
338 /* are we using textured borders? */
339 if (DFS_FACE_TYPE(df
->style
) == TiledPixmapButton
&&
340 GetDecor(t
, BorderStyle
.active
.u
.p
->depth
) == Pdepth
)
342 cd
->texture_pixmap
= GetDecor(
343 t
, BorderStyle
.active
.u
.p
->picture
);
344 cd
->texture_pixmap_width
= GetDecor(
345 t
, BorderStyle
.active
.u
.p
->width
);
346 cd
->texture_pixmap_height
= GetDecor(
347 t
, BorderStyle
.active
.u
.p
->height
);
349 else if (DFS_FACE_TYPE(df
->style
) == ColorsetButton
)
351 cd
->bg_border_cs
= GetDecor(
352 t
, BorderStyle
.active
.u
.acs
.cs
);
354 cd
->back_pixmap
= Scr
.gray_pixmap
;
357 draw_colors
= &(t
->border_hicolors
);
358 cd
->cs
= t
->border_cs_hi
;
362 draw_colors
= &(t
->hicolors
);
368 if (DFS_FACE_TYPE(df
->style
) == TiledPixmapButton
&&
369 GetDecor(t
, BorderStyle
.inactive
.u
.p
->depth
) == Pdepth
)
371 cd
->texture_pixmap
= GetDecor(
372 t
, BorderStyle
.inactive
.u
.p
->picture
);
373 cd
->texture_pixmap_width
= GetDecor(
374 t
, BorderStyle
.inactive
.u
.p
->width
);
375 cd
->texture_pixmap_height
= GetDecor(
376 t
, BorderStyle
.inactive
.u
.p
->height
);
378 else if (DFS_FACE_TYPE(df
->style
) == ColorsetButton
)
380 cd
->bg_border_cs
= GetDecor(
381 t
, BorderStyle
.inactive
.u
.acs
.cs
);
383 if (IS_STICKY_ACROSS_PAGES(t
) || IS_STICKY_ACROSS_DESKS(t
))
385 cd
->back_pixmap
= Scr
.sticky_gray_pixmap
;
389 cd
->back_pixmap
= Scr
.light_gray_pixmap
;
393 draw_colors
= &(t
->border_colors
);
394 cd
->cs
= t
->border_cs
;
398 draw_colors
= &(t
->colors
);
402 cd
->fore_color
= draw_colors
->fore
;
403 cd
->back_color
= draw_colors
->back
;
406 Globalgcv
.foreground
= draw_colors
->hilight
;
407 Globalgcm
= GCForeground
;
408 XChangeGC(dpy
, Scr
.ScratchGC1
, Globalgcm
, &Globalgcv
);
409 Globalgcv
.foreground
= draw_colors
->shadow
;
410 XChangeGC(dpy
, Scr
.ScratchGC2
, Globalgcm
, &Globalgcv
);
411 cd
->relief_gc
= Scr
.ScratchGC1
;
412 cd
->shadow_gc
= Scr
.ScratchGC2
;
415 /* MWMBorder style means thin 3d effects */
416 cd
->relief_width
= (HAS_MWM_BORDER(t
) ? 1 : 2);
418 if (cd
->texture_pixmap
)
420 cd
->attributes
.background_pixmap
= cd
->texture_pixmap
;
421 cd
->valuemask
= CWBackPixmap
;
427 cd
->attributes
.background_pixmap
= cd
->back_pixmap
;
428 cd
->valuemask
= CWBackPixmap
;
432 cd
->attributes
.background_pixel
= cd
->back_color
;
433 cd
->valuemask
= CWBackPixel
;
438 cd
->notex_attributes
.background_pixmap
= cd
->back_pixmap
;
439 cd
->notex_valuemask
= CWBackPixmap
;
443 cd
->notex_attributes
.background_pixel
= cd
->back_color
;
444 cd
->notex_valuemask
= CWBackPixel
;
450 static window_parts
border_get_changed_border_parts(
451 FvwmWindow
*fw
, rectangle
*old_sidebar_g
, rectangle
*new_sidebar_g
,
454 window_parts changed_parts
;
456 changed_parts
= PART_NONE
;
457 if (!CSET_IS_TRANSPARENT_PR(cs
) && CSET_HAS_PIXMAP(cs
) &&
458 (old_sidebar_g
->x
!= new_sidebar_g
->x
||
459 old_sidebar_g
->y
!= new_sidebar_g
->y
||
460 old_sidebar_g
->width
!= new_sidebar_g
->width
||
461 old_sidebar_g
->height
!= new_sidebar_g
->height
))
464 changed_parts
|= PART_FRAME
;
465 return changed_parts
;
467 if (old_sidebar_g
->x
!= new_sidebar_g
->x
)
469 changed_parts
|= (PART_FRAME
& (~PART_BORDER_W
));
471 if (old_sidebar_g
->y
!= new_sidebar_g
->y
)
473 changed_parts
|= (PART_FRAME
& (~PART_BORDER_N
));
475 if (old_sidebar_g
->width
!= new_sidebar_g
->width
)
478 PART_BORDER_N
| PART_BORDER_S
;
479 if (DFS_FACE_TYPE(GetDecor(fw
, BorderStyle
.active
.style
)) ==
483 PART_BORDER_NE
| PART_BORDER_E
| PART_BORDER_SE
;
486 if (old_sidebar_g
->height
!= new_sidebar_g
->height
)
489 PART_BORDER_W
| PART_BORDER_E
;
490 if (DFS_FACE_TYPE(GetDecor(fw
, BorderStyle
.active
.style
)) ==
494 PART_BORDER_SW
| PART_BORDER_S
| PART_BORDER_SE
;
498 return changed_parts
;
501 static int border_get_parts_and_pos_to_draw(
502 common_decorations_type
*cd
, FvwmWindow
*fw
,
503 window_parts pressed_parts
, window_parts force_draw_parts
,
504 rectangle
*old_g
, rectangle
*new_g
, Bool do_hilight
,
505 border_relief_descr
*br
)
507 window_parts draw_parts
;
508 window_parts parts_to_light
;
509 rectangle sidebar_g_old
;
510 DecorFaceStyle
*borderstyle
;
512 Bool has_x_marks_old
;
514 Bool has_y_marks_old
;
515 int cs
= cd
->bg_border_cs
;
518 borderstyle
= (do_hilight
) ?
519 &GetDecor(fw
, BorderStyle
.active
.style
) :
520 &GetDecor(fw
, BorderStyle
.inactive
.style
);
521 frame_get_sidebar_geometry(
522 fw
, borderstyle
, new_g
, &br
->sidebar_g
, &has_x_marks
,
524 if (has_x_marks
== True
)
526 draw_parts
|= PART_X_HANDLES
;
527 br
->marks
.has_x_marks
= 1;
531 br
->marks
.has_x_marks
= 0;
533 if (has_y_marks
== True
)
535 draw_parts
|= PART_Y_HANDLES
;
536 br
->marks
.has_y_marks
= 1;
540 br
->marks
.has_y_marks
= 0;
542 draw_parts
|= (pressed_parts
^ fw
->decor_state
.parts_inverted
);
543 parts_to_light
= (do_hilight
== True
) ? PART_FRAME
: PART_NONE
;
544 draw_parts
|= (parts_to_light
^ fw
->decor_state
.parts_lit
);
545 draw_parts
|= (~(fw
->decor_state
.parts_drawn
) & PART_FRAME
);
546 draw_parts
|= force_draw_parts
;
549 old_g
= &fw
->g
.frame
;
551 if ((draw_parts
& PART_FRAME
) == PART_FRAME
)
553 draw_parts
|= PART_FRAME
;
556 frame_get_sidebar_geometry(
557 fw
, borderstyle
, old_g
, &sidebar_g_old
, &has_x_marks_old
,
559 if (has_x_marks_old
!= has_x_marks
)
561 draw_parts
|= (PART_FRAME
& (~(PART_BORDER_N
| PART_BORDER_S
)));
563 if (has_y_marks_old
!= has_y_marks
)
565 draw_parts
|= (PART_FRAME
& (~(PART_BORDER_W
| PART_BORDER_E
)));
567 draw_parts
|= border_get_changed_border_parts(
568 fw
, &sidebar_g_old
, &br
->sidebar_g
, cs
);
569 draw_parts
&= (PART_FRAME
| PART_HANDLES
);
574 static window_parts
border_get_tb_parts_to_draw(
575 FvwmWindow
*fw
, titlebar_descr
*td
, rectangle
*old_g
, rectangle
*new_g
,
576 window_parts force_draw_parts
)
578 window_parts draw_parts
;
579 ButtonState old_state
;
583 td
->tbstate
.draw_bmask
= 0;
584 draw_parts
= PART_NONE
;
586 draw_parts
|= (~(fw
->decor_state
.parts_drawn
) & PART_TITLE
);
587 td
->tbstate
.draw_bmask
|= (~(fw
->decor_state
.buttons_drawn
));
589 draw_parts
|= force_draw_parts
;
590 td
->tbstate
.draw_bmask
|= (force_draw_parts
& PART_BUTTONS
) ? ~0 : 0;
591 /* check if state changed */
592 old_state
= border_flags_to_button_state(
593 (fw
->decor_state
.parts_inverted
& PART_TITLE
),
594 (fw
->decor_state
.parts_lit
& PART_TITLE
), 0);
595 if (old_state
!= td
->tbstate
.tstate
)
597 draw_parts
|= PART_TITLE
;
600 if ((td
->old_layout
.title_g
.width
!= td
->layout
.title_g
.width
||
601 td
->old_layout
.title_g
.height
!= td
->layout
.title_g
.height
) &&
602 td
->layout
.title_g
.x
>= 0 && td
->layout
.title_g
.y
>= 0)
604 draw_parts
|= PART_TITLE
;
606 /* same for buttons */
607 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
609 unsigned int mask
= (1 << i
);
611 if (FW_W_BUTTON(fw
, i
) == None
)
615 old_state
= border_flags_to_button_state(
616 (fw
->decor_state
.buttons_inverted
& mask
),
617 (fw
->decor_state
.buttons_lit
& mask
),
618 (fw
->decor_state
.buttons_toggled
& mask
));
619 if (old_state
!= td
->tbstate
.bstate
[i
])
621 draw_parts
|= PART_BUTTONS
;
622 td
->tbstate
.draw_bmask
|= mask
;
624 if ((td
->old_layout
.button_g
[i
].width
!=
625 td
->layout
.button_g
[i
].width
||
626 td
->old_layout
.button_g
[i
].height
!=
627 td
->layout
.button_g
[i
].height
) &&
628 td
->layout
.button_g
[i
].x
>= 0 &&
629 td
->layout
.button_g
[i
].y
>= 0)
631 draw_parts
|= PART_BUTTONS
;
632 td
->tbstate
.draw_bmask
|= mask
;
635 /* position changed and background is tiled or a cset? */
636 if ((draw_parts
& PART_TITLE
) == PART_NONE
&&
637 td
->layout
.title_g
.x
>= 0 &&
638 td
->layout
.title_g
.y
>= 0)
640 df
= &TB_STATE(GetDecor(fw
, titlebar
))[td
->tbstate
.tstate
];
641 if (DFS_USE_BORDER_STYLE(df
->style
) &&
642 (((td
->old_layout
.title_g
.x
!= td
->layout
.title_g
.x
||
643 td
->old_layout
.title_g
.y
!= td
->layout
.title_g
.y
) &&
644 ((td
->cd
->valuemask
& CWBackPixmap
) ||
645 CSET_PIXMAP_IS_TILED(td
->cd
->bg_border_cs
)))
647 (old_g
->width
!= new_g
->width
&&
648 CSET_PIXMAP_IS_X_STRETCHED(td
->cd
->bg_border_cs
))
650 (old_g
->height
!= new_g
->height
651 && CSET_PIXMAP_IS_Y_STRETCHED(td
->cd
->bg_border_cs
))
653 ((old_g
->x
!= new_g
->x
|| old_g
->y
!= new_g
->y
)
654 && CSET_IS_TRANSPARENT_ROOT(td
->cd
->bg_border_cs
))))
656 draw_parts
|= PART_TITLE
;
658 if ((draw_parts
& PART_TITLE
) == PART_NONE
&&
659 (old_g
->x
!= new_g
->x
|| old_g
->y
!= new_g
->y
))
661 for (tdf
= df
; tdf
!= NULL
; tdf
= tdf
->next
)
663 if (DFS_FACE_TYPE(tdf
->style
) ==
665 CSET_IS_TRANSPARENT_ROOT(tdf
->u
.acs
.cs
))
667 draw_parts
|= PART_TITLE
;
673 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
680 GetDecor(fw
, buttons
[i
]))[td
->tbstate
.bstate
[i
]].style
;
681 if ((td
->tbstate
.draw_bmask
& mask
) ||
682 td
->layout
.button_g
[i
].x
< 0 ||
683 td
->layout
.button_g
[i
].y
< 0)
687 if (DFS_USE_BORDER_STYLE(*bs
) &&
688 (((td
->old_layout
.button_g
[i
].x
!=
689 td
->layout
.button_g
[i
].x
||
690 td
->old_layout
.button_g
[i
].y
!=
691 td
->layout
.button_g
[i
].y
)
692 && ((td
->cd
->valuemask
& CWBackPixmap
) ||
693 CSET_PIXMAP_IS_TILED(td
->cd
->bg_border_cs
)))
695 (old_g
->width
!= new_g
->width
&&
696 CSET_PIXMAP_IS_X_STRETCHED(td
->cd
->bg_border_cs
))
698 (old_g
->height
!= new_g
->height
699 && CSET_PIXMAP_IS_Y_STRETCHED(td
->cd
->bg_border_cs
))
701 ((old_g
->x
!= new_g
->x
|| old_g
->y
!= new_g
->y
)
702 && CSET_IS_TRANSPARENT_ROOT(td
->cd
->bg_border_cs
))))
704 td
->tbstate
.draw_bmask
|= mask
;
706 else if (DFS_USE_TITLE_STYLE(*bs
))
708 df
= &TB_STATE(GetDecor(
709 fw
, titlebar
))[td
->tbstate
.bstate
[i
]];
710 for(tdf
= df
; tdf
!= NULL
; tdf
= tdf
->next
)
713 if (DFS_FACE_TYPE(tdf
->style
) == MultiPixmap
)
715 /* can be improved */
716 td
->tbstate
.draw_bmask
|= mask
;
719 if (DFS_FACE_TYPE(tdf
->style
) != ColorsetButton
720 || !CSET_HAS_PIXMAP(tdf
->u
.acs
.cs
))
725 if(((td
->old_layout
.button_g
[i
].x
!=
726 td
->layout
.button_g
[i
].x
||
727 td
->old_layout
.button_g
[i
].y
!=
728 td
->layout
.button_g
[i
].y
) ||
729 CSET_PIXMAP_IS_TILED(cs
))
731 (old_g
->width
!= new_g
->width
&&
732 CSET_PIXMAP_IS_X_STRETCHED(cs
))
734 (old_g
->height
!= new_g
->height
&&
735 CSET_PIXMAP_IS_Y_STRETCHED(cs
))
737 ((old_g
->x
!= new_g
->x
||
738 old_g
->y
!= new_g
->y
)
739 && CSET_IS_TRANSPARENT_ROOT(cs
)))
741 td
->tbstate
.draw_bmask
|= mask
;
746 if (td
->tbstate
.draw_bmask
& mask
)
750 if (old_g
->x
!= new_g
->x
|| old_g
->y
!= new_g
->y
)
752 df
= &TB_STATE(GetDecor(
753 fw
, buttons
[i
]))[td
->tbstate
.bstate
[i
]];
754 for(tdf
= df
; tdf
!= NULL
; tdf
= tdf
->next
)
756 if (DFS_FACE_TYPE(tdf
->style
) ==
758 CSET_IS_TRANSPARENT_ROOT(tdf
->u
.acs
.cs
))
760 td
->tbstate
.draw_bmask
|= mask
;
766 td
->tbstate
.max_bmask
= 0;
767 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
769 if (FW_W_BUTTON(fw
, i
) == None
)
773 if ((i
& 1) == 1 && i
/ 2 < Scr
.nr_right_buttons
)
775 td
->tbstate
.max_bmask
|= (1 << i
);
777 else if ((i
& 1) == 0 && i
/ 2 < Scr
.nr_left_buttons
)
779 td
->tbstate
.max_bmask
|= (1 << i
);
782 td
->tbstate
.draw_bmask
&= td
->tbstate
.max_bmask
;
783 td
->tbstate
.pressed_bmask
&= td
->tbstate
.max_bmask
;
784 td
->tbstate
.lit_bmask
&= td
->tbstate
.max_bmask
;
785 td
->tbstate
.toggled_bmask
&= td
->tbstate
.max_bmask
;
786 td
->tbstate
.clear_bmask
&= td
->tbstate
.max_bmask
;
787 if (td
->tbstate
.draw_bmask
== 0)
789 draw_parts
&= ~PART_BUTTONS
;
793 draw_parts
|= PART_BUTTONS
;
795 draw_parts
&= PART_TITLEBAR
;
800 static void border_get_border_gcs(
801 draw_border_gcs
*ret_gcs
, common_decorations_type
*cd
, FvwmWindow
*fw
,
804 static GC transparent_gc
= None
;
805 DecorFaceStyle
*borderstyle
;
806 Bool is_reversed
= False
;
808 if (transparent_gc
== None
&& !HAS_NO_BORDER(fw
) && !HAS_MWM_BORDER(fw
))
812 xgcv
.function
= GXnoop
;
814 transparent_gc
= fvwmlib_XCreateGC(
815 dpy
, Scr
.NoFocusWin
, GCFunction
| GCPlaneMask
, &xgcv
);
817 ret_gcs
->transparent
= transparent_gc
;
818 /* get the border style bits */
819 borderstyle
= (do_hilight
) ?
820 &GetDecor(fw
, BorderStyle
.active
.style
) :
821 &GetDecor(fw
, BorderStyle
.inactive
.style
);
822 if (borderstyle
->flags
.button_relief
== DFS_BUTTON_IS_SUNK
)
828 ret_gcs
->shadow
= cd
->relief_gc
;
829 ret_gcs
->relief
= cd
->shadow_gc
;
833 ret_gcs
->relief
= cd
->relief_gc
;
834 ret_gcs
->shadow
= cd
->shadow_gc
;
840 static void trim_border_layout(
841 FvwmWindow
*fw
, DecorFaceStyle
*borderstyle
,
842 border_relief_size_descr
*ret_size_descr
)
844 /* If the border is too thin to accomodate the standard look, we remove
845 * parts of the border so that at least one pixel of the original
846 * colour is visible. We make an exception for windows with a border
847 * width of 2, though. */
848 if ((!IS_SHADED(fw
) || HAS_TITLE(fw
)) && fw
->boundary_width
== 2)
850 ret_size_descr
->trim
--;
852 if (ret_size_descr
->trim
< 0)
854 ret_size_descr
->trim
= 0;
856 for ( ; ret_size_descr
->trim
> 0; ret_size_descr
->trim
--)
858 if (ret_size_descr
->w_hiout
> 1)
860 ret_size_descr
->w_hiout
--;
862 else if (ret_size_descr
->w_shin
> 0)
864 ret_size_descr
->w_shin
--;
866 else if (ret_size_descr
->w_hiout
> 0)
868 ret_size_descr
->w_hiout
--;
870 else if (ret_size_descr
->w_trout
> 0)
872 ret_size_descr
->w_trout
= 0;
873 ret_size_descr
->w_trin
= 0;
874 ret_size_descr
->w_din
= 0;
875 ret_size_descr
->w_hiout
= 1;
877 ret_size_descr
->sum
--;
879 ret_size_descr
->w_c
= fw
->boundary_width
- ret_size_descr
->sum
;
884 static void check_remove_inset(
885 DecorFaceStyle
*borderstyle
, border_relief_size_descr
*ret_size_descr
)
887 if (!DFS_HAS_NO_INSET(*borderstyle
))
891 ret_size_descr
->w_shin
= 0;
892 ret_size_descr
->sum
--;
893 ret_size_descr
->trim
--;
894 if (ret_size_descr
->w_trin
)
896 ret_size_descr
->w_trout
= 0;
897 ret_size_descr
->w_trin
= 0;
898 ret_size_descr
->w_din
= 0;
899 ret_size_descr
->w_hiout
= 1;
900 ret_size_descr
->sum
-= 2;
901 ret_size_descr
->trim
-= 2;
907 static void border_fetch_mwm_layout(
908 FvwmWindow
*fw
, DecorFaceStyle
*borderstyle
,
909 border_relief_size_descr
*ret_size_descr
)
911 /* MWM borders look like this:
913 * HHCCCCS from outside to inside on the left and top border
914 * SSCCCCH from outside to inside on the bottom and right border
916 * |||||||__ w_shin (inner shadow area)
917 * ||||||___ w_c (transparent area)
918 * |||||____ w_c (transparent area)
919 * ||||_____ w_c (transparent area)
920 * |||______ w_c (transparent area)
921 * ||_______ w_hiout (outer hilight area)
922 * |________ w_hiout (outer hilight area)
925 * C = original colour
929 ret_size_descr
->w_dout
= 0;
930 ret_size_descr
->w_hiout
= 2;
931 ret_size_descr
->w_trout
= 0;
932 ret_size_descr
->w_trin
= 0;
933 ret_size_descr
->w_shin
= 1;
934 ret_size_descr
->w_din
= 0;
935 ret_size_descr
->sum
= 3;
936 ret_size_descr
->trim
= ret_size_descr
->sum
- fw
->boundary_width
+ 1;
937 check_remove_inset(borderstyle
, ret_size_descr
);
938 trim_border_layout(fw
, borderstyle
, ret_size_descr
);
943 static void border_fetch_fvwm_layout(
944 FvwmWindow
*fw
, DecorFaceStyle
*borderstyle
,
945 border_relief_size_descr
*ret_size_descr
)
947 /* Fvwm borders look like this:
949 * SHHCCSS from outside to inside on the left and top border
950 * SSCCHHS from outside to inside on the bottom and right border
952 * |||||||__ w_din (inner dark area)
953 * ||||||___ w_shin (inner shadow area)
954 * |||||____ w_trin (inner transparent/shadow area)
955 * ||||_____ w_c (transparent area)
956 * |||______ w_trout (outer transparent/hilight area)
957 * ||_______ w_hiout (outer hilight area)
958 * |________ w_dout (outer dark area)
960 * C = original colour
964 * reduced to 5 pixels it looks like this:
969 * |||||__ w_din (inner dark area)
970 * ||||___ w_trin (inner transparent/shadow area)
971 * |||____ w_trout (outer transparent/hilight area)
972 * ||_____ w_hiout (outer hilight area)
973 * |______ w_dout (outer dark area)
975 ret_size_descr
->w_dout
= 1;
976 ret_size_descr
->w_hiout
= 1;
977 ret_size_descr
->w_trout
= 1;
978 ret_size_descr
->w_trin
= 1;
979 ret_size_descr
->w_shin
= 1;
980 ret_size_descr
->w_din
= 1;
981 /* w_trout + w_trin counts only as one pixel of border because
982 * they let one pixel of the original colour shine through. */
983 ret_size_descr
->sum
= 6;
984 ret_size_descr
->trim
= ret_size_descr
->sum
- fw
->boundary_width
;
985 check_remove_inset(borderstyle
, ret_size_descr
);
986 trim_border_layout(fw
, borderstyle
, ret_size_descr
);
991 static void border_get_border_relief_size_descr(
992 border_relief_size_descr
*ret_size_descr
, FvwmWindow
*fw
,
995 DecorFaceStyle
*borderstyle
;
997 if (is_window_border_minimal(fw
))
999 /* the border is too small, only a background but no relief */
1000 ret_size_descr
->is_flat
= 1;
1003 borderstyle
= (do_hilight
) ?
1004 &GetDecor(fw
, BorderStyle
.active
.style
) :
1005 &GetDecor(fw
, BorderStyle
.inactive
.style
);
1006 if (borderstyle
->flags
.button_relief
== DFS_BUTTON_IS_FLAT
)
1008 ret_size_descr
->is_flat
= 1;
1011 ret_size_descr
->is_flat
= 0;
1012 /* get the relief layout */
1013 if (HAS_MWM_BORDER(fw
))
1015 border_fetch_mwm_layout(fw
, borderstyle
, ret_size_descr
);
1019 border_fetch_fvwm_layout(fw
, borderstyle
, ret_size_descr
);
1025 static void border_get_border_marks_descr(
1026 common_decorations_type
*cd
, border_relief_descr
*br
, FvwmWindow
*fw
)
1030 /* get mark's length and thickness */
1031 inset
= (br
->relief
.w_shin
!= 0 || br
->relief
.w_din
!= 0);
1032 br
->marks
.length
= fw
->boundary_width
- br
->relief
.w_dout
- inset
;
1033 if (br
->marks
.length
<= 0)
1035 br
->marks
.has_x_marks
= 0;
1036 br
->marks
.has_y_marks
= 0;
1039 br
->marks
.thickness
= cd
->relief_width
;
1040 if (br
->marks
.thickness
> br
->marks
.length
)
1042 br
->marks
.thickness
= br
->marks
.length
;
1044 /* get offsets from outer side of window */
1045 br
->marks
.offset_tl
= br
->relief
.w_dout
;
1046 br
->marks
.offset_br
=
1047 -br
->relief
.w_dout
- br
->marks
.length
- br
->marks
.offset_tl
;
1052 static Pixmap
border_create_decor_pixmap(
1053 common_decorations_type
*cd
, rectangle
*decor_g
)
1058 dpy
, Scr
.Root
, decor_g
->width
, decor_g
->height
, Pdepth
);
1063 static void border_draw_part_relief(
1064 border_relief_descr
*br
, rectangle
*frame_g
, rectangle
*part_g
,
1065 Pixmap dest_pix
, Bool is_inverted
)
1070 int width
= frame_g
->width
- 1;
1071 int height
= frame_g
->height
- 1;
1075 w
[0] = br
->relief
.w_dout
;
1076 w
[1] = br
->relief
.w_hiout
;
1077 w
[2] = br
->relief
.w_trout
;
1078 w
[3] = br
->relief
.w_c
;
1079 w
[4] = br
->relief
.w_trin
;
1080 w
[5] = br
->relief
.w_shin
;
1081 w
[6] = br
->relief
.w_din
;
1082 gc
[(is_inverted
== True
)] = br
->gcs
.relief
;
1083 gc
[!(is_inverted
== True
)] = br
->gcs
.shadow
;
1084 gc
[2] = br
->gcs
.transparent
;
1085 gc
[3] = br
->gcs
.shadow
;
1089 width
= frame_g
->width
- 1;
1090 height
= frame_g
->height
- 1;
1091 for (i
= 0; i
< 7; i
++)
1093 if (ulgc
[i
] != 0x7f && w
[i
] > 0)
1095 do_relieve_rectangle(
1096 dpy
, dest_pix
, off_x
, off_y
,
1097 width
, height
, gc
[(int)ulgc
[i
]],
1098 gc
[(int)brgc
[i
]], w
[i
], False
);
1109 static void border_draw_x_mark(
1110 border_relief_descr
*br
, int x
, int y
, Pixmap dest_pix
,
1111 Bool do_draw_shadow
)
1117 if (br
->marks
.has_x_marks
== 0)
1121 x
+= br
->marks
.offset_tl
;
1122 gc
= (do_draw_shadow
) ? br
->gcs
.shadow
: br
->gcs
.relief
;
1124 for (k
= 0, length
= br
->marks
.length
- 1; k
< br
->marks
.thickness
;
1148 XDrawLine(dpy
, dest_pix
, gc
, x1
, y1
, x2
, y2
);
1154 static void border_draw_y_mark(
1155 border_relief_descr
*br
, int x
, int y
, Pixmap dest_pix
,
1156 Bool do_draw_shadow
)
1162 if (br
->marks
.has_y_marks
== 0)
1166 y
+= br
->marks
.offset_tl
;
1167 gc
= (do_draw_shadow
) ? br
->gcs
.shadow
: br
->gcs
.relief
;
1169 for (k
= 0, length
= br
->marks
.length
; k
< br
->marks
.thickness
;
1192 y2
= y1
+ length
- 1;
1193 XDrawLine(dpy
, dest_pix
, gc
, x1
, y1
, x2
, y2
);
1199 static void border_draw_part_marks(
1200 border_relief_descr
*br
, rectangle
*part_g
, window_parts part
,
1209 l
= br
->sidebar_g
.x
;
1210 t
= br
->sidebar_g
.y
;
1213 o
= br
->marks
.offset_br
;
1217 border_draw_y_mark(br
, 0, 0, dest_pix
, False
);
1218 border_draw_y_mark(br
, w
, 0, dest_pix
, True
);
1221 border_draw_y_mark(br
, 0, h
+ o
, dest_pix
, False
);
1222 border_draw_y_mark(br
, w
, h
+ o
, dest_pix
, True
);
1225 border_draw_x_mark(br
, w
+ o
, 0, dest_pix
, False
);
1226 border_draw_x_mark(br
, w
+ o
, h
, dest_pix
, True
);
1229 border_draw_x_mark(br
, 0, 0, dest_pix
, False
);
1230 border_draw_x_mark(br
, 0, h
, dest_pix
, True
);
1232 case PART_BORDER_NW
:
1233 border_draw_x_mark(br
, 0, t
, dest_pix
, True
);
1234 border_draw_y_mark(br
, l
, 0, dest_pix
, True
);
1236 case PART_BORDER_NE
:
1237 border_draw_x_mark(br
, l
+ o
, t
, dest_pix
, True
);
1238 border_draw_y_mark(br
, 0, 0, dest_pix
, False
);
1240 case PART_BORDER_SW
:
1241 border_draw_x_mark(br
, 0, 0, dest_pix
, False
);
1242 border_draw_y_mark(br
, l
, t
+ o
, dest_pix
, True
);
1244 case PART_BORDER_SE
:
1245 border_draw_x_mark(br
, l
+ o
, 0, dest_pix
, False
);
1246 border_draw_y_mark(br
, 0, t
+ o
, dest_pix
, False
);
1255 inline static void border_set_part_background(
1256 Window w
, Pixmap pix
)
1258 XSetWindowAttributes xswa
;
1260 xswa
.background_pixmap
= pix
;
1261 XChangeWindowAttributes(dpy
, w
, CWBackPixmap
, &xswa
);
1266 /* render the an image into the pixmap */
1267 static void border_fill_pixmap_background(
1268 Pixmap dest_pix
, rectangle
*dest_g
, pixmap_background_type
*bg
,
1269 common_decorations_type
*cd
)
1274 unsigned long valuemask
;
1275 Pixmap p
= None
, shape
= None
, alpha
= None
;
1276 int src_width
, src_height
;
1278 do_tile
= (bg
->flags
.use_pixmap
&& bg
->pixmap
.flags
.is_tiled
) ?
1280 do_stretch
= (bg
->flags
.use_pixmap
&& bg
->pixmap
.flags
.is_stretched
) ?
1282 xgcv
.fill_style
= FillSolid
;
1283 valuemask
= GCFillStyle
;
1284 if (!bg
->flags
.use_pixmap
)
1287 xgcv
.foreground
= bg
->pixel
;
1288 xgcv
.clip_x_origin
= 0;
1289 xgcv
.clip_y_origin
= 0;
1290 xgcv
.clip_mask
= None
;
1291 valuemask
|= GCForeground
| GCClipMask
| GCClipXOrigin
|
1293 XChangeGC(dpy
, Scr
.BordersGC
, valuemask
, &xgcv
);
1295 dpy
, dest_pix
, Scr
.BordersGC
, dest_g
->x
, dest_g
->y
,
1296 dest_g
->width
- dest_g
->x
, dest_g
->height
- dest_g
->y
);
1304 p
= CreateStretchPixmap(
1306 bg
->pixmap
.g
.width
, bg
->pixmap
.g
.height
,
1308 bg
->pixmap
.stretch_w
, bg
->pixmap
.stretch_h
,
1309 (bg
->pixmap
.depth
== 1)?
1310 Scr
.MonoGC
:Scr
.BordersGC
);
1312 if (bg
->pixmap
.shape
)
1314 shape
= CreateStretchPixmap(
1315 dpy
, bg
->pixmap
.shape
,
1316 bg
->pixmap
.g
.width
, bg
->pixmap
.g
.height
, 1,
1317 bg
->pixmap
.stretch_w
, bg
->pixmap
.stretch_h
,
1320 if (bg
->pixmap
.alpha
)
1322 alpha
= CreateStretchPixmap(
1323 dpy
, bg
->pixmap
.alpha
,
1324 bg
->pixmap
.g
.width
, bg
->pixmap
.g
.height
,
1325 FRenderGetAlphaDepth(),
1326 bg
->pixmap
.stretch_w
, bg
->pixmap
.stretch_h
,
1329 src_width
= bg
->pixmap
.stretch_w
;
1330 src_height
= bg
->pixmap
.stretch_h
;
1335 shape
= bg
->pixmap
.shape
;
1336 alpha
= bg
->pixmap
.alpha
;
1337 src_width
= bg
->pixmap
.g
.width
;
1338 src_height
= bg
->pixmap
.g
.height
;
1341 if (do_tile
== False
)
1343 /* pixmap, offset stored in dest_g->x/y */
1344 xgcv
.foreground
= cd
->fore_color
;
1345 xgcv
.background
= cd
->back_color
;
1346 valuemask
|= GCForeground
|GCBackground
;
1347 XChangeGC(dpy
, Scr
.BordersGC
, valuemask
, &xgcv
);
1348 PGraphicsRenderPixmaps(
1349 dpy
, Scr
.NoFocusWin
, p
, shape
, alpha
,
1350 bg
->pixmap
.depth
, &(bg
->pixmap
.fra
),
1351 dest_pix
, Scr
.BordersGC
, Scr
.MonoGC
, Scr
.AlphaGC
,
1352 bg
->pixmap
.g
.x
, bg
->pixmap
.g
.y
,
1353 src_width
, src_height
,
1354 dest_g
->x
, dest_g
->y
, dest_g
->width
- dest_g
->x
,
1355 dest_g
->height
- dest_g
->y
, False
);
1360 xgcv
.foreground
= cd
->fore_color
;
1361 xgcv
.background
= cd
->back_color
;
1362 valuemask
|= GCForeground
|GCBackground
;
1363 XChangeGC(dpy
, Scr
.BordersGC
, valuemask
, &xgcv
);
1364 PGraphicsRenderPixmaps(
1365 dpy
, Scr
.NoFocusWin
, p
, shape
, alpha
,
1366 bg
->pixmap
.depth
, &(bg
->pixmap
.fra
),
1367 dest_pix
, Scr
.BordersGC
, Scr
.MonoGC
, Scr
.AlphaGC
,
1368 bg
->pixmap
.g
.x
, bg
->pixmap
.g
.y
,
1369 src_width
, src_height
,
1370 dest_g
->x
, dest_g
->y
,
1371 dest_g
->width
- dest_g
->x
,
1372 dest_g
->height
- dest_g
->y
, True
);
1374 if (p
&& p
!= bg
->pixmap
.p
)
1376 XFreePixmap(dpy
, p
);
1378 if (shape
&& shape
!= bg
->pixmap
.shape
)
1380 XFreePixmap(dpy
, shape
);
1382 if (alpha
&& alpha
!= bg
->pixmap
.alpha
)
1384 XFreePixmap(dpy
, alpha
);
1389 /* create a root transparent colorset bg, we take in account a possible
1390 * drawing rotation */
1391 static Pixmap
border_create_root_transparent_pixmap(
1392 titlebar_descr
*td
, Window w
, int width
, int height
, int cs
)
1397 if (!CSET_IS_TRANSPARENT_ROOT(cs
))
1401 if (td
->td_is_rotated
&&
1402 (td
->draw_rotation
== ROTATION_90
||
1403 td
->draw_rotation
== ROTATION_270
))
1413 p
= CreateBackgroundPixmap(
1414 dpy
, w
, my_w
, my_h
, &Colorset
[cs
],
1415 Pdepth
, Scr
.BordersGC
, False
);
1416 if (p
&& td
->td_is_rotated
)
1419 tmp
= CreateRotatedPixmap(
1420 dpy
, p
, my_w
, my_h
, Pdepth
, Scr
.BordersGC
,
1421 td
->restore_rotation
);
1422 XFreePixmap(dpy
, p
);
1428 static void border_get_frame_pixmap(
1429 common_decorations_type
*cd
, rectangle
*frame_g
)
1431 dynamic_common_decorations
*dcd
= &(cd
->dynamic_cd
);
1433 if (dcd
->frame_pixmap
!= None
)
1435 /* should not happen */
1436 fprintf(stderr
, "Bad use of border_get_frame_pixmap!!\n");
1437 dcd
->frame_pixmap
= None
;
1440 if (cd
->bg_border_cs
< 0 || CSET_IS_TRANSPARENT(cd
->bg_border_cs
))
1442 /* should not happen */
1446 dcd
->frame_pixmap
= CreateBackgroundPixmap(
1447 dpy
, Scr
.NoFocusWin
, frame_g
->width
, frame_g
->height
,
1448 &Colorset
[cd
->bg_border_cs
], Pdepth
, Scr
.BordersGC
,
1454 static void border_get_border_background(
1455 pixmap_background_type
*bg
, common_decorations_type
*cd
,
1456 rectangle
*part_g
, rectangle
*relative_g
, int *free_bg_pixmap
, Window w
)
1458 *free_bg_pixmap
= False
;
1460 if (cd
->texture_pixmap
)
1462 bg
->flags
.use_pixmap
= 1;
1463 bg
->pixmap
.p
= cd
->texture_pixmap
;
1464 bg
->pixmap
.g
.width
= cd
->texture_pixmap_width
;
1465 bg
->pixmap
.g
.height
= cd
->texture_pixmap_height
;
1466 bg
->pixmap
.shape
= None
;
1467 bg
->pixmap
.alpha
= None
;
1468 bg
->pixmap
.depth
= Pdepth
;
1469 bg
->pixmap
.flags
.is_tiled
= 1;
1470 bg
->pixmap
.flags
.is_stretched
= 0;
1471 bg
->pixmap
.fra
.mask
= 0;
1473 else if (cd
->bg_border_cs
>= 0 &&
1474 !CSET_IS_TRANSPARENT_PR(cd
->bg_border_cs
))
1476 colorset_t
*cs_t
= &Colorset
[cd
->bg_border_cs
];
1479 if (CSET_IS_TRANSPARENT_ROOT(cd
->bg_border_cs
))
1481 bg
->pixmap
.p
= CreateBackgroundPixmap(
1482 dpy
, w
, part_g
->width
, part_g
->height
, cs_t
,
1483 Pdepth
, Scr
.BordersGC
, False
);
1488 if (cd
->dynamic_cd
.frame_pixmap
== None
)
1490 border_get_frame_pixmap(cd
, relative_g
);
1492 bg
->pixmap
.p
= XCreatePixmap(
1493 dpy
, cd
->dynamic_cd
.frame_pixmap
, part_g
->width
,
1494 part_g
->height
, Pdepth
);
1495 xgcv
.fill_style
= FillTiled
;
1496 xgcv
.tile
= cd
->dynamic_cd
.frame_pixmap
;
1497 xgcv
.ts_x_origin
= - relative_g
->x
;
1498 xgcv
.ts_y_origin
= - relative_g
->y
;
1500 dpy
, Scr
.BordersGC
, GCTile
| GCTileStipXOrigin
|
1501 GCTileStipYOrigin
| GCFillStyle
, &xgcv
);
1503 dpy
, bg
->pixmap
.p
, Scr
.BordersGC
, 0, 0,
1504 part_g
->width
, part_g
->height
);
1505 xgcv
.fill_style
= FillSolid
;
1506 XChangeGC(dpy
, Scr
.BordersGC
, GCFillStyle
, &xgcv
);
1508 bg
->pixmap
.g
.width
= part_g
->width
;
1509 bg
->pixmap
.g
.height
= part_g
->height
;
1510 bg
->flags
.use_pixmap
= 1;
1511 bg
->pixmap
.shape
= None
;
1512 bg
->pixmap
.alpha
= None
;
1513 bg
->pixmap
.depth
= Pdepth
;
1514 bg
->pixmap
.flags
.is_tiled
= 1;
1515 bg
->pixmap
.flags
.is_stretched
= 0;
1516 bg
->pixmap
.fra
.mask
= 0;
1517 *free_bg_pixmap
= True
;
1521 bg
->flags
.use_pixmap
= 0;
1522 bg
->pixel
= cd
->attributes
.background_pixel
;
1528 static void border_draw_one_border_part(
1529 common_decorations_type
*cd
, FvwmWindow
*fw
, rectangle
*sidebar_g
,
1530 rectangle
*frame_g
, border_relief_descr
*br
, window_parts part
,
1531 window_parts draw_handles
, Bool is_inverted
, Bool do_clear
)
1533 pixmap_background_type bg
;
1536 rectangle relative_g
;
1539 Bool free_bg_pixmap
= False
;
1542 border_get_part_geometry(fw
, part
, sidebar_g
, &part_g
, &w
);
1543 if (part_g
.width
<= 0 || part_g
.height
<= 0)
1547 p
= border_create_decor_pixmap(cd
, &part_g
);
1548 /* set the background tile */
1549 relative_g
.width
= fw
->g
.frame
.width
;
1550 relative_g
.height
= fw
->g
.frame
.height
;
1551 relative_g
.x
= part_g
.x
;
1552 relative_g
.y
= part_g
.y
;
1553 border_get_border_background(
1554 &bg
, cd
, &part_g
, &relative_g
, &free_bg_pixmap
, w
);
1555 if (cd
->texture_pixmap
)
1560 bg
.pixmap
.g
.x
= frame_g
->width
- fw
->boundary_width
;
1562 case PART_BORDER_NE
:
1563 case PART_BORDER_SE
:
1564 bg
.pixmap
.g
.x
= frame_g
->width
- fw
->corner_width
;
1568 bg
.pixmap
.g
.x
= fw
->corner_width
;
1577 bg
.pixmap
.g
.y
= frame_g
->height
- fw
->boundary_width
;
1579 case PART_BORDER_SW
:
1580 case PART_BORDER_SE
:
1581 bg
.pixmap
.g
.y
= frame_g
->height
- fw
->corner_width
;
1585 bg
.pixmap
.g
.y
= fw
->corner_width
;
1597 /* set the geometry for drawing the Tiled pixmap; maybe add the relief
1601 pix_g
.width
= part_g
.width
;
1602 pix_g
.height
= part_g
.height
;
1603 border_fill_pixmap_background(p
, &pix_g
, &bg
, cd
);
1604 if (free_bg_pixmap
&& bg
.pixmap
.p
)
1606 XFreePixmap(dpy
, bg
.pixmap
.p
);
1608 /* draw the relief over the background */
1609 if (!br
->relief
.is_flat
)
1611 border_draw_part_relief(br
, frame_g
, &part_g
, p
, is_inverted
);
1612 /* draw the handle marks */
1613 if (br
->marks
.has_x_marks
|| br
->marks
.has_y_marks
)
1615 border_draw_part_marks(br
, &part_g
, part
, p
);
1618 /* apply the pixmap and destroy it */
1619 border_set_part_background(w
, p
);
1620 if (do_clear
== True
)
1622 XClearWindow(dpy
,w
);
1624 XFreePixmap(dpy
, p
);
1629 static void border_draw_all_border_parts(
1630 common_decorations_type
*cd
, FvwmWindow
*fw
, border_relief_descr
*br
,
1631 rectangle
*frame_g
, window_parts draw_parts
,
1632 window_parts pressed_parts
, Bool do_hilight
, Bool do_clear
)
1635 window_parts draw_handles
;
1637 /* get the description of the drawing directives */
1638 border_get_border_relief_size_descr(&br
->relief
, fw
, do_hilight
);
1639 border_get_border_marks_descr(cd
, br
, fw
);
1640 /* fetch the gcs used to draw the border */
1641 border_get_border_gcs(&br
->gcs
, cd
, fw
, do_hilight
);
1642 /* draw everything in a big loop */
1643 draw_parts
&= (PART_FRAME
| PART_HANDLES
);
1644 draw_handles
= (draw_parts
& PART_HANDLES
);
1646 for (part
= PART_BORDER_N
; (part
& PART_FRAME
); part
<<= 1)
1648 if (part
& draw_parts
)
1650 border_draw_one_border_part(
1651 cd
, fw
, &br
->sidebar_g
, frame_g
, br
, part
,
1653 (pressed_parts
& part
) ? True
: False
,
1663 * Draws a little pattern within a window (more complex)
1666 static void border_draw_vector_to_pixmap(
1667 Pixmap dest_pix
, common_decorations_type
*cd
, int is_toggled
,
1668 struct vector_coords
*coords
, rectangle
*pixmap_g
)
1673 if (coords
->use_fgbg
== 1)
1675 Globalgcv
.foreground
= cd
->fore_color
;
1676 Globalgcm
= GCForeground
;
1677 XChangeGC(dpy
, Scr
.ScratchGC3
, Globalgcm
, &Globalgcv
);
1678 Globalgcv
.foreground
= cd
->back_color
;
1679 XChangeGC(dpy
, Scr
.ScratchGC4
, Globalgcm
, &Globalgcv
);
1680 gcs
[3] = Scr
.ScratchGC3
; /* @3 is fg */
1681 gcs
[2] = Scr
.ScratchGC4
; /* @2 is bg */
1685 gcs
[0] = cd
->relief_gc
;
1686 gcs
[1] = cd
->shadow_gc
;
1690 gcs
[0] = cd
->shadow_gc
;
1691 gcs
[1] = cd
->relief_gc
;
1693 for (i
= 1; i
< coords
->num
; i
++)
1695 if (coords
->c
[i
] < 0 || coords
->c
[i
] >= 4)
1697 /* don't draw a line */
1701 dpy
, dest_pix
, gcs
[coords
->c
[i
]],
1702 pixmap_g
->width
* coords
->x
[i
-1] / 100 +
1704 pixmap_g
->height
* coords
->y
[i
-1] / 100 +
1706 pixmap_g
->width
* coords
->x
[i
] / 100 +
1708 pixmap_g
->height
* coords
->y
[i
] / 100 +
1717 * Handle Title pixmaps used for UseTitleStyle
1720 static void border_setup_bar_pixmaps(
1721 titlebar_descr
*td
, dynamic_common_decorations
*dcd
, DecorFace
*df
,
1724 int count
= dcd
->bar_pixmaps
[bs
].count
;
1726 int i
, j
, mp_part_left
, mp_part_right
;
1734 for (tsdf
= df
; tsdf
!= NULL
; tsdf
= tsdf
->next
)
1736 if (DFS_FACE_TYPE(tsdf
->style
) == ColorsetButton
)
1740 else if (DFS_FACE_TYPE(tsdf
->style
) == MultiPixmap
)
1742 border_mp_get_use_title_style_parts_and_geometry(
1743 td
, tsdf
->u
.mp
.pixmaps
, tsdf
->u
.mp
.acs
,
1744 tsdf
->u
.mp
.solid_flags
, True
, NULL
,
1746 border_mp_get_use_title_style_parts_and_geometry(
1747 td
, tsdf
->u
.mp
.pixmaps
, tsdf
->u
.mp
.acs
,
1748 tsdf
->u
.mp
.solid_flags
, False
, NULL
,
1750 for (j
= 0; j
< UTS_TBMP_NUM_PIXMAPS
; j
++)
1752 if (j
!= mp_part_left
&& j
!= mp_part_right
)
1756 if (tsdf
->u
.mp
.acs
[j
].cs
>= 0 ||
1757 tsdf
->u
.mp
.pixmaps
[j
])
1766 dcd
->bar_pixmaps
[bs
].count
= -1;
1771 dcd
->bar_pixmaps
[bs
].bps
=
1772 (bar_pixmap
*)safemalloc(count
*sizeof(bar_pixmap
));
1774 dcd
->bar_pixmaps
[bs
].count
= count
;
1776 for (tsdf
= df
; tsdf
!= NULL
; tsdf
= tsdf
->next
)
1778 if (DFS_FACE_TYPE(tsdf
->style
) == ColorsetButton
)
1780 dcd
->bar_pixmaps
[bs
].bps
[i
].p
= None
;
1781 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
= NULL
;
1782 dcd
->bar_pixmaps
[bs
].bps
[i
].cs
= tsdf
->u
.acs
.cs
;
1783 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_pic
= NULL
;
1784 dcd
->bar_pixmaps
[bs
].bps
[i
].created
= 0;
1785 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_part
= TBMP_NONE
;
1788 else if (DFS_FACE_TYPE(tsdf
->style
) == MultiPixmap
)
1790 border_mp_get_use_title_style_parts_and_geometry(
1791 td
, tsdf
->u
.mp
.pixmaps
, tsdf
->u
.mp
.acs
,
1792 tsdf
->u
.mp
.solid_flags
, True
, NULL
,
1794 border_mp_get_use_title_style_parts_and_geometry(
1795 td
, tsdf
->u
.mp
.pixmaps
, tsdf
->u
.mp
.acs
,
1796 tsdf
->u
.mp
.solid_flags
, False
, NULL
,
1798 for (j
= 0; j
< UTS_TBMP_NUM_PIXMAPS
; j
++)
1800 if (j
!= mp_part_left
&& j
!= mp_part_right
)
1804 if (tsdf
->u
.mp
.acs
[j
].cs
>= 0 ||
1805 tsdf
->u
.mp
.pixmaps
[j
])
1807 dcd
->bar_pixmaps
[bs
].bps
[i
].p
= None
;
1808 dcd
->bar_pixmaps
[bs
].bps
[i
].
1809 mp_created_pic
= NULL
;
1810 dcd
->bar_pixmaps
[bs
].bps
[i
].cs
=
1811 tsdf
->u
.mp
.acs
[j
].cs
;
1812 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_pic
=
1813 tsdf
->u
.mp
.pixmaps
[j
];
1814 dcd
->bar_pixmaps
[bs
].bps
[i
].created
= 0;
1815 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_part
= j
;
1823 static Pixmap
border_get_bar_pixmaps(
1824 dynamic_common_decorations
*dcd
, rectangle
*bar_g
, ButtonState bs
,
1825 int cset
, FvwmPicture
*mp_pic
, int mp_part
, int stretch
,
1826 FvwmPicture
**mp_ret_pic
)
1830 int count
= dcd
->bar_pixmaps
[bs
].count
;
1839 (dcd
->bar_pixmaps
[bs
].bps
[i
].cs
!= cset
||
1840 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_part
!= mp_part
||
1841 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_pic
!= mp_pic
))
1851 *mp_ret_pic
= dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
;
1853 if (dcd
->bar_pixmaps
[bs
].bps
[i
].p
== None
)
1855 /* see if we have it */
1857 while (b
< BS_MaxButtonState
)
1859 int c
= dcd
->bar_pixmaps
[b
].count
;
1862 (dcd
->bar_pixmaps
[b
].bps
[j
].cs
!= cset
||
1863 dcd
->bar_pixmaps
[b
].bps
[j
].mp_part
!= mp_part
||
1864 dcd
->bar_pixmaps
[b
].bps
[j
].mp_pic
!= mp_pic
))
1868 if (j
< c
&& dcd
->bar_pixmaps
[b
].bps
[j
].p
)
1870 dcd
->bar_pixmaps
[bs
].bps
[i
].p
=
1871 dcd
->bar_pixmaps
[b
].bps
[j
].p
;
1872 if (mp_pic
&& mp_ret_pic
)
1875 dcd
->bar_pixmaps
[bs
].bps
[i
].
1877 dcd
->bar_pixmaps
[b
].bps
[j
].
1885 if (dcd
->bar_pixmaps
[bs
].bps
[i
].p
== None
)
1889 dcd
->bar_pixmaps
[bs
].bps
[i
].p
= CreateBackgroundPixmap(
1890 dpy
, Scr
.NoFocusWin
, bar_g
->width
, bar_g
->height
,
1891 &Colorset
[cset
], Pdepth
, Scr
.BordersGC
, False
);
1892 dcd
->bar_pixmaps
[bs
].bps
[i
].created
= True
;
1894 else if (mp_pic
&& mp_ret_pic
)
1898 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
=
1899 PGraphicsCreateStretchPicture(
1900 dpy
, Scr
.NoFocusWin
, mp_pic
,
1901 bar_g
->width
, bar_g
->height
,
1902 Scr
.BordersGC
, Scr
.MonoGC
,
1907 dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
=
1908 PGraphicsCreateTiledPicture(
1909 dpy
, Scr
.NoFocusWin
, mp_pic
,
1910 bar_g
->width
, bar_g
->height
,
1911 Scr
.BordersGC
, Scr
.MonoGC
,
1914 if (dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
)
1916 dcd
->bar_pixmaps
[bs
].bps
[i
].created
= True
;
1918 dcd
->bar_pixmaps
[bs
].bps
[i
].
1920 dcd
->bar_pixmaps
[bs
].bps
[i
].p
=
1921 dcd
->bar_pixmaps
[bs
].bps
[i
].
1922 mp_created_pic
->picture
;
1926 return dcd
->bar_pixmaps
[bs
].bps
[i
].p
;
1929 static void border_free_bar_pixmaps(
1930 dynamic_common_decorations
*dcd
)
1935 for (bs
= 0; bs
< BS_MaxButtonState
; bs
++)
1937 if (dcd
->bar_pixmaps
[bs
].count
< 1)
1941 for (i
= 0; i
< dcd
->bar_pixmaps
[bs
].count
; i
++)
1943 if (dcd
->bar_pixmaps
[bs
].bps
[i
].mp_created_pic
&&
1944 dcd
->bar_pixmaps
[bs
].bps
[i
].created
)
1946 PDestroyFvwmPicture(
1948 dcd
->bar_pixmaps
[bs
].bps
[i
].
1951 else if (dcd
->bar_pixmaps
[bs
].bps
[i
].p
!= None
&&
1952 dcd
->bar_pixmaps
[bs
].bps
[i
].created
)
1955 dpy
, dcd
->bar_pixmaps
[bs
].bps
[i
].p
);
1958 free(dcd
->bar_pixmaps
[bs
].bps
);
1964 * MultiPixmap (aka, fancy title bar) (tril@igs.net)
1967 #define TBMP_HAS_PART(p, pm, acs, sf) \
1968 (pm[p] || acs[p].cs >= 0 || (sf & (1 << p)))
1970 /* Tile or stretch src into dest, starting at the given location and
1971 * continuing for the given width and height. This is a utility function used
1972 * by border_mp_draw_mp_titlebar. (tril@igs.net) */
1973 static void border_mp_render_into_pixmap(
1974 titlebar_descr
*td
, common_decorations_type
*cd
, FvwmPicture
**src
,
1975 FvwmAcs
*acs
, Pixel
*pixels
, unsigned short solid_flags
,
1976 unsigned short stretch_flags
, int part
, Pixmap dest
, Window w
,
1977 rectangle
*full_g
, rectangle
*title_g
, ButtonState bs
, rectangle
*g
)
1981 pixmap_background_type bg
;
1983 dynamic_common_decorations
*dcd
;
1985 dcd
= &cd
->dynamic_cd
;
1986 /* setup some default */
1987 bg
.pixmap
.fra
.mask
= 0;
1988 bg
.pixmap
.flags
.is_stretched
= 0;
1989 bg
.pixmap
.flags
.is_tiled
= 0;
1990 bg
.flags
.use_pixmap
= 1;
1991 bg
.pixmap
.p
= bg
.pixmap
.alpha
= bg
.pixmap
.shape
= None
;
1994 dest_g
.width
= g
->width
+ g
->x
;
1995 dest_g
.height
= g
->height
+ g
->y
;
1999 if (solid_flags
& (1 << part
))
2001 bg
.flags
.use_pixmap
= 0;
2002 bg
.pixel
= pixels
[part
];
2003 border_fill_pixmap_background(dest
, &dest_g
, &bg
, cd
);
2006 else if (acs
[part
].cs
>= 0)
2010 bg
.pixmap
.fra
.mask
= FRAM_HAVE_ADDED_ALPHA
;
2011 bg
.pixmap
.fra
.added_alpha_percent
= acs
[part
].alpha_percent
;
2012 if (CSET_IS_TRANSPARENT_PR(acs
[part
].cs
))
2016 if (CSET_IS_TRANSPARENT_ROOT(acs
[part
].cs
))
2018 p
= border_create_root_transparent_pixmap(
2019 td
, w
, g
->width
+ g
->x
, g
->height
+ g
->y
,
2022 bg
.pixmap
.depth
= Pdepth
;
2023 bg
.pixmap
.g
.width
= g
->width
;
2024 bg
.pixmap
.g
.height
= g
->height
;
2025 bg
.pixmap
.g
.x
= g
->x
;
2026 bg
.pixmap
.g
.y
= g
->y
;
2028 else if (full_g
!= NULL
)
2030 bg
.pixmap
.p
= border_get_bar_pixmaps(
2031 dcd
, full_g
, bs
, acs
[part
].cs
, NULL
, part
,
2032 (stretch_flags
& (1 << part
)), NULL
);
2035 if (part
!= TBMP_RIGHT_MAIN
)
2037 /* left buttons offset */
2038 x
= title_g
->x
- full_g
->x
;
2039 y
= title_g
->y
- full_g
->y
;
2041 bg
.pixmap
.g
.width
= full_g
->width
;
2042 bg
.pixmap
.g
.height
= full_g
->height
;
2043 bg
.pixmap
.flags
.is_tiled
= 1;
2046 bg
.pixmap
.depth
= Pdepth
;
2053 p
= CreateBackgroundPixmap(
2054 dpy
, w
, g
->width
, g
->height
,
2055 &Colorset
[acs
[part
].cs
], Pdepth
, Scr
.BordersGC
,
2058 GetWindowBackgroundPixmapSize(
2059 &Colorset
[acs
[part
].cs
], g
->width
, g
->height
,
2061 bg
.pixmap
.g
.width
= bg_w
;
2062 bg
.pixmap
.g
.height
= bg_h
;
2063 bg
.pixmap
.depth
= Pdepth
;
2064 bg
.pixmap
.flags
.is_tiled
= 1;
2068 border_fill_pixmap_background(dest
, &dest_g
, &bg
, cd
);
2072 XFreePixmap(dpy
, p
);
2077 FvwmPicture
*full_pic
= NULL
;
2082 p
= border_get_bar_pixmaps(
2083 dcd
, full_g
, bs
, -1, src
[part
], part
,
2084 (stretch_flags
& (1 << part
)), &full_pic
);
2087 if (part
!= TBMP_RIGHT_MAIN
)
2089 /* left buttons offset */
2090 x
= title_g
->x
- full_g
->x
;
2091 y
= title_g
->y
- full_g
->y
;
2093 bg
.pixmap
.p
= full_pic
->picture
;
2094 bg
.pixmap
.shape
= full_pic
->mask
;
2095 bg
.pixmap
.alpha
= full_pic
->alpha
;
2096 bg
.pixmap
.depth
= full_pic
->depth
;
2097 bg
.pixmap
.g
.width
= full_pic
->width
;
2098 bg
.pixmap
.g
.height
= full_pic
->height
;
2105 if (stretch_flags
& (1 << part
))
2107 bg
.pixmap
.flags
.is_stretched
= 1;
2111 bg
.pixmap
.flags
.is_tiled
= 1;
2113 bg
.pixmap
.p
= src
[part
]->picture
;
2114 bg
.pixmap
.shape
= src
[part
]->mask
;
2115 bg
.pixmap
.alpha
= src
[part
]->alpha
;
2116 bg
.pixmap
.depth
= src
[part
]->depth
;
2117 bg
.pixmap
.g
.width
= src
[part
]->width
;
2118 bg
.pixmap
.g
.height
= src
[part
]->height
;
2119 bg
.pixmap
.stretch_w
= dest_g
.width
- dest_g
.x
;
2120 bg
.pixmap
.stretch_h
= dest_g
.height
- dest_g
.y
;
2125 border_fill_pixmap_background(dest
, &dest_g
, &bg
, cd
);
2132 static int border_mp_get_length(
2133 titlebar_descr
*td
, FvwmPicture
**pm
, FvwmAcs
*acs
,
2134 unsigned int solid_flags
, int part
)
2136 if (acs
[part
].cs
>= 0 || (solid_flags
& (1 << part
)))
2141 return td
->bar_g
.width
/2;
2145 return td
->bar_g
.height
/2;
2148 if (pm
[part
] == NULL
)
2152 else if (td
->has_vt
)
2154 return pm
[part
]->height
;
2158 return pm
[part
]->width
;
2162 /* geometries relatively to the frame */
2163 static void border_mp_get_titlebar_descr(
2164 FvwmWindow
*fw
, titlebar_descr
*td
, DecorFace
*df
)
2170 int left_of_text
= 0;
2171 int right_of_text
= 0;
2174 int before_space
, after_space
, under_offset
, under_width
;
2175 Bool has_mp
= False
;
2176 JustificationType just
;
2180 just
= TB_JUSTIFICATION(GetDecor(fw
, titlebar
));
2181 /* first compute under text width */
2184 under_width
= td
->length
+ 2*TBMP_TITLE_PADDING
;
2190 if (under_width
> fw
->title_length
)
2192 under_width
= fw
->title_length
;
2193 td
->offset
= (fw
->title_length
- td
->length
) / 2;
2196 for (tsdf
= df
; tsdf
!= NULL
; tsdf
= tsdf
->next
)
2198 if (tsdf
->style
.face_type
!= MultiPixmap
)
2203 acs
= tsdf
->u
.mp
.acs
;
2204 pm
= tsdf
->u
.mp
.pixmaps
;
2205 sf
= tsdf
->u
.mp
.solid_flags
;
2206 add
= border_mp_get_length(
2207 td
, pm
, acs
, sf
, TBMP_LEFT_OF_TEXT
);
2208 if (add
> left_of_text
&&
2209 add
+ left_end
+ right_of_text
+ right_end
+ under_width
+
2210 2*TBMP_MIN_RL_TITLE_LENGTH
<= fw
->title_length
)
2214 add
= border_mp_get_length(
2215 td
, pm
, acs
, sf
, TBMP_RIGHT_OF_TEXT
);
2216 if (add
> right_of_text
&&
2217 add
+ left_end
+ left_of_text
+ right_end
+ under_width
+
2218 2*TBMP_MIN_RL_TITLE_LENGTH
<= fw
->title_length
)
2220 right_of_text
= add
;
2222 add
= border_mp_get_length(
2223 td
, pm
, acs
, sf
, TBMP_LEFT_END
);
2224 if (add
> left_end
&&
2225 add
+ right_of_text
+ left_of_text
+ right_end
+
2226 under_width
+ 2*TBMP_MIN_RL_TITLE_LENGTH
<= fw
->title_length
)
2230 add
= border_mp_get_length(
2231 td
, pm
, acs
, sf
, TBMP_RIGHT_END
);
2232 if (add
> right_end
&&
2233 add
+ right_of_text
+ left_of_text
+ left_end
+
2234 under_width
+ 2*TBMP_MIN_RL_TITLE_LENGTH
<= fw
->title_length
)
2251 if (td
->has_an_upsidedown_rotation
)
2253 is_start
= !is_start
;
2257 if (td
->has_an_upsidedown_rotation
)
2260 td
->offset
, right_of_text
+ right_end
+
2261 TBMP_MIN_RL_TITLE_LENGTH
+
2262 TBMP_TITLE_PADDING
);
2267 td
->offset
, left_of_text
+ left_end
+
2268 TBMP_MIN_RL_TITLE_LENGTH
+
2269 TBMP_TITLE_PADDING
);
2274 if (td
->has_an_upsidedown_rotation
)
2277 td
->offset
, fw
->title_length
-
2278 (td
->length
+ left_of_text
+
2279 left_end
+ TBMP_MIN_RL_TITLE_LENGTH
+
2280 TBMP_TITLE_PADDING
));
2285 td
->offset
, fw
->title_length
-
2286 (td
->length
+ right_of_text
+
2287 right_end
+ TBMP_MIN_RL_TITLE_LENGTH
+
2288 TBMP_TITLE_PADDING
));
2297 under_offset
= td
->offset
- (under_width
- td
->length
)/2;
2298 before_space
= under_offset
;
2302 td
->layout
.title_g
.height
- before_space
- under_width
;
2307 td
->layout
.title_g
.width
- before_space
- under_width
;
2309 if (td
->has_an_upsidedown_rotation
)
2311 td
->left_end_length
= right_end
;
2312 td
->left_of_text_length
= right_of_text
;
2313 td
->right_of_text_length
= left_of_text
;
2314 td
->right_end_length
= left_end
;
2315 tmpi
= before_space
;
2316 before_space
= after_space
;
2321 td
->left_end_length
= left_end
;
2322 td
->left_of_text_length
= left_of_text
;
2323 td
->right_of_text_length
= right_of_text
;
2324 td
->right_end_length
= right_end
;
2329 td
->under_text_g
.width
= td
->bar_g
.width
;
2330 td
->under_text_g
.height
= under_width
;
2331 td
->under_text_g
.x
= 0;
2332 td
->under_text_g
.y
= under_offset
;
2336 td
->under_text_g
.height
= td
->bar_g
.height
;
2337 td
->under_text_g
.width
= under_width
;
2338 td
->under_text_g
.x
= under_offset
;
2339 td
->under_text_g
.y
= 0;
2342 /* width & height */
2346 td
->full_left_main_g
.width
= td
->bar_g
.width
;
2347 td
->full_left_main_g
.height
=
2348 before_space
+ td
->left_buttons_g
.height
;
2349 td
->left_main_g
.width
= td
->bar_g
.width
;
2350 td
->left_main_g
.height
= before_space
;
2352 td
->full_right_main_g
.width
= td
->bar_g
.width
;
2353 td
->full_right_main_g
.height
= after_space
+
2354 td
->right_buttons_g
.height
;
2355 td
->right_main_g
.width
= td
->bar_g
.width
;
2356 td
->right_main_g
.height
= after_space
;
2361 td
->full_left_main_g
.height
= td
->bar_g
.height
;
2362 td
->full_left_main_g
.width
=
2363 before_space
+ td
->left_buttons_g
.width
;
2364 td
->left_main_g
.height
= td
->bar_g
.height
;
2365 td
->left_main_g
.width
= before_space
;
2367 td
->full_right_main_g
.height
= td
->bar_g
.height
;
2368 td
->full_right_main_g
.width
= after_space
+
2369 td
->right_buttons_g
.width
;
2370 td
->right_main_g
.height
= td
->bar_g
.height
;
2371 td
->right_main_g
.width
= after_space
;
2375 if (td
->has_an_upsidedown_rotation
)
2377 td
->full_right_main_g
.x
= td
->bar_g
.x
;
2378 td
->full_right_main_g
.y
= td
->bar_g
.y
;
2379 td
->right_main_g
.x
= 0;
2380 td
->right_main_g
.y
= 0;
2384 td
->full_left_main_g
.x
= td
->bar_g
.x
;
2385 td
->full_left_main_g
.y
= td
->bar_g
.y
;
2386 td
->left_main_g
.x
= 0;
2387 td
->left_main_g
.y
= 0;
2392 if (td
->has_an_upsidedown_rotation
)
2394 td
->full_left_main_g
.x
= td
->bar_g
.x
;
2395 td
->full_left_main_g
.y
=
2396 td
->full_right_main_g
.height
+ td
->bar_g
.y
+
2397 td
->under_text_g
.height
;
2399 td
->under_text_g
.y
+ td
->under_text_g
.height
;
2400 td
->left_main_g
.x
= 0;
2404 td
->full_right_main_g
.x
= td
->bar_g
.x
;
2405 td
->full_right_main_g
.y
=
2406 td
->full_left_main_g
.height
+ td
->bar_g
.y
+
2407 td
->under_text_g
.height
;
2408 td
->right_main_g
.y
=
2409 td
->under_text_g
.y
+ td
->under_text_g
.height
;
2410 td
->right_main_g
.x
= 0;
2415 if (td
->has_an_upsidedown_rotation
)
2417 td
->full_left_main_g
.x
=
2418 td
->full_right_main_g
.width
+ td
->bar_g
.x
+
2419 td
->under_text_g
.width
;
2420 td
->full_left_main_g
.y
= td
->bar_g
.y
;
2422 td
->under_text_g
.x
+ td
->under_text_g
.width
;
2423 td
->left_main_g
.y
= 0;
2427 td
->full_right_main_g
.x
=
2428 td
->full_left_main_g
.width
+ td
->bar_g
.x
+
2429 td
->under_text_g
.width
;
2430 td
->full_right_main_g
.y
= td
->bar_g
.y
;
2431 td
->right_main_g
.x
=
2432 td
->under_text_g
.x
+ td
->under_text_g
.width
;
2433 td
->right_main_g
.y
= 0;
2438 /* the returned geometries are relative to the titlebar (not the frame) */
2439 static void border_mp_get_extreme_geometry(
2440 titlebar_descr
*td
, FvwmPicture
**pm
, FvwmAcs
*acs
, unsigned short sf
,
2441 rectangle
*left_of_text_g
, rectangle
*right_of_text_g
,
2442 rectangle
*left_end_g
, rectangle
*right_end_g
)
2444 int left_of_text
= 0;
2445 int right_of_text
= 0;
2449 left_of_text
= border_mp_get_length(
2450 td
, pm
, acs
, sf
, TBMP_LEFT_OF_TEXT
);
2451 left_end
= border_mp_get_length(
2452 td
, pm
, acs
, sf
, TBMP_LEFT_END
);
2453 right_of_text
= border_mp_get_length(
2454 td
, pm
, acs
, sf
, TBMP_RIGHT_OF_TEXT
);
2455 right_end
= border_mp_get_length(
2456 td
, pm
, acs
, sf
, TBMP_RIGHT_END
);
2458 if (left_of_text
> 0 && left_of_text
<= td
->left_of_text_length
)
2462 left_of_text_g
->y
= td
->under_text_g
.y
- left_of_text
;
2463 left_of_text_g
->x
= 0;
2464 left_of_text_g
->height
= left_of_text
;
2465 left_of_text_g
->width
= td
->bar_g
.width
;
2469 left_of_text_g
->x
= td
->under_text_g
.x
- left_of_text
;
2470 left_of_text_g
->y
= 0;
2471 left_of_text_g
->width
= left_of_text
;
2472 left_of_text_g
->height
= td
->bar_g
.height
;
2477 left_of_text_g
->x
= 0;
2478 left_of_text_g
->y
= 0;
2479 left_of_text_g
->width
= 0;
2480 left_of_text_g
->height
= 0;
2483 if (right_of_text
> 0 && right_of_text
<= td
->right_of_text_length
)
2487 right_of_text_g
->y
=
2488 td
->under_text_g
.y
+ td
->under_text_g
.height
;
2489 right_of_text_g
->x
= 0;
2490 right_of_text_g
->height
= right_of_text
;
2491 right_of_text_g
->width
= td
->bar_g
.width
;
2495 right_of_text_g
->x
=
2496 td
->under_text_g
.x
+ td
->under_text_g
.width
;
2497 right_of_text_g
->y
= 0;
2498 right_of_text_g
->width
= right_of_text
;
2499 right_of_text_g
->height
= td
->bar_g
.height
;
2504 right_of_text_g
->x
= 0;
2505 right_of_text_g
->y
= 0;
2506 right_of_text_g
->width
= 0;
2507 right_of_text_g
->height
= 0;
2510 if (left_end
> 0 && left_end
<= td
->left_end_length
)
2516 left_end_g
->height
= left_end
;
2517 left_end_g
->width
= td
->bar_g
.width
;
2523 left_end_g
->width
= left_end
;
2524 left_end_g
->height
= td
->bar_g
.height
;
2531 left_end_g
->width
= 0;
2532 left_end_g
->height
= 0;
2535 if (right_end
> 0 && right_end
<= td
->right_end_length
)
2540 td
->layout
.title_g
.height
- right_end
;
2542 right_end_g
->height
= right_end
;
2543 right_end_g
->width
= td
->bar_g
.width
;
2548 td
->layout
.title_g
.width
- right_end
;
2550 right_end_g
->width
= right_end
;
2551 right_end_g
->height
= td
->bar_g
.height
;
2558 right_end_g
->width
= 0;
2559 right_end_g
->height
= 0;
2565 static Bool
border_mp_get_use_title_style_parts_and_geometry(
2566 titlebar_descr
*td
, FvwmPicture
**pm
, FvwmAcs
*acs
,
2567 unsigned short sf
, int is_left
, rectangle
*g
, int *part
)
2569 rectangle
*tmp_g
= NULL
;
2572 if (is_left
&& TBMP_HAS_PART(TBMP_LEFT_BUTTONS
, pm
, acs
, sf
))
2574 *part
= TBMP_LEFT_BUTTONS
;
2575 tmp_g
= &td
->left_buttons_g
;
2577 else if (!is_left
&& TBMP_HAS_PART(TBMP_RIGHT_BUTTONS
, pm
, acs
, sf
))
2579 *part
= TBMP_RIGHT_BUTTONS
;
2580 tmp_g
= &td
->right_buttons_g
;
2582 else if (is_left
&& TBMP_HAS_PART(TBMP_LEFT_MAIN
, pm
, acs
, sf
))
2584 *part
= TBMP_LEFT_MAIN
;
2585 tmp_g
= &td
->full_left_main_g
;
2587 else if (!is_left
&& TBMP_HAS_PART(TBMP_RIGHT_MAIN
, pm
, acs
, sf
))
2589 *part
= TBMP_RIGHT_MAIN
;
2590 tmp_g
= &td
->full_right_main_g
;
2592 else if (TBMP_HAS_PART(TBMP_MAIN
, pm
, acs
, sf
))
2595 tmp_g
= &(td
->bar_g
);
2605 g
->width
= tmp_g
->width
;
2606 g
->height
= tmp_g
->height
;
2613 /* Redraws multi-pixmap titlebar (tril@igs.net) */
2614 static void border_mp_draw_mp_titlebar(
2615 FvwmWindow
*fw
, titlebar_descr
*td
, DecorFace
*df
, Pixmap dest_pix
,
2621 unsigned short solid_flags
;
2622 unsigned short stretch_flags
;
2623 rectangle tmp_g
, left_of_text_g
,left_end_g
,right_of_text_g
,right_end_g
;
2624 dynamic_common_decorations
*dcd
;
2627 dcd
= &(td
->cd
->dynamic_cd
);
2628 bs
= td
->tbstate
.tstate
;
2629 pm
= df
->u
.mp
.pixmaps
;
2631 pixels
= df
->u
.mp
.pixels
;
2632 stretch_flags
= df
->u
.mp
.stretch_flags
;
2633 solid_flags
= df
->u
.mp
.solid_flags
;
2636 tmp_g
.width
= td
->layout
.title_g
.width
;
2637 tmp_g
.height
= td
->layout
.title_g
.height
;
2639 if (TBMP_HAS_PART(TBMP_MAIN
, pm
, acs
, solid_flags
))
2641 border_mp_render_into_pixmap(
2642 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
, stretch_flags
,
2643 TBMP_MAIN
, dest_pix
, w
, &td
->bar_g
, &td
->layout
.title_g
,
2646 else if (td
->length
<= 0)
2648 border_mp_render_into_pixmap(
2649 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
, stretch_flags
,
2650 TBMP_LEFT_MAIN
, dest_pix
, w
, NULL
, &td
->layout
.title_g
,
2654 border_mp_get_extreme_geometry(
2655 td
, pm
, acs
, solid_flags
, &left_of_text_g
, &right_of_text_g
,
2656 &left_end_g
, &right_end_g
);
2660 if (TBMP_HAS_PART(TBMP_LEFT_MAIN
, pm
, acs
, solid_flags
) &&
2661 td
->left_main_g
.width
> 0 && td
->left_main_g
.height
> 0)
2663 border_mp_render_into_pixmap(
2664 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
,
2665 stretch_flags
, TBMP_LEFT_MAIN
, dest_pix
, w
,
2666 &td
->full_left_main_g
, &td
->layout
.title_g
, bs
,
2669 if (TBMP_HAS_PART(TBMP_RIGHT_MAIN
, pm
, acs
, solid_flags
) &&
2670 td
->right_main_g
.width
> 0 && td
->right_main_g
.height
> 0)
2672 border_mp_render_into_pixmap(
2673 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
,
2674 stretch_flags
, TBMP_RIGHT_MAIN
, dest_pix
, w
,
2675 &td
->full_right_main_g
, &td
->layout
.title_g
, bs
,
2678 if (TBMP_HAS_PART(TBMP_UNDER_TEXT
, pm
, acs
, solid_flags
) &&
2679 td
->under_text_g
.width
> 0 && td
->under_text_g
.height
> 0)
2681 border_mp_render_into_pixmap(
2682 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
,
2683 stretch_flags
, TBMP_UNDER_TEXT
, dest_pix
, w
,
2684 NULL
, &td
->layout
.title_g
, bs
,
2687 if (left_of_text_g
.width
> 0 && left_of_text_g
.height
> 0)
2689 border_mp_render_into_pixmap(
2690 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
,
2691 stretch_flags
, TBMP_LEFT_OF_TEXT
, dest_pix
, w
,
2692 NULL
, &td
->layout
.title_g
, bs
, &left_of_text_g
);
2694 if (right_of_text_g
.width
> 0 && right_of_text_g
.height
> 0)
2696 border_mp_render_into_pixmap(
2697 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
,
2698 stretch_flags
, TBMP_RIGHT_OF_TEXT
, dest_pix
, w
,
2699 NULL
, &td
->layout
.title_g
, bs
, &right_of_text_g
);
2702 if (left_end_g
.width
> 0 && left_end_g
.height
> 0)
2704 border_mp_render_into_pixmap(
2705 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
, stretch_flags
,
2706 TBMP_LEFT_END
, dest_pix
, w
, NULL
, &td
->layout
.title_g
,
2709 if (right_end_g
.width
> 0 && right_end_g
.height
> 0)
2711 border_mp_render_into_pixmap(
2712 td
, td
->cd
, pm
, acs
, pixels
, solid_flags
, stretch_flags
,
2713 TBMP_RIGHT_END
, dest_pix
, w
, NULL
, &td
->layout
.title_g
,
2722 * draw title bar and buttons
2725 static void border_draw_decor_to_pixmap(
2726 FvwmWindow
*fw
, Pixmap dest_pix
, Window w
,
2727 pixmap_background_type
*solid_bg
, rectangle
*w_g
,
2728 DecorFace
*df
, titlebar_descr
*td
, ButtonState bs
,
2729 int use_title_style
, int is_toggled
, int left1right0
)
2731 register DecorFaceType type
= DFS_FACE_TYPE(df
->style
);
2732 pixmap_background_type bg
;
2737 int lr_just
, tb_just
;
2738 common_decorations_type
*cd
;
2741 /* setup some default */
2742 bg
.pixmap
.fra
.mask
= 0;
2743 bg
.pixmap
.flags
.is_stretched
= 0;
2744 bg
.pixmap
.flags
.is_tiled
= 0;
2745 bg
.flags
.use_pixmap
= 0;
2749 if (DFS_BUTTON_RELIEF(df
->style
) == DFS_BUTTON_IS_FLAT
)
2755 border
= HAS_MWM_BORDER(fw
) ? 1 : 2;
2757 dest_g
.width
= w_g
->width
;
2758 dest_g
.height
= w_g
->height
;
2768 /* overwrite with the default background */
2771 border_fill_pixmap_background(dest_pix
, &dest_g
, solid_bg
, cd
);
2774 case DefaultVectorButton
:
2775 border_draw_vector_to_pixmap(
2776 dest_pix
, cd
, is_toggled
, &df
->u
.vector
, w_g
);
2778 case MiniIconButton
:
2780 case ShrunkPixmapButton
:
2781 case StretchedPixmapButton
:
2782 if (w_g
->width
- 2*border
<= 0 || w_g
->height
- 2*border
<= 0)
2786 if (FMiniIconsSupported
&& type
== MiniIconButton
)
2795 bg
.pixmap
.fra
.mask
|= FRAM_HAVE_ICON_CSET
;
2796 bg
.pixmap
.fra
.colorset
= &Colorset
[cd
->cs
];
2805 if ((type
== ShrunkPixmapButton
|| type
== MiniIconButton
) &&
2806 (p
->width
> w_g
->width
- 2*border
||
2807 p
->height
> w_g
->height
- 2*border
))
2809 /* do so that the picture fit into the destination */
2810 bg
.pixmap
.stretch_w
= width
=
2811 min(w_g
->width
- 2*border
, p
->width
);
2812 bg
.pixmap
.stretch_h
= height
=
2813 min(w_g
->height
- 2*border
, p
->height
);
2814 bg
.pixmap
.flags
.is_stretched
= 1;
2816 else if (type
== StretchedPixmapButton
&&
2817 (p
->width
< w_g
->width
- 2*border
||
2818 p
->height
< w_g
->height
- 2*border
))
2820 /* do so that the picture fit into the destination */
2821 bg
.pixmap
.stretch_w
= width
=
2822 max(w_g
->width
- 2*border
, p
->width
);
2823 bg
.pixmap
.stretch_h
= height
=
2824 max(w_g
->height
- 2*border
, p
->height
);
2825 bg
.pixmap
.flags
.is_stretched
= 1;
2827 lr_just
= DFS_H_JUSTIFICATION(df
->style
);
2828 tb_just
= DFS_V_JUSTIFICATION(df
->style
);
2829 if (!td
->td_is_rotated
&& fw
->title_text_rotation
!= ROTATION_0
)
2831 if (fw
->title_text_rotation
== ROTATION_180
)
2836 lr_just
= JUST_RIGHT
;
2839 lr_just
= JUST_LEFT
;
2848 tb_just
= JUST_BOTTOM
;
2858 else if (fw
->title_text_rotation
== ROTATION_90
)
2866 tb_just
= JUST_BOTTOM
;
2870 tb_just
= JUST_CENTER
;
2873 switch (DFS_V_JUSTIFICATION(df
->style
))
2876 lr_just
= JUST_RIGHT
;
2879 lr_just
= JUST_LEFT
;
2883 lr_just
= JUST_CENTER
;
2887 else if (fw
->title_text_rotation
== ROTATION_270
)
2892 tb_just
= JUST_BOTTOM
;
2899 tb_just
= JUST_CENTER
;
2902 switch (DFS_V_JUSTIFICATION(df
->style
))
2905 lr_just
= JUST_LEFT
;
2908 lr_just
= JUST_RIGHT
;
2912 lr_just
= JUST_CENTER
;
2923 dest_g
.x
= (int)(w_g
->width
- width
- border
);
2928 dest_g
.x
= (int)(w_g
->width
- width
) / 2;
2937 dest_g
.y
= (int)(w_g
->height
- height
- border
);
2942 dest_g
.y
= (int)(w_g
->height
- height
) / 2;
2945 if (dest_g
.x
< border
)
2949 if (dest_g
.y
< border
)
2953 bg
.flags
.use_pixmap
= 1;
2954 bg
.pixmap
.p
= p
->picture
;
2955 bg
.pixmap
.shape
= p
->mask
;
2956 bg
.pixmap
.alpha
= p
->alpha
;
2957 bg
.pixmap
.depth
= p
->depth
;
2958 bg
.pixmap
.g
.width
= p
->width
;
2959 bg
.pixmap
.g
.height
= p
->height
;
2960 border_fill_pixmap_background(dest_pix
, &dest_g
, &bg
, cd
);
2962 case TiledPixmapButton
:
2963 case AdjustedPixmapButton
:
2964 if (w_g
->width
- 2*border
<= 0 || w_g
->height
- 2*border
<= 0)
2969 if (type
== TiledPixmapButton
)
2971 bg
.pixmap
.flags
.is_tiled
= 1;
2975 bg
.pixmap
.stretch_w
= width
= w_g
->width
- 2*dest_g
.x
;
2976 bg
.pixmap
.stretch_h
= height
= w_g
->height
- 2*dest_g
.y
;
2977 bg
.pixmap
.flags
.is_stretched
= 1;
2979 bg
.flags
.use_pixmap
= 1;
2980 bg
.pixmap
.p
= p
->picture
;
2981 bg
.pixmap
.shape
= p
->mask
;
2982 bg
.pixmap
.alpha
= p
->alpha
;
2983 bg
.pixmap
.depth
= p
->depth
;
2984 bg
.pixmap
.g
.width
= p
->width
;
2985 bg
.pixmap
.g
.height
= p
->height
;
2986 border_fill_pixmap_background(dest_pix
, &dest_g
, &bg
, cd
);
2988 case MultiPixmap
: /* for UseTitleStyle only */
2990 int is_left
= left1right0
;
2991 int part
= TBMP_NONE
;
2993 unsigned int stretch
;
2995 FvwmPicture
*full_pic
= NULL
;
2997 dynamic_common_decorations
*dcd
= &(cd
->dynamic_cd
);
3003 pm
= df
->u
.mp
.pixmaps
;
3005 pixels
= df
->u
.mp
.pixels
;
3006 sf
= df
->u
.mp
.solid_flags
;
3007 if (!border_mp_get_use_title_style_parts_and_geometry(
3008 td
, pm
, acs
, sf
, is_left
, &g
, &part
))
3016 if (part
== TBMP_NONE
)
3021 if (sf
& (1 << part
))
3023 bg
.flags
.use_pixmap
= 0;
3024 bg
.pixel
= pixels
[part
];
3025 border_fill_pixmap_background(
3026 dest_pix
, &dest_g
, &bg
, cd
);
3030 ap
= acs
[part
].alpha_percent
;
3031 if (CSET_IS_TRANSPARENT_PR(cs
))
3037 bg
.pixmap
.fra
.mask
= FRAM_HAVE_ADDED_ALPHA
;
3038 bg
.pixmap
.fra
.added_alpha_percent
= ap
;
3040 stretch
= !!(df
->u
.mp
.stretch_flags
& (1 << part
));
3041 bg
.flags
.use_pixmap
= 1;
3045 if (cs
>= 0 && use_title_style
&& g
.width
> 0 && g
.height
> 0 &&
3046 !CSET_IS_TRANSPARENT_ROOT(cs
) &&
3047 (bg
.pixmap
.p
= border_get_bar_pixmaps(
3048 dcd
, &g
, bs
, cs
, NULL
, part
, stretch
, NULL
)) != None
)
3050 bg
.pixmap
.g
.width
= g
.width
;
3051 bg
.pixmap
.g
.height
= g
.height
;
3052 bg
.pixmap
.flags
.is_tiled
= 1;
3053 bg
.pixmap
.g
.x
= w_g
->x
- g
.x
;
3054 bg
.pixmap
.g
.y
= w_g
->y
- g
.y
;
3055 bg
.pixmap
.shape
= None
;
3056 bg
.pixmap
.alpha
= None
;
3057 bg
.pixmap
.depth
= Pdepth
;
3059 else if (CSET_IS_TRANSPARENT_ROOT(cs
))
3061 tmp
= border_create_root_transparent_pixmap(
3062 td
, w
, w_g
->width
, w_g
->height
, cs
);
3064 bg
.pixmap
.g
.width
= w_g
->width
;
3065 bg
.pixmap
.g
.height
= w_g
->height
;
3066 bg
.pixmap
.shape
= None
;
3067 bg
.pixmap
.alpha
= None
;
3068 bg
.pixmap
.depth
= Pdepth
;
3074 tmp
= CreateBackgroundPixmap(
3076 w_g
->height
, &Colorset
[cs
],
3077 Pdepth
, Scr
.BordersGC
, False
);
3079 GetWindowBackgroundPixmapSize(
3080 &Colorset
[cs
], w_g
->width
,
3081 w_g
->height
, &bg_w
, &bg_h
);
3082 bg
.pixmap
.g
.width
= bg_w
;
3083 bg
.pixmap
.g
.height
= bg_h
;
3084 bg
.pixmap
.shape
= None
;
3085 bg
.pixmap
.alpha
= None
;
3086 bg
.pixmap
.depth
= Pdepth
;
3087 bg
.pixmap
.flags
.is_tiled
= 1;
3089 else if (pm
[part
] && g
.width
> 0 && g
.height
> 0 &&
3090 border_get_bar_pixmaps(
3091 dcd
, &g
, bs
, -1, pm
[part
], part
, stretch
,
3092 &full_pic
) != None
&& full_pic
)
3094 bg
.pixmap
.p
= full_pic
->picture
;
3095 bg
.pixmap
.shape
= full_pic
->mask
;
3096 bg
.pixmap
.alpha
= full_pic
->alpha
;
3097 bg
.pixmap
.depth
= full_pic
->depth
;
3098 bg
.pixmap
.g
.width
= full_pic
->width
;
3099 bg
.pixmap
.g
.height
= full_pic
->height
;
3100 bg
.pixmap
.g
.x
= w_g
->x
- g
.x
;
3101 bg
.pixmap
.g
.y
= w_g
->y
- g
.y
;
3106 if (df
->u
.mp
.stretch_flags
& (1 << part
))
3108 bg
.pixmap
.flags
.is_stretched
= 1;
3112 bg
.pixmap
.flags
.is_tiled
= 1;
3114 bg
.pixmap
.p
= p
->picture
;
3115 bg
.pixmap
.shape
= p
->mask
;
3116 bg
.pixmap
.alpha
= p
->alpha
;
3117 bg
.pixmap
.depth
= p
->depth
;
3118 bg
.pixmap
.g
.width
= p
->width
;
3119 bg
.pixmap
.g
.height
= p
->height
;
3120 bg
.pixmap
.stretch_w
= dest_g
.width
- dest_g
.x
;
3121 bg
.pixmap
.stretch_h
= dest_g
.height
- dest_g
.y
;
3125 /* should not happen */
3128 if (bg
.pixmap
.p
!= None
)
3130 border_fill_pixmap_background(
3131 dest_pix
, &dest_g
, &bg
, cd
);
3135 XFreePixmap(dpy
, tmp
);
3139 case ColorsetButton
:
3141 colorset_t
*cs_t
= &Colorset
[df
->u
.acs
.cs
];
3142 int cs
= df
->u
.acs
.cs
;
3146 if (CSET_IS_TRANSPARENT_PR(cs
))
3152 if (use_title_style
&&
3153 !CSET_IS_TRANSPARENT_ROOT(cs
) &&
3154 (bg
.pixmap
.p
= border_get_bar_pixmaps(
3155 &(cd
->dynamic_cd
), &(td
->bar_g
), bs
, cs
, NULL
,
3156 TBMP_NONE
, 0, NULL
))
3159 bg
.pixmap
.g
.width
= td
->bar_g
.width
;
3160 bg
.pixmap
.g
.height
= td
->bar_g
.height
;
3161 bg
.pixmap
.g
.x
= w_g
->x
- td
->bar_g
.x
;
3162 bg
.pixmap
.g
.y
= w_g
->y
- td
->bar_g
.y
;
3164 else if (CSET_IS_TRANSPARENT_ROOT(cs
))
3166 tmp
= border_create_root_transparent_pixmap(
3167 td
, w
, w_g
->width
, w_g
->height
, cs
);
3173 bg
.pixmap
.g
.width
= w_g
->width
;
3174 bg
.pixmap
.g
.height
= w_g
->height
;
3175 bg
.pixmap
.shape
= None
;
3176 bg
.pixmap
.alpha
= None
;
3177 bg
.pixmap
.depth
= Pdepth
;
3181 tmp
= CreateBackgroundPixmap(
3182 dpy
, w
, w_g
->width
, w_g
->height
,
3183 cs_t
, Pdepth
, Scr
.BordersGC
, False
);
3189 GetWindowBackgroundPixmapSize(
3190 cs_t
, w_g
->width
, w_g
->height
,
3192 bg
.pixmap
.g
.width
= bg_w
;
3193 bg
.pixmap
.g
.height
= bg_h
;
3197 bg
.flags
.use_pixmap
= 1;
3198 bg
.pixmap
.shape
= None
;
3199 bg
.pixmap
.alpha
= None
;
3200 bg
.pixmap
.depth
= Pdepth
;
3201 bg
.pixmap
.flags
.is_tiled
= 1;
3202 bg
.pixmap
.fra
.mask
= FRAM_HAVE_ADDED_ALPHA
;
3203 bg
.pixmap
.fra
.added_alpha_percent
= df
->u
.acs
.alpha_percent
;
3204 border_fill_pixmap_background(dest_pix
, &dest_g
, &bg
, cd
);
3207 XFreePixmap(dpy
, tmp
);
3211 case GradientButton
:
3212 /* draw the gradient into the pixmap */
3213 CreateGradientPixmap(
3214 dpy
, dest_pix
, Scr
.TransMaskGC
,
3215 df
->u
.grad
.gradient_type
, 0, 0, df
->u
.grad
.npixels
,
3216 df
->u
.grad
.xcs
, df
->u
.grad
.do_dither
,
3217 &df
->u
.grad
.d_pixels
, &df
->u
.grad
.d_npixels
,
3218 dest_pix
, 0, 0, w_g
->width
, w_g
->height
, NULL
);
3223 fvwm_msg(ERR
, "DrawButton", "unknown button type: %i", type
);
3230 static void border_set_button_pixmap(
3231 FvwmWindow
*fw
, titlebar_descr
*td
, int button
, Pixmap
*dest_pix
,
3234 pixmap_background_type bg
;
3237 int do_reverse_relief
;
3240 rectangle
*button_g
;
3243 Bool free_bg_pixmap
= False
;
3246 /* prepare variables */
3247 mask
= (1 << button
);
3248 if (td
->has_an_upsidedown_rotation
)
3250 is_left_button
= (button
& 1);
3254 is_left_button
= !(button
& 1);
3256 button_g
= &td
->layout
.button_g
[button
];
3257 bs
= td
->tbstate
.bstate
[button
];
3258 df
= &TB_STATE(GetDecor(fw
, buttons
[button
]))[bs
];
3259 rgc
= td
->cd
->relief_gc
;
3260 sgc
= td
->cd
->shadow_gc
;
3261 /* prepare background, either from the window colour or from the
3263 if (!DFS_USE_BORDER_STYLE(df
->style
))
3265 /* fill with the button background colour */
3266 bg
.flags
.use_pixmap
= 0;
3267 bg
.pixel
= td
->cd
->back_color
;
3270 pix_g
.width
= button_g
->width
;
3271 pix_g
.height
= button_g
->height
;
3272 border_fill_pixmap_background(*dest_pix
, &pix_g
, &bg
, td
->cd
);
3276 /* draw pixmap background inherited from border style */
3277 rectangle relative_g
;
3279 relative_g
.width
= td
->frame_g
.width
;
3280 relative_g
.height
= td
->frame_g
.height
;
3281 relative_g
.x
= button_g
->x
;
3282 relative_g
.y
= button_g
->y
;
3283 border_get_border_background(
3284 &bg
, td
->cd
, button_g
, &relative_g
, &free_bg_pixmap
, w
);
3287 /* set the geometry for drawing the Tiled pixmap;
3288 * FIXME: maybe add the relief as offset? */
3291 pix_g
.width
= button_g
->width
;
3292 pix_g
.height
= button_g
->height
;
3293 border_fill_pixmap_background(*dest_pix
, &pix_g
, &bg
, td
->cd
);
3294 if (free_bg_pixmap
&& bg
.pixmap
.p
)
3296 XFreePixmap(dpy
, bg
.pixmap
.p
);
3300 /* handle title style */
3301 if (DFS_USE_TITLE_STYLE(df
->style
))
3303 /* draw background inherited from title style */
3307 if (td
->draw_rotation
!= ROTATION_0
)
3309 tmp
= CreateRotatedPixmap(
3311 td
->layout
.button_g
[button
].width
,
3312 td
->layout
.button_g
[button
].height
,
3313 Pdepth
, Scr
.BordersGC
, td
->restore_rotation
);
3314 XFreePixmap(dpy
, *dest_pix
);
3316 border_rotate_titlebar_descr(fw
, td
);
3317 button_g
= &td
->layout
.button_g
[button
];
3318 is_left_button
= !(button
& 1);
3320 for (tsdf
= &TB_STATE(GetDecor(fw
, titlebar
))[bs
]; tsdf
!= NULL
;
3323 bg
.pixel
= tsdf
->u
.back
;
3324 border_draw_decor_to_pixmap(
3325 fw
, *dest_pix
, w
, &bg
, button_g
, tsdf
, td
,
3326 bs
, True
, (td
->tbstate
.toggled_bmask
& mask
),
3329 if (td
->draw_rotation
!= ROTATION_0
)
3331 tmp
= CreateRotatedPixmap(
3333 td
->layout
.button_g
[button
].width
,
3334 td
->layout
.button_g
[button
].height
,
3335 Pdepth
, Scr
.BordersGC
, td
->draw_rotation
);
3336 XFreePixmap(dpy
, *dest_pix
);
3338 border_rotate_titlebar_descr(fw
, td
);
3339 button_g
= &td
->layout
.button_g
[button
];
3340 if (td
->has_an_upsidedown_rotation
)
3342 is_left_button
= (button
& 1);
3346 is_left_button
= !(button
& 1);
3350 /* handle button style */
3351 for ( ; df
; df
= df
->next
)
3353 /* draw background from button style */
3354 bg
.pixel
= df
->u
.back
;
3355 border_draw_decor_to_pixmap(
3356 fw
, *dest_pix
, w
, &bg
, button_g
, df
, td
, bs
, False
,
3357 (td
->tbstate
.toggled_bmask
& mask
), is_left_button
);
3359 /* draw the button relief */
3360 do_reverse_relief
= !!(td
->tbstate
.pressed_bmask
& mask
);
3361 switch (DFS_BUTTON_RELIEF(
3362 TB_STATE(GetDecor(fw
, buttons
[button
]))[bs
].style
))
3364 case DFS_BUTTON_IS_SUNK
:
3365 do_reverse_relief
^= 1;
3367 case DFS_BUTTON_IS_UP
:
3368 do_relieve_rectangle(
3369 dpy
, *dest_pix
, 0, 0, button_g
->width
- 1,
3370 button_g
->height
- 1,
3371 (do_reverse_relief
) ? sgc
: rgc
,
3372 (do_reverse_relief
) ? rgc
: sgc
,
3373 td
->cd
->relief_width
, True
);
3383 static void border_draw_one_button(
3384 FvwmWindow
*fw
, titlebar_descr
*td
, int button
)
3389 if (td
->layout
.button_g
[button
].x
< 0 ||
3390 td
->layout
.button_g
[button
].y
< 0)
3395 p
= border_create_decor_pixmap(td
->cd
, &(td
->layout
.button_g
[button
]));
3396 /* set the background tile */
3397 border_set_button_pixmap(fw
, td
, button
, &p
, FW_W_BUTTON(fw
, button
));
3398 /* apply the pixmap and destroy it */
3399 border_set_part_background(FW_W_BUTTON(fw
, button
), p
);
3400 XFreePixmap(dpy
, p
);
3401 if ((td
->tbstate
.clear_bmask
& (1 << button
)) != 0)
3403 XClearWindow(dpy
, FW_W_BUTTON(fw
, button
));
3409 static void border_draw_title_stick_lines(
3410 FvwmWindow
*fw
, titlebar_descr
*td
, title_draw_descr
*tdd
,
3421 int under_text_length
= 0;
3422 int under_text_offset
= 0;
3423 int right_length
= 0;
3424 int left_length
= 0;
3425 rotation_t rotation
;
3427 if (!( (HAS_STICKY_STIPPLED_TITLE(fw
) &&
3428 (IS_STICKY_ACROSS_PAGES(fw
) || IS_STICKY_ACROSS_DESKS(fw
)))
3429 || HAS_STIPPLED_TITLE(fw
)))
3433 if (td
->td_is_rotated
)
3435 rotation
= td
->restore_rotation
;
3439 rotation
= ROTATION_0
;
3441 if (td
->has_vt
&& td
->under_text_g
.height
> 0)
3443 under_text_length
= td
->under_text_g
.height
;
3444 under_text_offset
= td
->under_text_g
.y
;
3445 left_length
= td
->left_main_g
.height
- td
->left_of_text_length
3446 - td
->left_end_length
;
3447 right_length
= td
->right_main_g
.height
-
3448 td
->right_of_text_length
- td
->right_end_length
;
3451 else if (!td
->has_vt
&& td
->under_text_g
.width
> 0)
3453 under_text_length
= td
->under_text_g
.width
;
3454 under_text_offset
= td
->under_text_g
.x
;
3455 left_length
= td
->left_main_g
.width
- td
->left_of_text_length
3456 - td
->left_end_length
;
3457 right_length
= td
->right_main_g
.width
-
3458 td
->right_of_text_length
- td
->right_end_length
;
3461 /* If the window is sticky either across pages or
3462 * desks and it has a stippled title, but nothing for
3463 * sticky_stippled_title, then don't bother drawing them, just
3464 * return immediately. -- Thomas Adam
3466 if ( (IS_STICKY_ACROSS_PAGES(fw
) || IS_STICKY_ACROSS_DESKS(fw
)) &&
3467 (!HAS_STICKY_STIPPLED_TITLE(fw
) && HAS_STIPPLED_TITLE(fw
)) )
3472 num
= (int)(fw
->title_thickness
/ WINDOW_TITLE_STICK_VERT_DIST
/ 2) *
3474 min
= fw
->title_thickness
/ 2 - num
* 2 + 1;
3475 max
= fw
->title_thickness
/ 2 + num
* 2 -
3476 WINDOW_TITLE_STICK_VERT_DIST
+ 1;
3477 left_x
= WINDOW_TITLE_STICK_OFFSET
+ td
->left_end_length
;
3478 left_w
= ((under_text_length
== 0)? td
->offset
:under_text_offset
)
3479 - left_x
- WINDOW_TITLE_TO_STICK_GAP
- td
->left_of_text_length
;
3480 right_x
= ((under_text_length
== 0)?
3481 td
->offset
+ td
->length
:
3482 under_text_offset
+ under_text_length
)
3483 + td
->right_of_text_length
+ WINDOW_TITLE_TO_STICK_GAP
- 1;
3484 right_w
= fw
->title_length
- right_x
- WINDOW_TITLE_STICK_OFFSET
3485 - td
->right_end_length
;
3486 /* an odd number of lines every WINDOW_TITLE_STICK_VERT_DIST pixels */
3487 if (left_w
< WINDOW_TITLE_STICK_MIN_WIDTH
)
3489 left_x
= td
->left_end_length
+
3490 ((left_length
> WINDOW_TITLE_STICK_MIN_WIDTH
)?
3491 (left_length
- WINDOW_TITLE_STICK_MIN_WIDTH
)/2 : 0);
3492 left_w
= WINDOW_TITLE_STICK_MIN_WIDTH
;
3494 if (right_w
< WINDOW_TITLE_STICK_MIN_WIDTH
)
3496 right_w
= WINDOW_TITLE_STICK_MIN_WIDTH
;
3497 right_x
= fw
->title_length
- WINDOW_TITLE_STICK_MIN_WIDTH
- 1
3498 - td
->right_end_length
-
3499 ((right_length
> WINDOW_TITLE_STICK_MIN_WIDTH
)?
3501 WINDOW_TITLE_STICK_MIN_WIDTH
)/2 : 0);
3503 for (i
= min
; i
<= max
; i
+= WINDOW_TITLE_STICK_VERT_DIST
)
3507 do_relieve_rectangle_with_rotation(
3509 SWAP_ARGS(td
->has_vt
, left_x
, i
),
3510 SWAP_ARGS(td
->has_vt
, left_w
, 1),
3511 tdd
->sgc
, tdd
->rgc
, 1, False
, rotation
);
3515 do_relieve_rectangle_with_rotation(
3517 SWAP_ARGS(td
->has_vt
, right_x
, i
),
3518 SWAP_ARGS(td
->has_vt
, right_w
, 1),
3519 tdd
->sgc
, tdd
->rgc
, 1, False
, rotation
);
3526 static void border_draw_title_mono(
3527 FvwmWindow
*fw
, titlebar_descr
*td
, title_draw_descr
*tdd
,
3528 FlocaleWinString
*fstr
, Pixmap dest_pix
)
3532 has_vt
= HAS_VERTICAL_TITLE(fw
);
3534 dpy
, dest_pix
, td
->cd
->relief_gc
,
3535 td
->offset
- 2, 0, td
->length
+4, fw
->title_thickness
);
3536 if (fw
->visible_name
!= (char *)NULL
)
3538 FlocaleDrawString(dpy
, fw
->title_font
, fstr
, 0);
3540 /* for mono, we clear an area in the title bar where the window
3541 * title goes, so that its more legible. For color, no need */
3542 do_relieve_rectangle(
3543 dpy
, dest_pix
, 0, 0,
3544 SWAP_ARGS(has_vt
, td
->offset
- 3,
3545 fw
->title_thickness
- 1),
3546 tdd
->rgc
, tdd
->sgc
, td
->cd
->relief_width
, False
);
3547 do_relieve_rectangle(
3549 SWAP_ARGS(has_vt
, td
->offset
+ td
->length
+ 2, 0),
3550 SWAP_ARGS(has_vt
, fw
->title_length
- td
->length
-
3551 td
->offset
- 3, fw
->title_thickness
- 1),
3552 tdd
->rgc
, tdd
->sgc
, td
->cd
->relief_width
, False
);
3554 dpy
, dest_pix
, tdd
->sgc
,
3555 SWAP_ARGS(has_vt
, 0, td
->offset
+ td
->length
+ 1),
3556 SWAP_ARGS(has_vt
, td
->offset
+ td
->length
+ 1,
3557 fw
->title_thickness
));
3562 static void border_draw_title_relief(
3563 FvwmWindow
*fw
, titlebar_descr
*td
, title_draw_descr
*tdd
,
3567 rotation_t rotation
;
3569 if (td
->td_is_rotated
)
3571 rotation
= td
->restore_rotation
;
3575 rotation
= ROTATION_0
;
3577 /* draw title relief */
3578 switch (DFS_BUTTON_RELIEF(*tdd
->tstyle
))
3580 case DFS_BUTTON_IS_SUNK
:
3582 case DFS_BUTTON_IS_UP
:
3583 do_relieve_rectangle_with_rotation(
3584 dpy
, dest_pix
, 0, 0,
3586 td
->has_vt
, fw
->title_length
- 1,
3587 fw
->title_thickness
- 1),
3588 (reverse
) ? tdd
->sgc
: tdd
->rgc
,
3589 (reverse
) ? tdd
->rgc
: tdd
->sgc
, td
->cd
->relief_width
,
3600 static void border_draw_title_deep(
3601 FvwmWindow
*fw
, titlebar_descr
*td
, title_draw_descr
*tdd
,
3602 FlocaleWinString
*fstr
, Pixmap dest_pix
, Window w
)
3605 pixmap_background_type bg
;
3607 bg
.flags
.use_pixmap
= 0;
3608 for (df
= tdd
->df
; df
!= NULL
; df
= df
->next
)
3610 if (df
->style
.face_type
== MultiPixmap
)
3612 border_mp_draw_mp_titlebar(
3613 fw
, td
, df
, dest_pix
, w
);
3617 bg
.pixel
= df
->u
.back
;
3618 border_draw_decor_to_pixmap(
3619 fw
, dest_pix
, w
, &bg
, &td
->layout
.title_g
, df
,
3620 td
, td
->tbstate
.tstate
, True
, tdd
->is_toggled
,
3624 FlocaleDrawString(dpy
, fw
->title_font
, &tdd
->fstr
, 0);
3629 static void border_get_titlebar_draw_descr(
3630 FvwmWindow
*fw
, titlebar_descr
*td
, title_draw_descr
*tdd
,
3635 memset(tdd
, 0, sizeof(*tdd
));
3636 /* prepare the gcs and variables */
3637 if (td
->tbstate
.is_title_pressed
)
3639 tdd
->rgc
= td
->cd
->shadow_gc
;
3640 tdd
->sgc
= td
->cd
->relief_gc
;
3644 tdd
->rgc
= td
->cd
->relief_gc
;
3645 tdd
->sgc
= td
->cd
->shadow_gc
;
3647 NewFontAndColor(fw
->title_font
, td
->cd
->fore_color
, td
->cd
->back_color
);
3648 title_g
= &td
->layout
.title_g
;
3649 tdd
->tstyle
= &TB_STATE(
3650 GetDecor(fw
, titlebar
))[td
->tbstate
.tstate
].style
;
3651 tdd
->df
= &TB_STATE(GetDecor(fw
, titlebar
))[td
->tbstate
.tstate
];
3653 /* fetch the title string */
3654 tdd
->fstr
.str
= fw
->visible_name
;
3655 tdd
->fstr
.win
= dest_pix
;
3656 if (td
->td_is_rotated
)
3658 tdd
->fstr
.flags
.text_rotation
= ROTATION_0
;
3662 tdd
->fstr
.flags
.text_rotation
= fw
->title_text_rotation
;
3666 tdd
->fstr
.y
= td
->offset
;
3667 tdd
->fstr
.x
= fw
->title_text_offset
+ 1;
3671 tdd
->fstr
.x
= td
->offset
;
3672 tdd
->fstr
.y
= fw
->title_text_offset
+ 1;
3674 if (td
->cd
->cs
>= 0)
3676 tdd
->fstr
.colorset
= &Colorset
[td
->cd
->cs
];
3677 tdd
->fstr
.flags
.has_colorset
= 1;
3679 tdd
->fstr
.gc
= Scr
.TitleGC
;
3684 static void border_set_title_pixmap(
3685 FvwmWindow
*fw
, titlebar_descr
*td
, Pixmap
*dest_pix
, Window w
)
3687 pixmap_background_type bg
;
3688 title_draw_descr tdd
;
3689 FlocaleWinString fstr
;
3690 Bool free_bg_pixmap
= False
;
3693 border_get_titlebar_draw_descr(fw
, td
, &tdd
, *dest_pix
);
3694 /* prepare background, either from the window colour or from the
3696 if (!DFS_USE_BORDER_STYLE(*tdd
.tstyle
))
3698 /* fill with the button background colour */
3699 bg
.flags
.use_pixmap
= 0;
3700 bg
.pixel
= td
->cd
->back_color
;
3703 pix_g
.width
= td
->layout
.title_g
.width
;
3704 pix_g
.height
= td
->layout
.title_g
.height
;
3705 border_fill_pixmap_background(
3706 *dest_pix
, &pix_g
, &bg
, td
->cd
);
3710 /* draw pixmap background inherited from border style */
3711 rectangle relative_g
;
3714 if (td
->draw_rotation
!= ROTATION_0
)
3716 tmp
= CreateRotatedPixmap(
3718 td
->layout
.title_g
.width
,
3719 td
->layout
.title_g
.height
,
3720 Pdepth
, Scr
.BordersGC
, td
->restore_rotation
);
3721 XFreePixmap(dpy
, *dest_pix
);
3723 border_rotate_titlebar_descr(fw
, td
);
3725 relative_g
.width
= td
->frame_g
.width
;
3726 relative_g
.height
= td
->frame_g
.height
;
3727 relative_g
.x
= td
->layout
.title_g
.x
;
3728 relative_g
.y
= td
->layout
.title_g
.y
;
3729 border_get_border_background(
3730 &bg
, td
->cd
, &td
->layout
.title_g
, &relative_g
,
3731 &free_bg_pixmap
, w
);
3734 /* set the geometry for drawing the Tiled pixmap;
3735 * FIXME: maybe add the relief as offset? */
3738 pix_g
.width
= td
->layout
.title_g
.width
;
3739 pix_g
.height
= td
->layout
.title_g
.height
;
3740 border_fill_pixmap_background(
3741 *dest_pix
, &pix_g
, &bg
, td
->cd
);
3742 if (free_bg_pixmap
&& bg
.pixmap
.p
)
3744 XFreePixmap(dpy
, bg
.pixmap
.p
);
3746 if (td
->draw_rotation
!= ROTATION_0
)
3748 tmp
= CreateRotatedPixmap(
3750 td
->layout
.title_g
.width
,
3751 td
->layout
.title_g
.height
,
3752 Pdepth
, Scr
.BordersGC
, td
->draw_rotation
);
3753 XFreePixmap(dpy
, *dest_pix
);
3755 border_rotate_titlebar_descr(fw
, td
);
3761 border_draw_title_mono(fw
, td
, &tdd
, &fstr
, *dest_pix
);
3765 border_draw_title_deep(fw
, td
, &tdd
, &fstr
, *dest_pix
, w
);
3767 border_draw_title_relief(fw
, td
, &tdd
, *dest_pix
);
3768 border_draw_title_stick_lines(fw
, td
, &tdd
, *dest_pix
);
3773 static void border_draw_title(
3774 FvwmWindow
*fw
, titlebar_descr
*td
)
3778 if (td
->layout
.title_g
.x
< 0 || td
->layout
.title_g
.y
< 0)
3782 if (td
->draw_rotation
!= ROTATION_0
)
3784 border_rotate_titlebar_descr(fw
, td
);
3787 p
= border_create_decor_pixmap(td
->cd
, &(td
->layout
.title_g
));
3788 /* set the background tile */
3790 fprintf(stderr
,"drawing title\n");
3792 border_set_title_pixmap(fw
, td
, &p
, FW_W_TITLE(fw
));
3793 if (td
->draw_rotation
!= ROTATION_0
)
3797 tmp
= CreateRotatedPixmap(
3798 dpy
, p
, td
->layout
.title_g
.width
,
3799 td
->layout
.title_g
.height
, Pdepth
, Scr
.BordersGC
,
3801 XFreePixmap(dpy
, p
);
3803 border_rotate_titlebar_descr(fw
, td
);
3805 /* apply the pixmap and destroy it */
3806 border_set_part_background(FW_W_TITLE(fw
), p
);
3807 XFreePixmap(dpy
, p
);
3808 if (td
->tbstate
.do_clear_title
)
3810 XClearWindow(dpy
, FW_W_TITLE(fw
));
3816 static void border_draw_buttons(
3817 FvwmWindow
*fw
, titlebar_descr
*td
)
3821 /* draw everything in a big loop */
3823 fprintf(stderr
, "drawing buttons 0x%04x\n", td
->tbstate
.draw_bmask
);
3825 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
3827 unsigned int mask
= (1 << i
);
3829 if ((td
->tbstate
.draw_bmask
& mask
) != 0)
3831 border_draw_one_button(fw
, td
, i
);
3834 /* update the button states */
3835 fw
->decor_state
.buttons_drawn
|= td
->tbstate
.draw_bmask
;
3836 fw
->decor_state
.buttons_inverted
= td
->tbstate
.pressed_bmask
;
3837 fw
->decor_state
.buttons_lit
= td
->tbstate
.lit_bmask
;
3838 fw
->decor_state
.buttons_toggled
= td
->tbstate
.toggled_bmask
;
3843 static void border_setup_use_title_style(
3844 FvwmWindow
*fw
, titlebar_descr
*td
)
3847 DecorFace
*df
, *tsdf
;
3848 ButtonState bs
, tsbs
;
3850 /* use a full bar pixmap (for Colorset) or non window size pixmaps
3851 * (for MultiPixmap) under certain condition:
3852 * - for the buttons which use title style
3853 * - for title which have a button with UseTitle style
3855 tsbs
= td
->tbstate
.tstate
;
3856 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
3858 bs
= td
->tbstate
.bstate
[i
];
3859 df
= &TB_STATE(GetDecor(fw
, buttons
[i
]))[bs
];
3860 tsdf
= &TB_STATE(GetDecor(fw
, buttons
[i
]))[tsbs
];
3861 if (FW_W_BUTTON(fw
, i
) != None
)
3863 if (DFS_USE_TITLE_STYLE(df
->style
))
3865 border_setup_bar_pixmaps(
3866 td
, &(td
->cd
->dynamic_cd
),
3867 &TB_STATE(GetDecor(fw
, titlebar
))[bs
],
3870 if (DFS_USE_TITLE_STYLE(tsdf
->style
))
3872 border_setup_bar_pixmaps(
3873 td
, &(td
->cd
->dynamic_cd
),
3874 &TB_STATE(GetDecor(fw
, titlebar
))[tsbs
],
3882 static void border_rotate_titlebar_descr(
3883 FvwmWindow
*fw
, titlebar_descr
*td
)
3885 rotation_t rotation
;
3887 static titlebar_descr saved_td
;
3889 if (td
->draw_rotation
== ROTATION_0
)
3893 if (!td
->has_been_saved
)
3895 td
->has_been_saved
= True
;
3896 memcpy(&saved_td
, td
, sizeof(titlebar_descr
));
3898 if (!td
->td_is_rotated
)
3900 /* make the bar horizontal */
3901 switch(td
->draw_rotation
)
3903 case ROTATION_90
: /* cw */
3904 rotation
= ROTATION_270
;
3906 case ROTATION_270
: /* ccw */
3907 rotation
= ROTATION_90
;
3910 rotation
= ROTATION_180
;
3916 td
->has_an_upsidedown_rotation
= 0;
3917 td
->td_is_rotated
= 1;
3922 memcpy(td
, &saved_td
, sizeof(titlebar_descr
));
3923 td
->td_is_rotated
= 0;
3927 #define ROTATE_RECTANGLE(rot, r, vs_frame, vs_titlebar, vs_title) \
3932 tr.width = r->width; \
3933 tr.height = r->height; \
3936 case ROTATION_270: /* ccw */ \
3940 tr.y = td->frame_g.width - (r->x+r->width); \
3942 else if (vs_titlebar) \
3944 tr.y = td->bar_g.width - \
3947 else if (vs_title) \
3949 tr.y = td->layout.title_g.width - \
3956 tr.width = r->height; \
3957 tr.height = r->width; \
3959 case ROTATION_90: /* cw */ \
3962 tr.x = td->frame_g.height - (r->y+r->height); \
3964 else if (vs_titlebar) \
3966 tr.x = td->bar_g.height - \
3969 else if (vs_title) \
3971 tr.x = td->layout.title_g.height - \
3979 tr.width = r->height; \
3980 tr.height = r->width; \
3982 case ROTATION_180: \
3985 tr.x = td->frame_g.width - (r->x+r->width); \
3987 else if (vs_titlebar) \
3989 tr.x = td->bar_g.width - \
3990 (r->x + r->width); \
3992 else if (vs_title) \
3994 tr.x = td->layout.title_g.width - \
3995 (r->x + r->width); \
4007 r->width = tr.width; \
4008 r->height = tr.height; \
4015 td
->layout
.title_g
.height
- td
->offset
- td
->length
;
4016 tmpi
= td
->left_end_length
;
4017 td
->left_end_length
= td
->right_end_length
;
4018 td
->right_end_length
= tmpi
;
4019 tmpi
= td
->left_of_text_length
;
4020 td
->left_of_text_length
= td
->right_of_text_length
;
4021 td
->right_of_text_length
= tmpi
;
4026 td
->offset
= td
->layout
.title_g
.width
- td
->offset
- td
->length
;
4027 tmpi
= td
->left_end_length
;
4028 td
->left_end_length
= td
->right_end_length
;
4029 td
->right_end_length
= tmpi
;
4030 tmpi
= td
->left_of_text_length
;
4031 td
->left_of_text_length
= td
->right_of_text_length
;
4032 td
->right_of_text_length
= tmpi
;
4038 ROTATE_RECTANGLE(rotation
, (&td
->left_buttons_g
), True
, False
, False
)
4039 ROTATE_RECTANGLE(rotation
, (&td
->right_buttons_g
), True
, False
, False
)
4040 for (i
=0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
4043 rotation
, (&td
->layout
.button_g
[i
]), True
, False
, False
)
4045 ROTATE_RECTANGLE(rotation
, (&td
->under_text_g
), False
, False
, True
)
4046 ROTATE_RECTANGLE(rotation
, (&td
->left_main_g
), False
, False
, True
)
4047 ROTATE_RECTANGLE(rotation
, (&td
->right_main_g
), False
, False
, True
)
4048 ROTATE_RECTANGLE(rotation
, (&td
->full_left_main_g
), True
, False
, False
)
4049 ROTATE_RECTANGLE(rotation
, (&td
->full_right_main_g
), True
, False
, False
)
4050 ROTATE_RECTANGLE(rotation
, (&td
->layout
.title_g
), True
, False
, False
)
4051 ROTATE_RECTANGLE(rotation
, (&td
->bar_g
), True
, False
, False
)
4052 ROTATE_RECTANGLE(rotation
, (&td
->frame_g
), False
, False
, False
);
4054 #undef ROTATE_RECTANGLE
4057 static void border_get_titlebar_descr_state(
4058 FvwmWindow
*fw
, window_parts pressed_parts
, int pressed_button
,
4059 clear_window_parts clear_parts
, Bool do_hilight
,
4060 border_titlebar_state
*tbstate
)
4064 if ((pressed_parts
& PART_BUTTONS
) != PART_NONE
&& pressed_button
>= 0)
4066 tbstate
->pressed_bmask
= (1 << pressed_button
);
4070 tbstate
->pressed_bmask
= 0;
4072 if ((clear_parts
& CLEAR_BUTTONS
) != CLEAR_NONE
)
4074 tbstate
->clear_bmask
= ~0;
4078 tbstate
->clear_bmask
= 0;
4080 tbstate
->lit_bmask
= (do_hilight
== True
) ? ~0 : 0;
4081 if ((pressed_parts
& PART_TITLE
) != PART_NONE
)
4083 tbstate
->is_title_pressed
= 1;
4087 tbstate
->is_title_pressed
= 0;
4089 if ((clear_parts
& CLEAR_TITLE
) != CLEAR_NONE
)
4091 tbstate
->do_clear_title
= 1;
4095 tbstate
->do_clear_title
= 0;
4097 tbstate
->is_title_lit
= (do_hilight
== True
) ? 1 : 0;
4098 tbstate
->toggled_bmask
= 0;
4099 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
4101 unsigned int mask
= (1 << i
);
4103 if (is_button_toggled(fw
, i
))
4105 tbstate
->toggled_bmask
|= mask
;
4107 tbstate
->bstate
[i
] = border_flags_to_button_state(
4108 tbstate
->pressed_bmask
& mask
,
4109 tbstate
->lit_bmask
& mask
,
4110 tbstate
->toggled_bmask
& mask
);
4112 tbstate
->tstate
= border_flags_to_button_state(
4113 tbstate
->is_title_pressed
, tbstate
->is_title_lit
, 0);
4116 static window_parts
border_get_titlebar_descr(
4117 common_decorations_type
*cd
, FvwmWindow
*fw
,
4118 window_parts pressed_parts
, int pressed_button
,
4119 window_parts force_draw_parts
, clear_window_parts clear_parts
,
4120 rectangle
*old_g
, rectangle
*new_g
, Bool do_hilight
,
4121 titlebar_descr
*ret_td
)
4123 window_parts draw_parts
;
4127 JustificationType just
;
4132 ret_td
->frame_g
= *new_g
;
4135 old_g
= &fw
->g
.frame
;
4137 frame_get_titlebar_dimensions(fw
, old_g
, NULL
, &ret_td
->old_layout
);
4138 frame_get_titlebar_dimensions(fw
, new_g
, NULL
, &ret_td
->layout
);
4140 ret_td
->has_vt
= HAS_VERTICAL_TITLE(fw
);
4141 if (USE_TITLE_DECOR_ROTATION(fw
))
4143 ret_td
->draw_rotation
= fw
->title_text_rotation
;
4144 switch(ret_td
->draw_rotation
)
4147 ret_td
->restore_rotation
= ROTATION_270
;
4149 case ROTATION_270
: /* ccw */
4150 ret_td
->restore_rotation
= ROTATION_90
;
4153 ret_td
->restore_rotation
= ROTATION_180
;
4159 if (fw
->title_text_rotation
== ROTATION_270
||
4160 fw
->title_text_rotation
== ROTATION_180
)
4162 ret_td
->has_an_upsidedown_rotation
= True
;
4164 /* geometry of the title bar title + buttons */
4165 if (!ret_td
->has_vt
)
4167 ret_td
->bar_g
.width
= new_g
->width
- 2 * fw
->boundary_width
;
4168 ret_td
->bar_g
.height
= ret_td
->layout
.title_g
.height
;
4169 ret_td
->bar_g
.x
= fw
->boundary_width
;
4170 ret_td
->bar_g
.y
= ret_td
->layout
.title_g
.y
;
4174 ret_td
->bar_g
.width
= ret_td
->layout
.title_g
.width
;
4175 ret_td
->bar_g
.height
= new_g
->height
- 2 * fw
->boundary_width
;
4176 ret_td
->bar_g
.y
= fw
->boundary_width
;
4177 ret_td
->bar_g
.x
= ret_td
->layout
.title_g
.x
;
4180 /* buttons geometries */
4183 ret_td
->left_buttons_g
.width
= ret_td
->bar_g
.width
;
4184 ret_td
->right_buttons_g
.width
= ret_td
->bar_g
.width
;
4188 ret_td
->left_buttons_g
.height
= ret_td
->bar_g
.height
;
4189 ret_td
->right_buttons_g
.height
= ret_td
->bar_g
.width
;
4192 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
4194 if (FW_W_BUTTON(fw
, i
) == None
)
4202 rbl
+= ret_td
->layout
.button_g
[i
].height
;
4206 lbl
+= ret_td
->layout
.button_g
[i
].height
;
4213 rbl
+= ret_td
->layout
.button_g
[i
].width
;
4217 lbl
+= ret_td
->layout
.button_g
[i
].width
;
4222 if (ret_td
->has_an_upsidedown_rotation
)
4226 ret_td
->left_buttons_g
.height
= rbl
;
4227 ret_td
->right_buttons_g
.height
= lbl
;
4228 ret_td
->right_buttons_g
.y
= fw
->boundary_width
;
4229 ret_td
->right_buttons_g
.x
= ret_td
->bar_g
.x
;
4230 ret_td
->left_buttons_g
.y
= ret_td
->layout
.title_g
.y
+
4231 ret_td
->layout
.title_g
.height
;
4232 ret_td
->left_buttons_g
.x
= ret_td
->bar_g
.x
;
4236 ret_td
->left_buttons_g
.width
= rbl
;
4237 ret_td
->right_buttons_g
.width
= lbl
;
4238 ret_td
->right_buttons_g
.x
= fw
->boundary_width
;
4239 ret_td
->right_buttons_g
.y
= ret_td
->bar_g
.y
;
4240 ret_td
->left_buttons_g
.x
= ret_td
->layout
.title_g
.x
+
4241 ret_td
->layout
.title_g
.width
;
4242 ret_td
->left_buttons_g
.y
= ret_td
->bar_g
.y
;
4249 ret_td
->left_buttons_g
.height
= lbl
;
4250 ret_td
->right_buttons_g
.height
= rbl
;
4251 ret_td
->left_buttons_g
.y
= fw
->boundary_width
;
4252 ret_td
->left_buttons_g
.x
= ret_td
->bar_g
.x
;
4253 ret_td
->right_buttons_g
.y
= ret_td
->layout
.title_g
.y
+
4254 ret_td
->layout
.title_g
.height
;
4255 ret_td
->right_buttons_g
.x
= ret_td
->bar_g
.x
;
4259 ret_td
->left_buttons_g
.width
= lbl
;
4260 ret_td
->right_buttons_g
.width
= rbl
;
4261 ret_td
->left_buttons_g
.x
= fw
->boundary_width
;
4262 ret_td
->left_buttons_g
.y
= ret_td
->bar_g
.y
;
4263 ret_td
->right_buttons_g
.x
= ret_td
->layout
.title_g
.x
+
4264 ret_td
->layout
.title_g
.width
;
4265 ret_td
->right_buttons_g
.y
= ret_td
->bar_g
.y
;
4269 /* initialise flags */
4270 border_get_titlebar_descr_state(
4271 fw
, pressed_parts
, pressed_button
, clear_parts
, do_hilight
,
4272 &(ret_td
->tbstate
));
4274 /* get the title string length and position
4275 * This is not in "tdd" (titlebar_draw_descr), because these are needed
4276 * to draw the buttons with UseTitleStyle */
4277 just
= TB_JUSTIFICATION(GetDecor(fw
, titlebar
));
4278 if (fw
->visible_name
!= (char *)NULL
)
4280 ret_td
->length
= FlocaleTextWidth(
4281 fw
->title_font
, fw
->visible_name
,
4282 (ret_td
->has_vt
) ? -strlen(fw
->visible_name
) :
4283 strlen(fw
->visible_name
));
4284 if (ret_td
->length
> fw
->title_length
-
4285 2*MIN_WINDOW_TITLE_TEXT_OFFSET
)
4287 ret_td
->length
= fw
->title_length
-
4288 2*MIN_WINDOW_TITLE_TEXT_OFFSET
;
4291 if (ret_td
->length
< 0)
4300 if (ret_td
->length
== 0)
4304 df
= &TB_STATE(GetDecor(fw
, titlebar
))[ret_td
->tbstate
.tstate
];
4311 if (ret_td
->has_an_upsidedown_rotation
)
4313 is_start
= !is_start
;
4317 if (WINDOW_TITLE_TEXT_OFFSET
+ ret_td
->length
<=
4320 ret_td
->offset
= WINDOW_TITLE_TEXT_OFFSET
;
4325 fw
->title_length
- ret_td
->length
;
4330 ret_td
->offset
= fw
->title_length
- ret_td
->length
-
4331 WINDOW_TITLE_TEXT_OFFSET
;
4336 ret_td
->offset
= (fw
->title_length
- ret_td
->length
) / 2;
4340 if (ret_td
->offset
< MIN_WINDOW_TITLE_TEXT_OFFSET
)
4342 ret_td
->offset
= MIN_WINDOW_TITLE_TEXT_OFFSET
;
4345 /* setup MultiPixmap */
4346 border_mp_get_titlebar_descr(fw
, ret_td
, df
);
4348 /* determine the parts to draw */
4349 draw_parts
= border_get_tb_parts_to_draw(
4350 fw
, ret_td
, old_g
, new_g
, force_draw_parts
);
4356 static void border_draw_titlebar(
4357 common_decorations_type
*cd
, FvwmWindow
*fw
,
4358 window_parts pressed_parts
, int pressed_button
,
4359 window_parts force_draw_parts
, clear_window_parts clear_parts
,
4360 rectangle
*old_g
, rectangle
*new_g
, Bool do_hilight
)
4362 window_parts draw_parts
;
4367 /* just reset border states */
4368 fw
->decor_state
.parts_drawn
&= ~(PART_TITLE
);
4369 fw
->decor_state
.parts_lit
&= ~(PART_TITLE
);
4370 fw
->decor_state
.parts_inverted
&= ~(PART_TITLE
);
4371 fw
->decor_state
.buttons_drawn
= 0;
4372 fw
->decor_state
.buttons_lit
= 0;
4373 fw
->decor_state
.buttons_inverted
= 0;
4374 fw
->decor_state
.buttons_toggled
= 0;
4377 memset(&td
, 0, sizeof(td
));
4378 draw_parts
= border_get_titlebar_descr(
4379 cd
, fw
, pressed_parts
, pressed_button
, force_draw_parts
,
4380 clear_parts
, old_g
, new_g
, do_hilight
, &td
);
4381 if ((draw_parts
& PART_TITLE
) != PART_NONE
||
4382 (draw_parts
& PART_BUTTONS
) != PART_NONE
)
4384 /* set up UseTitleStyle Colorset */
4385 border_setup_use_title_style(fw
, &td
);
4387 if ((draw_parts
& PART_TITLE
) != PART_NONE
)
4389 border_draw_title(fw
, &td
);
4391 if ((draw_parts
& PART_BUTTONS
) != PART_NONE
)
4393 border_draw_buttons(fw
, &td
);
4395 border_free_bar_pixmaps(&(td
.cd
->dynamic_cd
));
4397 /* update the decor states */
4398 fw
->decor_state
.parts_drawn
|= draw_parts
;
4401 fw
->decor_state
.parts_lit
|= draw_parts
;
4405 fw
->decor_state
.parts_lit
&= ~draw_parts
;
4407 fw
->decor_state
.parts_inverted
&= ~draw_parts
;
4408 fw
->decor_state
.parts_inverted
|= (draw_parts
& pressed_parts
);
4409 if (draw_parts
& PART_BUTTONS
)
4411 fw
->decor_state
.buttons_drawn
|= td
.tbstate
.draw_bmask
;
4412 fw
->decor_state
.parts_lit
= (do_hilight
) ? ~0 : 0;
4413 if (td
.tbstate
.pressed_bmask
)
4415 fw
->decor_state
.buttons_inverted
=
4416 td
.tbstate
.pressed_bmask
;
4420 fw
->decor_state
.buttons_inverted
&=
4421 ~td
.tbstate
.draw_bmask
;
4423 fw
->decor_state
.buttons_toggled
=
4424 (fw
->decor_state
.buttons_toggled
&
4425 ~td
.tbstate
.max_bmask
) | td
.tbstate
.toggled_bmask
;
4433 * Redraws the windows borders
4436 static void border_draw_border_parts(
4437 common_decorations_type
*cd
, FvwmWindow
*fw
,
4438 window_parts pressed_parts
, window_parts force_draw_parts
,
4439 clear_window_parts clear_parts
, rectangle
*old_g
, rectangle
*new_g
,
4442 border_relief_descr br
;
4443 window_parts draw_parts
;
4446 if (HAS_NO_BORDER(fw
))
4448 /* just reset border states */
4449 fw
->decor_state
.parts_drawn
&= ~(PART_FRAME
| PART_HANDLES
);
4450 fw
->decor_state
.parts_lit
&= ~(PART_FRAME
| PART_HANDLES
);
4451 fw
->decor_state
.parts_inverted
&= ~(PART_FRAME
| PART_HANDLES
);
4454 do_clear
= (clear_parts
& CLEAR_FRAME
) ? True
: False
;
4455 /* determine the parts to draw and the position to place them */
4456 if (HAS_DEPRESSABLE_BORDER(fw
))
4458 pressed_parts
&= PART_FRAME
;
4462 pressed_parts
= PART_NONE
;
4464 force_draw_parts
&= PART_FRAME
;
4465 memset(&br
, 0, sizeof(br
));
4466 draw_parts
= border_get_parts_and_pos_to_draw(
4467 cd
, fw
, pressed_parts
, force_draw_parts
, old_g
, new_g
,
4469 if ((draw_parts
& PART_FRAME
) != PART_NONE
)
4471 border_draw_all_border_parts(
4472 cd
, fw
, &br
, new_g
, draw_parts
, pressed_parts
,
4473 do_hilight
, do_clear
);
4475 /* update the decor states */
4476 fw
->decor_state
.parts_drawn
|= draw_parts
;
4479 fw
->decor_state
.parts_lit
|= draw_parts
;
4483 fw
->decor_state
.parts_lit
&= ~draw_parts
;
4485 fw
->decor_state
.parts_inverted
&= ~draw_parts
;
4486 fw
->decor_state
.parts_inverted
|= (draw_parts
& pressed_parts
);
4491 /* ---------------------------- interface functions ------------------------ */
4493 DecorFace
*border_get_border_style(
4494 FvwmWindow
*fw
, Bool has_focus
)
4498 if (has_focus
== True
)
4500 df
= &(GetDecor(fw
, BorderStyle
.active
));
4504 df
= &(GetDecor(fw
, BorderStyle
.inactive
));
4510 int border_is_using_border_style(
4511 FvwmWindow
*fw
, Bool has_focus
)
4519 is_pressed
= (FW_W_TITLE(fw
) == PressedW
);
4520 bs
= border_flags_to_button_state(is_pressed
, has_focus
, 0);
4521 if (DFS_USE_BORDER_STYLE(TB_STATE(GetDecor(fw
, titlebar
))[bs
].style
))
4525 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
4527 if (FW_W_BUTTON(fw
, i
) == None
)
4531 is_pressed
= (FW_W_BUTTON(fw
, i
) == PressedW
);
4532 is_toggled
= (is_button_toggled(fw
, i
) == True
);
4533 bs
= border_flags_to_button_state(
4534 is_pressed
, (has_focus
== True
), is_toggled
);
4535 if (DFS_USE_BORDER_STYLE(
4536 TB_STATE(GetDecor(fw
, buttons
[i
]))[bs
].style
))
4545 int border_context_to_parts(
4548 if (context
== C_FRAME
|| context
== C_SIDEBAR
||
4549 context
== (C_FRAME
| C_SIDEBAR
))
4553 else if (context
== C_F_TOPLEFT
)
4555 return PART_BORDER_NW
;
4557 else if (context
== C_F_TOPRIGHT
)
4559 return PART_BORDER_NE
;
4561 else if (context
== C_F_BOTTOMLEFT
)
4563 return PART_BORDER_SW
;
4565 else if (context
== C_F_BOTTOMRIGHT
)
4567 return PART_BORDER_SE
;
4569 else if (context
== C_SB_LEFT
)
4571 return PART_BORDER_W
;
4573 else if (context
== C_SB_RIGHT
)
4575 return PART_BORDER_E
;
4577 else if (context
== C_SB_TOP
)
4579 return PART_BORDER_N
;
4581 else if (context
== C_SB_BOTTOM
)
4583 return PART_BORDER_S
;
4585 else if (context
== C_TITLE
)
4589 else if (context
& (C_LALL
| C_RALL
))
4591 return PART_BUTTONS
;
4597 void border_get_part_geometry(
4598 FvwmWindow
*fw
, window_parts part
, rectangle
*sidebar_g
,
4599 rectangle
*ret_g
, Window
*ret_w
)
4603 bw
= fw
->boundary_width
;
4604 /* ret_g->x and ret->y is just an offset relatively to the w,
4605 * maybe we can take the relief in account? */
4609 ret_g
->x
= sidebar_g
->x
;
4611 *ret_w
= FW_W_SIDE(fw
, 0);
4614 ret_g
->x
= 2 * sidebar_g
->x
+ sidebar_g
->width
- bw
;
4615 ret_g
->y
= sidebar_g
->y
;
4616 *ret_w
= FW_W_SIDE(fw
, 1);
4619 ret_g
->x
= sidebar_g
->x
;
4620 ret_g
->y
= 2 * sidebar_g
->y
+ sidebar_g
->height
- bw
;
4621 *ret_w
= FW_W_SIDE(fw
, 2);
4625 ret_g
->y
= sidebar_g
->y
;
4626 *ret_w
= FW_W_SIDE(fw
, 3);
4628 case PART_BORDER_NW
:
4631 *ret_w
= FW_W_CORNER(fw
, 0);
4633 case PART_BORDER_NE
:
4634 ret_g
->x
= sidebar_g
->x
+ sidebar_g
->width
;
4636 *ret_w
= FW_W_CORNER(fw
, 1);
4638 case PART_BORDER_SW
:
4640 ret_g
->y
= sidebar_g
->y
+ sidebar_g
->height
;
4641 *ret_w
= FW_W_CORNER(fw
, 2);
4643 case PART_BORDER_SE
:
4644 ret_g
->x
= sidebar_g
->x
+ sidebar_g
->width
;
4645 ret_g
->y
= sidebar_g
->y
+ sidebar_g
->height
;
4646 *ret_w
= FW_W_CORNER(fw
, 3);
4656 ret_g
->width
= sidebar_g
->width
;
4662 ret_g
->height
= sidebar_g
->height
;
4664 case PART_BORDER_NW
:
4665 case PART_BORDER_NE
:
4666 case PART_BORDER_SW
:
4667 case PART_BORDER_SE
:
4668 ret_g
->width
= sidebar_g
->x
;
4669 ret_g
->height
= sidebar_g
->y
;
4678 int get_button_number(int context
)
4682 for (i
= 0; (C_L1
<< i
) & (C_LALL
| C_RALL
); i
++)
4684 if (context
& (C_L1
<< i
))
4693 void border_draw_decorations(
4694 FvwmWindow
*fw
, window_parts draw_parts
, Bool has_focus
, Bool do_force
,
4695 clear_window_parts clear_parts
, rectangle
*old_g
, rectangle
*new_g
)
4697 common_decorations_type cd
;
4698 Bool do_redraw_titlebar
= False
;
4699 window_parts pressed_parts
;
4700 window_parts force_parts
;
4708 if (WAS_NEVER_DRAWN(fw
))
4710 /* force drawing everything */
4712 draw_parts
= PART_ALL
;
4713 SET_WAS_NEVER_DRAWN(fw
, 0);
4715 memset(&cd
, 0, sizeof(cd
));
4717 /* can't compare with True here, old code calls this with value "2" */
4718 if (do_force
!= False
)
4720 force_parts
= draw_parts
;
4724 force_parts
= PART_NONE
;
4728 /* don't re-draw just for kicks */
4729 if (Scr
.Hilite
!= fw
&& Scr
.Hilite
!= NULL
)
4731 FvwmWindow
*t
= Scr
.Hilite
;
4734 /* make sure that the previously highlighted
4735 * window got unhighlighted */
4736 border_draw_decorations(
4737 t
, PART_ALL
, False
, True
, CLEAR_ALL
, NULL
,
4742 else if (fw
== Scr
.Hilite
)
4746 if (fw
->Desk
!= Scr
.CurrentDesk
)
4750 if (IS_ICONIFIED(fw
))
4752 DrawIconWindow(fw
, True
, True
, True
, False
, NULL
);
4755 /* calculate some values and flags */
4756 if ((draw_parts
& PART_TITLEBAR
) && HAS_TITLE(fw
))
4758 do_redraw_titlebar
= True
;
4760 get_common_decorations(
4761 &cd
, fw
, draw_parts
, has_focus
, False
, do_redraw_titlebar
);
4763 context
= frame_window_id_to_context(fw
, PressedW
, &item
);
4764 if ((context
& (C_LALL
| C_RALL
)) == 0)
4768 pressed_parts
= border_context_to_parts(context
);
4771 new_g
= &fw
->g
.frame
;
4773 if (do_redraw_titlebar
)
4775 border_draw_titlebar(
4776 &cd
, fw
, pressed_parts
& PART_TITLEBAR
, item
,
4777 force_parts
& PART_TITLEBAR
,
4778 clear_parts
, old_g
, new_g
, has_focus
);
4780 if (draw_parts
& PART_FRAME
)
4782 Pixmap save_pix
= cd
.dynamic_cd
.frame_pixmap
;
4784 memset(&cd
, 0, sizeof(cd
));
4785 get_common_decorations(
4786 &cd
, fw
, draw_parts
, has_focus
, True
, True
);
4787 cd
.dynamic_cd
.frame_pixmap
= save_pix
;
4788 border_draw_border_parts(
4790 (pressed_parts
& (PART_FRAME
| PART_HANDLES
)),
4791 (force_parts
& (PART_FRAME
| PART_HANDLES
)),
4792 clear_parts
, old_g
, new_g
, has_focus
);
4794 if (cd
.dynamic_cd
.frame_pixmap
!= None
)
4796 XFreePixmap(dpy
, cd
.dynamic_cd
.frame_pixmap
);
4801 void border_undraw_decorations(
4804 memset(&fw
->decor_state
, 0, sizeof(fw
->decor_state
));
4811 * redraw the decoration when style change
4814 void border_redraw_decorations(
4817 FvwmWindow
*u
= Scr
.Hilite
;
4819 /* domivogt (6-Jun-2000): Don't check if the window is visible here.
4820 * If we do, some updates are not applied and when the window becomes
4821 * visible again, the X Server may not redraw the window. */
4822 border_draw_decorations(
4823 fw
, PART_ALL
, (Scr
.Hilite
== fw
), True
, CLEAR_ALL
, NULL
, NULL
);
4831 * get the the root transparent parts of the decoration
4834 unsigned int border_get_transparent_decorations_part(FvwmWindow
*fw
)
4837 unsigned int draw_parts
= PART_NONE
;
4839 window_parts pressed_parts
;
4842 border_titlebar_state tbstate
;
4843 Bool title_use_borderstyle
= False
;
4844 Bool buttons_use_borderstyle
= False
;
4845 Bool buttons_use_titlestyle
= False
;
4847 context
= frame_window_id_to_context(fw
, PressedW
, &item
);
4848 if ((context
& (C_LALL
| C_RALL
)) == 0)
4852 pressed_parts
= border_context_to_parts(context
);
4854 memset(&tbstate
, 0, sizeof(tbstate
));
4855 border_get_titlebar_descr_state(
4856 fw
, pressed_parts
& PART_TITLEBAR
, item
,
4857 CLEAR_ALL
, (Scr
.Hilite
== fw
), &tbstate
);
4859 for(i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
4861 df
= &TB_STATE(GetDecor(fw
, buttons
[i
]))[tbstate
.bstate
[i
]];
4863 if (DFS_USE_TITLE_STYLE(df
->style
))
4865 buttons_use_titlestyle
= True
;
4867 if (DFS_USE_BORDER_STYLE(df
->style
))
4869 buttons_use_borderstyle
= True
;
4871 for(tdf
= df
; tdf
!= NULL
; tdf
= tdf
->next
)
4873 if (DFS_FACE_TYPE(tdf
->style
) == ColorsetButton
&&
4874 CSET_IS_TRANSPARENT_ROOT(tdf
->u
.acs
.cs
))
4876 draw_parts
|= PART_BUTTONS
;
4882 df
= &TB_STATE(GetDecor(fw
, titlebar
))[tbstate
.tstate
];
4883 if (DFS_USE_BORDER_STYLE(df
->style
))
4885 title_use_borderstyle
= True
;
4887 for(tdf
= df
; tdf
!= NULL
; tdf
= tdf
->next
)
4889 if (DFS_FACE_TYPE(tdf
->style
) == ColorsetButton
&&
4890 CSET_IS_TRANSPARENT_ROOT(tdf
->u
.acs
.cs
))
4892 draw_parts
|= PART_TITLE
;
4895 else if (DFS_FACE_TYPE(tdf
->style
) == MultiPixmap
)
4899 for (i
= 0; i
< TBMP_NUM_PIXMAPS
; i
++)
4901 if (CSET_IS_TRANSPARENT_ROOT(
4902 tdf
->u
.mp
.acs
[i
].cs
))
4904 draw_parts
|= PART_TITLE
;
4911 df
= border_get_border_style(fw
, (Scr
.Hilite
== fw
));
4912 if (DFS_FACE_TYPE(df
->style
) == ColorsetButton
&&
4913 CSET_IS_TRANSPARENT_ROOT(df
->u
.acs
.cs
))
4915 draw_parts
|= PART_FRAME
|PART_HANDLES
;
4917 if (draw_parts
& PART_FRAME
)
4919 if (title_use_borderstyle
)
4921 draw_parts
|= PART_TITLE
;
4923 if (buttons_use_borderstyle
)
4925 draw_parts
|= PART_BUTTONS
;
4928 if ((draw_parts
& PART_TITLE
) && buttons_use_titlestyle
)
4930 draw_parts
|= PART_BUTTONS
;
4933 fprintf(stderr
,"Transparant Part: %u\n", draw_parts
);
4938 /* ---------------------------- builtin commands --------------------------- */
4942 * Sets the allowed button states
4945 void CMD_ButtonState(F_CMD_ARGS
)
4949 while ((token
= PeekToken(action
, &action
)))
4951 static char first
= True
;
4952 if (!token
&& first
)
4954 Scr
.gs
.use_active_down_buttons
=
4955 DEFAULT_USE_ACTIVE_DOWN_BUTTONS
;
4956 Scr
.gs
.use_inactive_buttons
=
4957 DEFAULT_USE_INACTIVE_BUTTONS
;
4958 Scr
.gs
.use_inactive_down_buttons
=
4959 DEFAULT_USE_INACTIVE_DOWN_BUTTONS
;
4963 if (StrEquals("activedown", token
))
4965 Scr
.gs
.use_active_down_buttons
= ParseToggleArgument(
4967 DEFAULT_USE_ACTIVE_DOWN_BUTTONS
, True
);
4969 else if (StrEquals("inactive", token
))
4971 Scr
.gs
.use_inactive_buttons
= ParseToggleArgument(
4973 DEFAULT_USE_INACTIVE_BUTTONS
, True
);
4975 else if (StrEquals("inactivedown", token
))
4977 Scr
.gs
.use_inactive_down_buttons
= ParseToggleArgument(
4979 DEFAULT_USE_INACTIVE_DOWN_BUTTONS
, True
);
4983 Scr
.gs
.use_active_down_buttons
=
4984 DEFAULT_USE_ACTIVE_DOWN_BUTTONS
;
4985 Scr
.gs
.use_inactive_buttons
=
4986 DEFAULT_USE_INACTIVE_BUTTONS
;
4987 Scr
.gs
.use_inactive_down_buttons
=
4988 DEFAULT_USE_INACTIVE_DOWN_BUTTONS
;
4989 fvwm_msg(ERR
, "cmd_button_state",
4990 "Unknown button state %s", token
);
5000 * Sets the border style (veliaa@rpi.edu)
5003 void CMD_BorderStyle(F_CMD_ARGS
)
5008 FvwmDecor
*decor
= Scr
.cur_decor
? Scr
.cur_decor
: &Scr
.DefaultDecor
;
5010 FvwmDecor
*decor
= &Scr
.DefaultDecor
;
5013 Scr
.flags
.do_need_window_update
= 1;
5014 decor
->flags
.has_changed
= 1;
5015 for (prev
= action
; (parm
= PeekToken(action
, &action
)); prev
= action
)
5017 if (StrEquals(parm
, "active") || StrEquals(parm
, "inactive"))
5021 DecorFace tmpdf
, *df
;
5023 memset(&tmpdf
.style
, 0, sizeof(tmpdf
.style
));
5024 DFS_FACE_TYPE(tmpdf
.style
) = SimpleButton
;
5026 if (FMiniIconsSupported
)
5030 if (StrEquals(parm
,"active"))
5032 df
= &decor
->BorderStyle
.active
;
5036 df
= &decor
->BorderStyle
.inactive
;
5038 df
->flags
.has_changed
= 1;
5039 while (isspace(*action
))
5048 ERR
, "SetBorderStyle",
5049 "error in %s border"
5050 " specification", parm
);
5053 while (isspace(*action
))
5057 if (ReadDecorFace(action
, &tmpdf
,-1,True
))
5059 FreeDecorFace(dpy
, df
);
5064 end
= strchr(++action
, ')');
5068 ERR
, "SetBorderStyle",
5069 "error in %s border specification",
5073 len
= end
- action
+ 1;
5074 tmp
= safemalloc(len
);
5075 strncpy(tmp
, action
, len
- 1);
5077 ReadDecorFace(tmp
, df
,-1,True
);
5081 else if (strcmp(parm
,"--")==0)
5084 prev
, &decor
->BorderStyle
.active
,-1,True
))
5087 prev
, &decor
->BorderStyle
.inactive
, -1,
5090 decor
->BorderStyle
.active
.flags
.has_changed
= 1;
5091 decor
->BorderStyle
.inactive
.flags
.has_changed
= 1;
5097 memset(&tmpdf
.style
, 0, sizeof(tmpdf
.style
));
5098 DFS_FACE_TYPE(tmpdf
.style
) = SimpleButton
;
5100 if (FMiniIconsSupported
)
5104 if (ReadDecorFace(prev
, &tmpdf
,-1,True
))
5106 FreeDecorFace(dpy
,&decor
->BorderStyle
.active
);
5107 decor
->BorderStyle
.active
= tmpdf
;
5109 prev
, &decor
->BorderStyle
.inactive
, -1,
5111 decor
->BorderStyle
.active
.flags
.has_changed
= 1;
5112 decor
->BorderStyle
.inactive
.flags
.has_changed
=