]>
Dogcows Code - chaz/openbox/blob - src/frame.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
9 #include <X11/extensions/shape.h>
17 #include "bindings.hh"
18 #include "otk/display.hh"
24 const long Frame::event_mask
;
26 Frame::Frame(Client
*client
, otk::RenderStyle
*style
)
27 : otk::Widget(openbox
, style
, Horizontal
, 0, 1, true),
28 WidgetBase(WidgetBase::Type_Frame
),
30 _screen(otk::display
->screenInfo(client
->screen())),
31 _plate(this, WidgetBase::Type_Plate
),
32 _titlebar(this, WidgetBase::Type_Titlebar
),
33 _button_close(&_titlebar
, WidgetBase::Type_CloseButton
, client
),
34 _button_iconify(&_titlebar
, WidgetBase::Type_IconifyButton
, client
),
35 _button_max(&_titlebar
, WidgetBase::Type_MaximizeButton
, client
),
36 _button_alldesk(&_titlebar
, WidgetBase::Type_AllDesktopsButton
, client
),
37 _label(&_titlebar
, WidgetBase::Type_Label
),
38 _handle(this, WidgetBase::Type_Handle
),
39 _grip_left(&_handle
, WidgetBase::Type_LeftGrip
, client
),
40 _grip_right(&_handle
, WidgetBase::Type_RightGrip
, client
),
41 _decorations(client
->decorations())
46 XSelectInput(**otk::display
, _window
, Frame::event_mask
);
48 _grip_left
.setCursor(openbox
->cursors().ll_angle
);
49 _grip_right
.setCursor(openbox
->cursors().lr_angle
);
51 _label
.setText(_client
->title());
56 otk::Widget::unfocus(); // stuff starts out appearing focused in otk
58 _plate
.show(); // the other stuff is shown based on decor settings
67 void Frame::setTitle(const otk::ustring
&text
)
74 void Frame::setStyle(otk::RenderStyle
*style
)
78 // if a style was previously set, then 'replace' is true, cause we're
80 bool replace
= (_style
);
82 otk::Widget::setStyle(style
);
85 // XXX: do shit here whatever
90 setBorderColor(_style
->frameBorderColor());
92 // if !replace, then adjust() will get called after the client is grabbed!
94 // size/position everything
103 otk::Widget::focus();
108 void Frame::unfocus()
110 otk::Widget::unfocus();
117 // the party all happens in adjustSize
121 void Frame::adjustSize()
123 // XXX: only if not overridden or something!!! MORE LOGIC HERE!!
124 _decorations
= _client
->decorations();
126 // true/false for whether to show each element of the titlebar
127 bool tit_i
= false, tit_m
= false, tit_s
= false, tit_c
= false;
128 int width
; // the width of the client and its border
129 int bwidth
; // width to make borders
130 int cbwidth
; // width of the inner client border
131 int fontheight
= _style
->labelFont()->height(); // height of the font
132 int butsize
= fontheight
- 2; // width and height of the titlebar buttons
133 const int bevel
= _style
->bevelWidth();
135 if (_decorations
& Client::Decor_Border
) {
136 bwidth
= _style
->frameBorderWidth();
137 cbwidth
= _style
->clientBorderWidth();
139 bwidth
= cbwidth
= 0;
140 _innersize
.left
= _innersize
.top
= _innersize
.bottom
= _innersize
.right
=
142 width
= _client
->area().width() + cbwidth
* 2;
144 _plate
.setBorderWidth(cbwidth
);
146 setBorderWidth(bwidth
);
147 _titlebar
.setBorderWidth(bwidth
);
148 _grip_left
.setBorderWidth(bwidth
);
149 _grip_right
.setBorderWidth(bwidth
);
150 _handle
.setBorderWidth(bwidth
);
152 if (_decorations
& Client::Decor_Titlebar
) {
153 // set the titlebar size
154 _titlebar
.setGeometry(-bwidth
,
157 _style
->labelFont()->height() + (bevel
* 2));
158 _innersize
.top
+= _titlebar
.height() + bwidth
;
160 // set the label size
161 _label
.setGeometry(0, bevel
, width
, fontheight
);
162 // set the buttons sizes
163 if (_decorations
& Client::Decor_Iconify
)
164 _button_iconify
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
165 if (_decorations
& Client::Decor_Maximize
)
166 _button_max
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
167 if (_decorations
& Client::Decor_AllDesktops
)
168 _button_alldesk
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
169 if (_decorations
& Client::Decor_Close
)
170 _button_close
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
172 // separation between titlebar elements
173 const int sep
= bevel
+ 1;
176 if (!python_get_string("titlebar_layout", &layout
))
179 // this code ensures that the string only has one of each possible
180 // letter, all of the letters are valid, and L exists somewhere in the
184 for (std::string::size_type i
= 0; i
< layout
.size(); ++i
) {
188 if (!tit_i
&& (_decorations
& Client::Decor_Iconify
)) {
202 if (!tit_m
&& (_decorations
& Client::Decor_Maximize
)) {
209 if (!tit_s
&& (_decorations
& Client::Decor_AllDesktops
)) {
216 if (!tit_c
&& (_decorations
& Client::Decor_Close
)) {
222 // if we get here then we don't want the letter, kill it
223 layout
.erase(i
--, 1);
228 // the size of the label. this ASSUMES the layout has only buttons other
229 // that the ONE LABEL!!
230 // adds an extra sep so that there's a space on either side of the
231 // titlebar.. note: x = sep, below.
232 int lwidth
= width
- sep
* 2 -
233 (butsize
+ sep
) * (layout
.size() - 1);
234 // quick sanity check for really small windows. if this is needed, its
235 // obviously not going to be displayed right...
236 // XXX: maybe we should make this look better somehow? constraints?
237 if (lwidth
<= 0) lwidth
= 1;
238 _label
.setWidth(lwidth
);
241 for (std::string::size_type i
= 0, len
= layout
.size(); i
< len
; ++i
) {
245 _button_iconify
.move(x
, _button_iconify
.rect().y());
246 x
+= _button_iconify
.width();
250 _label
.move(x
, _label
.rect().y());
255 _button_max
.move(x
, _button_max
.rect().y());
256 x
+= _button_max
.width();
260 _button_alldesk
.move(x
, _button_alldesk
.rect().y());
261 x
+= _button_alldesk
.width();
265 _button_close
.move(x
, _button_close
.rect().y());
266 x
+= _button_close
.width();
269 assert(false); // the layout string is invalid!
275 if (_decorations
& Client::Decor_Handle
) {
276 _handle
.setGeometry(-bwidth
,
277 _innersize
.top
+ _client
->area().height() + cbwidth
,
278 width
, _style
->handleWidth());
279 _grip_left
.setGeometry(-bwidth
,
283 _grip_right
.setGeometry(((_handle
.rect().right() + 1) -
288 _innersize
.bottom
+= _handle
.height() + bwidth
;
292 // position/size all the windows
294 if (_client
->shaded())
295 resize(_innersize
.left
+ _innersize
.right
+ _client
->area().width(),
298 resize(_innersize
.left
+ _innersize
.right
+ _client
->area().width(),
299 _innersize
.top
+ _innersize
.bottom
+ _client
->area().height());
301 _plate
.setGeometry(_innersize
.left
- cbwidth
, _innersize
.top
- cbwidth
,
302 _client
->area().width(), _client
->area().height());
304 // map/unmap all the windows
305 if (_decorations
& Client::Decor_Titlebar
) {
308 _button_iconify
.show();
310 _button_iconify
.hide();
316 _button_alldesk
.show();
318 _button_alldesk
.hide();
320 _button_close
.show();
322 _button_close
.hide();
325 _titlebar
.hide(true);
328 if (_decorations
& Client::Decor_Handle
)
333 _size
.left
= _innersize
.left
+ bwidth
;
334 _size
.right
= _innersize
.right
+ bwidth
;
335 _size
.top
= _innersize
.top
+ bwidth
;
336 _size
.bottom
= _innersize
.bottom
+ bwidth
;
344 void Frame::adjustPosition()
352 void Frame::adjustShape()
355 int bwidth
= (_decorations
& Client::Decor_Border
) ?
356 _style
->frameBorderWidth() : 0;
358 if (!_client
->shaped()) {
359 // clear the shape on the frame window
360 XShapeCombineMask(**otk::display
, _window
, ShapeBounding
,
365 // make the frame's shape match the clients
366 XShapeCombineShape(**otk::display
, _window
, ShapeBounding
,
369 _client
->window(), ShapeBounding
, ShapeSet
);
374 if (_decorations
& Client::Decor_Titlebar
) {
375 xrect
[0].x
= _titlebar
.rect().x();
376 xrect
[0].y
= _titlebar
.rect().y();
377 xrect
[0].width
= _titlebar
.width() + bwidth
* 2; // XXX: this is useless once the widget handles borders!
378 xrect
[0].height
= _titlebar
.height() + bwidth
* 2;
382 if (_decorations
& Client::Decor_Handle
) {
383 xrect
[1].x
= _handle
.rect().x();
384 xrect
[1].y
= _handle
.rect().y();
385 xrect
[1].width
= _handle
.width() + bwidth
* 2; // XXX: this is useless once the widget handles borders!
386 xrect
[1].height
= _handle
.height() + bwidth
* 2;
390 XShapeCombineRectangles(**otk::display
, window(),
391 ShapeBounding
, 0, 0, xrect
, num
,
392 ShapeUnion
, Unsorted
);
398 void Frame::adjustState()
400 _button_alldesk
.update();
401 _button_max
.update();
405 void Frame::grabClient()
407 // reparent the client to the frame
408 XReparentWindow(**otk::display
, _client
->window(), _plate
.window(), 0, 0);
410 When reparenting the client window, it is usually not mapped yet, since
411 this occurs from a MapRequest. However, in the case where Openbox is
412 starting up, the window is already mapped, so we'll see unmap events for
413 it. There are 2 unmap events generated that we see, one with the 'event'
414 member set the root window, and one set to the client, but both get handled
415 and need to be ignored.
417 if (openbox
->state() == Openbox::State_Starting
)
418 _client
->ignore_unmaps
+= 2;
420 // select the event mask on the client's parent (to receive config/map req's)
421 XSelectInput(**otk::display
, _plate
.window(), SubstructureRedirectMask
);
423 // map the client so it maps when the frame does
424 XMapWindow(**otk::display
, _client
->window());
431 void Frame::releaseClient()
435 // check if the app has already reparented its window away
436 if (XCheckTypedWindowEvent(**otk::display
, _client
->window(),
437 ReparentNotify
, &ev
)) {
438 XPutBackEvent(**otk::display
, &ev
);
439 // re-map the window since the unmanaging process unmaps it
440 XMapWindow(**otk::display
, _client
->window());
442 // according to the ICCCM - if the client doesn't reparent itself, then we
443 // will reparent the window to root for them
444 XReparentWindow(**otk::display
, _client
->window(),
445 _screen
->rootWindow(),
446 _client
->area().x(), _client
->area().y());
451 void Frame::clientGravity(int &x
, int &y
)
453 x
= _client
->area().x();
454 y
= _client
->area().y();
457 switch (_client
->gravity()) {
459 case NorthWestGravity
:
460 case SouthWestGravity
:
467 x
-= (_size
.left
+ _size
.right
) / 2;
470 case NorthEastGravity
:
471 case SouthEastGravity
:
473 x
-= _size
.left
+ _size
.right
;
483 switch (_client
->gravity()) {
485 case NorthWestGravity
:
486 case NorthEastGravity
:
493 y
-= (_size
.top
+ _size
.bottom
) / 2;
496 case SouthWestGravity
:
497 case SouthEastGravity
:
499 y
-= _size
.top
+ _size
.bottom
;
510 void Frame::frameGravity(int &x
, int &y
)
516 switch (_client
->gravity()) {
518 case NorthWestGravity
:
520 case SouthWestGravity
:
525 x
+= (_size
.left
+ _size
.right
) / 2;
527 case NorthEastGravity
:
529 case SouthEastGravity
:
530 x
+= _size
.left
+ _size
.right
;
539 switch (_client
->gravity()) {
541 case NorthWestGravity
:
543 case SouthWestGravity
:
548 y
+= (_size
.top
+ _size
.bottom
) / 2;
550 case NorthEastGravity
:
552 case SouthEastGravity
:
553 y
+= _size
.top
+ _size
.bottom
;
This page took 0.072296 seconds and 4 git commands to generate.