]> icculus.org git repositories - mikachu/openbox.git/blob - src/frame.cc
some more things to happen when changing styles on a frame
[mikachu/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     resize();
56     
57     XSetWindowBorderWidth(otk::OBDisplay::display, _window,
58                           _style->getBorderWidth());
59
60     XMoveWindow(otk::OBDisplay::display, _client->window(),
61                 _size.left, _size.top);
62
63     // XXX: make everything redraw
64   }
65 }
66
67
68 void OBFrame::resize()
69 {
70   XResizeWindow(otk::OBDisplay::display, _window,
71                 _size.left + _size.right + _client->area().width(),
72                 _size.top + _size.bottom + _client->area().height());
73   // XXX: more is gunna have to happen here
74 }
75
76
77 void OBFrame::shape()
78 {
79   // XXX: if shaped, shape the frame to the client..
80 }
81
82
83 void OBFrame::grabClient()
84 {
85   
86   XGrabServer(otk::OBDisplay::display);
87
88   // select the event mask on the frame
89   XSelectInput(otk::OBDisplay::display, _window, SubstructureRedirectMask);
90
91   // reparent the client to the frame
92   XSelectInput(otk::OBDisplay::display, _client->window(),
93                OBClient::event_mask & ~StructureNotifyMask);
94   XReparentWindow(otk::OBDisplay::display, _client->window(), _window,
95                   _size.left, _size.top);
96   XSelectInput(otk::OBDisplay::display, _client->window(),
97                OBClient::event_mask);
98
99   // raise the client above the frame
100   XRaiseWindow(otk::OBDisplay::display, _client->window());
101   // map the client so it maps when the frame does
102   XMapWindow(otk::OBDisplay::display, _client->window());
103   
104   XUngrabServer(otk::OBDisplay::display);
105
106   resize();
107   shape();
108 }
109
110
111 void OBFrame::releaseClient(bool remap)
112 {
113   // check if the app has already reparented its window to the root window
114   XEvent ev;
115   if (XCheckTypedWindowEvent(otk::OBDisplay::display, _client->window(),
116                              ReparentNotify, &ev)) {
117     remap = true; // XXX: why do we remap the window if they already
118                   // reparented to root?
119   } else {
120     // according to the ICCCM - if the client doesn't reparent to
121     // root, then we have to do it for them
122     XReparentWindow(otk::OBDisplay::display, _client->window(),
123                     _screen->getRootWindow(),
124                     _client->area().x(), _client->area().y());
125   }
126
127   // if we want to remap the window, do so now
128   if (remap)
129     XMapWindow(otk::OBDisplay::display, _client->window());
130 }
131
132
133 Window OBFrame::createFrame()
134 {
135   XSetWindowAttributes attrib_create;
136   unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
137                               CWOverrideRedirect | CWEventMask;
138
139   attrib_create.background_pixmap = None;
140   attrib_create.colormap = _screen->getColormap();
141   attrib_create.override_redirect = True;
142   attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | ButtonPress;
143   /*
144     We catch button presses because other wise they get passed down to the
145     root window, which will then cause root menus to show when you click the
146     window's frame.
147   */
148
149   return XCreateWindow(otk::OBDisplay::display, _screen->getRootWindow(),
150                        0, 0, 1, 1, _style->getBorderWidth(),
151                        _screen->getDepth(), InputOutput, _screen->getVisual(),
152                        create_mask, &attrib_create);
153 }
154
155 }