]> Dogcows Code - chaz/openbox/blob - src/frame.cc
support for the shape extension works!
[chaz/openbox] / src / frame.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 extern "C" {
8 #ifdef SHAPE
9 #include <X11/extensions/shape.h>
10 #endif // SHAPE
11 }
12
13 #include "frame.hh"
14 #include "client.hh"
15 #include "otk/display.hh"
16
17 namespace ob {
18
19 OBFrame::OBFrame(const OBClient *client, const otk::Style *style)
20 : _client(client),
21 _screen(otk::OBDisplay::screenInfo(client->screen()))
22 {
23 assert(client);
24 assert(style);
25
26 _style = 0;
27 loadStyle(style);
28
29 _window = createFrame();
30 assert(_window);
31
32 grabClient();
33 }
34
35
36 OBFrame::~OBFrame()
37 {
38 releaseClient(false);
39 }
40
41
42 void OBFrame::loadStyle(const otk::Style *style)
43 {
44 assert(style);
45
46 // if a style was previously set, then 'replace' is true, cause we're
47 // replacing a style
48 // NOTE: if this is false, then DO NOT DO SHIT WITH _window, it doesnt exist
49 bool replace = (_style);
50
51 if (replace) {
52 // XXX: do shit here whatever
53 }
54
55 _style = style;
56
57 // XXX: load shit like this from the style!
58 _size.left = _size.top = _size.bottom = _size.right = 2;
59
60 if (replace) {
61 resize();
62
63 XSetWindowBorderWidth(otk::OBDisplay::display, _window,
64 _style->getBorderWidth());
65
66 XMoveWindow(otk::OBDisplay::display, _client->window(),
67 _size.left, _size.top);
68
69 // XXX: make everything redraw
70 }
71 }
72
73
74 void OBFrame::resize()
75 {
76 XResizeWindow(otk::OBDisplay::display, _window,
77 _size.left + _size.right + _client->area().width(),
78 _size.top + _size.bottom + _client->area().height());
79 // XXX: more is gunna have to happen here
80 }
81
82
83 void OBFrame::shape()
84 {
85 #ifdef SHAPE
86 if (!_client->shaped()) {
87 // clear the shape on the frame window
88 XShapeCombineMask(otk::OBDisplay::display, _window, ShapeBounding,
89 _size.left - 2,//frame.margin.left - frame.border_w,
90 _size.top - 2,//frame.margin.top - frame.border_w,
91 None, ShapeSet);
92 } else {
93 // make the frame's shape match the clients
94 XShapeCombineShape(otk::OBDisplay::display, _window, ShapeBounding,
95 _size.left - 2,
96 _size.top - 2,
97 _client->window(), ShapeBounding, ShapeSet);
98
99 int num = 0;
100 XRectangle xrect[2];
101
102 /*
103 if (decorations & Decor_Titlebar) {
104 xrect[0].x = xrect[0].y = -frame.border_w;
105 xrect[0].width = frame.rect.width();
106 xrect[0].height = frame.title_h + (frame.border_w * 2);
107 ++num;
108 }
109
110 if (decorations & Decor_Handle) {
111 xrect[1].x = -frame.border_w;
112 xrect[1].y = frame.rect.height() - frame.margin.bottom +
113 frame.mwm_border_w - frame.border_w;
114 xrect[1].width = frame.rect.width();
115 xrect[1].height = frame.handle_h + (frame.border_w * 2);
116 ++num;
117 }*/
118
119 XShapeCombineRectangles(otk::OBDisplay::display, _window,
120 ShapeBounding, 0, 0, xrect, num,
121 ShapeUnion, Unsorted);
122 }
123 #endif // SHAPE
124 }
125
126
127 void OBFrame::grabClient()
128 {
129
130 XGrabServer(otk::OBDisplay::display);
131
132 // select the event mask on the frame
133 XSelectInput(otk::OBDisplay::display, _window, SubstructureRedirectMask);
134
135 // reparent the client to the frame
136 XSelectInput(otk::OBDisplay::display, _client->window(),
137 OBClient::event_mask & ~StructureNotifyMask);
138 XReparentWindow(otk::OBDisplay::display, _client->window(), _window,
139 _size.left, _size.top);
140 XSelectInput(otk::OBDisplay::display, _client->window(),
141 OBClient::event_mask);
142
143 // raise the client above the frame
144 XRaiseWindow(otk::OBDisplay::display, _client->window());
145 // map the client so it maps when the frame does
146 XMapWindow(otk::OBDisplay::display, _client->window());
147
148 XUngrabServer(otk::OBDisplay::display);
149
150 resize();
151 shape();
152 }
153
154
155 void OBFrame::releaseClient(bool remap)
156 {
157 // check if the app has already reparented its window to the root window
158 XEvent ev;
159 if (XCheckTypedWindowEvent(otk::OBDisplay::display, _client->window(),
160 ReparentNotify, &ev)) {
161 remap = true; // XXX: why do we remap the window if they already
162 // reparented to root?
163 } else {
164 // according to the ICCCM - if the client doesn't reparent to
165 // root, then we have to do it for them
166 XReparentWindow(otk::OBDisplay::display, _client->window(),
167 _screen->getRootWindow(),
168 _client->area().x(), _client->area().y());
169 }
170
171 // if we want to remap the window, do so now
172 if (remap)
173 XMapWindow(otk::OBDisplay::display, _client->window());
174 }
175
176
177 Window OBFrame::createFrame()
178 {
179 XSetWindowAttributes attrib_create;
180 unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
181 CWOverrideRedirect | CWEventMask;
182
183 attrib_create.background_pixmap = None;
184 attrib_create.colormap = _screen->getColormap();
185 attrib_create.override_redirect = True;
186 attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | ButtonPress;
187 /*
188 We catch button presses because other wise they get passed down to the
189 root window, which will then cause root menus to show when you click the
190 window's frame.
191 */
192
193 return XCreateWindow(otk::OBDisplay::display, _screen->getRootWindow(),
194 0, 0, 1, 1, _style->getBorderWidth(),
195 _screen->getDepth(), InputOutput, _screen->getVisual(),
196 create_mask, &attrib_create);
197 }
198
199 }
This page took 0.04404 seconds and 5 git commands to generate.