LOGIN / SIGN UP
2 Author: Claes Nästén
Date: Mon Mar 08 21:52:04 +0100 2010
Subject: Same visual/depth on container window for 32 bit depth clients.
    To allow composited clients the container window needs to have the
    same depth/visual/colormap. Patch inspired by Openbox patch at
    http://bugzilla.icculus.org/show_bug.cgi?id=2850

src/Frame.cc
 
61 @@ -61,7 +61,7 @@
61 //! @brief Frame constructor
62 Frame::Frame(Client *client, AutoProperty *ap)
63 : PDecor(WindowManager::instance()->getScreen()->getDpy(), WindowManager::instance()->getTheme(),
64 Frame::getClientDecorName(client)),
65 Frame::getClientDecorName(client), client->getWindow()),
66 _id(0), _client(0), _class_hint(0),
67 _non_fullscreen_decor_state(0), _non_fullscreen_layer(LAYER_NORMAL)
68 {
...  
1120 @@ -1120,6 +1120,7 @@
1120 }
1121
1122 setShaded(STATE_UNSET); // make sure the frame isn't shaded
1123 setStateFullscreen(STATE_UNSET);
1124
1125 // Initialize variables
1126 int start_x, new_x;
...  
1376 @@ -1375,6 +1376,7 @@
1376 }
1377
1378 setShaded(STATE_UNSET);
1379 setStateFullscreen(STATE_UNSET);
1380
1381 // make sure the two states are in sync if toggling
1382 if ((horz == vert) && (sa == STATE_TOGGLE)) {
...  
1465 @@ -1463,7 +1465,7 @@
1465 }
1466
1467 fixGeometry(); // harbour already considered
1466 downSize(true, true); // keep x and keep y ( make conform to inc size )
1469 downSize(_gm, true, true); // keep x and keep y ( make conform to inc size )
1470
1471 moveResize(_gm.x, _gm.y, _gm.width, _gm.height);
1472
...  
1754 @@ -1752,7 +1754,7 @@
1754 break;
1755 }
1756
1755 downSize((direction != DIRECTION_LEFT), (direction != DIRECTION_UP));
1758 downSize(_gm, (direction != DIRECTION_LEFT), (direction != DIRECTION_UP));
1759
1760 moveResize(_gm.x, _gm.y, _gm.width, _gm.height);
1761 }
...  
1929 @@ -1927,9 +1929,11 @@
1929 }
1930 }
1931
1930 //! @brief Makes Frame conform to Clients width and height inc
1933 /**
1934 * Makes gm conform to _clients width and height inc.
1935 */
1936 void
1935 Frame::downSize(bool keep_x, bool keep_y)
1938 Frame::downSize(Geometry &gm, bool keep_x, bool keep_y)
1939 {
1940 XSizeHints *size_hint = _client->getXSizeHints(); // convenience
1941
...  
1944 @@ -1940,9 +1944,9 @@
1944 ? size_hint->base_width
1945 : (size_hint->flags&PMinSize) ? size_hint->min_width : 0;
1946
1943 _gm.width -= (getChildWidth() - b_x) % size_hint->width_inc;
1948 gm.width -= (getChildWidth() - b_x) % size_hint->width_inc;
1949 if (! keep_x) {
1946 _gm.x = o_r - _gm.width;
1951 gm.x = o_r - gm.width;
1952 }
1953 }
1954
...  
1957 @@ -1953,9 +1957,9 @@
1957 ? size_hint->base_height
1958 : (size_hint->flags&PMinSize) ? size_hint->min_height : 0;
1959
1956 _gm.height -= (getChildHeight() - b_y) % size_hint->height_inc;
1961 gm.height -= (getChildHeight() - b_y) % size_hint->height_inc;
1962 if (! keep_y) {
1959 _gm.y = o_b - _gm.height;
1964 gm.y = o_b - gm.height;
1965 }
1966 }
1967 }
...  
2021 @@ -2017,125 +2021,72 @@
2021 void
2022 Frame::handleConfigureRequestGeometry(XConfigureRequestEvent *ev, Client *client)
2023 {
2020 // Look for fullscreen requests
2021 const long all_geometry = CWX|CWY|CWWidth|CWHeight;
2022 bool is_fullscreen = false;
2023 if (Config::instance()->isFullscreenDetect()
2024 && ! client->isCfgDeny(CFG_DENY_SIZE)
2025 && ! client->isCfgDeny(CFG_DENY_POSITION)
2026 && ((ev->value_mask&all_geometry) == static_cast<unsigned>(all_geometry))) {
2027
2028 Geometry gm_request(ev->x, ev->y, ev->width, ev->height);
2029 if (gm_request == _scr->getScreenGeometry()
2030 || gm_request == _scr->getHeadGeometry(_scr->getNearestHead(ev->x, ev->y))) {
2031
2032 is_fullscreen = true;
2033 setStateFullscreen(STATE_SET);
2034 }
2039 if (isRequestGeometryFullscreen(ev, client)) {
2040 client->configureRequestSend();
2041 return;
2042 }
2043
2040 if (! is_fullscreen) {
2041 bool change_geometry = false;
2042
2043 if (! client->isCfgDeny(CFG_DENY_SIZE)
2044 && (ev->value_mask & (CWWidth|CWHeight)) ) {
2045
2046 resizeChild(ev->width, ev->height);
2047 _client->setShaped(setShape());
2052 bool change_geometry = false;
2053 if (! client->isCfgDeny(CFG_DENY_SIZE)
2054 && (ev->value_mask & (CWWidth|CWHeight))) {
2055 resizeChild(ev->width, ev->height);
2056 _client->setShaped(setShape());
2057 change_geometry = true;
2058 }
2059
2056 change_geometry = true;
2057 }
2062 if (! client->isCfgDeny(CFG_DENY_POSITION)
2063 && (ev->value_mask & (CWX|CWY)) ) {
2064 calcGravityPosition(_client->getXSizeHints()->win_gravity,
2065 ev->x, ev->y, _gm.x, _gm.y);
2066 move(_gm.x, _gm.y);
2067 change_geometry = true;
2068 }
2069
2066 if (! client->isCfgDeny(CFG_DENY_POSITION)
2067 && (ev->value_mask & (CWX|CWY)) ) {
2072 // Remove fullscreen state if client changes it size
2073 if (change_geometry && Config::instance()->isFullscreenDetect()) {
2074 setStateFullscreen(STATE_UNSET);
2075 }
2076 }
2077
2074 calcGravityPosition(_client->getXSizeHints()->win_gravity,
2075 ev->x, ev->y, _gm.x, _gm.y);
2076 move(_gm.x, _gm.y);
2081 /**
2082 * Check if requested size if "fullscreen"
2083 */
2084 bool
2085 Frame::isRequestGeometryFullscreen(XConfigureRequestEvent *ev, Client *client)
2086 {
2087 bool is_fullscreen = false;
2088 if (! client->isCfgDeny(CFG_DENY_SIZE)
2089 && ! client->isCfgDeny(CFG_DENY_POSITION)) {
2090 int nearest_head = _scr->getNearestHead(ev->x, ev->y);
2091 Geometry gm_request(ev->x, ev->y, ev->width, ev->height);
2092 Geometry gm_screen(_scr->getScreenGeometry());
2093 Geometry gm_head(_scr->getHeadGeometry(nearest_head));
2094
2091 change_geometry = true;
2096 if (gm_request == gm_screen || gm_request == gm_head) {
2097 is_fullscreen = true;
2098 } else {
2099 downSize(gm_screen, true, true);
2100 downSize(gm_head, true, true);
2101 if (gm_request == gm_screen || gm_request == gm_head) {
2102 is_fullscreen = true;
2103 }
2104 }
2105
2102 // Remove fullscreen state if client changes it size
2103 if (change_geometry && Config::instance()->isFullscreenDetect()) {
2104 setStateFullscreen(STATE_UNSET);
2109 if (is_fullscreen && Config::instance()->isFullscreenDetect()) {
2110 setStateFullscreen(STATE_SET);
2111 }
2112 }
2113 return is_fullscreen;
2114 }
2115
2112 //! @brief
2117 /**
2118 * Handle client message.
2119 */
2120 void
2121 Frame::handleClientMessage(XClientMessageEvent *ev, Client *client)
2122 {
2119 StateAction sa;
2120
2125 if (ev->message_type == Atoms::getAtom(STATE)) {
2122 if (ev->data.l[0]== NET_WM_STATE_REMOVE) {
2123 sa = STATE_UNSET;
2124 } else if (ev->data.l[0]== NET_WM_STATE_ADD) {
2125 sa = STATE_SET;
2126 } else if (ev->data.l[0]== NET_WM_STATE_TOGGLE) {
2127 sa = STATE_TOGGLE;
2128 } else {
2129 #ifdef DEBUG
2130 cerr << __FILE__ << "@" << __LINE__ << ": "
2131 << "None of StateAdd, StateRemove or StateToggle." << endl;
2132 #endif // DEBUG
2133 return;
2134 }
2135
2136 #define IS_STATE(S) ((ev->data.l[1] == long(Atoms::getAtom(S))) || (ev->data.l[2] == long(Atoms::getAtom(S))))
2137
2138 // actions that only is going to be applied on the active client
2139 if (client == _client) {
2140 // there is no modal support in pekwm yet
2141 // if (IS_STATE(STATE_MODAL)) {
2142 // is_modal=true;
2143 // }
2144 if (IS_STATE(STATE_STICKY)) {
2145 setStateSticky(sa);
2146 }
2147 if (IS_STATE(STATE_MAXIMIZED_HORZ)
2148 && ! client->isCfgDeny(CFG_DENY_STATE_MAXIMIZED_HORZ)) {
2149 setStateMaximized(sa, true, false, false);
2150 }
2151 if (IS_STATE(STATE_MAXIMIZED_VERT)
2152 && ! client->isCfgDeny(CFG_DENY_STATE_MAXIMIZED_VERT)) {
2153 setStateMaximized(sa, false, true, false);
2154 }
2155 if (IS_STATE(STATE_SHADED)) {
2156 setShaded(sa);
2157 }
2158 if (IS_STATE(STATE_HIDDEN)
2159 && ! client->isCfgDeny(CFG_DENY_STATE_HIDDEN)) {
2160 setStateIconified(sa);
2161 }
2162 if (IS_STATE(STATE_FULLSCREEN)
2163 && ! client->isCfgDeny(CFG_DENY_STATE_FULLSCREEN)) {
2164 setStateFullscreen(sa);
2165 }
2166 if (IS_STATE(STATE_ABOVE)
2167 && ! client->isCfgDeny(CFG_DENY_STATE_ABOVE)) {
2168 setStateAlwaysOnTop(sa);
2169 }
2170 if (IS_STATE(STATE_BELOW)
2171 && ! client->isCfgDeny(CFG_DENY_STATE_BELOW)) {
2172 setStateAlwaysBelow(sa);
2173 }
2174 }
2175
2176 if (IS_STATE(STATE_SKIP_TASKBAR)) {
2177 client->setStateSkip(sa, SKIP_TASKBAR);
2178 }
2179 if (IS_STATE(STATE_SKIP_PAGER)) {
2180 client->setStateSkip(sa, SKIP_PAGER);
2181 }
2182 if (IS_STATE(STATE_DEMANDS_ATTENTION)) {
2183 client->setStateDemandsAttention(sa, true);
2184 }
2185
2186 client->updateEwmhStates();
2187
2192 handleClientStateMessage(ev, client);
2193 } else if (ev->message_type == Atoms::getAtom(NET_ACTIVE_WINDOW)) {
2194 if (! client->isCfgDeny(CFG_DENY_ACTIVE_WINDOW)) {
2195 // Active child if it's not the active child
...  
2118 @@ -2167,9 +2118,107 @@
2118 iconify();
2119 }
2120 }
2170 #undef IS_STATE
2122 }
2123
2124 /**
2125 * Handle _NET_WM_STATE atom.
2126 */
2127 void
2128 Frame::handleClientStateMessage(XClientMessageEvent *ev, Client *client)
2129 {
2130 StateAction sa = getStateActionFromMessage(ev);
2131 handleStateAtom(sa, ev->data.l[1], client);
2132 if (ev->data.l[2] != 0) {
2133 handleStateAtom(sa, ev->data.l[2], client);
2134 }
2135 client->updateEwmhStates();
2136 }
2137
2138 /**
2139 * Get StateAction from NET_WM atom.
2140 */
2141 StateAction
2142 Frame::getStateActionFromMessage(XClientMessageEvent *ev)
2143 {
2144 StateAction sa = STATE_SET;
2145 if (ev->data.l[0]== NET_WM_STATE_REMOVE) {
2146 sa = STATE_UNSET;
2147 } else if (ev->data.l[0]== NET_WM_STATE_ADD) {
2148 sa = STATE_SET;
2149 } else if (ev->data.l[0]== NET_WM_STATE_TOGGLE) {
2150 sa = STATE_TOGGLE;
2151 }
2152 return sa;
2153 }
2154
2155 /**
2156 * Handle state atom for client.
2157 */
2158 void
2159 Frame::handleStateAtom(StateAction sa, long atom, Client *client)
2160 {
2161 if (client == _client) {
2162 handleCurrentClientStateAtom(sa, atom, client);
2163 }
2164
2165 switch (atom) {
2166 case STATE_SKIP_TASKBAR:
2167 client->setStateSkip(sa, SKIP_TASKBAR);
2168 break;
2169 case STATE_SKIP_PAGER:
2170 client->setStateSkip(sa, SKIP_PAGER);
2171 break;
2172 case STATE_DEMANDS_ATTENTION:
2173 client->setStateDemandsAttention(sa, true);
2174 break;
2175 }
2176 }
2177
2178 /**
2179 * Handle state atom for actions that apply only on active client.
2180 */
2181 void
2182 Frame::handleCurrentClientStateAtom(StateAction sa, long atom, Client *client)
2183 {
2184 switch (atom) {
2185 case STATE_STICKY:
2186 setStateSticky(sa);
2187 break;
2188 case STATE_MAXIMIZED_HORZ:
2189 if (! client->isCfgDeny(CFG_DENY_STATE_MAXIMIZED_HORZ)) {
2190 setStateMaximized(sa, true, false, false);
2191 }
2192 break;
2193 case STATE_MAXIMIZED_VERT:
2194 if (! client->isCfgDeny(CFG_DENY_STATE_MAXIMIZED_VERT)) {
2195 setStateMaximized(sa, false, true, false);
2196 }
2197 break;
2198 case STATE_SHADED:
2199 setShaded(sa);
2200 break;
2201 case STATE_HIDDEN:
2202 if (! client->isCfgDeny(CFG_DENY_STATE_HIDDEN)) {
2203 setStateIconified(sa);
2204 }
2205 break;
2206 case STATE_FULLSCREEN:
2207 if (! client->isCfgDeny(CFG_DENY_STATE_FULLSCREEN)) {
2208 setStateFullscreen(sa);
2209 }
2210 break;
2211 case STATE_ABOVE:
2212 if (! client->isCfgDeny(CFG_DENY_STATE_ABOVE)) {
2213 setStateAlwaysOnTop(sa);
2214 }
2215 break;
2216 case STATE_BELOW:
2217 if (! client->isCfgDeny(CFG_DENY_STATE_BELOW)) {
2218 setStateAlwaysBelow(sa);
2219 }
2220 break;
2221 }
2222 }
2223
2224 //! @brief
2225 void
...  

src/PDecor.cc
 
1 @@ -1,6 +1,6 @@
1 //
2 // PDecor.cc for pekwm
3 // Copyright © 2004-2009 Claes Nästén <me{@}pekdon{.}net>
4 // Copyright © 2004-2009 Claes Nästén <me@pekdon.net>
5 //
6 // This program is licensed under the GNU GPL.
7 // See the LICENSE file for more information.
...  
184 @@ -184,7 +184,8 @@
184 //! @param dpy Display
185 //! @param theme Theme
186 //! @param decor_name String, if not DEFAULT_DECOR_NAME sets _decor_name_override
187 PDecor::PDecor(Display *dpy, Theme *theme, const std::string decor_name)
188 PDecor::PDecor(Display *dpy, Theme *theme,
189 const std::string decor_name, const Window child_window)
190 : PWinObj(dpy),
191 _theme(theme),_decor_name(decor_name),
192 _child(0), _button(0), _button_press_win(None),
...  
214 @@ -213,43 +214,115 @@
214 _data = _theme->getPDecorData(DEFAULT_DECOR_NAME);
215 }
216
216 XSetWindowAttributes attr;
217 attr.override_redirect = True;
218 attr.event_mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
219 EnterWindowMask|SubstructureRedirectMask|SubstructureNotifyMask;
220 _window =
221 XCreateWindow(_dpy, PScreen::instance()->getRoot(),
222 _gm.x, _gm.y, _gm.width, _gm.height, 0,
223 CopyFromParent, InputOutput, CopyFromParent,
224 CWOverrideRedirect|CWEventMask, &attr);
226 CreateWindowParams window_params;
227 getParentWindowAttributes(window_params, child_window);
228 createParentWindow(window_params);
229 if (window_params.mask & CWColormap) {
230 window_params.depth = PScreen::instance()->getDepth();
231 window_params.visual = PScreen::instance()->getVisual()->getXVisual();
232 window_params.attr.colormap = PScreen::instance()->getColormap();
233 }
234 createTitle(window_params);
235 createBorder(window_params);
236
236 attr.event_mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask;
237 attr.override_redirect = True;
238 _title_wo.setWindow(XCreateWindow(_dpy, _window,
239 borderLeft(), borderTop(), 1, 1, 0, // don't know our size yet
240 CopyFromParent, InputOutput, CopyFromParent,
241 CWOverrideRedirect|CWEventMask, &attr));
243 // sets buttons etc up
244 loadDecor();
245
246 // map title and border windows
247 XMapSubwindows(_dpy, _window);
248
249 _pdecor_list.push_back(this);
250 }
251
252 /**
253 * Create window attributes
254 */
255 void
256 PDecor::getParentWindowAttributes(CreateWindowParams &params,
257 Window child_window)
258 {
259 params.mask = CWOverrideRedirect|CWEventMask|CWBorderPixel|CWBackPixel;
260 params.depth = CopyFromParent;
261 params.visual = CopyFromParent;
262 params.attr.override_redirect = True;
263 params.attr.border_pixel = 0;
264 params.attr.background_pixel = 0;
265
266 if (child_window != None) {
267 getChildWindowAttributes(params, child_window);
268 }
269 }
270
271 /**
272 * Get window attributes from child window
273 */
274 void
275 PDecor::getChildWindowAttributes(CreateWindowParams &params,
276 Window child_window)
277 {
278 XWindowAttributes attr;
279 Status status = XGetWindowAttributes(_dpy, child_window, &attr);
280 if (status != BadDrawable && status != BadWindow && attr.depth == 32) {
281 params.mask |= CWColormap;
282 params.depth = attr.depth;
283 params.visual = attr.visual;
284 params.attr.colormap = XCreateColormap(_dpy,
285 PScreen::instance()->getRoot(),
286 params.visual, AllocNone);
287 }
288 }
289
290 /**
291 * Create container window.
292 */
293 void
294 PDecor::createParentWindow(CreateWindowParams &params)
295 {
296 params.attr.event_mask = ButtonPressMask|ButtonReleaseMask|
297 ButtonMotionMask|EnterWindowMask|SubstructureRedirectMask|
298 SubstructureNotifyMask;
299 _window = XCreateWindow(_dpy, PScreen::instance()->getRoot(),
300 _gm.x, _gm.y, _gm.width, _gm.height, 0,
301 params.depth, InputOutput, params.visual,
302 params.mask, &params.attr);
303 }
304
305 /**
306 * Create title window.
307 */
308 void
309 PDecor::createTitle(CreateWindowParams &params)
310 {
311 params.attr.event_mask = ButtonPressMask|ButtonReleaseMask|
312 ButtonMotionMask|EnterWindowMask;
313 Window title = XCreateWindow(_dpy, _window,
314 borderLeft(), borderTop(), 1, 1, 0,
315 params.depth, InputOutput, params.visual,
316 params.mask, &params.attr);
317 _title_wo.setWindow(title);
318 addChildWindow(_title_wo.getWindow());
319 }
320
320 // create border windows
322 /**
323 * Create border windows
324 */
325 void
326 PDecor::createBorder(CreateWindowParams &params)
327 {
328 params.attr.event_mask = ButtonPressMask|ButtonReleaseMask|
329 ButtonMotionMask|EnterWindowMask;
330
331 ScreenResources *sr = ScreenResources::instance();
332 for (uint i = 0; i < BORDER_NO_POS; ++i) {
332 attr.cursor = ScreenResources::instance()->getCursor(ScreenResources::CursorType(i));
334 params.attr.cursor = sr->getCursor(ScreenResources::CursorType(i));
335
336 _border_win[i] =
337 XCreateWindow(_dpy, _window, -1, -1, 1, 1, 0,
337 CopyFromParent, InputOutput, CopyFromParent,
338 CWOverrideRedirect|CWEventMask|CWCursor, &attr);
340 params.depth, InputOutput, params.visual,
341 params.mask|CWCursor, &params.attr);
342 _border_pos_map[BorderPosition(i)] = None;
343 addChildWindow(_border_win[i]);
344 }
344
345 // sets buttons etc up
346 loadDecor();
347
348 // map title and border windows
349 XMapSubwindows(_dpy, _window);
350
351 _pdecor_list.push_back(this);
353 }
354
355 //! @brief PDecor destructor
...