aboutsummaryrefslogtreecommitdiff
path: root/src/WinClient.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/WinClient.cc')
-rw-r--r--src/WinClient.cc318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/WinClient.cc b/src/WinClient.cc
new file mode 100644
index 0000000..467b2b5
--- /dev/null
+++ b/src/WinClient.cc
@@ -0,0 +1,318 @@
1// WinClient.cc for Fluxbox - an X11 Window manager
2// Copyright (c) 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id: WinClient.cc,v 1.2 2003/04/14 12:08:21 fluxgen Exp $
23
24#include "WinClient.hh"
25
26#include "Window.hh"
27#include "fluxbox.hh"
28#include "Screen.hh"
29#include "i18n.hh"
30
31#include <iostream>
32#include <algorithm>
33#include <iterator>
34using namespace std;
35
36WinClient::WinClient(Window win, FluxboxWindow &fbwin):FbTk::FbWindow(win),
37 transient_for(0),
38 window_group(0),
39 x(0), y(0), old_bw(0),
40 min_width(1), min_height(1),
41 max_width(1), max_height(1),
42 width_inc(1), height_inc(1),
43 min_aspect_x(1), min_aspect_y(1),
44 max_aspect_x(1), max_aspect_y(1),
45 base_width(1), base_height(1),
46 win_gravity(0),
47 initial_state(0),
48 normal_hint_flags(0),
49 wm_hint_flags(0),
50 mwm_hint(0),
51 blackbox_hint(0),
52 m_win(&fbwin),
53 m_title(""), m_icon_title(""),
54 m_diesig(*this) { }
55
56WinClient::~WinClient() {
57#ifdef DEBUG
58 cerr<<__FILE__<<"(~"<<__FUNCTION__<<")[this="<<this<<"]"<<endl;
59#endif // DEBUG
60
61 m_diesig.notify();
62
63 Fluxbox *fluxbox = Fluxbox::instance();
64
65 if (transient_for != 0) {
66 if (transientFor() == m_win) {
67 transient_for = 0;
68 }
69
70 fluxbox->setFocusedWindow(transient_for);
71
72 if (transient_for != 0) {
73 FluxboxWindow::ClientList::iterator client_it =
74 transientFor()->clientList().begin();
75 FluxboxWindow::ClientList::iterator client_it_end =
76 transientFor()->clientList().end();
77 for (; client_it != client_it_end; ++client_it) {
78 (*client_it)->transientList().remove(m_win);
79 }
80
81 transient_for->setInputFocus();
82 transient_for = 0;
83 }
84 }
85
86 while (!transients.empty()) {
87 FluxboxWindow::ClientList::iterator it =
88 transients.back()->clientList().begin();
89 FluxboxWindow::ClientList::iterator it_end =
90 transients.back()->clientList().end();
91 for (; it != it_end; ++it) {
92 if ((*it)->transientFor() == m_win)
93 (*it)->transient_for = 0;
94 }
95
96 transients.pop_back();
97 }
98
99 if (window_group != 0) {
100 fluxbox->removeGroupSearch(window_group);
101 window_group = 0;
102 }
103
104 if (mwm_hint != 0)
105 XFree(mwm_hint);
106
107 if (blackbox_hint != 0)
108 XFree(blackbox_hint);
109
110 if (window())
111 fluxbox->removeWindowSearch(window());
112
113 if (m_win != 0)
114 m_win->removeClient(*this);
115 m_win = 0;
116
117}
118
119void WinClient::updateRect(int x, int y,
120 unsigned int width, unsigned int height) {
121 Display *disp = FbTk::App::instance()->display();
122 XEvent event;
123 event.type = ConfigureNotify;
124
125 event.xconfigure.display = disp;
126 event.xconfigure.event = window();
127 event.xconfigure.window = window();
128 event.xconfigure.x = x;
129 event.xconfigure.y = y;
130 event.xconfigure.width = width;
131 event.xconfigure.height = height;
132 //!! TODO
133 event.xconfigure.border_width = 1;//client.old_bw;
134 //!! TODO
135 event.xconfigure.above = None; //m_frame.window().window();
136 event.xconfigure.override_redirect = false;
137
138 XSendEvent(disp, window(), False, StructureNotifyMask, &event);
139
140}
141
142void WinClient::sendFocus() {
143 Display *disp = FbTk::App::instance()->display();
144 // setup focus msg
145 XEvent ce;
146 ce.xclient.type = ClientMessage;
147 ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom();
148 ce.xclient.display = disp;
149 ce.xclient.window = window();
150 ce.xclient.format = 32;
151 ce.xclient.data.l[0] = FbAtoms::instance()->getWMTakeFocusAtom();
152 ce.xclient.data.l[1] = Fluxbox::instance()->getLastTime();
153 ce.xclient.data.l[2] = 0l;
154 ce.xclient.data.l[3] = 0l;
155 ce.xclient.data.l[4] = 0l;
156 // send focus msg
157 XSendEvent(disp, window(), false, NoEventMask, &ce);
158}
159
160void WinClient::sendClose() {
161 Display *disp = FbTk::App::instance()->display();
162 // fill in XClientMessage structure for delete message
163 XEvent ce;
164 ce.xclient.type = ClientMessage;
165 ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom();
166 ce.xclient.display = disp;
167 ce.xclient.window = window();
168 ce.xclient.format = 32;
169 ce.xclient.data.l[0] = FbAtoms::instance()->getWMDeleteAtom();
170 ce.xclient.data.l[1] = CurrentTime;
171 ce.xclient.data.l[2] = 0l;
172 ce.xclient.data.l[3] = 0l;
173 ce.xclient.data.l[4] = 0l;
174 // send event delete message to client window
175 XSendEvent(disp, window(), false, NoEventMask, &ce);
176}
177
178void WinClient::reparent(Window win, int x, int y) {
179 XReparentWindow(FbTk::App::instance()->display(), window(), win, x, y);
180}
181
182bool WinClient::getAttrib(XWindowAttributes &attr) const {
183 return XGetWindowAttributes(FbTk::App::instance()->display(), window(), &attr);
184}
185
186bool WinClient::getWMName(XTextProperty &textprop) const {
187 return XGetWMName(FbTk::App::instance()->display(), window(), &textprop);
188}
189
190bool WinClient::getWMIconName(XTextProperty &textprop) const {
191 return XGetWMName(FbTk::App::instance()->display(), window(), &textprop);
192}
193
194void WinClient::updateTransientInfo() {
195 if (m_win == 0)
196 return;
197 // remove us from parent
198 if (transientFor() != 0) {
199 //!! TODO
200 // since we don't know which client in transientFor()
201 // that we're transient for then we just remove us
202 // from every client in transientFor() clientlist
203 FluxboxWindow::ClientList::iterator client_it =
204 transientFor()->clientList().begin();
205 FluxboxWindow::ClientList::iterator client_it_end =
206 transientFor()->clientList().end();
207 for (; client_it != client_it_end; ++client_it) {
208 (*client_it)->transientList().remove(m_win);
209 }
210 }
211
212 transient_for = 0;
213 Display *disp = FbTk::App::instance()->display();
214 // determine if this is a transient window
215 Window win;
216 if (!XGetTransientForHint(disp, window(), &win))
217 return;
218
219 // we can't be transient to ourself
220 if (win == window())
221 return;
222
223 if (win != 0 && m_win->getScreen().getRootWindow() == win) {
224 m_win->modal = true;
225 return;
226 }
227
228 transient_for = Fluxbox::instance()->searchWindow(win);
229 if (transient_for != 0 &&
230 window_group != None && win == window_group) {
231 transient_for = Fluxbox::instance()->searchGroup(win, m_win);
232 }
233
234 // make sure we don't have deadlock loop in transient chain
235 for (FluxboxWindow *w = m_win; w != 0; w = w->m_client->transient_for) {
236 if (w == w->m_client->transient_for) {
237 w->m_client->transient_for = 0;
238 break;
239 }
240 }
241
242 if (transientFor() != 0) {
243 // we need to add ourself to the right client in
244 // the transientFor() window so we search client
245 WinClient *client = transientFor()->findClient(win);
246 assert(client != 0);
247 client->transientList().push_back(m_win);
248 // make sure we only have on instance of this
249 client->transientList().unique();
250 if (transientFor()->isStuck())
251 m_win->stick();
252 }
253}
254
255
256void WinClient::updateTitle() {
257 XTextProperty text_prop;
258 char **list = 0;
259 int num = 0;
260 I18n *i18n = I18n::instance();
261
262 if (getWMName(text_prop)) {
263 if (text_prop.value && text_prop.nitems > 0) {
264 if (text_prop.encoding != XA_STRING) {
265
266 text_prop.nitems = strlen((char *) text_prop.value);
267
268 if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop,
269 &list, &num) == Success &&
270 num > 0 && *list) {
271 m_title = static_cast<char *>(*list);
272 XFreeStringList(list);
273 } else
274 m_title = (char *)text_prop.value;
275
276 } else
277 m_title = (char *)text_prop.value;
278 XFree((char *) text_prop.value);
279 } else { // ok, we don't have a name, set default name
280 m_title = i18n->getMessage(
281 FBNLS::WindowSet, FBNLS::WindowUnnamed,
282 "Unnamed");
283 }
284 } else {
285 m_title = i18n->getMessage(
286 FBNLS::WindowSet, FBNLS::WindowUnnamed,
287 "Unnamed");
288 }
289
290}
291
292void WinClient::updateIconTitle() {
293 XTextProperty text_prop;
294 char **list = 0;
295 int num = 0;
296
297 if (getWMIconName(text_prop)) {
298 if (text_prop.value && text_prop.nitems > 0) {
299 if (text_prop.encoding != XA_STRING) {
300 text_prop.nitems = strlen((char *) text_prop.value);
301
302 if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop,
303 &list, &num) == Success &&
304 num > 0 && *list) {
305 m_icon_title = (char *)*list;
306 XFreeStringList(list);
307 } else
308 m_icon_title = (char *)text_prop.value;
309 } else
310 m_icon_title = (char *)text_prop.value;
311
312 XFree((char *) text_prop.value);
313 } else
314 m_icon_title = title();
315 } else
316 m_icon_title = title();
317
318}