3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 oroborus - (c) 2001 Ken Lynch
18 xfwm4 - (c) 2002-2007 Olivier Fourdan
29 #include <pango/pango.h>
30 #include <libxfce4util/libxfce4util.h>
38 #include "compositor.h"
47 xfwmPixmap pm_sides
[SIDE_COUNT
];
52 frameDecorationLeft (ScreenInfo
*screen_info
)
54 TRACE ("entering frameDecorationLeft");
56 g_return_val_if_fail (screen_info
!= NULL
, 0);
57 return screen_info
->sides
[SIDE_LEFT
][ACTIVE
].width
;
61 frameDecorationRight (ScreenInfo
*screen_info
)
63 TRACE ("entering frameDecorationRight");
65 g_return_val_if_fail (screen_info
!= NULL
, 0);
66 return screen_info
->sides
[SIDE_RIGHT
][ACTIVE
].width
;
70 frameDecorationTop (ScreenInfo
*screen_info
)
72 TRACE ("entering frameDecorationTop");
74 g_return_val_if_fail (screen_info
!= NULL
, 0);
75 return screen_info
->title
[TITLE_3
][ACTIVE
].height
;
79 frameDecorationBottom (ScreenInfo
*screen_info
)
81 TRACE ("entering frameDecorationBottom");
83 g_return_val_if_fail (screen_info
!= NULL
, 0);
84 return screen_info
->sides
[SIDE_BOTTOM
][ACTIVE
].height
;
88 frameLeft (Client
* c
)
90 TRACE ("entering frameLeft");
92 g_return_val_if_fail (c
!= NULL
, 0);
93 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
94 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
95 && (!FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
96 || !(c
->screen_info
->params
->borderless_maximize
)))
98 return c
->screen_info
->sides
[SIDE_LEFT
][ACTIVE
].width
;
104 frameRight (Client
* c
)
106 TRACE ("entering frameRight");
108 g_return_val_if_fail (c
!= NULL
, 0);
109 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
110 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
111 && (!FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
112 || !(c
->screen_info
->params
->borderless_maximize
)))
114 return c
->screen_info
->sides
[SIDE_RIGHT
][ACTIVE
].width
;
120 frameTop (Client
* c
)
122 TRACE ("entering frameTop");
124 g_return_val_if_fail (c
!= NULL
, 0);
125 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
126 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
128 return c
->screen_info
->title
[TITLE_3
][ACTIVE
].height
;
134 frameBottom (Client
* c
)
136 TRACE ("entering frameBottom");
138 g_return_val_if_fail (c
!= NULL
, 0);
139 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
140 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
141 && (!FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
142 || !(c
->screen_info
->params
->borderless_maximize
)))
144 return c
->screen_info
->sides
[SIDE_BOTTOM
][ACTIVE
].height
;
152 TRACE ("entering frameX");
154 g_return_val_if_fail (c
!= NULL
, 0);
155 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
156 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
157 && (!FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
158 || !(c
->screen_info
->params
->borderless_maximize
)))
160 return c
->x
- frameLeft (c
);
168 TRACE ("entering frameY");
170 g_return_val_if_fail (c
!= NULL
, 0);
171 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
172 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
174 return c
->y
- frameTop (c
);
180 frameWidth (Client
* c
)
182 TRACE ("entering frameWidth");
184 g_return_val_if_fail (c
!= NULL
, 0);
185 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
186 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
187 && (!FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
188 || !(c
->screen_info
->params
->borderless_maximize
)))
190 return c
->width
+ frameLeft (c
) + frameRight (c
);
196 frameHeight (Client
* c
)
198 TRACE ("entering frameHeight");
200 g_return_val_if_fail (c
!= NULL
, 0);
201 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
202 && FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
)
203 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
205 return frameTop (c
) + frameBottom (c
);
207 else if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
208 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
210 return c
->height
+ frameTop (c
) + frameBottom (c
);
216 frameTopLeftWidth (Client
* c
, int state
)
218 TRACE ("entering frameTopLeftWidth");
220 g_return_val_if_fail (c
!= NULL
, 0);
221 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
222 && c
->screen_info
->params
->borderless_maximize
)
226 return c
->screen_info
->corners
[CORNER_TOP_LEFT
][state
].width
;
231 frameTopRightWidth (Client
* c
, int state
)
233 TRACE ("entering frameTopRightWidth");
235 g_return_val_if_fail (c
!= NULL
, 0);
236 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
237 && c
->screen_info
->params
->borderless_maximize
)
241 return c
->screen_info
->corners
[CORNER_TOP_RIGHT
][state
].width
;
245 frameButtonOffset (Client
*c
)
247 TRACE ("entering frameButtonOffset");
249 g_return_val_if_fail (c
!= NULL
, 0);
250 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
251 && c
->screen_info
->params
->borderless_maximize
)
253 return MAX (0, c
->screen_info
->params
->maximized_offset
);
255 return c
->screen_info
->params
->button_offset
;
259 frameFillTitlePixmap (Client
* c
, int state
, int part
, int x
, int w
, int h
, xfwmPixmap
* title_pm
, xfwmPixmap
* top_pm
)
261 ScreenInfo
*screen_info
;
263 TRACE ("entering frameFillTitlePixmap");
265 g_return_if_fail (c
);
266 g_return_if_fail (title_pm
);
267 g_return_if_fail (top_pm
);
269 screen_info
= c
->screen_info
;
271 if (!xfwmPixmapNone(&screen_info
->top
[part
][state
]))
273 xfwmPixmapFill (&screen_info
->top
[part
][state
], top_pm
, x
, 0, w
, h
);
277 xfwmPixmapFill (&screen_info
->title
[part
][state
], top_pm
, x
, 0, w
, h
);
279 xfwmPixmapFill (&screen_info
->title
[part
][state
], title_pm
, x
, 0, w
, frameTop (c
));
283 frameCreateTitlePixmap (Client
* c
, int state
, int left
, int right
, xfwmPixmap
* title_pm
, xfwmPixmap
* top_pm
)
285 ScreenInfo
*screen_info
;
286 DisplayInfo
*display_info
;
291 PangoRectangle logical_rect
;
292 int width
, x
, hoffset
, w1
, w2
, w3
, w4
, w5
, temp
;
293 int voffset
, title_x
, title_y
;
296 TRACE ("entering frameCreateTitlePixmap");
298 g_return_if_fail (c
);
299 g_return_if_fail (title_pm
);
300 g_return_if_fail (top_pm
);
302 screen_info
= c
->screen_info
;
303 display_info
= screen_info
->display_info
;
312 width
= frameWidth (c
) - frameTopLeftWidth (c
, state
) - frameTopRightWidth (c
, state
);
318 layout
= gtk_widget_create_pango_layout (myScreenGetGtkWidget (screen_info
), c
->name
);
319 pango_layout_get_pixel_extents (layout
, NULL
, &logical_rect
);
321 if (left
< frameTopLeftWidth (c
, state
))
323 left
= frameTopLeftWidth (c
, state
);
325 if (right
> frameWidth (c
) - frameTopRightWidth (c
, state
))
327 right
= frameWidth (c
) - frameTopRightWidth (c
, state
);
329 if (right
< frameTopLeftWidth (c
, state
))
331 right
= frameTopLeftWidth (c
, state
);
334 left
= left
- frameTopLeftWidth (c
, state
);
335 right
= right
- frameTopLeftWidth (c
, state
);
342 voffset
= screen_info
->params
->title_vertical_offset_active
;
346 voffset
= screen_info
->params
->title_vertical_offset_inactive
;
349 title_y
= voffset
+ (frameTop (c
) - logical_rect
.height
) / 2;
350 if (title_y
+ logical_rect
.height
> frameTop (c
))
352 title_y
= MAX (0, frameTop (c
) - logical_rect
.height
);
355 if (!xfwmPixmapNone(&screen_info
->top
[3][ACTIVE
]))
357 top_height
= screen_info
->top
[3][ACTIVE
].height
;
361 top_height
= frameTop (c
) / 10 + 1;
362 if (top_height
> title_y
- 1)
364 top_height
= MAX (title_y
- 1, 0);
369 w2
= screen_info
->title
[TITLE_2
][state
].width
;
370 w4
= screen_info
->title
[TITLE_4
][state
].width
;
372 if (screen_info
->params
->full_width_title
)
376 w3
= width
- w1
- w2
- w4
- w5
;
381 switch (screen_info
->params
->title_alignment
)
384 hoffset
= screen_info
->params
->title_horizontal_offset
;
387 hoffset
= w3
- logical_rect
.width
- screen_info
->params
->title_horizontal_offset
;
390 hoffset
= (w3
/ 2) - (logical_rect
.width
/ 2);
393 if (hoffset
< screen_info
->params
->title_horizontal_offset
)
395 hoffset
= screen_info
->params
->title_horizontal_offset
;
400 w3
= logical_rect
.width
;
402 if (w3
> width
- w2
- w4
)
404 w3
= width
- w2
- w4
;
410 switch (screen_info
->params
->title_alignment
)
413 w1
= left
+ screen_info
->params
->title_horizontal_offset
;
416 w1
= right
- w2
- w3
- w4
- screen_info
->params
->title_horizontal_offset
;
419 w1
= left
+ ((right
- left
) / 2) - (w3
/ 2) - w2
;
428 xfwmPixmapCreate (screen_info
, top_pm
, width
, top_height
);
429 xfwmPixmapCreate (screen_info
, title_pm
, width
, frameTop (c
));
430 gpixmap
= gdk_pixmap_foreign_new (title_pm
->pixmap
);
431 gdk_drawable_set_colormap (gpixmap
, gdk_screen_get_rgb_colormap (screen_info
->gscr
));
432 gc
= gdk_gc_new (gpixmap
);
436 frameFillTitlePixmap (c
, state
, TITLE_1
, x
, w1
, top_height
, title_pm
, top_pm
);
440 frameFillTitlePixmap (c
, state
, TITLE_2
, x
, w2
, top_height
, title_pm
, top_pm
);
445 frameFillTitlePixmap (c
, state
, TITLE_3
, x
, w3
, top_height
, title_pm
, top_pm
);
446 title_x
= hoffset
+ x
;
447 if (screen_info
->params
->title_shadow
[state
])
449 gdk_gc_get_values (screen_info
->title_shadow_colors
[state
].gc
, &values
);
450 gdk_gc_set_values (gc
, &values
, GDK_GC_FOREGROUND
);
451 if (screen_info
->params
->title_shadow
[state
] == TITLE_SHADOW_UNDER
)
453 gdk_draw_layout (gpixmap
, gc
, title_x
+ 1, title_y
+ 1, layout
);
457 gdk_draw_layout (gpixmap
, gc
, title_x
- 1, title_y
, layout
);
458 gdk_draw_layout (gpixmap
, gc
, title_x
, title_y
- 1, layout
);
459 gdk_draw_layout (gpixmap
, gc
, title_x
+ 1, title_y
, layout
);
460 gdk_draw_layout (gpixmap
, gc
, title_x
, title_y
+ 1, layout
);
463 gdk_gc_get_values (screen_info
->title_colors
[state
].gc
, &values
);
464 gdk_gc_set_values (gc
, &values
, GDK_GC_FOREGROUND
);
465 gdk_draw_layout (gpixmap
, gc
, title_x
, title_y
, layout
);
473 frameFillTitlePixmap (c
, state
, TITLE_4
, x
, w4
, top_height
, title_pm
, top_pm
);
478 frameFillTitlePixmap (c
, state
, TITLE_5
, x
, w5
, top_height
, title_pm
, top_pm
);
480 g_object_unref (G_OBJECT (gc
));
481 g_object_unref (G_OBJECT (gpixmap
));
482 g_object_unref (G_OBJECT (layout
));
486 getButtonFromLetter (char chr
, Client
* c
)
490 TRACE ("entering getButtonFromLetter");
496 if (CLIENT_CAN_HIDE_WINDOW (c
))
502 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_CLOSE
))
508 if (CLIENT_CAN_MAXIMIZE_WINDOW (c
))
517 if (FLAG_TEST_ALL (c
->xfwm_flags
, XFWM_FLAG_HAS_STICK
| XFWM_FLAG_HAS_MENU
))
523 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MENU
))
538 getLetterFromButton (int i
, Client
* c
)
542 TRACE ("entering getLetterFromButton");
548 if (CLIENT_CAN_HIDE_WINDOW (c
))
554 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_CLOSE
))
559 case MAXIMIZE_BUTTON
:
560 if (CLIENT_CAN_MAXIMIZE_WINDOW (c
))
569 if (FLAG_TEST_ALL (c
->xfwm_flags
, XFWM_FLAG_HAS_STICK
| XFWM_FLAG_HAS_MENU
))
575 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MENU
))
587 frameSetShape (Client
* c
, int state
, FramePixmap
* frame_pix
, int button_x
[BUTTON_COUNT
])
589 ScreenInfo
*screen_info
;
590 DisplayInfo
*display_info
;
593 xfwmPixmap
*my_pixmap
;
596 TRACE ("entering frameSetShape");
597 TRACE ("setting shape for client (0x%lx)", c
->window
);
599 screen_info
= c
->screen_info
;
600 display_info
= screen_info
->display_info
;
602 if (!display_info
->have_shape
)
607 shape_win
= XCreateSimpleWindow (display_info
->dpy
, c
->frame
, 0, 0, frameWidth (c
), frameHeight (c
), 0, 0, 0);
609 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
613 rect
.width
= frameWidth (c
);
614 rect
.height
= frameHeight (c
);
615 XShapeCombineRectangles (display_info
->dpy
, shape_win
, ShapeBounding
, 0, 0, &rect
, 1, ShapeSubtract
, Unsorted
);
617 else if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_HAS_SHAPE
))
619 rect
.x
= frameLeft (c
);
620 rect
.y
= frameTop (c
);
621 rect
.width
= c
->width
;
622 rect
.height
= c
->height
;
623 XShapeCombineRectangles (display_info
->dpy
, shape_win
, ShapeBounding
, 0, 0, &rect
, 1, ShapeSet
, Unsorted
);
627 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, frameLeft (c
),
628 frameTop (c
), c
->window
, ShapeBounding
, ShapeSet
);
632 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->title
), ShapeBounding
,
633 0, 0, frame_pix
->pm_title
.mask
, ShapeSet
);
634 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
636 if (xfwmWindowVisible (&c
->sides
[SIDE_LEFT
]))
638 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->sides
[SIDE_LEFT
]),
639 ShapeBounding
, 0, 0, frame_pix
->pm_sides
[SIDE_LEFT
].mask
, ShapeSet
);
642 if (xfwmWindowVisible (&c
->sides
[SIDE_RIGHT
]))
644 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->sides
[SIDE_RIGHT
]),
645 ShapeBounding
, 0, 0, frame_pix
->pm_sides
[SIDE_RIGHT
].mask
, ShapeSet
);
649 if (xfwmWindowVisible (&c
->sides
[SIDE_BOTTOM
]))
651 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->sides
[SIDE_BOTTOM
]),
652 ShapeBounding
, 0, 0, frame_pix
->pm_sides
[SIDE_BOTTOM
].mask
, ShapeSet
);
655 if (xfwmWindowVisible (&c
->sides
[SIDE_TOP
]))
657 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->sides
[SIDE_TOP
]),
658 ShapeBounding
, 0, 0, frame_pix
->pm_sides
[SIDE_TOP
].mask
, ShapeSet
);
661 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_LEFT
]))
663 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_LEFT
]),
664 ShapeBounding
, 0, 0, screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].mask
, ShapeSet
);
667 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_RIGHT
]))
669 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_RIGHT
]),
670 ShapeBounding
, 0, 0, screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].mask
, ShapeSet
);
673 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_LEFT
]))
675 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_LEFT
]),
676 ShapeBounding
, 0, 0, screen_info
->corners
[CORNER_TOP_LEFT
][state
].mask
, ShapeSet
);
679 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_RIGHT
]))
681 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_RIGHT
]),
682 ShapeBounding
, 0, 0, screen_info
->corners
[CORNER_TOP_RIGHT
][state
].mask
, ShapeSet
);
685 for (i
= 0; i
< BUTTON_COUNT
; i
++)
687 if (xfwmWindowVisible (&c
->buttons
[i
]))
689 my_pixmap
= clientGetButtonPixmap (c
, i
, clientGetButtonState (c
, i
, state
));
690 XShapeCombineMask (display_info
->dpy
, MYWINDOW_XWINDOW (c
->buttons
[i
]),
691 ShapeBounding
, 0, 0, my_pixmap
->mask
, ShapeSet
);
695 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_LEFT
]) &&
696 (screen_info
->corners
[CORNER_TOP_LEFT
][state
].height
> frameHeight (c
) - frameBottom (c
) + 1))
699 rect
.y
= frameHeight (c
) - frameBottom (c
) + 1;
700 rect
.width
= frameTopLeftWidth (c
, state
);
701 rect
.height
= screen_info
->corners
[CORNER_TOP_LEFT
][state
].height
702 - (frameHeight (c
) - frameBottom (c
) + 1);
703 XShapeCombineRectangles (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_LEFT
]),
704 ShapeBounding
, 0, 0, &rect
, 1, ShapeSubtract
, 0);
707 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_RIGHT
]) &&
708 (screen_info
->corners
[CORNER_TOP_RIGHT
][state
].height
> frameHeight (c
) - frameBottom (c
) + 1))
711 rect
.y
= frameHeight (c
) - frameBottom (c
) + 1;
712 rect
.width
= frameTopRightWidth (c
, state
);
713 rect
.height
= screen_info
->corners
[CORNER_TOP_RIGHT
][state
].height
714 - (frameHeight (c
) - frameBottom (c
) + 1);
715 XShapeCombineRectangles (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_RIGHT
]),
716 ShapeBounding
, 0, 0, &rect
, 1, ShapeSubtract
, 0);
719 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_LEFT
]) &&
720 (screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
> frameHeight (c
) - frameTop (c
) + 1))
724 rect
.width
= screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
;
725 rect
.height
= screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
726 - (frameHeight (c
) - frameTop (c
) + 1);
727 XShapeCombineRectangles (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_LEFT
]),
728 ShapeBounding
, 0, 0, &rect
, 1, ShapeSubtract
, 0);
731 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_RIGHT
]) &&
732 (screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
> frameHeight (c
) - frameTop (c
) + 1))
736 rect
.width
= screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].width
;
737 rect
.height
= screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
738 - (frameHeight (c
) - frameTop (c
) + 1);
739 XShapeCombineRectangles (display_info
->dpy
, MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_RIGHT
]),
740 ShapeBounding
, 0, 0, &rect
, 1, ShapeSubtract
, 0);
743 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
745 if (xfwmWindowVisible (&c
->sides
[SIDE_LEFT
]))
747 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, 0, frameTop (c
),
748 MYWINDOW_XWINDOW (c
->sides
[SIDE_LEFT
]), ShapeBounding
, ShapeUnion
);
751 if (xfwmWindowVisible (&c
->sides
[SIDE_RIGHT
]))
753 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, frameWidth (c
) - frameRight (c
), frameTop (c
),
754 MYWINDOW_XWINDOW (c
->sides
[SIDE_RIGHT
]), ShapeBounding
, ShapeUnion
);
758 if (xfwmWindowVisible (&c
->title
))
760 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
,
761 frameTopLeftWidth (c
, state
), 0,
762 MYWINDOW_XWINDOW (c
->title
), ShapeBounding
, ShapeUnion
);
765 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_LEFT
]))
768 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, 0, 0,
769 MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_LEFT
]), ShapeBounding
, ShapeUnion
);
772 if (xfwmWindowVisible (&c
->sides
[SIDE_BOTTOM
]))
774 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
,
775 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
,
776 frameHeight (c
) - frameBottom (c
),
777 MYWINDOW_XWINDOW (c
->sides
[SIDE_BOTTOM
]), ShapeBounding
, ShapeUnion
);
780 if (xfwmWindowVisible (&c
->sides
[SIDE_TOP
]))
782 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
,
783 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
,
784 frameTop (c
) - frameBottom (c
),
785 MYWINDOW_XWINDOW (c
->sides
[SIDE_TOP
]), ShapeBounding
, ShapeUnion
);
788 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_LEFT
]))
790 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, 0,
791 frameHeight (c
) - screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
,
792 MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_LEFT
]), ShapeBounding
, ShapeUnion
);
795 if (xfwmWindowVisible (&c
->corners
[CORNER_BOTTOM_RIGHT
]))
797 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
,
798 frameWidth (c
) - screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].width
,
799 frameHeight (c
) - screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
,
800 MYWINDOW_XWINDOW (c
->corners
[CORNER_BOTTOM_RIGHT
]), ShapeBounding
, ShapeUnion
);
803 if (xfwmWindowVisible (&c
->corners
[CORNER_TOP_RIGHT
]))
805 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
,
806 frameWidth (c
) - frameTopRightWidth (c
, state
),
807 0, MYWINDOW_XWINDOW (c
->corners
[CORNER_TOP_RIGHT
]), ShapeBounding
, ShapeUnion
);
810 for (i
= 0; i
< BUTTON_COUNT
; i
++)
812 if (xfwmWindowVisible (&c
->buttons
[i
]))
814 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeBounding
, button_x
[i
],
815 (frameTop (c
) - screen_info
->buttons
[i
][state
].height
+ 1) / 2,
816 MYWINDOW_XWINDOW (c
->buttons
[i
]), ShapeBounding
, ShapeUnion
);
822 rect
.width
= frameWidth (c
);
823 rect
.height
= frameHeight (c
);
824 XShapeCombineRectangles (display_info
->dpy
, shape_win
, ShapeBounding
, 0, 0, &rect
, 1, ShapeIntersect
, Unsorted
);
825 XShapeCombineShape (display_info
->dpy
, c
->frame
, ShapeBounding
, 0, 0, shape_win
, ShapeBounding
, ShapeSet
);
827 /* Set Input shape when using XShape extension 1.1 and later */
828 if (display_info
->shape_version
>= 1001)
830 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeInput
, frameLeft (c
), frameTop (c
), c
->window
, ShapeBounding
, ShapeSubtract
);
831 XShapeCombineShape (display_info
->dpy
, shape_win
, ShapeInput
, frameLeft (c
), frameTop (c
), c
->window
, ShapeInput
, ShapeUnion
);
832 XShapeCombineShape (display_info
->dpy
, c
->frame
, ShapeInput
, 0, 0, shape_win
, ShapeInput
, ShapeSet
);
834 XDestroyWindow (display_info
->dpy
, shape_win
);
838 frameDraw (Client
* c
, gboolean clear_all
)
840 ScreenInfo
*screen_info
;
841 FramePixmap frame_pix
;
842 xfwmPixmap
*my_pixmap
;
843 int state
, i
, j
, x
, button
, left
, right
;
844 int top_width
, bottom_width
, left_height
, right_height
;
845 int button_x
[BUTTON_COUNT
];
846 gboolean requires_clearing
;
847 gboolean width_changed
;
848 gboolean height_changed
;
850 TRACE ("entering frameDraw");
851 TRACE ("drawing frame for \"%s\" (0x%lx)", c
->name
, c
->window
);
853 g_return_if_fail (c
!= NULL
);
855 screen_info
= c
->screen_info
;
856 requires_clearing
= FALSE
;
857 width_changed
= FALSE
;
858 height_changed
= FALSE
;
861 if (c
!= clientGetFocus ())
863 TRACE ("\"%s\" is not the active window", c
->name
);
864 if (FLAG_TEST (c
->wm_flags
, WM_FLAG_URGENT
))
866 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_SEEN_ACTIVE
))
881 if ((state
== INACTIVE
)
882 && FLAG_TEST(c
->xfwm_flags
, XFWM_FLAG_DRAW_ACTIVE
| XFWM_FLAG_FIRST_MAP
))
884 requires_clearing
= TRUE
;
885 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_DRAW_ACTIVE
);
887 else if ((state
== ACTIVE
)
888 && (!FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_DRAW_ACTIVE
)
889 || FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_FIRST_MAP
)))
891 requires_clearing
= TRUE
;
892 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_DRAW_ACTIVE
);
895 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_FIRST_MAP
);
900 width_changed
= TRUE
;
901 height_changed
= TRUE
;
902 requires_clearing
= TRUE
;
903 frameClearQueueDraw (c
);
904 if (c
->frame_timeout_id
)
906 g_source_remove (c
->frame_timeout_id
);
907 c
->frame_timeout_id
= 0;
913 if (c
->previous_width
!= c
->width
)
915 width_changed
= TRUE
;
916 c
->previous_width
= c
->width
;
918 if (c
->previous_height
!= c
->height
)
920 height_changed
= TRUE
;
921 c
->previous_height
= c
->height
;
925 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
926 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
928 /* First, hide the buttons that we don't have... */
929 for (i
= 0; i
< BUTTON_COUNT
; i
++)
931 char b
= getLetterFromButton (i
, c
);
932 if ((!b
) || !strchr (screen_info
->params
->button_layout
, b
))
934 xfwmWindowHide (&c
->buttons
[i
]);
938 /* Then, show the ones that we do have on left... */
939 x
= frameLeft (c
) + frameButtonOffset (c
);
944 right
= frameWidth (c
) - frameRight (c
) - frameButtonOffset (c
);
945 for (i
= 0; i
< strlen (screen_info
->params
->button_layout
); i
++)
947 button
= getButtonFromLetter (screen_info
->params
->button_layout
[i
], c
);
948 if (button
== TITLE_SEPARATOR
)
952 else if (button
>= 0)
954 if (x
+ screen_info
->buttons
[button
][state
].width
+ screen_info
->params
->button_spacing
< right
)
956 my_pixmap
= clientGetButtonPixmap (c
, button
, clientGetButtonState (c
, button
, state
));
957 if (!xfwmPixmapNone(my_pixmap
))
959 xfwmWindowSetBG (&c
->buttons
[button
], my_pixmap
);
961 xfwmWindowShow (&c
->buttons
[button
], x
,
962 (frameTop (c
) - screen_info
->buttons
[button
][state
].height
+ 1) / 2,
963 screen_info
->buttons
[button
][state
].width
,
964 screen_info
->buttons
[button
][state
].height
, TRUE
);
965 button_x
[button
] = x
;
966 x
= x
+ screen_info
->buttons
[button
][state
].width
+
967 screen_info
->params
->button_spacing
;
971 xfwmWindowHide (&c
->buttons
[button
]);
975 left
= x
+ screen_info
->params
->button_spacing
;
977 /* and those that we do have on right... */
978 x
= frameWidth (c
) - frameRight (c
) + screen_info
->params
->button_spacing
-
979 frameButtonOffset (c
);
980 for (j
= strlen (screen_info
->params
->button_layout
) - 1; j
>= i
; j
--)
982 button
= getButtonFromLetter (screen_info
->params
->button_layout
[j
], c
);
983 if (button
== TITLE_SEPARATOR
)
987 else if (button
>= 0)
989 if (x
- screen_info
->buttons
[button
][state
].width
- screen_info
->params
->button_spacing
> left
)
991 my_pixmap
= clientGetButtonPixmap (c
, button
, clientGetButtonState (c
, button
, state
));
992 if (!xfwmPixmapNone(my_pixmap
))
994 xfwmWindowSetBG (&c
->buttons
[button
], my_pixmap
);
996 x
= x
- screen_info
->buttons
[button
][state
].width
-
997 screen_info
->params
->button_spacing
;
998 xfwmWindowShow (&c
->buttons
[button
], x
,
999 (frameTop (c
) - screen_info
->buttons
[button
][state
].height
+ 1) / 2,
1000 screen_info
->buttons
[button
][state
].width
,
1001 screen_info
->buttons
[button
][state
].height
, TRUE
);
1002 button_x
[button
] = x
;
1006 xfwmWindowHide (&c
->buttons
[button
]);
1010 left
= left
- 2 * screen_info
->params
->button_spacing
;
1013 top_width
= frameWidth (c
) - frameTopLeftWidth (c
, state
) - frameTopRightWidth (c
, state
);
1014 bottom_width
= frameWidth (c
) -
1015 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
-
1016 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].width
;
1017 left_height
= frameHeight (c
) - frameTop (c
) -
1018 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
;
1019 right_height
= frameHeight (c
) - frameTop (c
) -
1020 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
;
1022 xfwmPixmapInit (screen_info
, &frame_pix
.pm_title
);
1023 xfwmPixmapInit (screen_info
, &frame_pix
.pm_sides
[SIDE_TOP
]);
1024 xfwmPixmapInit (screen_info
, &frame_pix
.pm_sides
[SIDE_BOTTOM
]);
1025 xfwmPixmapInit (screen_info
, &frame_pix
.pm_sides
[SIDE_LEFT
]);
1026 xfwmPixmapInit (screen_info
, &frame_pix
.pm_sides
[SIDE_RIGHT
]);
1028 /* The title is always visible */
1029 frameCreateTitlePixmap (c
, state
, left
, right
, &frame_pix
.pm_title
, &frame_pix
.pm_sides
[SIDE_TOP
]);
1030 xfwmWindowSetBG (&c
->title
, &frame_pix
.pm_title
);
1031 xfwmWindowShow (&c
->title
,
1032 frameTopLeftWidth (c
, state
), 0, top_width
,
1033 frameTop (c
), (requires_clearing
| width_changed
));
1035 /* Corners are never resized, we need to update them separately */
1036 if (requires_clearing
)
1038 xfwmWindowSetBG (&c
->corners
[CORNER_TOP_LEFT
],
1039 &screen_info
->corners
[CORNER_TOP_LEFT
][state
]);
1040 xfwmWindowSetBG (&c
->corners
[CORNER_TOP_RIGHT
],
1041 &screen_info
->corners
[CORNER_TOP_RIGHT
][state
]);
1042 xfwmWindowSetBG (&c
->corners
[CORNER_BOTTOM_LEFT
],
1043 &screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
]);
1044 xfwmWindowSetBG (&c
->corners
[CORNER_BOTTOM_RIGHT
],
1045 &screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
]);
1048 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
1049 && (c
->screen_info
->params
->borderless_maximize
))
1051 xfwmWindowHide (&c
->sides
[SIDE_LEFT
]);
1052 xfwmWindowHide (&c
->sides
[SIDE_RIGHT
]);
1053 xfwmWindowHide (&c
->sides
[SIDE_BOTTOM
]);
1054 xfwmWindowHide (&c
->sides
[SIDE_TOP
]);
1055 xfwmWindowHide (&c
->corners
[CORNER_TOP_LEFT
]);
1056 xfwmWindowHide (&c
->corners
[CORNER_TOP_RIGHT
]);
1057 xfwmWindowHide (&c
->corners
[CORNER_BOTTOM_LEFT
]);
1058 xfwmWindowHide (&c
->corners
[CORNER_BOTTOM_RIGHT
]);
1062 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
1064 xfwmWindowHide (&c
->sides
[SIDE_LEFT
]);
1065 xfwmWindowHide (&c
->sides
[SIDE_RIGHT
]);
1069 xfwmPixmapCreate (screen_info
, &frame_pix
.pm_sides
[SIDE_LEFT
],
1070 frameLeft (c
), left_height
);
1071 xfwmPixmapFill (&screen_info
->sides
[SIDE_LEFT
][state
],
1072 &frame_pix
.pm_sides
[SIDE_LEFT
],
1073 0, 0, frameLeft (c
), left_height
);
1074 xfwmWindowSetBG (&c
->sides
[SIDE_LEFT
],
1075 &frame_pix
.pm_sides
[SIDE_LEFT
]);
1076 xfwmWindowShow (&c
->sides
[SIDE_LEFT
], 0, frameTop (c
),
1077 frameLeft (c
), left_height
, (requires_clearing
| height_changed
));
1079 xfwmPixmapCreate (screen_info
, &frame_pix
.pm_sides
[SIDE_RIGHT
],
1080 frameRight (c
), right_height
);
1081 xfwmPixmapFill (&screen_info
->sides
[SIDE_RIGHT
][state
],
1082 &frame_pix
.pm_sides
[SIDE_RIGHT
],
1083 0, 0, frameRight (c
), right_height
);
1084 xfwmWindowSetBG (&c
->sides
[SIDE_RIGHT
],
1085 &frame_pix
.pm_sides
[SIDE_RIGHT
]);
1086 xfwmWindowShow (&c
->sides
[SIDE_RIGHT
],
1087 frameWidth (c
) - frameRight (c
), frameTop (c
), frameRight (c
),
1088 right_height
, (requires_clearing
| height_changed
));
1091 xfwmPixmapCreate (screen_info
, &frame_pix
.pm_sides
[SIDE_BOTTOM
],
1092 bottom_width
, frameBottom (c
));
1093 xfwmPixmapFill (&screen_info
->sides
[SIDE_BOTTOM
][state
],
1094 &frame_pix
.pm_sides
[SIDE_BOTTOM
],
1095 0, 0, bottom_width
, frameBottom (c
));
1096 xfwmWindowSetBG (&c
->sides
[SIDE_BOTTOM
],
1097 &frame_pix
.pm_sides
[SIDE_BOTTOM
]);
1098 xfwmWindowShow (&c
->sides
[SIDE_BOTTOM
],
1099 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
,
1100 frameHeight (c
) - frameBottom (c
), bottom_width
, frameBottom (c
),
1101 (requires_clearing
| width_changed
));
1103 if (!xfwmPixmapNone(&frame_pix
.pm_sides
[SIDE_TOP
]))
1105 xfwmWindowSetBG (&c
->sides
[SIDE_TOP
], &frame_pix
.pm_sides
[SIDE_TOP
]);
1106 xfwmWindowShow (&c
->sides
[SIDE_TOP
],
1107 screen_info
->corners
[CORNER_TOP_LEFT
][state
].width
,
1108 0, top_width
, frame_pix
.pm_sides
[SIDE_TOP
].height
,
1109 (requires_clearing
| width_changed
));
1113 xfwmWindowHide (&c
->sides
[SIDE_TOP
]);
1116 xfwmWindowShow (&c
->corners
[CORNER_TOP_LEFT
], 0, 0,
1117 frameTopLeftWidth (c
, state
),
1118 screen_info
->corners
[CORNER_TOP_LEFT
][state
].height
,
1121 xfwmWindowShow (&c
->corners
[CORNER_TOP_RIGHT
],
1122 frameWidth (c
) - frameTopRightWidth (c
, state
),
1123 0, frameTopRightWidth (c
, state
),
1124 screen_info
->corners
[CORNER_TOP_RIGHT
][state
].height
,
1127 xfwmWindowShow (&c
->corners
[CORNER_BOTTOM_LEFT
], 0,
1129 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
,
1130 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].width
,
1131 screen_info
->corners
[CORNER_BOTTOM_LEFT
][state
].height
,
1134 xfwmWindowShow (&c
->corners
[CORNER_BOTTOM_RIGHT
],
1136 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].width
,
1138 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
,
1139 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].width
,
1140 screen_info
->corners
[CORNER_BOTTOM_RIGHT
][state
].height
,
1143 frameSetShape (c
, state
, &frame_pix
, button_x
);
1145 xfwmPixmapFree (&frame_pix
.pm_title
);
1146 xfwmPixmapFree (&frame_pix
.pm_sides
[SIDE_TOP
]);
1147 xfwmPixmapFree (&frame_pix
.pm_sides
[SIDE_BOTTOM
]);
1148 xfwmPixmapFree (&frame_pix
.pm_sides
[SIDE_LEFT
]);
1149 xfwmPixmapFree (&frame_pix
.pm_sides
[SIDE_RIGHT
]);
1153 if (xfwmWindowVisible (&c
->title
))
1155 xfwmWindowHide (&c
->title
);
1157 for (i
= 0; i
< 4; i
++)
1159 if (MYWINDOW_XWINDOW (c
->sides
[i
]) && xfwmWindowVisible (&c
->sides
[i
]))
1161 xfwmWindowHide (&c
->sides
[i
]);
1164 for (i
= 0; i
< 4; i
++)
1166 if (MYWINDOW_XWINDOW (c
->corners
[i
]) && xfwmWindowVisible (&c
->corners
[i
]))
1168 xfwmWindowHide (&c
->corners
[i
]);
1171 for (i
= 0; i
< BUTTON_COUNT
; i
++)
1173 if (MYWINDOW_XWINDOW (c
->buttons
[i
]) && xfwmWindowVisible (&c
->buttons
[i
]))
1175 xfwmWindowHide (&c
->buttons
[i
]);
1178 frameSetShape (c
, 0, NULL
, 0);
1183 update_frame_idle_cb (gpointer data
)
1187 TRACE ("entering update_frame_idle_cb");
1189 c
= (Client
*) data
;
1190 g_return_val_if_fail (c
, FALSE
);
1192 frameDraw (c
, TRUE
);
1193 c
->frame_timeout_id
= 0;
1199 frameClearQueueDraw (Client
* c
)
1201 g_return_if_fail (c
);
1203 TRACE ("entering frameClearQueueDraw for \"%s\" (0x%lx)", c
->name
, c
->window
);
1205 if (c
->frame_timeout_id
)
1207 g_source_remove (c
->frame_timeout_id
);
1208 c
->frame_timeout_id
= 0;
1213 frameQueueDraw (Client
* c
)
1215 g_return_if_fail (c
);
1217 TRACE ("entering frameQueueDraw for \"%s\" (0x%lx)", c
->name
, c
->window
);
1219 if (c
->frame_timeout_id
== 0)
1221 c
->frame_timeout_id
= g_idle_add_full (G_PRIORITY_DEFAULT_IDLE
,
1222 update_frame_idle_cb
, c
, NULL
);