1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*********************************************************************/
20
21#include "bridge.h"
22
23#include "client.h"
24#include "options.h"
25
26#include <kconfiggroup.h>
27#include "composite.h"
28#include "workspace.h"
29
30namespace KWin
31{
32
33Bridge::Bridge(Client* cl)
34 : c(cl)
35{
36}
37
38#define BRIDGE_HELPER( rettype, prototype, args1, args2, cst ) \
39 rettype Bridge::prototype ( args1 ) cst \
40 { \
41 return c->prototype( args2 ); \
42 }
43
44BRIDGE_HELPER(bool, isCloseable, , , const)
45BRIDGE_HELPER(bool, isMaximizable, , , const)
46BRIDGE_HELPER(Bridge::MaximizeMode, maximizeMode, , , const)
47BRIDGE_HELPER(Bridge::QuickTileMode, quickTileMode, , , const)
48BRIDGE_HELPER(bool, isMinimizable, , , const)
49BRIDGE_HELPER(bool, providesContextHelp, , , const)
50BRIDGE_HELPER(int, desktop, , , const)
51BRIDGE_HELPER(bool, isModal, , , const)
52BRIDGE_HELPER(bool, isShadeable, , , const)
53BRIDGE_HELPER(bool, isShade, , , const)
54BRIDGE_HELPER(bool, keepAbove, , , const)
55BRIDGE_HELPER(bool, keepBelow, , , const)
56BRIDGE_HELPER(bool, isMovable, , , const)
57BRIDGE_HELPER(bool, isResizable, , , const)
58BRIDGE_HELPER(void, processMousePressEvent, QMouseEvent* e, e,)
59BRIDGE_HELPER(QRect, geometry, , , const)
60BRIDGE_HELPER(void, closeWindow, , ,)
61BRIDGE_HELPER(void, maximize, MaximizeMode m, m,)
62BRIDGE_HELPER(void, minimize, , ,)
63BRIDGE_HELPER(void, showContextHelp, , ,)
64BRIDGE_HELPER(void, setDesktop, int desktop, desktop,)
65
66bool Bridge::isActive() const
67{
68 return c->isActive() || (c->tabGroup() && c->tabGroup()->isActive());
69}
70
71void Bridge::setKeepAbove(bool set)
72{
73 if (c->keepAbove() != set)
74 workspace()->performWindowOperation(c, KeepAboveOp);
75}
76
77void Bridge::setKeepBelow(bool set)
78{
79 if (c->keepBelow() != set)
80 workspace()->performWindowOperation(c, KeepBelowOp);
81}
82
83NET::WindowType Bridge::windowType(unsigned long supported_types) const
84{
85 return c->windowType(false, supported_types);
86}
87
88QIcon Bridge::icon() const
89{
90 QIcon ret(c->icon());
91 ret.addPixmap(c->miniIcon());
92 return ret;
93}
94
95bool Bridge::isSetShade() const
96{
97 return c->shadeMode() != ShadeNone;
98}
99
100void Bridge::showWindowMenu(const QPoint &p)
101{
102 workspace()->showWindowMenu(QRect(p,p), c);
103}
104
105void Bridge::showWindowMenu(const QPoint &p, long id)
106{
107 Client *cc = clientForId(id);
108 if (!cc)
109 cc = c;
110 workspace()->showWindowMenu(QRect(p,p), cc);
111}
112
113void Bridge::showWindowMenu(const QRect &p)
114{
115 workspace()->showWindowMenu(p, c);
116}
117
118void Bridge::showApplicationMenu(const QPoint &p)
119{
120#ifdef KWIN_BUILD_KAPPMENU
121 c->showApplicationMenu(p);
122#endif
123}
124
125bool Bridge::menuAvailable() const
126{
127#ifdef KWIN_BUILD_KAPPMENU
128 return c->menuAvailable();
129#else
130 return false;
131#endif
132}
133
134void Bridge::performWindowOperation(WindowOperation op)
135{
136 workspace()->performWindowOperation(c, op);
137}
138
139void Bridge::setMask(const QRegion& r, int mode)
140{
141 c->setMask(r, mode);
142}
143
144bool Bridge::isPreview() const
145{
146 return false;
147}
148
149QRect Bridge::iconGeometry() const
150{
151 NETRect r = c->info->iconGeometry();
152 return QRect(r.pos.x, r.pos.y, r.size.width, r.size.height);
153}
154
155WId Bridge::windowId() const
156{
157 return c->window();
158}
159
160void Bridge::titlebarDblClickOperation()
161{
162 workspace()->performWindowOperation(c, options->operationTitlebarDblClick());
163}
164
165void Bridge::titlebarMouseWheelOperation(int delta)
166{
167 c->performMouseCommand(options->operationTitlebarMouseWheel(delta), cursorPos());
168}
169
170void Bridge::setShade(bool set)
171{
172 c->setShade(set ? ShadeNormal : ShadeNone);
173}
174
175int Bridge::currentDesktop() const
176{
177 return VirtualDesktopManager::self()->current();
178}
179
180QWidget* Bridge::initialParentWidget() const
181{
182 return NULL;
183}
184
185Qt::WFlags Bridge::initialWFlags() const
186{
187 return 0;
188}
189
190QRegion Bridge::unobscuredRegion(const QRegion& r) const
191{
192 QRegion reg(r);
193 const ToplevelList stacking_order = workspace()->stackingOrder();
194 int pos = stacking_order.indexOf(c);
195 ++pos;
196 for (; pos < stacking_order.count(); ++pos) {
197 Client *client = qobject_cast<Client*>(stacking_order[pos]);
198 if (!client) {
199 continue;
200 }
201 if (!client->isShown(true))
202 continue; // these don't obscure the window
203 if (c->isOnAllDesktops()) {
204 if (!client->isOnCurrentDesktop())
205 continue;
206 } else {
207 if (!client->isOnDesktop(c->desktop()))
208 continue;
209 }
210 /* the clients all have their mask-regions in local coords
211 so we have to translate them to a shared coord system
212 we choose ours */
213 int dx = client->x() - c->x();
214 int dy = client->y() - c->y();
215 QRegion creg = client->mask();
216 creg.translate(dx, dy);
217 reg -= creg;
218 if (reg.isEmpty()) {
219 // early out, we are completely obscured
220 break;
221 }
222 }
223 return reg;
224}
225
226void Bridge::grabXServer(bool grab)
227{
228 if (grab)
229 KWin::grabXServer();
230 else
231 KWin::ungrabXServer();
232}
233
234bool Bridge::compositingActive() const
235{
236 return Compositor::compositing();
237}
238
239QRect Bridge::transparentRect() const
240{
241 return c->transparentRect().translated(-c->decorationRect().topLeft());
242}
243
244//BEGIN TABBING
245
246Client *Bridge::clientForId(long id) const
247{
248 Client* client = reinterpret_cast<Client*>(id);
249 if (!workspace()->hasClient(client)) {
250 kWarning(1212) << "****** ARBITRARY CODE EXECUTION ATTEMPT DETECTED ******" << id;
251 return 0;
252 }
253 return client;
254}
255
256int Bridge::tabCount() const
257{
258 if (c->tabGroup())
259 return c->tabGroup()->count();
260 return 1;
261}
262
263long Bridge::tabId(int idx) const
264{
265 if (c->tabGroup())
266 return tabIdOf(c->tabGroup()->clients().at(idx));
267 return tabIdOf(c);
268}
269
270QIcon Bridge::icon(int idx) const
271{
272 if (c->tabGroup()) {
273 Client *tabC = c->tabGroup()->clients().at(idx);
274 QIcon icon(tabC->icon());
275 icon.addPixmap(tabC->miniIcon());
276 return icon;
277 }
278 return icon();
279}
280
281QString Bridge::caption() const
282{
283 return c->caption(true, true);
284}
285
286QString Bridge::caption(int idx) const
287{
288 if (c->tabGroup())
289 return c->tabGroup()->clients().at(idx)->caption(true, true);
290 return c->caption(true, true);
291}
292
293long Bridge::currentTabId() const
294{
295 if (c->tabGroup())
296 return tabIdOf(c->tabGroup()->current());
297 return 0;
298}
299
300void Bridge::setCurrentTab(long id)
301{
302 if (c->tabGroup())
303 c->tabGroup()->setCurrent(clientForId(id));
304}
305
306void Bridge::tab_A_before_B(long A, long B)
307{
308 if (!B) {
309 if (c->tabGroup()) {
310 if (Client *a = clientForId(A))
311 a->untab();
312 }
313 return;
314 }
315
316 if (Client *a = clientForId(A))
317 if (Client *b = clientForId(B))
318 if (a != b)
319 a->tabBefore(b, true);
320}
321
322void Bridge::tab_A_behind_B(long A, long B)
323{
324 if (!B) {
325 if (c->tabGroup()) {
326 if (Client *a = clientForId(A))
327 a->untab();
328 }
329 return;
330 }
331
332 if (Client *a = clientForId(A))
333 if (Client *b = clientForId(B))
334 if (a != b)
335 a->tabBehind(b, true);
336}
337
338
339void Bridge::untab(long id, const QRect& newGeom)
340{
341 if (c->tabGroup())
342 if (Client* client = clientForId(id))
343 if (client->untab(newGeom)) {
344 if (options->focusPolicyIsReasonable())
345 workspace()->takeActivity(client, ActivityFocus | ActivityRaise, true);
346 workspace()->raiseClient(client);
347 }
348}
349
350void Bridge::closeTab(long id)
351{
352 if (Client* client = clientForId(id))
353 client->closeWindow();
354}
355
356void Bridge::closeTabGroup()
357{
358 if (c->tabGroup())
359 c->tabGroup()->closeAll();
360}
361
362//END TABBING
363
364KDecoration::WindowOperation Bridge::buttonToWindowOperation(Qt::MouseButtons button)
365{
366 return c->mouseButtonToWindowOperation(button);
367}
368
369} // namespace
370