Move mainClients() and allMainClients from Client to AbstractClient

AbstractClient::mainClients is virtual and overriden in Client,
allMainClients has only a common implementation in AbstractClient.

In activation.cpp we still need one case where a temporary ClientList
needs to be constructed. Once transients are fully migrated that should
be removable again.
This commit is contained in:
Martin Gräßlin 2015-09-11 15:55:23 +02:00
parent a5d3317645
commit 1d242d9daf
12 changed files with 81 additions and 56 deletions

View file

@ -828,4 +828,21 @@ bool AbstractClient::hasTransient(const AbstractClient *c, bool indirect) const
return c->transientFor() == this;
}
QList< AbstractClient* > AbstractClient::mainClients() const
{
if (const AbstractClient *t = transientFor()) {
return QList<AbstractClient*>{const_cast< AbstractClient* >(t)};
}
return QList<AbstractClient*>();
}
QList<AbstractClient*> AbstractClient::allMainClients() const
{
auto result = mainClients();
foreach (const auto *cl, result) {
result += cl->allMainClients();
}
return result;
}
}

View file

@ -264,6 +264,8 @@ public:
* @todo: remove boolean trap
**/
virtual bool hasTransient(const AbstractClient* c, bool indirect) const;
virtual QList<AbstractClient*> mainClients() const; // Call once before loop , is not indirect
QList<AbstractClient*> allMainClients() const; // Call once before loop , is indirect
/**
* Returns true for "special" windows and false for windows which are "normal"
* (normal=window which has a border, can be moved by the user, can be closed, etc.)

View file

@ -483,13 +483,11 @@ bool Workspace::activateNextClient(AbstractClient* c)
if (!get_focus) { // no suitable window under the mouse -> find sth. else
// first try to pass the focus to the (former) active clients leader
if (Client *client = qobject_cast<Client*>(c)) {
if (client->isTransient()) {
ClientList leaders = client->mainClients();
if (leaders.count() == 1 && FocusChain::self()->isUsableFocusCandidate(leaders.at(0), c)) {
get_focus = leaders.at(0);
raiseClient(get_focus); // also raise - we don't know where it came from
}
if (c->isTransient()) {
auto leaders = c->mainClients();
if (leaders.count() == 1 && FocusChain::self()->isUsableFocusCandidate(leaders.at(0), c)) {
get_focus = leaders.at(0);
raiseClient(get_focus); // also raise - we don't know where it came from
}
}
if (!get_focus) {
@ -730,11 +728,21 @@ xcb_timestamp_t Client::readUserTimeMapTimestamp(const KStartupInfoId *asn_id, c
&& cl != this && Client::belongToSameApplication(cl, this, true);
};
if (isTransient()) {
auto clientMainClients = [this] () -> ClientList {
ClientList ret;
const auto mcs = mainClients();
for (auto mc: mcs) {
if (Client *c = dynamic_cast<Client*>(mc)) {
ret << c;
}
}
return ret;
};
if (act->hasTransient(this, true))
; // is transient for currently active window, even though it's not
// the same app (e.g. kcookiejar dialog) -> allow activation
else if (groupTransient() &&
findInList<Client, Client>(mainClients(), sameApplicationActiveHackPredicate) == NULL)
findInList<Client, Client>(clientMainClients(), sameApplicationActiveHackPredicate) == NULL)
; // standalone transient
else
first_window = false;
@ -782,8 +790,8 @@ void Client::doSetActive()
{
StackingUpdatesBlocker blocker(workspace());
workspace()->updateClientLayer(this); // active windows may get different layer
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = mainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd();
++it)
if ((*it)->isFullScreen()) // fullscreens go high even if their transient is active

View file

@ -706,8 +706,8 @@ bool Client::isMinimizable() const
if (isTransient()) {
// #66868 - Let other xmms windows be minimized when the mainwindow is minimized
bool shown_mainwindow = false;
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = mainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd();
++it)
if ((*it)->isShown(true))
@ -747,7 +747,11 @@ QRect Client::iconGeometry() const
return geom;
else {
// Check all mainwindows of this window (recursively)
foreach (Client * mainwin, mainClients()) {
foreach (AbstractClient * amainwin, mainClients()) {
Client *mainwin = dynamic_cast<Client*>(amainwin);
if (!mainwin) {
continue;
}
geom = mainwin->iconGeometry();
if (geom.isValid())
return geom;
@ -1235,7 +1239,7 @@ void Client::doSetDesktop(int desktop, int was_desk)
// the (just moved) modal dialog will confusingly return to the mainwindow with
// the next desktop change
{
foreach (Client * c2, mainClients())
foreach (AbstractClient * c2, mainClients())
c2->setDesktop(desktop);
}
updateVisibility();
@ -1754,8 +1758,8 @@ void Client::getIcons()
}
if (icon.isNull() && isTransient()) {
// Then mainclients
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = mainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd() && icon.isNull();
++it) {
if (!(*it)->icon().isNull()) {

View file

@ -177,8 +177,7 @@ public:
bool isTransient() const override;
bool groupTransient() const;
bool wasOriginallyGroupTransient() const;
ClientList mainClients() const; // Call once before loop , is not indirect
ClientList allMainClients() const; // Call once before loop , is indirect
QList<AbstractClient*> mainClients() const override; // Call once before loop , is not indirect
bool hasTransient(const AbstractClient* c, bool indirect) const override;
const ClientList& transients() const; // Is not indirect
void checkTransient(xcb_window_t w);

View file

@ -102,9 +102,11 @@ void Deleted::copyToDeleted(Toplevel* c)
}
m_minimized = client->isMinimized();
m_modal = client->isModal();
}
if (AbstractClient *client = dynamic_cast<AbstractClient*>(c)) {
m_mainClients = client->mainClients();
foreach (Client *c, m_mainClients) {
connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(mainClientClosed(KWin::Toplevel*)));
foreach (AbstractClient *c, m_mainClients) {
connect(c, &AbstractClient::windowClosed, this, &Deleted::mainClientClosed);
}
}
}

View file

@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
class AbstractClient;
namespace Decoration
{
class Renderer;
@ -64,7 +66,7 @@ public:
bool isModal() const {
return m_modal;
}
ClientList mainClients() const {
QList<AbstractClient*> mainClients() const {
return m_mainClients;
}
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
@ -102,7 +104,7 @@ private:
Layer m_layer;
bool m_minimized;
bool m_modal;
ClientList m_mainClients;
QList<AbstractClient*> m_mainClients;
bool m_wasClient;
Decoration::Renderer *m_decorationRenderer;
double m_opacity;

View file

@ -1668,8 +1668,8 @@ EffectWindowList getMainWindows(Toplevel *toplevel)
{
T *c = static_cast<T*>(toplevel);
EffectWindowList ret;
ClientList mainclients = c->mainClients();
for (Client * tmp : mainclients)
const auto mainclients = c->mainClients();
for (auto tmp : mainclients)
ret.append(tmp->effectWindow());
return ret;
}

View file

@ -358,7 +358,7 @@ void Workspace::updateMinimizedOfTransients(Client* c)
}
}
if (c->isModal()) { // if a modal dialog is minimized, minimize its mainwindow too
foreach (Client * c2, c->mainClients())
foreach (AbstractClient * c2, c->mainClients())
c2->minimize();
}
} else {
@ -372,7 +372,7 @@ void Workspace::updateMinimizedOfTransients(Client* c)
}
}
if (c->isModal()) {
foreach (Client * c2, c->mainClients())
foreach (AbstractClient * c2, c->mainClients())
c2->unminimize();
}
}
@ -884,13 +884,13 @@ bool Client::hasTransientInternal(const Client* cl, bool indirect, ConstClientLi
return false;
}
ClientList Client::mainClients() const
QList<AbstractClient*> Client::mainClients() const
{
if (!isTransient())
return ClientList();
if (const Client *t = qobject_cast<const Client*>(transientFor()))
return ClientList() << const_cast< Client* >(t);
ClientList result;
return QList<AbstractClient*>();
if (const AbstractClient *t = transientFor())
return QList<AbstractClient*>{const_cast< AbstractClient* >(t)};
QList<AbstractClient*> result;
Q_ASSERT(group());
for (ClientList::ConstIterator it = group()->members().constBegin();
it != group()->members().constEnd();
@ -900,14 +900,6 @@ ClientList Client::mainClients() const
return result;
}
ClientList Client::allMainClients() const
{
ClientList result = mainClients();
foreach (const Client * cl, result)
result += cl->allMainClients();
return result;
}
AbstractClient* Client::findModal(bool allow_itself)
{
for (auto it = transients().constBegin();

View file

@ -188,12 +188,12 @@ bool Client::manage(xcb_window_t w, bool isMapped)
// same window as its parent. this is necessary when an application
// starts up on a different desktop than is currently displayed
if (isTransient()) {
ClientList mainclients = mainClients();
auto mainclients = mainClients();
bool on_current = false;
bool on_all = false;
Client* maincl = NULL;
AbstractClient* maincl = nullptr;
// This is slightly duplicated from Placement::placeOnMainWindow()
for (ClientList::ConstIterator it = mainclients.constBegin();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd();
++it) {
if (mainclients.count() > 1 && (*it)->isSpecialWindow())
@ -470,8 +470,8 @@ bool Client::manage(xcb_window_t w, bool isMapped)
// if client has initial state set to Iconic and is transient with a parent
// window that is not Iconic, set init_state to Normal
if (init_minimize && isTransient()) {
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = mainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd();
++it)
if ((*it)->isShown(true))
@ -482,8 +482,8 @@ bool Client::manage(xcb_window_t w, bool isMapped)
bool visible_parent = false;
// Use allMainClients(), to include also main clients of group transients
// that have been optimized out in Client::checkGroupTransients()
ClientList mainclients = allMainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = allMainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd();
++it)
if ((*it)->isShown(true))
@ -591,10 +591,12 @@ bool Client::manage(xcb_window_t w, bool isMapped)
*/
needsSessionInteract = true;
//show the parent too
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
auto mainclients = mainClients();
for (auto it = mainclients.constBegin();
it != mainclients.constEnd(); ++it) {
(*it)->setSessionInteract(true);
if (Client *mc = dynamic_cast<Client*>((*it))) {
mc->setSessionInteract(true);
}
(*it)->unminimize();
}
} else if (allow) {

View file

@ -521,14 +521,11 @@ void Placement::placeOnMainWindow(AbstractClient* c, QRect& area, Policy nextPla
if (nextPlacement == Maximizing) // maximize if needed
placeMaximizing(c, area, NoPlacement);
area = checkArea(c, area);
ClientList mainwindows;
if (Client *client = qobject_cast<Client*>(c)) {
mainwindows = client->mainClients();
}
auto mainwindows = c->mainClients();
AbstractClient* place_on = nullptr;
AbstractClient* place_on2 = nullptr;
int mains_count = 0;
for (ClientList::ConstIterator it = mainwindows.constBegin();
for (auto it = mainwindows.constBegin();
it != mainwindows.constEnd();
++it) {
if (mainwindows.count() > 1 && (*it)->isSpecialWindow())

View file

@ -693,12 +693,12 @@ void Workspace::updateToolWindows(bool also_hide)
show = false;
}
if (!show && also_hide) {
const ClientList mainclients = c->mainClients();
const auto mainclients = c->mainClients();
// Don't hide utility windows which are standalone(?) or
// have e.g. kicker as mainwindow
if (mainclients.isEmpty())
show = true;
for (ClientList::ConstIterator it2 = mainclients.constBegin();
for (auto it2 = mainclients.constBegin();
it2 != mainclients.constEnd();
++it2) {
if ((*it2)->isSpecialWindow())