Use smart pointers to protect access to TabBoxClient

Client holds a SharedPointer to the TabBoxClient and only
provides access to a WeakPointer which is passed to TabBox.
ClientModel is adjusted to hold a list of WeakPointers instead
of the direct pointers.

This fixes the following reproducable crash:
1. Configure both primary and secondary TabBox with different
   layouts
2. Use primary TabBox
3. Close a window, best the one which used to be active
4. Use secondary TabBox
-> Crash

The reason is that the ClientModel still contains the pointer
to the deleted TabBoxClient in step 3 and while creating the
layout access to the TabBoxClient is needed to get the Client's
icon.

By using the weak pointer it can be ensured that we don't try
to dereference the deleted pointer and prevent the crash.

CCBUG: 290482
CCBUG: 285747
CCBUG: 237345
REVIEW: 105000
This commit is contained in:
Martin Gräßlin 2012-05-20 15:52:24 +02:00
parent f24103481e
commit d75e7a6d60
8 changed files with 109 additions and 66 deletions

View file

@ -187,7 +187,7 @@ Client::Client(Workspace* ws)
#ifdef KWIN_BUILD_TABBOX #ifdef KWIN_BUILD_TABBOX
// TabBoxClient // TabBoxClient
m_tabBoxClient = new TabBox::TabBoxClientImpl(this); m_tabBoxClient = QSharedPointer<TabBox::TabBoxClientImpl>(new TabBox::TabBoxClientImpl(this));
#endif #endif
geom = QRect(0, 0, 100, 100); // So that decorations don't start with size being (0,0) geom = QRect(0, 0, 100, 100); // So that decorations don't start with size being (0,0)
@ -221,9 +221,6 @@ Client::~Client()
assert(block_geometry_updates == 0); assert(block_geometry_updates == 0);
assert(!check_active_modal); assert(!check_active_modal);
delete bridge; delete bridge;
#ifdef KWIN_BUILD_TABBOX
delete m_tabBoxClient;
#endif
} }
// Use destroyClient() or releaseWindow(), Client instances cannot be deleted directly // Use destroyClient() or releaseWindow(), Client instances cannot be deleted directly

View file

@ -621,8 +621,8 @@ public:
}; };
void layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom, CoordinateMode mode) const; void layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom, CoordinateMode mode) const;
TabBox::TabBoxClientImpl* tabBoxClient() const { QWeakPointer<TabBox::TabBoxClientImpl> tabBoxClient() const {
return m_tabBoxClient; return m_tabBoxClient.toWeakRef();
} }
bool isFirstInTabBox() const { bool isFirstInTabBox() const {
return m_firstInTabBox; return m_firstInTabBox;
@ -945,7 +945,7 @@ private:
// we (instead of Qt) initialize the Pixmaps, and have to free them // we (instead of Qt) initialize the Pixmaps, and have to free them
bool m_responsibleForDecoPixmap; bool m_responsibleForDecoPixmap;
PaintRedirector* paintRedirector; PaintRedirector* paintRedirector;
TabBox::TabBoxClientImpl* m_tabBoxClient; QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
bool m_firstInTabBox; bool m_firstInTabBox;
bool electricMaximizing; bool electricMaximizing;

View file

@ -63,22 +63,26 @@ QVariant ClientModel::data(const QModelIndex& index, int role) const
int clientIndex = index.row() * columnCount() + index.column(); int clientIndex = index.row() * columnCount() + index.column();
if (clientIndex >= m_clientList.count()) if (clientIndex >= m_clientList.count())
return QVariant(); return QVariant();
QSharedPointer<TabBoxClient> client = m_clientList[ clientIndex ].toStrongRef();
if (!client) {
return QVariant();
}
switch(role) { switch(role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case CaptionRole: case CaptionRole:
return m_clientList[ clientIndex ]->caption(); return client->caption();
case ClientRole: case ClientRole:
return qVariantFromValue((void*)m_clientList[ clientIndex ]); return qVariantFromValue((void*)client.data());
case DesktopNameRole: { case DesktopNameRole: {
return tabBox->desktopName(m_clientList[ clientIndex ]); return tabBox->desktopName(client.data());
} }
case WIdRole: case WIdRole:
return qulonglong(m_clientList[ clientIndex ]->window()); return qulonglong(client->window());
case MinimizedRole: case MinimizedRole:
return m_clientList[ clientIndex ]->isMinimized(); return client->isMinimized();
case CloseableRole: case CloseableRole:
//clients that claim to be first are not closeable //clients that claim to be first are not closeable
return m_clientList[ clientIndex ]->isCloseable() && !m_clientList[ clientIndex ]->isFirstInTabBox(); return client->isCloseable() && !client->isFirstInTabBox();
default: default:
return QVariant(); return QVariant();
} }
@ -87,7 +91,8 @@ QVariant ClientModel::data(const QModelIndex& index, int role) const
QString ClientModel::longestCaption() const QString ClientModel::longestCaption() const
{ {
QString caption; QString caption;
foreach (TabBoxClient *client, m_clientList) { foreach (QWeakPointer<TabBoxClient> clientPointer, m_clientList) {
QSharedPointer<TabBoxClient> client = clientPointer.toStrongRef();
if (client->caption().size() > caption.size()) { if (client->caption().size() > caption.size()) {
caption = client->caption(); caption = client->caption();
} }
@ -148,7 +153,7 @@ QModelIndex ClientModel::index(int row, int column, const QModelIndex& parent) c
return createIndex(row, column); return createIndex(row, column);
} }
QModelIndex ClientModel::index(TabBoxClient* client) const QModelIndex ClientModel::index(QWeakPointer<TabBoxClient> client) const
{ {
if (!m_clientList.contains(client)) if (!m_clientList.contains(client))
return QModelIndex(); return QModelIndex();
@ -165,31 +170,35 @@ void ClientModel::createClientList(bool partialReset)
void ClientModel::createClientList(int desktop, bool partialReset) void ClientModel::createClientList(int desktop, bool partialReset)
{ {
TabBoxClient* start = tabBox->activeClient(); TabBoxClient* start = tabBox->activeClient().toStrongRef().data();
// TODO: new clients are not added at correct position // TODO: new clients are not added at correct position
if (partialReset && !m_clientList.isEmpty()) if (partialReset && !m_clientList.isEmpty()) {
start = m_clientList.first(); QSharedPointer<TabBoxClient> firstClient = m_clientList.first().toStrongRef();
if (firstClient) {
start = firstClient.data();
}
}
m_clientList.clear(); m_clientList.clear();
QList<TabBoxClient*> stickyClients; QList< QWeakPointer< TabBoxClient > > stickyClients;
switch(tabBox->config().clientSwitchingMode()) { switch(tabBox->config().clientSwitchingMode()) {
case TabBoxConfig::FocusChainSwitching: { case TabBoxConfig::FocusChainSwitching: {
TabBoxClient* c = tabBox->nextClientFocusChain(start); TabBoxClient* c = tabBox->nextClientFocusChain(start).data();
TabBoxClient* stop = c; TabBoxClient* stop = c;
while (c) { while (c) {
TabBoxClient* add = tabBox->clientToAddToList(c, desktop); QWeakPointer<TabBoxClient> add = tabBox->clientToAddToList(c, desktop);
if (add != NULL) { if (!add.isNull()) {
if (start == add) { if (start == add.data()) {
m_clientList.removeAll(add); m_clientList.removeAll(add);
m_clientList.prepend(add); m_clientList.prepend(add);
} else } else
m_clientList += add; m_clientList += add;
if (add->isFirstInTabBox()) { if (add.data()->isFirstInTabBox()) {
stickyClients << add; stickyClients << add;
} }
} }
c = tabBox->nextClientFocusChain(c); c = tabBox->nextClientFocusChain(c).data();
if (c == stop) if (c == stop)
break; break;
@ -199,25 +208,25 @@ void ClientModel::createClientList(int desktop, bool partialReset)
case TabBoxConfig::StackingOrderSwitching: { case TabBoxConfig::StackingOrderSwitching: {
// TODO: needs improvement // TODO: needs improvement
TabBoxClientList stacking = tabBox->stackingOrder(); TabBoxClientList stacking = tabBox->stackingOrder();
TabBoxClient* c = stacking.first(); TabBoxClient* c = stacking.first().data();
TabBoxClient* stop = c; TabBoxClient* stop = c;
int index = 0; int index = 0;
while (c) { while (c) {
TabBoxClient* add = tabBox->clientToAddToList(c, desktop); QWeakPointer<TabBoxClient> add = tabBox->clientToAddToList(c, desktop);
if (add != NULL) { if (!add.isNull()) {
if (start == add) { if (start == add.data()) {
m_clientList.removeAll(add); m_clientList.removeAll(add);
m_clientList.prepend(add); m_clientList.prepend(add);
} else } else
m_clientList += add; m_clientList += add;
if (add->isFirstInTabBox()) { if (add.data()->isFirstInTabBox()) {
stickyClients << add; stickyClients << add;
} }
} }
if (index >= stacking.size() - 1) { if (index >= stacking.size() - 1) {
c = NULL; c = NULL;
} else { } else {
c = stacking[++index]; c = stacking[++index].data();
} }
if (c == stop) if (c == stop)
@ -226,13 +235,13 @@ void ClientModel::createClientList(int desktop, bool partialReset)
break; break;
} }
} }
foreach (TabBoxClient *c, stickyClients) { foreach (QWeakPointer< TabBoxClient > c, stickyClients) {
m_clientList.removeAll(c); m_clientList.removeAll(c);
m_clientList.prepend(c); m_clientList.prepend(c);
} }
if (tabBox->config().showDesktopMode() == TabBoxConfig::ShowDesktopClient || m_clientList.isEmpty()) { if (tabBox->config().showDesktopMode() == TabBoxConfig::ShowDesktopClient || m_clientList.isEmpty()) {
TabBoxClient* desktopClient = tabBox->desktopClient(); QWeakPointer<TabBoxClient> desktopClient = tabBox->desktopClient();
if (desktopClient) if (!desktopClient.isNull())
m_clientList.append(desktopClient); m_clientList.append(desktopClient);
} }
reset(); reset();
@ -244,7 +253,10 @@ void ClientModel::close(int i)
if (!ind.isValid()) { if (!ind.isValid()) {
return; return;
} }
m_clientList.at(i)->close(); QSharedPointer<TabBoxClient> client = m_clientList.at(i).toStrongRef();
if (client) {
client->close();
}
} }
void ClientModel::activate(int i) void ClientModel::activate(int i)

View file

@ -71,7 +71,7 @@ public:
* @return Returns the ModelIndex of given TabBoxClient or an invalid ModelIndex * @return Returns the ModelIndex of given TabBoxClient or an invalid ModelIndex
* if the model does not contain the given TabBoxClient. * if the model does not contain the given TabBoxClient.
*/ */
QModelIndex index(TabBoxClient* client) const; QModelIndex index(QWeakPointer<TabBoxClient> client) const;
/** /**
* Generates a new list of TabBoxClients based on the current config. * Generates a new list of TabBoxClients based on the current config.

View file

@ -93,14 +93,14 @@ QString TabBoxHandlerImpl::desktopName(int desktop) const
return Workspace::self()->desktopName(desktop); return Workspace::self()->desktopName(desktop);
} }
TabBoxClient* TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient* client) const QWeakPointer<TabBoxClient> TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient* client) const
{ {
if (TabBoxClientImpl* c = static_cast< TabBoxClientImpl* >(client)) { if (TabBoxClientImpl* c = static_cast< TabBoxClientImpl* >(client)) {
Client* next = Workspace::self()->tabBox()->nextClientFocusChain(c->client()); Client* next = Workspace::self()->tabBox()->nextClientFocusChain(c->client());
if (next) if (next)
return next->tabBoxClient(); return next->tabBoxClient();
} }
return NULL; return QWeakPointer<TabBoxClient>();
} }
int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const
@ -113,12 +113,12 @@ int TabBoxHandlerImpl::numberOfDesktops() const
return Workspace::self()->numberOfDesktops(); return Workspace::self()->numberOfDesktops();
} }
TabBoxClient* TabBoxHandlerImpl::activeClient() const QWeakPointer<TabBoxClient> TabBoxHandlerImpl::activeClient() const
{ {
if (Workspace::self()->activeClient()) if (Workspace::self()->activeClient())
return Workspace::self()->activeClient()->tabBoxClient(); return Workspace::self()->activeClient()->tabBoxClient();
else else
return NULL; return QWeakPointer<TabBoxClient>();
} }
bool TabBoxHandlerImpl::checkDesktop(TabBoxClient* client, int desktop) const bool TabBoxHandlerImpl::checkDesktop(TabBoxClient* client, int desktop) const
@ -153,26 +153,35 @@ bool TabBoxHandlerImpl::checkApplications(TabBoxClient* client) const
{ {
Client* current = (static_cast< TabBoxClientImpl* >(client))->client(); Client* current = (static_cast< TabBoxClientImpl* >(client))->client();
TabBoxClientImpl* c; TabBoxClientImpl* c;
QListIterator< TabBoxClient* > i(clientList()); QListIterator< QWeakPointer<TabBoxClient> > i(clientList());
switch (config().clientApplicationsMode()) { switch (config().clientApplicationsMode()) {
case TabBoxConfig::OneWindowPerApplication: case TabBoxConfig::OneWindowPerApplication:
// check if the list already contains an entry of this application // check if the list already contains an entry of this application
while (i.hasNext()) { while (i.hasNext()) {
if ((c = dynamic_cast< TabBoxClientImpl* >(i.next()))) { QSharedPointer<TabBoxClient> client = i.next().toStrongRef();
if (!client) {
continue;
}
if ((c = dynamic_cast< TabBoxClientImpl* >(client.data()))) {
if (c->client()->resourceClass() == current->resourceClass()) { if (c->client()->resourceClass() == current->resourceClass()) {
return false; return false;
} }
} }
} }
return true; return true;
case TabBoxConfig::AllWindowsCurrentApplication: case TabBoxConfig::AllWindowsCurrentApplication: {
if ((c = dynamic_cast< TabBoxClientImpl* >(tabBox->activeClient()))) { QSharedPointer<TabBoxClient> pointer = tabBox->activeClient().toStrongRef();
if (!pointer) {
return false;
}
if ((c = dynamic_cast< TabBoxClientImpl* >(pointer.data()))) {
if (c->client()->resourceClass() == current->resourceClass()) { if (c->client()->resourceClass() == current->resourceClass()) {
return true; return true;
} }
} }
return false; return false;
}
default: // TabBoxConfig::AllWindowsAllApplications default: // TabBoxConfig::AllWindowsAllApplications
return true; return true;
} }
@ -205,7 +214,7 @@ bool TabBoxHandlerImpl::checkMultiScreen(TabBoxClient* client) const
} }
} }
TabBoxClient* TabBoxHandlerImpl::clientToAddToList(TabBoxClient* client, int desktop) const QWeakPointer<TabBoxClient> TabBoxHandlerImpl::clientToAddToList(TabBoxClient* client, int desktop) const
{ {
Client* ret = NULL; Client* ret = NULL;
Client* current = (static_cast< TabBoxClientImpl* >(client))->client(); Client* current = (static_cast< TabBoxClientImpl* >(client))->client();
@ -230,7 +239,7 @@ TabBoxClient* TabBoxHandlerImpl::clientToAddToList(TabBoxClient* client, int des
if (ret) if (ret)
return ret->tabBoxClient(); return ret->tabBoxClient();
else else
return NULL; return QWeakPointer<TabBoxClient>();
} }
TabBoxClientList TabBoxHandlerImpl::stackingOrder() const TabBoxClientList TabBoxHandlerImpl::stackingOrder() const
@ -268,7 +277,7 @@ void TabBoxHandlerImpl::elevateClient(TabBoxClient *c, WId tabbox, bool b) const
} }
TabBoxClient* TabBoxHandlerImpl::desktopClient() const QWeakPointer<TabBoxClient> TabBoxHandlerImpl::desktopClient() const
{ {
foreach (Toplevel *toplevel, Workspace::self()->stackingOrder()) { foreach (Toplevel *toplevel, Workspace::self()->stackingOrder()) {
Client *client = qobject_cast<Client*>(toplevel); Client *client = qobject_cast<Client*>(toplevel);
@ -276,7 +285,7 @@ TabBoxClient* TabBoxHandlerImpl::desktopClient() const
return client->tabBoxClient(); return client->tabBoxClient();
} }
} }
return NULL; return QWeakPointer<TabBoxClient>();
} }
void TabBoxHandlerImpl::showOutline(const QRect &outline) void TabBoxHandlerImpl::showOutline(const QRect &outline)
@ -575,8 +584,11 @@ ClientList TabBox::currentClientList()
{ {
TabBoxClientList list = m_tabBox->clientList(); TabBoxClientList list = m_tabBox->clientList();
ClientList ret; ClientList ret;
foreach (const TabBoxClient * client, list) { foreach (QWeakPointer<TabBoxClient> clientPointer, list) {
if (const TabBoxClientImpl* c = static_cast< const TabBoxClientImpl* >(client)) QSharedPointer<TabBoxClient> client = clientPointer.toStrongRef();
if (!client)
continue;
if (const TabBoxClientImpl* c = static_cast< const TabBoxClientImpl* >(client.data()))
ret.append(c->client()); ret.append(c->client());
} }
return ret; return ret;

View file

@ -46,19 +46,19 @@ public:
virtual ~TabBoxHandlerImpl(); virtual ~TabBoxHandlerImpl();
virtual int activeScreen() const; virtual int activeScreen() const;
virtual TabBoxClient* activeClient() const; virtual QWeakPointer< TabBoxClient > activeClient() const;
virtual int currentDesktop() const; virtual int currentDesktop() const;
virtual QString desktopName(TabBoxClient* client) const; virtual QString desktopName(TabBoxClient* client) const;
virtual QString desktopName(int desktop) const; virtual QString desktopName(int desktop) const;
virtual TabBoxClient* nextClientFocusChain(TabBoxClient* client) const; virtual QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const;
virtual int nextDesktopFocusChain(int desktop) const; virtual int nextDesktopFocusChain(int desktop) const;
virtual int numberOfDesktops() const; virtual int numberOfDesktops() const;
virtual TabBoxClientList stackingOrder() const; virtual TabBoxClientList stackingOrder() const;
virtual void elevateClient(TabBoxClient* c, WId tabbox, bool elevate) const; virtual void elevateClient(TabBoxClient* c, WId tabbox, bool elevate) const;
virtual void raiseClient(TabBoxClient *client) const; virtual void raiseClient(TabBoxClient *client) const;
virtual void restack(TabBoxClient *c, TabBoxClient *under); virtual void restack(TabBoxClient *c, TabBoxClient *under);
virtual TabBoxClient* clientToAddToList(TabBoxClient* client, int desktop) const; virtual QWeakPointer< TabBoxClient > clientToAddToList(KWin::TabBox::TabBoxClient* client, int desktop) const;
virtual TabBoxClient* desktopClient() const; virtual QWeakPointer< TabBoxClient > desktopClient() const;
virtual void hideOutline(); virtual void hideOutline();
virtual void showOutline(const QRect &outline); virtual void showOutline(const QRect &outline);
virtual QVector< Window > outlineWindowIds() const; virtual QVector< Window > outlineWindowIds() const;

View file

@ -158,8 +158,14 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
// TODO if ( (lastRaisedClientWasMinimized = lastRaisedClient->isMinimized()) ) // TODO if ( (lastRaisedClientWasMinimized = lastRaisedClient->isMinimized()) )
// lastRaisedClient->setMinimized( false ); // lastRaisedClient->setMinimized( false );
TabBoxClientList order = q->stackingOrder(); TabBoxClientList order = q->stackingOrder();
int succIdx = order.indexOf(lastRaisedClient) + 1; // this is likely related to the index parameter?! int succIdx = order.count() + 1;
lastRaisedClientSucc = (succIdx < order.count()) ? order.at(succIdx) : 0; for (int i=0; i<order.count(); ++i) {
if (order.at(i).data() == lastRaisedClient) {
succIdx = i + 1;
break;
}
}
lastRaisedClientSucc = (succIdx < order.count()) ? order.at(succIdx).data() : 0;
q->raiseClient(lastRaisedClient); q->raiseClient(lastRaisedClient);
} }
} }
@ -415,7 +421,7 @@ bool TabBoxHandler::containsPos(const QPoint& pos) const
return w->geometry().contains(pos); return w->geometry().contains(pos);
} }
QModelIndex TabBoxHandler::index(KWin::TabBox::TabBoxClient* client) const QModelIndex TabBoxHandler::index(QWeakPointer<KWin::TabBox::TabBoxClient> client) const
{ {
return d->clientModel()->index(client); return d->clientModel()->index(client);
} }
@ -440,13 +446,29 @@ TabBoxClient* TabBoxHandler::client(const QModelIndex& index) const
void TabBoxHandler::createModel(bool partialReset) void TabBoxHandler::createModel(bool partialReset)
{ {
switch(d->config.tabBoxMode()) { switch(d->config.tabBoxMode()) {
case TabBoxConfig::ClientTabBox: case TabBoxConfig::ClientTabBox: {
d->clientModel()->createClientList(partialReset); d->clientModel()->createClientList(partialReset);
if (d->lastRaisedClient && !stackingOrder().contains(d->lastRaisedClient)) // TODO: C++11 use lambda function
bool lastRaised = false;
bool lastRaisedSucc = false;
foreach (QWeakPointer<TabBoxClient> clientPointer, stackingOrder()) {
QSharedPointer<TabBoxClient> client = clientPointer.toStrongRef();
if (!client) {
continue;
}
if (client.data() == d->lastRaisedClient) {
lastRaised = true;
}
if (client.data() == d->lastRaisedClientSucc) {
lastRaisedSucc = true;
}
}
if (d->lastRaisedClient && !lastRaised)
d->lastRaisedClient = 0; d->lastRaisedClient = 0;
if (d->lastRaisedClientSucc && !stackingOrder().contains(d->lastRaisedClientSucc)) if (d->lastRaisedClientSucc && !lastRaisedSucc)
d->lastRaisedClientSucc = 0; d->lastRaisedClientSucc = 0;
break; break;
}
case TabBoxConfig::DesktopTabBox: case TabBoxConfig::DesktopTabBox:
d->desktopModel()->createDesktopList(); d->desktopModel()->createDesktopList();
break; break;

View file

@ -81,7 +81,7 @@ class ClientModel;
class TabBoxConfig; class TabBoxConfig;
class TabBoxClient; class TabBoxClient;
class TabBoxHandlerPrivate; class TabBoxHandlerPrivate;
typedef QList< TabBoxClient* > TabBoxClientList; typedef QList< QWeakPointer< TabBoxClient > > TabBoxClientList;
/** /**
* This class is a wrapper around KWin Workspace. It is used for accessing the * This class is a wrapper around KWin Workspace. It is used for accessing the
@ -105,12 +105,12 @@ public:
* @return The current active TabBoxClient or NULL * @return The current active TabBoxClient or NULL
* if there is no active client. * if there is no active client.
*/ */
virtual TabBoxClient* activeClient() const = 0; virtual QWeakPointer<TabBoxClient> activeClient() const = 0;
/** /**
* @param client The client which is starting point to find the next client * @param client The client which is starting point to find the next client
* @return The next TabBoxClient in focus chain * @return The next TabBoxClient in focus chain
*/ */
virtual TabBoxClient* nextClientFocusChain(TabBoxClient* client) const = 0; virtual QWeakPointer<TabBoxClient> nextClientFocusChain(TabBoxClient* client) const = 0;
/** /**
* @param client The client whose desktop name should be retrieved * @param client The client whose desktop name should be retrieved
* @return The desktop name of the given TabBoxClient. If the client is * @return The desktop name of the given TabBoxClient. If the client is
@ -172,11 +172,11 @@ public:
* @param allDesktops Add clients from all desktops or only from current * @param allDesktops Add clients from all desktops or only from current
* @return The client to be included in the list or NULL if it isn't to be included * @return The client to be included in the list or NULL if it isn't to be included
*/ */
virtual TabBoxClient* clientToAddToList(TabBoxClient* client, int desktop) const = 0; virtual QWeakPointer<TabBoxClient> clientToAddToList(TabBoxClient* client, int desktop) const = 0;
/** /**
* @return The first desktop window in the stacking order. * @return The first desktop window in the stacking order.
*/ */
virtual TabBoxClient* desktopClient() const = 0; virtual QWeakPointer<TabBoxClient> desktopClient() const = 0;
/** /**
* Activates the currently selected client and closes the TabBox. * Activates the currently selected client and closes the TabBox.
**/ **/
@ -278,7 +278,7 @@ public:
* if the model does not contain the given TabBoxClient. * if the model does not contain the given TabBoxClient.
* @see ClientModel::index * @see ClientModel::index
*/ */
QModelIndex index(TabBoxClient* client) const; QModelIndex index(QWeakPointer<TabBoxClient> client) const;
/** /**
* @return Returns the current list of TabBoxClients. * @return Returns the current list of TabBoxClients.
* If TabBoxMode is not TabBoxConfig::ClientTabBox an empty list will * If TabBoxMode is not TabBoxConfig::ClientTabBox an empty list will