1 | /******************************************************************** |
2 | KWin - the KDE window manager |
3 | This file is part of the KDE project. |
4 | |
5 | Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org> |
6 | |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | *********************************************************************/ |
20 | |
21 | #include "deleted.h" |
22 | |
23 | #include "workspace.h" |
24 | #include "client.h" |
25 | #include "netinfo.h" |
26 | #include "paintredirector.h" |
27 | #include "shadow.h" |
28 | |
29 | namespace KWin |
30 | { |
31 | |
32 | Deleted::Deleted() |
33 | : Toplevel() |
34 | , delete_refcount(1) |
35 | , no_border(true) |
36 | , padding_left(0) |
37 | , padding_top(0) |
38 | , padding_right(0) |
39 | , padding_bottom(0) |
40 | , m_layer(UnknownLayer) |
41 | , m_minimized(false) |
42 | , m_modal(false) |
43 | , m_paintRedirector(NULL) |
44 | , m_wasClient(false) |
45 | { |
46 | } |
47 | |
48 | Deleted::~Deleted() |
49 | { |
50 | if (delete_refcount != 0) |
51 | kError(1212) << "Deleted client has non-zero reference count (" << delete_refcount << ")" ; |
52 | assert(delete_refcount == 0); |
53 | workspace()->removeDeleted(this); |
54 | deleteEffectWindow(); |
55 | } |
56 | |
57 | Deleted* Deleted::create(Toplevel* c) |
58 | { |
59 | Deleted* d = new Deleted(); |
60 | d->copyToDeleted(c); |
61 | workspace()->addDeleted(d, c); |
62 | return d; |
63 | } |
64 | |
65 | // to be used only from Workspace::finishCompositing() |
66 | void Deleted::discard() |
67 | { |
68 | delete_refcount = 0; |
69 | delete this; |
70 | } |
71 | |
72 | void Deleted::copyToDeleted(Toplevel* c) |
73 | { |
74 | assert(dynamic_cast< Deleted* >(c) == NULL); |
75 | Toplevel::copyToDeleted(c); |
76 | desk = c->desktop(); |
77 | activityList = c->activities(); |
78 | contentsRect = QRect(c->clientPos(), c->clientSize()); |
79 | transparent_rect = c->transparentRect(); |
80 | m_layer = c->layer(); |
81 | if (WinInfo* cinfo = dynamic_cast< WinInfo* >(info)) |
82 | cinfo->disable(); |
83 | Client* client = dynamic_cast<Client*>(c); |
84 | if (client) { |
85 | m_wasClient = true; |
86 | no_border = client->noBorder(); |
87 | padding_left = client->paddingLeft(); |
88 | padding_right = client->paddingRight(); |
89 | padding_bottom = client->paddingBottom(); |
90 | padding_top = client->paddingTop(); |
91 | if (!no_border) { |
92 | client->layoutDecorationRects(decoration_left, |
93 | decoration_top, |
94 | decoration_right, |
95 | decoration_bottom, |
96 | Client::WindowRelative); |
97 | if (PaintRedirector *redirector = client->decorationPaintRedirector()) { |
98 | redirector->ensurePixmapsPainted(); |
99 | redirector->reparent(this); |
100 | m_paintRedirector = redirector; |
101 | } |
102 | } |
103 | m_minimized = client->isMinimized(); |
104 | m_modal = client->isModal(); |
105 | m_mainClients = client->mainClients(); |
106 | foreach (Client *c, m_mainClients) { |
107 | connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(mainClientClosed(KWin::Toplevel*))); |
108 | } |
109 | } |
110 | } |
111 | |
112 | void Deleted::unrefWindow() |
113 | { |
114 | if (--delete_refcount > 0) |
115 | return; |
116 | // needs to be delayed |
117 | // a) when calling from effects, otherwise it'd be rather complicated to handle the case of the |
118 | // window going away during a painting pass |
119 | // b) to prevent dangeling pointers in the stacking order, see bug #317765 |
120 | deleteLater(); |
121 | } |
122 | |
123 | int Deleted::desktop() const |
124 | { |
125 | return desk; |
126 | } |
127 | |
128 | QStringList Deleted::activities() const |
129 | { |
130 | return activityList; |
131 | } |
132 | |
133 | QPoint Deleted::clientPos() const |
134 | { |
135 | return contentsRect.topLeft(); |
136 | } |
137 | |
138 | QSize Deleted::clientSize() const |
139 | { |
140 | return contentsRect.size(); |
141 | } |
142 | |
143 | void Deleted::debug(QDebug& stream) const |
144 | { |
145 | stream << "\'ID:" << window() << "\' (deleted)" ; |
146 | } |
147 | |
148 | void Deleted::layoutDecorationRects(QRect& left, QRect& top, QRect& right, QRect& bottom, int) const |
149 | { |
150 | left = decoration_left; |
151 | top = decoration_top; |
152 | right = decoration_right; |
153 | bottom = decoration_bottom; |
154 | } |
155 | |
156 | QRect Deleted::decorationRect() const |
157 | { |
158 | return rect().adjusted(-padding_left, -padding_top, padding_top, padding_bottom); |
159 | } |
160 | |
161 | QRect Deleted::transparentRect() const |
162 | { |
163 | return transparent_rect; |
164 | } |
165 | |
166 | bool Deleted::isDeleted() const |
167 | { |
168 | return true; |
169 | } |
170 | |
171 | NET::WindowType Deleted::windowType(bool direct, int supportedTypes) const |
172 | { |
173 | Q_UNUSED(direct) |
174 | // TODO: maybe retrieve the actual window type when copying to deleted? |
175 | if (supportedTypes == 0) { |
176 | supportedTypes = SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK; |
177 | } |
178 | return info->windowType(supportedTypes); |
179 | } |
180 | |
181 | void Deleted::mainClientClosed(Toplevel *client) |
182 | { |
183 | m_mainClients.removeAll(static_cast<Client*>(client)); |
184 | } |
185 | |
186 | } // namespace |
187 | |
188 | #include "deleted.moc" |
189 | |