diff options
Diffstat (limited to 'util/fbcompose/BaseCompWindow.cc')
-rw-r--r-- | util/fbcompose/BaseCompWindow.cc | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/util/fbcompose/BaseCompWindow.cc b/util/fbcompose/BaseCompWindow.cc new file mode 100644 index 0000000..618a1fd --- /dev/null +++ b/util/fbcompose/BaseCompWindow.cc | |||
@@ -0,0 +1,258 @@ | |||
1 | /** BaseCompWindow.cc file for the fluxbox compositor. */ | ||
2 | |||
3 | // Copyright (c) 2011 Gediminas Liktaras (gliktaras at gmail dot com) | ||
4 | // | ||
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | // of this software and associated documentation files (the "Software"), to deal | ||
7 | // in the Software without restriction, including without limitation the rights | ||
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | // copies of the Software, and to permit persons to whom the Software is | ||
10 | // furnished to do so, subject to the following conditions: | ||
11 | // | ||
12 | // The above copyright notice and this permission notice shall be included in | ||
13 | // all copies or substantial portions of the Software. | ||
14 | // | ||
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
21 | // THE SOFTWARE. | ||
22 | |||
23 | |||
24 | #include "BaseCompWindow.hh" | ||
25 | |||
26 | #include "Atoms.hh" | ||
27 | #include "BaseScreen.hh" | ||
28 | #include "Logging.hh" | ||
29 | |||
30 | #include <X11/extensions/shape.h> | ||
31 | #include <X11/extensions/Xcomposite.h> | ||
32 | |||
33 | #include <algorithm> | ||
34 | #include <ostream> | ||
35 | |||
36 | using namespace FbCompositor; | ||
37 | |||
38 | |||
39 | //--- CONSTRUCTORS AND DESTRUCTORS --------------------------------------------- | ||
40 | |||
41 | // Constructor. | ||
42 | BaseCompWindow::BaseCompWindow(const BaseScreen &screen, Window window_xid, bool track_damage_deltas) : | ||
43 | FbTk::FbWindow(window_xid), | ||
44 | m_screen(screen) { | ||
45 | |||
46 | XWindowAttributes xwa; | ||
47 | XGetWindowAttributes(display(), window(), &xwa); | ||
48 | |||
49 | m_class = xwa.c_class; | ||
50 | m_is_mapped = (xwa.map_state != IsUnmapped); | ||
51 | m_is_remapped = true; | ||
52 | m_is_resized = true; | ||
53 | m_visual = xwa.visual; | ||
54 | |||
55 | m_clip_shape_changed = true; | ||
56 | m_clip_shape_rects = 0; | ||
57 | m_clip_shape_rect_count = 0; | ||
58 | |||
59 | m_is_ignored = false; | ||
60 | |||
61 | if (m_class == InputOutput) { | ||
62 | if (track_damage_deltas) { | ||
63 | m_damage = XDamageCreate(display(), window_xid, XDamageReportDeltaRectangles); | ||
64 | } else { | ||
65 | m_damage = XDamageCreate(display(), window_xid, XDamageReportNonEmpty); | ||
66 | } | ||
67 | } else { | ||
68 | m_damage = 0; | ||
69 | } | ||
70 | |||
71 | m_content_pixmap = None; | ||
72 | |||
73 | updateAlpha(); | ||
74 | updateWindowType(); | ||
75 | |||
76 | XShapeSelectInput(display(), window_xid, ShapeNotifyMask); | ||
77 | } | ||
78 | |||
79 | // Destructor. | ||
80 | BaseCompWindow::~BaseCompWindow() { | ||
81 | if (m_clip_shape_rects) { | ||
82 | XFree(m_clip_shape_rects); | ||
83 | } | ||
84 | if (m_content_pixmap) { | ||
85 | XFreePixmap(display(), m_content_pixmap); | ||
86 | } | ||
87 | // m_damage is apparently destroyed server-side. | ||
88 | } | ||
89 | |||
90 | |||
91 | //--- WINDOW MANIPULATION ------------------------------------------------------ | ||
92 | |||
93 | // Add damage to a window. | ||
94 | void BaseCompWindow::addDamage() { | ||
95 | m_is_damaged = true; | ||
96 | } | ||
97 | |||
98 | // Mark the window as mapped. | ||
99 | void BaseCompWindow::setMapped() { | ||
100 | m_is_mapped = true; | ||
101 | m_is_remapped = true; | ||
102 | } | ||
103 | |||
104 | // Mark the window as unmapped. | ||
105 | void BaseCompWindow::setUnmapped() { | ||
106 | m_is_mapped = false; | ||
107 | } | ||
108 | |||
109 | // Update the window's contents. | ||
110 | // Note: this is an example implementation of this function. You should not | ||
111 | // call this version at any time and override it in derived classes. | ||
112 | void BaseCompWindow::updateContents() { | ||
113 | updateContentPixmap(); | ||
114 | if (m_clip_shape_changed) { | ||
115 | updateShape(); | ||
116 | } | ||
117 | |||
118 | clearDamage(); | ||
119 | } | ||
120 | |||
121 | // Update window's geometry. | ||
122 | void BaseCompWindow::updateGeometry() { | ||
123 | unsigned int old_border_width = borderWidth(); | ||
124 | unsigned int old_height = height(); | ||
125 | unsigned int old_width = width(); | ||
126 | FbTk::FbWindow::updateGeometry(); | ||
127 | |||
128 | if ((borderWidth() != old_border_width) || (height() != old_height) || (width() != old_width)) { | ||
129 | setClipShapeChanged(); | ||
130 | m_is_resized = true; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // Update the window's clip shape. | ||
135 | void BaseCompWindow::updateShape() { | ||
136 | int rect_order; | ||
137 | |||
138 | if (m_clip_shape_rects) { | ||
139 | XFree(m_clip_shape_rects); | ||
140 | m_clip_shape_rects = NULL; | ||
141 | } | ||
142 | m_clip_shape_rects = XShapeGetRectangles(display(), window(), ShapeClip, &m_clip_shape_rect_count, &rect_order); | ||
143 | |||
144 | if (!m_clip_shape_rects) { | ||
145 | m_clip_shape_rect_count = 0; | ||
146 | } else { | ||
147 | // We have to adjust the size here to account for borders. | ||
148 | for (int i = 0; i < m_clip_shape_rect_count; i++) { | ||
149 | m_clip_shape_rects[i].height = std::min(m_clip_shape_rects[i].height + 2 * borderWidth(), realHeight()); | ||
150 | m_clip_shape_rects[i].width = std::min(m_clip_shape_rects[i].width + 2 * borderWidth(), realWidth()); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | // Update window's property. | ||
156 | void BaseCompWindow::updateProperty(Atom property, int /*state*/) { | ||
157 | if (property == Atoms::opacityAtom()) { | ||
158 | updateAlpha(); | ||
159 | } else if (property == Atoms::windowTypeAtom()) { | ||
160 | updateWindowType(); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | // Set the clip shape as changed. | ||
166 | void BaseCompWindow::setClipShapeChanged() { | ||
167 | m_clip_shape_changed = true; | ||
168 | } | ||
169 | |||
170 | |||
171 | //--- PROTECTED WINDOW MANIPULATION -------------------------------------------- | ||
172 | |||
173 | // Removes all damage from the window. | ||
174 | void BaseCompWindow::clearDamage() { | ||
175 | m_clip_shape_changed = false; | ||
176 | m_is_damaged = false; | ||
177 | m_is_remapped = false; | ||
178 | m_is_resized = false; | ||
179 | } | ||
180 | |||
181 | // Updates the window's content pixmap. | ||
182 | void BaseCompWindow::updateContentPixmap() { | ||
183 | // We must reset the damage here, otherwise we may miss damage events. | ||
184 | // TODO: BadDamage might be thrown here, probably safe to ignore for now. | ||
185 | XDamageSubtract(display(), m_damage, None, None); | ||
186 | |||
187 | if (m_is_resized || m_is_remapped) { | ||
188 | XGrabServer(display()); | ||
189 | |||
190 | XWindowAttributes xwa; | ||
191 | if (XGetWindowAttributes(display(), window(), &xwa)) { | ||
192 | if (xwa.map_state == IsViewable) { | ||
193 | Pixmap new_pixmap = XCompositeNameWindowPixmap(display(), window()); | ||
194 | if (new_pixmap) { | ||
195 | if (m_content_pixmap) { | ||
196 | XFreePixmap(display(), m_content_pixmap); | ||
197 | } | ||
198 | m_content_pixmap = new_pixmap; | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | XUngrabServer(display()); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | |||
207 | //--- PROPERTY UPDATE FUNCTIONS ---------------------------------------- | ||
208 | |||
209 | // Updates window's alpha. | ||
210 | void BaseCompWindow::updateAlpha() { | ||
211 | m_alpha = singlePropertyValue<long>(Atoms::opacityAtom(), 0xff) & 0xff; | ||
212 | } | ||
213 | |||
214 | // Updates the type of the window. | ||
215 | void BaseCompWindow::updateWindowType() { | ||
216 | static std::vector< std::pair<Atom, WindowType> > type_list = Atoms::windowTypeAtomList(); | ||
217 | Atom raw_type = singlePropertyValue<Atom>(Atoms::windowTypeAtom(), None); | ||
218 | |||
219 | m_type = WinType_Normal; | ||
220 | for (size_t i = 0; i < type_list.size(); i++) { | ||
221 | if (raw_type == type_list[i].first) { | ||
222 | m_type = type_list[i].second; | ||
223 | break; | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | |||
228 | |||
229 | //--- CONVENIENCE FUNCTIONS ---------------------------------------------------- | ||
230 | |||
231 | // Reads and returns raw property contents. | ||
232 | bool BaseCompWindow::rawPropertyData(Atom property_atom, Atom property_type, | ||
233 | unsigned long *item_count_return, unsigned char **data_return) { | ||
234 | Atom actual_type; | ||
235 | int actual_format; | ||
236 | unsigned long bytes_left; | ||
237 | |||
238 | if (property(property_atom, 0, 0x7fffffff, False, property_type, | ||
239 | &actual_type, &actual_format, item_count_return, &bytes_left, data_return)) { | ||
240 | if (*item_count_return > 0) { | ||
241 | return true; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return false; | ||
246 | } | ||
247 | |||
248 | |||
249 | //--- OPERATORS ---------------------------------------------------------------- | ||
250 | |||
251 | // << output stream operator for the window class. | ||
252 | std::ostream &FbCompositor::operator<<(std::ostream& out, const BaseCompWindow& w) { | ||
253 | out << "Window " << std::hex << w.window() << ": Geometry[" << std::dec << w.x() | ||
254 | << "," << w.y() << "," << w.width() << "," << w.height() << " " << w.borderWidth() | ||
255 | << "] Depth=" << w.depth() << " Type=" << w.type() << " Map=" << w.isMapped() | ||
256 | << " Dmg=" << w.isDamaged() << " Ignore=" << w.isIgnored(); | ||
257 | return out; | ||
258 | } | ||