]>
Dogcows Code - chaz/openbox/blob - src/frame.cc
9c24689de0c23208b9fa48d7371b9ce687ff48a3
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 OBFrame::event_mask
;
26 OBFrame::OBFrame(OBClient
*client
, otk::Style
*style
)
27 : otk::OtkWidget(Openbox::instance
, style
, Horizontal
, 0, 1, true),
30 _screen(otk::OBDisplay::screenInfo(client
->screen())),
31 _plate(this, OBWidget::Type_Plate
),
32 _titlebar(this, OBWidget::Type_Titlebar
),
33 _button_close(&_titlebar
, OBWidget::Type_CloseButton
),
34 _button_iconify(&_titlebar
, OBWidget::Type_IconifyButton
),
35 _button_max(&_titlebar
, OBWidget::Type_MaximizeButton
),
36 _button_stick(&_titlebar
, OBWidget::Type_StickyButton
),
37 _label(&_titlebar
, OBWidget::Type_Label
),
38 _handle(this, OBWidget::Type_Handle
),
39 _grip_left(&_handle
, OBWidget::Type_LeftGrip
),
40 _grip_right(&_handle
, OBWidget::Type_RightGrip
),
41 _decorations(client
->decorations())
46 XSelectInput(otk::OBDisplay::display
, _window
, OBFrame::event_mask
);
48 _grip_left
.setCursor(Openbox::instance
->cursors().ll_angle
);
49 _grip_right
.setCursor(Openbox::instance
->cursors().lr_angle
);
51 _label
.setText(_client
->title());
56 otk::OtkWidget::unfocus(); // stuff starts out appearing focused in otk
58 _plate
.show(); // the other stuff is shown based on decor settings
70 void OBFrame::setTitle(const std::string
&text
)
77 void OBFrame::setStyle(otk::Style
*style
)
81 otk::OtkWidget::setStyle(style
);
83 // if a style was previously set, then 'replace' is true, cause we're
85 bool replace
= (_style
);
88 // XXX: do shit here whatever
93 setBorderColor(_style
->getBorderColor());
95 // if !replace, then adjust() will get called after the client is grabbed!
97 // size/position everything
104 void OBFrame::focus()
106 otk::OtkWidget::focus();
111 void OBFrame::unfocus()
113 otk::OtkWidget::unfocus();
118 void OBFrame::adjust()
120 // the party all happens in adjustSize
124 void OBFrame::adjustSize()
126 // XXX: only if not overridden or something!!! MORE LOGIC HERE!!
127 _decorations
= _client
->decorations();
129 // true/false for whether to show each element of the titlebar
130 bool tit_i
= false, tit_m
= false, tit_s
= false, tit_c
= false;
131 int width
; // the width of the client and its border
132 int bwidth
; // width to make borders
133 int cbwidth
; // width of the inner client border
134 int butsize
=0; // width and height of the titlebar buttons
135 const int bevel
= _style
->getBevelWidth();
137 if (_decorations
& OBClient::Decor_Border
) {
138 bwidth
= _style
->getBorderWidth();
139 cbwidth
= _style
->getFrameWidth();
141 bwidth
= cbwidth
= 0;
142 _innersize
.left
= _innersize
.top
= _innersize
.bottom
= _innersize
.right
=
144 width
= _client
->area().width() + cbwidth
* 2;
146 _plate
.setBorderWidth(cbwidth
);
148 setBorderWidth(bwidth
);
149 _titlebar
.setBorderWidth(bwidth
);
150 _grip_left
.setBorderWidth(bwidth
);
151 _grip_right
.setBorderWidth(bwidth
);
152 _handle
.setBorderWidth(bwidth
);
154 if (_decorations
& OBClient::Decor_Titlebar
) {
155 // set the titlebar size
156 _titlebar
.setGeometry(-bwidth
,
159 _style
->getFont()->height() + bevel
* 2);
160 _innersize
.top
+= _titlebar
.height() + bwidth
;
162 // set the label size
163 _label
.setGeometry(0, bevel
, width
, _style
->getFont()->height());
164 // set the buttons sizes
165 butsize
= _label
.height() - 2;
166 if (_decorations
& OBClient::Decor_Iconify
)
167 _button_iconify
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
168 if (_decorations
& OBClient::Decor_Maximize
)
169 _button_max
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
170 if (_decorations
& OBClient::Decor_Sticky
)
171 _button_stick
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
172 if (_decorations
& OBClient::Decor_Close
)
173 _button_close
.setGeometry(0, bevel
+ 1, butsize
, butsize
);
175 // separation between titlebar elements
176 const int sep
= bevel
+ 1;
179 if (!python_get_string("titlebar_layout", &layout
))
182 // this code ensures that the string only has one of each possible
183 // letter, all of the letters are valid, and L exists somewhere in the
187 for (std::string::size_type i
= 0; i
< layout
.size(); ++i
) {
191 if (!tit_i
&& (_decorations
& OBClient::Decor_Iconify
)) {
205 if (!tit_m
&& (_decorations
& OBClient::Decor_Maximize
)) {
212 if (!tit_s
&& (_decorations
& OBClient::Decor_Sticky
)) {
219 if (!tit_c
&& (_decorations
& OBClient::Decor_Close
)) {
225 // if we get here then we don't want the letter, kill it
226 layout
.erase(i
--, 1);
229 layout
.append(1, 'L');
231 // the size of the label. this ASSUMES the layout has only buttons other
232 // that the ONE LABEL!!
233 // adds an extra sep so that there's a space on either side of the
234 // titlebar.. note: x = sep, below.
235 int lwidth
= width
- sep
* 2 -
236 (butsize
+ sep
) * (layout
.size() - 1);
237 // quick sanity check for really small windows. if this is needed, its
238 // obviously not going to be displayed right...
239 // XXX: maybe we should make this look better somehow? constraints?
240 if (lwidth
<= 0) lwidth
= 1;
241 _label
.setWidth(lwidth
);
244 for (std::string::size_type i
= 0, len
= layout
.size(); i
< len
; ++i
) {
248 _button_iconify
.move(x
, _button_iconify
.rect().y());
249 x
+= _button_iconify
.width();
253 _label
.move(x
, _label
.rect().y());
258 _button_max
.move(x
, _button_max
.rect().y());
259 x
+= _button_max
.width();
263 _button_stick
.move(x
, _button_stick
.rect().y());
264 x
+= _button_stick
.width();
268 _button_close
.move(x
, _button_close
.rect().y());
269 x
+= _button_close
.width();
272 assert(false); // the layout string is invalid!
278 if (_decorations
& OBClient::Decor_Handle
) {
279 _handle
.setGeometry(-bwidth
,
280 _innersize
.top
+ _client
->area().height() + cbwidth
,
281 width
, _style
->getHandleWidth());
282 _grip_left
.setGeometry(-bwidth
,
284 // XXX: get a Point class in otk and use that for
285 // the 'buttons size' since theyre all the same
288 _grip_right
.setGeometry(((_handle
.rect().right() + 1) -
291 // XXX: get a Point class in otk and use that for
292 // the 'buttons size' since theyre all the same
295 _innersize
.bottom
+= _handle
.height() + bwidth
;
299 // position/size all the windows
301 if (_client
->shaded())
302 resize(_innersize
.left
+ _innersize
.right
+ _client
->area().width(),
305 resize(_innersize
.left
+ _innersize
.right
+ _client
->area().width(),
306 _innersize
.top
+ _innersize
.bottom
+ _client
->area().height());
308 _plate
.setGeometry(_innersize
.left
- cbwidth
, _innersize
.top
- cbwidth
,
309 _client
->area().width(), _client
->area().height());
311 // map/unmap all the windows
312 if (_decorations
& OBClient::Decor_Titlebar
) {
315 _button_iconify
.show();
317 _button_iconify
.hide();
323 _button_stick
.show();
325 _button_stick
.hide();
327 _button_close
.show();
329 _button_close
.hide();
332 _titlebar
.hide(true);
335 if (_decorations
& OBClient::Decor_Handle
)
340 _size
.left
= _innersize
.left
+ bwidth
;
341 _size
.right
= _innersize
.right
+ bwidth
;
342 _size
.top
= _innersize
.top
+ bwidth
;
343 _size
.bottom
= _innersize
.bottom
+ bwidth
;
351 void OBFrame::adjustPosition()
359 void OBFrame::adjustShape()
362 int bwidth
= (_decorations
& OBClient::Decor_Border
) ?
363 _style
->getBorderWidth() : 0;
365 if (!_client
->shaped()) {
366 // clear the shape on the frame window
367 XShapeCombineMask(otk::OBDisplay::display
, _window
, ShapeBounding
,
372 // make the frame's shape match the clients
373 XShapeCombineShape(otk::OBDisplay::display
, _window
, ShapeBounding
,
376 _client
->window(), ShapeBounding
, ShapeSet
);
381 if (_decorations
& OBClient::Decor_Titlebar
) {
382 xrect
[0].x
= _titlebar
.rect().x();
383 xrect
[0].y
= _titlebar
.rect().y();
384 xrect
[0].width
= _titlebar
.width() + bwidth
* 2; // XXX: this is useless once the widget handles borders!
385 xrect
[0].height
= _titlebar
.height() + bwidth
* 2;
389 if (_decorations
& OBClient::Decor_Handle
) {
390 xrect
[1].x
= _handle
.rect().x();
391 xrect
[1].y
= _handle
.rect().y();
392 xrect
[1].width
= _handle
.width() + bwidth
* 2; // XXX: this is useless once the widget handles borders!
393 xrect
[1].height
= _handle
.height() + bwidth
* 2;
397 XShapeCombineRectangles(otk::OBDisplay::display
, window(),
398 ShapeBounding
, 0, 0, xrect
, num
,
399 ShapeUnion
, Unsorted
);
405 void OBFrame::grabClient()
407 // reparent the client to the frame
408 XReparentWindow(otk::OBDisplay::display
, _client
->window(),
409 _plate
.window(), 0, 0);
411 When reparenting the client window, it is usually not mapped yet, since
412 this occurs from a MapRequest. However, in the case where Openbox is
413 starting up, the window is already mapped, so we'll see unmap events for
414 it. There are 2 unmap events generated that we see, one with the 'event'
415 member set the root window, and one set to the client, but both get handled
416 and need to be ignored.
418 if (Openbox::instance
->state() == Openbox::State_Starting
)
419 _client
->ignore_unmaps
+= 2;
421 // select the event mask on the client's parent (to receive config req's)
422 XSelectInput(otk::OBDisplay::display
, _plate
.window(),
423 SubstructureRedirectMask
);
425 // map the client so it maps when the frame does
426 XMapWindow(otk::OBDisplay::display
, _client
->window());
433 void OBFrame::releaseClient()
435 // check if the app has already reparented its window to the root window
437 if (XCheckTypedWindowEvent(otk::OBDisplay::display
, _client
->window(),
438 ReparentNotify
, &ev
)) {
440 If the app reparented itself, then we unmanage the window. This causes
441 the window to be unmapped, so to be nice to it, we remap the window
442 here. We don't put the event back onto the stack because we put it there
445 XMapWindow(otk::OBDisplay::display
, _client
->window());
447 // according to the ICCCM - if the client doesn't reparent to
448 // root, then we have to do it for them
449 XReparentWindow(otk::OBDisplay::display
, _client
->window(),
450 _screen
->rootWindow(),
451 _client
->area().x(), _client
->area().y());
456 void OBFrame::clientGravity(int &x
, int &y
)
458 x
= _client
->area().x();
459 y
= _client
->area().y();
462 switch (_client
->gravity()) {
464 case NorthWestGravity
:
465 case SouthWestGravity
:
472 x
-= (_size
.left
+ _size
.right
) / 2;
475 case NorthEastGravity
:
476 case SouthEastGravity
:
478 x
-= _size
.left
+ _size
.right
;
488 switch (_client
->gravity()) {
490 case NorthWestGravity
:
491 case NorthEastGravity
:
498 y
-= (_size
.top
+ _size
.bottom
) / 2;
501 case SouthWestGravity
:
502 case SouthEastGravity
:
504 y
-= _size
.top
+ _size
.bottom
;
515 void OBFrame::frameGravity(int &x
, int &y
)
521 switch (_client
->gravity()) {
523 case NorthWestGravity
:
525 case SouthWestGravity
:
530 x
+= (_size
.left
+ _size
.right
) / 2;
532 case NorthEastGravity
:
534 case SouthEastGravity
:
535 x
+= _size
.left
+ _size
.right
;
544 switch (_client
->gravity()) {
546 case NorthWestGravity
:
548 case SouthWestGravity
:
553 y
+= (_size
.top
+ _size
.bottom
) / 2;
555 case NorthEastGravity
:
557 case SouthEastGravity
:
558 y
+= _size
.top
+ _size
.bottom
;
This page took 0.056831 seconds and 4 git commands to generate.