]> icculus.org git repositories - dana/openbox.git/blob - src/frame.cc
position the client inside the frame correctly.
[dana/openbox.git] / 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 #include "frame.hh"
8 #include "client.hh"
9 #include "otk/display.hh"
10
11 namespace ob {
12
13 OBFrame::OBFrame(const OBClient *client, const otk::Style *style)
14   : _client(client),
15     _screen(otk::OBDisplay::screenInfo(client->screen()))
16 {
17   assert(client);
18   assert(style);
19   
20   _style = 0;
21   loadStyle(style);
22
23   _window = createFrame();
24   assert(_window);
25
26   grabClient();
27 }
28
29
30 OBFrame::~OBFrame()
31 {
32   releaseClient(false);
33 }
34
35
36 void OBFrame::loadStyle(const otk::Style *style)
37 {
38   assert(style);
39
40   // if a style was previously set, then 'replace' is true, cause we're
41   // replacing a style
42   // NOTE: if this is false, then DO NOT DO SHIT WITH _window, it doesnt exist
43   bool replace = (_style);
44
45   if (replace) {
46     // XXX: do shit here whatever
47   }
48   
49   _style = style;
50
51   // XXX: load shit like this from the style!
52   _size.left = _size.top = _size.bottom = _size.right = 2;
53
54   if (replace) {
55     XSetWindowBorderWidth(otk::OBDisplay::display, _window,
56                           _style->getBorderWidth());
57
58     // XXX: make everything redraw
59   }
60 }
61
62
63 void OBFrame::resize()
64 {
65   XResizeWindow(otk::OBDisplay::display, _window,
66                 _size.left + _size.right + _client->area().width(),
67                 _size.top + _size.bottom + _client->area().height());
68   XMoveWindow(otk::OBDisplay::display, _client->window(),
69               _size.left, _size.top);
70   // XXX: more is gunna have to happen here
71 }
72
73
74 void OBFrame::shape()
75 {
76   // XXX: if shaped, shape the frame to the client..
77 }
78
79
80 void OBFrame::grabClient()
81 {
82   
83   XGrabServer(otk::OBDisplay::display);
84
85   // select the event mask on the frame
86   XSelectInput(otk::OBDisplay::display, _window, SubstructureRedirectMask);
87
88   // reparent the client to the frame
89   XSelectInput(otk::OBDisplay::display, _client->window(),
90                OBClient::event_mask & ~StructureNotifyMask);
91   XReparentWindow(otk::OBDisplay::display, _client->window(), _window, 0, 0);
92   XSelectInput(otk::OBDisplay::display, _client->window(),
93                OBClient::event_mask);
94
95   // raise the client above the frame
96   XRaiseWindow(otk::OBDisplay::display, _client->window());
97   // map the client so it maps when the frame does
98   XMapWindow(otk::OBDisplay::display, _client->window());
99   
100   XUngrabServer(otk::OBDisplay::display);
101
102   resize();
103   shape();
104 }
105
106
107 void OBFrame::releaseClient(bool remap)
108 {
109   // check if the app has already reparented its window to the root window
110   XEvent ev;
111   if (XCheckTypedWindowEvent(otk::OBDisplay::display, _client->window(),
112                              ReparentNotify, &ev)) {
113     remap = true; // XXX: why do we remap the window if they already
114                   // reparented to root?
115   } else {
116     // according to the ICCCM - if the client doesn't reparent to
117     // root, then we have to do it for them
118     XReparentWindow(otk::OBDisplay::display, _client->window(),
119                     _screen->getRootWindow(),
120                     _client->area().x(), _client->area().y());
121   }
122
123   // if we want to remap the window, do so now
124   if (remap)
125     XMapWindow(otk::OBDisplay::display, _client->window());
126 }
127
128
129 Window OBFrame::createFrame()
130 {
131   XSetWindowAttributes attrib_create;
132   unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
133                               CWOverrideRedirect | CWEventMask;
134
135   attrib_create.background_pixmap = None;
136   attrib_create.colormap = _screen->getColormap();
137   attrib_create.override_redirect = True;
138   attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | ButtonPress;
139   /*
140     We catch button presses because other wise they get passed down to the
141     root window, which will then cause root menus to show when you click the
142     window's frame.
143   */
144
145   return XCreateWindow(otk::OBDisplay::display, _screen->getRootWindow(),
146                        0, 0, 1, 1, _style->getBorderWidth(),
147                        _screen->getDepth(), InputOutput, _screen->getVisual(),
148                        create_mask, &attrib_create);
149 }
150
151 }