aboutsummaryrefslogtreecommitdiff
path: root/src/WinClient.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/WinClient.cc')
-rw-r--r--src/WinClient.cc319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/WinClient.cc b/src/WinClient.cc
new file mode 100644
index 0000000..5812b9b
--- /dev/null
+++ b/src/WinClient.cc
@@ -0,0 +1,319 @@
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.3 2003/04/15 12:12:29 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#include "FbAtoms.hh"
31
32#include <iostream>
33#include <algorithm>
34#include <iterator>
35using namespace std;
36
37WinClient::WinClient(Window win, FluxboxWindow &fbwin):FbTk::FbWindow(win),
38 transient_for(0),
39 window_group(0),
40 x(0), y(0), old_bw(0),
41 min_width(1), min_height(1),
42 max_width(1), max_height(1),
43 width_inc(1), height_inc(1),
44 min_aspect_x(1), min_aspect_y(1),
45 max_aspect_x(1), max_aspect_y(1),
46 base_width(1), base_height(1),
47 win_gravity(0),
48 initial_state(0),
49 normal_hint_flags(0),
50 wm_hint_flags(0),
51 mwm_hint(0),
52 blackbox_hint(0),
53 m_win(&fbwin),
54 m_title(""), m_icon_title(""),
55 m_diesig(*this) { }
56
57WinClient::~WinClient() {
58#ifdef DEBUG
59 cerr<<__FILE__<<"(~"<<__FUNCTION__<<")[this="<<this<<"]"<<endl;
60#endif // DEBUG
61
62 m_diesig.notify();
63
64 Fluxbox *fluxbox = Fluxbox::instance();
65
66 if (transient_for != 0) {
67 if (transientFor() == m_win) {
68 transient_for = 0;
69 }
70
71 fluxbox->setFocusedWindow(transient_for);
72
73 if (transient_for != 0) {
74 FluxboxWindow::ClientList::iterator client_it =
75 transientFor()->clientList().begin();
76 FluxboxWindow::ClientList::iterator client_it_end =
77 transientFor()->clientList().end();
78 for (; client_it != client_it_end; ++client_it) {
79 (*client_it)->transientList().remove(m_win);
80 }
81
82 transient_for->setInputFocus();
83 transient_for = 0;
84 }
85 }
86
87 while (!transients.empty()) {
88 FluxboxWindow::ClientList::iterator it =
89 transients.back()->clientList().begin();
90 FluxboxWindow::ClientList::iterator it_end =
91 transients.back()->clientList().end();
92 for (; it != it_end; ++it) {
93 if ((*it)->transientFor() == m_win)
94 (*it)->transient_for = 0;
95 }
96
97 transients.pop_back();
98 }
99
100 if (window_group != 0) {
101 fluxbox->removeGroupSearch(window_group);
102 window_group = 0;
103 }
104
105 if (mwm_hint != 0)
106 XFree(mwm_hint);
107
108 if (blackbox_hint != 0)
109 XFree(blackbox_hint);
110
111 if (window())
112 fluxbox->removeWindowSearch(window());
113
114 if (m_win != 0)
115 m_win->removeClient(*this);
116 m_win = 0;
117
118}
119
120void WinClient::updateRect(int x, int y,
121 unsigned int width, unsigned int height) {
122 Display *disp = FbTk::App::instance()->display();
123 XEvent event;
124 event.type = ConfigureNotify;
125
126 event.xconfigure.display = disp;
127 event.xconfigure.event = window();
128 event.xconfigure.window = window();
129 event.xconfigure.x = x;
130 event.xconfigure.y = y;
131 event.xconfigure.width = width;
132 event.xconfigure.height = height;
133 //!! TODO
134 event.xconfigure.border_width = 1;//client.old_bw;
135 //!! TODO
136 event.xconfigure.above = None; //m_frame.window().window();
137 event.xconfigure.override_redirect = false;
138
139 XSendEvent(disp, window(), False, StructureNotifyMask, &event);
140
141}
142
143void WinClient::sendFocus() {
144 Display *disp = FbTk::App::instance()->display();
145 // setup focus msg
146 XEvent ce;
147 ce.xclient.type = ClientMessage;
148 ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom();
149 ce.xclient.display = disp;
150 ce.xclient.window = window();
151 ce.xclient.format = 32;
152 ce.xclient.data.l[0] = FbAtoms::instance()->getWMTakeFocusAtom();
153 ce.xclient.data.l[1] = Fluxbox::instance()->getLastTime();
154 ce.xclient.data.l[2] = 0l;
155 ce.xclient.data.l[3] = 0l;
156 ce.xclient.data.l[4] = 0l;
157 // send focus msg
158 XSendEvent(disp, window(), false, NoEventMask, &ce);
159}
160
161void WinClient::sendClose() {
162 Display *disp = FbTk::App::instance()->display();
163 // fill in XClientMessage structure for delete message
164 XEvent ce;
165 ce.xclient.type = ClientMessage;
166 ce.xclient.message_type = FbAtoms::instance()->getWMProtocolsAtom();
167 ce.xclient.display = disp;
168 ce.xclient.window = window();
169 ce.xclient.format = 32;
170 ce.xclient.data.l[0] = FbAtoms::instance()->getWMDeleteAtom();
171 ce.xclient.data.l[1] = CurrentTime;
172 ce.xclient.data.l[2] = 0l;
173 ce.xclient.data.l[3] = 0l;
174 ce.xclient.data.l[4] = 0l;
175 // send event delete message to client window
176 XSendEvent(disp, window(), false, NoEventMask, &ce);
177}
178
179void WinClient::reparent(Window win, int x, int y) {
180 XReparentWindow(FbTk::App::instance()->display(), window(), win, x, y);
181}
182
183bool WinClient::getAttrib(XWindowAttributes &attr) const {
184 return XGetWindowAttributes(FbTk::App::instance()->display(), window(), &attr);
185}
186
187bool WinClient::getWMName(XTextProperty &textprop) const {
188 return XGetWMName(FbTk::App::instance()->display(), window(), &textprop);
189}
190
191bool WinClient::getWMIconName(XTextProperty &textprop) const {
192 return XGetWMName(FbTk::App::instance()->display(), window(), &textprop);
193}
194
195void WinClient::updateTransientInfo() {
196 if (m_win == 0)
197 return;
198 // remove us from parent
199 if (transientFor() != 0) {
200 //!! TODO
201 // since we don't know which client in transientFor()
202 // that we're transient for then we just remove us
203 // from every client in transientFor() clientlist
204 FluxboxWindow::ClientList::iterator client_it =
205 transientFor()->clientList().begin();
206 FluxboxWindow::ClientList::iterator client_it_end =
207 transientFor()->clientList().end();
208 for (; client_it != client_it_end; ++client_it) {
209 (*client_it)->transientList().remove(m_win);
210 }
211 }
212
213 transient_for = 0;
214 Display *disp = FbTk::App::instance()->display();
215 // determine if this is a transient window
216 Window win;
217 if (!XGetTransientForHint(disp, window(), &win))
218 return;
219
220 // we can't be transient to ourself
221 if (win == window())
222 return;
223
224 if (win != 0 && m_win->getScreen().getRootWindow() == win) {
225 m_win->modal = true;
226 return;
227 }
228
229 transient_for = Fluxbox::instance()->searchWindow(win);
230 if (transient_for != 0 &&
231 window_group != None && win == window_group) {
232 transient_for = Fluxbox::instance()->searchGroup(win, m_win);
233 }
234
235 // make sure we don't have deadlock loop in transient chain
236 for (FluxboxWindow *w = m_win; w != 0; w = w->m_client->transient_for) {
237 if (w == w->m_client->transient_for) {
238 w->m_client->transient_for = 0;
239 break;
240 }
241 }
242
243 if (transientFor() != 0) {
244 // we need to add ourself to the right client in
245 // the transientFor() window so we search client
246 WinClient *client = transientFor()->findClient(win);
247 assert(client != 0);
248 client->transientList().push_back(m_win);
249 // make sure we only have on instance of this
250 client->transientList().unique();
251 if (transientFor()->isStuck())
252 m_win->stick();
253 }
254}
255
256
257void WinClient::updateTitle() {
258 XTextProperty text_prop;
259 char **list = 0;
260 int num = 0;
261 I18n *i18n = I18n::instance();
262
263 if (getWMName(text_prop)) {
264 if (text_prop.value && text_prop.nitems > 0) {
265 if (text_prop.encoding != XA_STRING) {
266
267 text_prop.nitems = strlen((char *) text_prop.value);
268
269 if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop,
270 &list, &num) == Success &&
271 num > 0 && *list) {
272 m_title = static_cast<char *>(*list);
273 XFreeStringList(list);
274 } else
275 m_title = (char *)text_prop.value;
276
277 } else
278 m_title = (char *)text_prop.value;
279 XFree((char *) text_prop.value);
280 } else { // ok, we don't have a name, set default name
281 m_title = i18n->getMessage(
282 FBNLS::WindowSet, FBNLS::WindowUnnamed,
283 "Unnamed");
284 }
285 } else {
286 m_title = i18n->getMessage(
287 FBNLS::WindowSet, FBNLS::WindowUnnamed,
288 "Unnamed");
289 }
290
291}
292
293void WinClient::updateIconTitle() {
294 XTextProperty text_prop;
295 char **list = 0;
296 int num = 0;
297
298 if (getWMIconName(text_prop)) {
299 if (text_prop.value && text_prop.nitems > 0) {
300 if (text_prop.encoding != XA_STRING) {
301 text_prop.nitems = strlen((char *) text_prop.value);
302
303 if (XmbTextPropertyToTextList(FbTk::App::instance()->display(), &text_prop,
304 &list, &num) == Success &&
305 num > 0 && *list) {
306 m_icon_title = (char *)*list;
307 XFreeStringList(list);
308 } else
309 m_icon_title = (char *)text_prop.value;
310 } else
311 m_icon_title = (char *)text_prop.value;
312
313 XFree((char *) text_prop.value);
314 } else
315 m_icon_title = title();
316 } else
317 m_icon_title = title();
318
319}