Toplevel::windowType becomes a pure virtual function

The method windowType needs actually two implementations:
* one for Clients
* one for Unmanaged

as for Clients also the window rules are checked and hacks are applied
which is both not needed for Unmanaged windows.

To have the Client specific behavior in windowType the function used to
perform two dynamic_casts which made this method one of the most
expensive during compositing, e.g. for ~1000 frames
* called ~43000 times
* ~85000 dynamic casts
* incl. cost of method: 0.24
* self cost of method: 0.05
* incl. cost of the casts: 0.12

After the change to remove the dynamic casts we have for ~1500 frames
in Client::windowType:
* called ~31000 times
* incl. cost of 0.06
* self cost of 0.02

Calls on Unmanaged and Deleted are so low that we do not need to consider
them.

BUG: 306384
FIXED-IN: 4.10
REVIEW: 106349
icc-effect-5.14.5
Martin Gräßlin 2012-09-06 09:09:31 +02:00
parent 3aee94d798
commit 62d5e8124c
8 changed files with 46 additions and 21 deletions

View File

@ -2523,6 +2523,27 @@ bool Client::isClient() const
return true;
}
NET::WindowType Client::windowType(bool direct, int supportedTypes) const
{
// TODO: does it make sense to cache the returned window type for SUPPORTED_MANAGED_WINDOW_TYPES_MASK?
if (supportedTypes == 0) {
supportedTypes = SUPPORTED_MANAGED_WINDOW_TYPES_MASK;
}
NET::WindowType wt = info->windowType(supportedTypes);
if (direct) {
return wt;
}
NET::WindowType wt2 = client_rules.checkType(wt);
if (wt != wt2) {
wt = wt2;
info->setWindowType(wt); // force hint change
}
// hacks here
if (wt == NET::Unknown) // this is more or less suggested in NETWM spec
wt = isTransient() ? NET::Dialog : NET::Normal;
return wt;
}
} // namespace
#include "client.moc"

View File

@ -324,6 +324,7 @@ public:
#ifdef HAVE_XSYNC
void syncEvent(XSyncAlarmNotifyEvent* e);
#endif
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
bool manage(Window w, bool isMapped);
void releaseWindow(bool on_shutdown = false);

View File

@ -157,6 +157,16 @@ bool Deleted::isDeleted() const
return true;
}
NET::WindowType Deleted::windowType(bool direct, int supportedTypes) const
{
Q_UNUSED(direct)
// TODO: maybe retrieve the actual window type when copying to deleted?
if (supportedTypes == 0) {
supportedTypes = SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK;
}
return info->windowType(supportedTypes);
}
} // namespace
#include "deleted.moc"

View File

@ -66,6 +66,7 @@ public:
bool isMinimized() const {
return m_minimized;
}
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
protected:
virtual void debug(QDebug& stream) const;
virtual bool shouldUnredirect() const;

View File

@ -159,26 +159,6 @@ QRect Toplevel::visibleRect() const
return r.translated(geometry().topLeft());
}
NET::WindowType Toplevel::windowType(bool direct, int supported_types) const
{
if (supported_types == 0)
supported_types = dynamic_cast< const Client* >(this) != NULL
? SUPPORTED_MANAGED_WINDOW_TYPES_MASK : SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK;
NET::WindowType wt = info->windowType(supported_types);
if (direct)
return wt;
const Client* cl = dynamic_cast< const Client* >(this);
NET::WindowType wt2 = cl ? cl->rules()->checkType(wt) : wt;
if (wt != wt2) {
wt = wt2;
info->setWindowType(wt); // force hint change
}
// hacks here
if (wt == NET::Unknown && cl != NULL) // this is more or less suggested in NETWM spec
wt = cl->isTransient() ? NET::Dialog : NET::Normal;
return wt;
}
void Toplevel::getWindowRole()
{
window_role = getStringProperty(window(), atoms->wm_window_role).toLower();

View File

@ -188,7 +188,7 @@ public:
// prefer isXXX() instead
// 0 for supported types means default for managed/unmanaged types
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
virtual NET::WindowType windowType(bool direct = false, int supported_types = 0) const = 0;
bool hasNETSupport() const;
bool isDesktop() const;
bool isDock() const;

View File

@ -137,6 +137,17 @@ void Unmanaged::debug(QDebug& stream) const
stream << "\'ID:" << window() << "\'";
}
NET::WindowType Unmanaged::windowType(bool direct, int supportedTypes) const
{
// for unmanaged windows the direct does not make any difference
// as there are no rules to check and no hacks to apply
Q_UNUSED(direct)
if (supportedTypes == 0) {
supportedTypes = SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK;
}
return info->windowType(supportedTypes);
}
} // namespace
#include "unmanaged.moc"

View File

@ -46,6 +46,7 @@ public:
virtual Layer layer() const {
return UnmanagedLayer;
}
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
protected:
virtual void damageNotifyEvent(XDamageNotifyEvent* e);
virtual void debug(QDebug& stream) const;