1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 2006 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 "deleted.h"
22
23#include "workspace.h"
24#include "client.h"
25#include "netinfo.h"
26#include "paintredirector.h"
27#include "shadow.h"
28
29namespace KWin
30{
31
32Deleted::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
48Deleted::~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
57Deleted* 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()
66void Deleted::discard()
67{
68 delete_refcount = 0;
69 delete this;
70}
71
72void 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
112void 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
123int Deleted::desktop() const
124{
125 return desk;
126}
127
128QStringList Deleted::activities() const
129{
130 return activityList;
131}
132
133QPoint Deleted::clientPos() const
134{
135 return contentsRect.topLeft();
136}
137
138QSize Deleted::clientSize() const
139{
140 return contentsRect.size();
141}
142
143void Deleted::debug(QDebug& stream) const
144{
145 stream << "\'ID:" << window() << "\' (deleted)";
146}
147
148void 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
156QRect Deleted::decorationRect() const
157{
158 return rect().adjusted(-padding_left, -padding_top, padding_top, padding_bottom);
159}
160
161QRect Deleted::transparentRect() const
162{
163 return transparent_rect;
164}
165
166bool Deleted::isDeleted() const
167{
168 return true;
169}
170
171NET::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
181void Deleted::mainClientClosed(Toplevel *client)
182{
183 m_mainClients.removeAll(static_cast<Client*>(client));
184}
185
186} // namespace
187
188#include "deleted.moc"
189