[kwin] Use a QIcon in Client for the icons instead of Pixmaps

Client used to have dedicated methods for different icon sizes instead
of combining all pixmaps into one QIcon. This resulted in various parts
of KWin having different access to the icons:
* effects only got one pixmap of size 32x32
* decorations only got the 16x16 and 32x32 pixmaps combined into a QIcon
* tabbox could request all icon sizes, but only as pixmap

Now all sizes are available in one QIcon allowing to easily access the
best fitting icon in a given UI.
This commit is contained in:
Martin Gräßlin 2013-12-06 14:41:23 +01:00
parent 7aeec8ef89
commit 2372e02752
18 changed files with 72 additions and 158 deletions

View file

@ -91,9 +91,7 @@ NET::WindowType Bridge::windowType(unsigned long supported_types) const
QIcon Bridge::icon() const
{
QIcon ret(c->icon());
ret.addPixmap(c->miniIcon());
return ret;
return c->icon();
}
bool Bridge::isSetShade() const
@ -277,10 +275,7 @@ long Bridge::tabId(int idx) const
QIcon Bridge::icon(int idx) const
{
if (c->tabGroup()) {
Client *tabC = c->tabGroup()->clients().at(idx);
QIcon icon(tabC->icon());
icon.addPixmap(tabC->miniIcon());
return icon;
return c->tabGroup()->clients().at(idx)->icon();
}
return icon();
}

View file

@ -2010,77 +2010,47 @@ void Client::getMotifHints()
emit decoration->decorationButtonsChanged();
}
void Client::readIcons(xcb_window_t win, QPixmap* icon, QPixmap* miniicon, QPixmap* bigicon, QPixmap* hugeicon)
{
// Get the icons, allow scaling
if (icon != NULL)
*icon = KWindowSystem::icon(win, 32, 32, true, KWindowSystem::NETWM | KWindowSystem::WMHints);
if (miniicon != NULL) {
if (icon == NULL || !icon->isNull())
*miniicon = KWindowSystem::icon(win, 16, 16, true, KWindowSystem::NETWM | KWindowSystem::WMHints);
else
*miniicon = QPixmap();
}
if (bigicon != NULL) {
if (icon == NULL || !icon->isNull())
*bigicon = KWindowSystem::icon(win, 64, 64, false, KWindowSystem::NETWM | KWindowSystem::WMHints);
else
*bigicon = QPixmap();
}
if (hugeicon != NULL) {
if (icon == NULL || !icon->isNull())
*hugeicon = KWindowSystem::icon(win, 128, 128, false, KWindowSystem::NETWM | KWindowSystem::WMHints);
else
*hugeicon = QPixmap();
}
}
void Client::getIcons()
{
// First read icons from the window itself
readIcons(window(), &icon_pix, &miniicon_pix, &bigicon_pix, &hugeicon_pix);
if (icon_pix.isNull()) {
m_icon = QIcon();
auto readIcon = [this](int size, bool scale = true) {
const QPixmap pix = KWindowSystem::icon(window(), size, size, scale, KWindowSystem::NETWM | KWindowSystem::WMHints);
if (!pix.isNull()) {
m_icon.addPixmap(pix);
}
};
readIcon(16);
readIcon(32);
readIcon(48, false);
readIcon(64, false);
readIcon(128, false);
if (m_icon.isNull()) {
// Then try window group
icon_pix = group()->icon();
miniicon_pix = group()->miniIcon();
bigicon_pix = group()->bigIcon();
hugeicon_pix = group()->hugeIcon();
m_icon = group()->icon();
}
if (icon_pix.isNull() && isTransient()) {
if (m_icon.isNull() && isTransient()) {
// Then mainclients
ClientList mainclients = mainClients();
for (ClientList::ConstIterator it = mainclients.constBegin();
it != mainclients.constEnd() && icon_pix.isNull();
it != mainclients.constEnd() && m_icon.isNull();
++it) {
icon_pix = (*it)->icon();
miniicon_pix = (*it)->miniIcon();
bigicon_pix = (*it)->bigIcon();
hugeicon_pix = (*it)->hugeIcon();
if (!(*it)->icon().isNull()) {
m_icon = (*it)->icon();
break;
}
}
}
if (icon_pix.isNull()) {
if (m_icon.isNull()) {
// And if nothing else, load icon from classhint or xapp icon
icon_pix = KWindowSystem::icon(window(), 32, 32, true, KWindowSystem::ClassHint | KWindowSystem::XApp);
miniicon_pix = KWindowSystem::icon(window(), 16, 16, true, KWindowSystem::ClassHint | KWindowSystem::XApp);
bigicon_pix = KWindowSystem::icon(window(), 64, 64, false, KWindowSystem::ClassHint | KWindowSystem::XApp);
hugeicon_pix = KWindowSystem::icon(window(), 128, 128, false, KWindowSystem::ClassHint | KWindowSystem::XApp);
m_icon.addPixmap(KWindowSystem::icon(window(), 32, 32, true, KWindowSystem::ClassHint | KWindowSystem::XApp));
m_icon.addPixmap(KWindowSystem::icon(window(), 16, 16, true, KWindowSystem::ClassHint | KWindowSystem::XApp));
m_icon.addPixmap(KWindowSystem::icon(window(), 64, 64, false, KWindowSystem::ClassHint | KWindowSystem::XApp));
m_icon.addPixmap(KWindowSystem::icon(window(), 128, 128, false, KWindowSystem::ClassHint | KWindowSystem::XApp));
}
emit iconChanged();
}
QPixmap Client::icon(const QSize& size) const
{
const int iconSize = qMin(size.width(), size.height());
if (iconSize <= 16)
return miniIcon();
else if (iconSize <= 32)
return icon();
if (iconSize <= 64)
return bigIcon();
else
return hugeIcon();
}
void Client::getWindowProtocols()
{
Atom* p;

View file

@ -206,8 +206,7 @@ class Client
* Because of that no changed signal is provided.
**/
Q_PROPERTY(bool wantsInput READ wantsInput)
// TODO: a QIcon with all icon sizes?
Q_PROPERTY(QPixmap icon READ icon NOTIFY iconChanged)
Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
/**
* Whether the Client should be excluded from window switching effects.
**/
@ -332,11 +331,7 @@ public:
QSize adjustedSize(const QSize&, Sizemode mode = SizemodeAny) const;
QSize adjustedSize() const;
QPixmap icon() const;
QPixmap icon(const QSize& size) const;
QPixmap miniIcon() const;
QPixmap bigIcon() const;
QPixmap hugeIcon() const;
const QIcon &icon() const;
bool isActive() const;
void setActive(bool);
@ -511,7 +506,6 @@ public:
static bool belongToSameApplication(const Client* c1, const Client* c2, bool active_hack = false);
static bool sameAppWindowRoleMatch(const Client* c1, const Client* c2, bool active_hack);
static void readIcons(xcb_window_t win, QPixmap* icon, QPixmap* miniicon, QPixmap* bigicon, QPixmap* hugeicon);
void setMinimized(bool set);
void minimize(bool avoid_animation = false);
@ -916,12 +910,8 @@ private:
bool blocks_compositing;
WindowRules client_rules;
void getWMHints();
void readIcons();
void getWindowProtocols();
QPixmap icon_pix;
QPixmap miniicon_pix;
QPixmap bigicon_pix;
QPixmap hugeicon_pix;
QIcon m_icon;
Qt::CursorShape m_cursor;
// DON'T reorder - Saved to config files !!!
enum FullScreenMode {
@ -1109,24 +1099,9 @@ inline ShadeMode Client::shadeMode() const
return shade_mode;
}
inline QPixmap Client::icon() const
inline const QIcon &Client::icon() const
{
return icon_pix;
}
inline QPixmap Client::miniIcon() const
{
return miniicon_pix;
}
inline QPixmap Client::bigIcon() const
{
return bigicon_pix;
}
inline QPixmap Client::hugeIcon() const
{
return hugeicon_pix;
return m_icon;
}
inline QRect Client::geometryRestore() const

View file

@ -1960,19 +1960,19 @@ void EffectFrameImpl::setGeometry(const QRect& geometry, bool force)
free();
}
const QPixmap& EffectFrameImpl::icon() const
const QIcon& EffectFrameImpl::icon() const
{
return m_icon;
}
void EffectFrameImpl::setIcon(const QPixmap& icon)
void EffectFrameImpl::setIcon(const QIcon& icon)
{
m_icon = icon;
if (isCrossFade()) {
m_sceneFrame->crossFadeIcon();
}
if (m_iconSize.isEmpty()) { // Set a size if we don't already have one
setIconSize(m_icon.size());
if (m_iconSize.isEmpty() && !m_icon.availableSizes().isEmpty()) { // Set a size if we don't already have one
setIconSize(m_icon.availableSizes().first());
}
m_sceneFrame->freeIconFrame();
}

View file

@ -370,8 +370,8 @@ public:
virtual void setFont(const QFont& font);
virtual const QRect& geometry() const;
virtual void setGeometry(const QRect& geometry, bool force = false);
virtual const QPixmap& icon() const;
virtual void setIcon(const QPixmap& icon);
virtual const QIcon& icon() const override;
virtual void setIcon(const QIcon& icon) override;
virtual const QSize& iconSize() const;
virtual void setIconSize(const QSize& size);
virtual void setPosition(const QPoint& point);
@ -426,7 +426,7 @@ private:
// Contents
QString m_text;
QFont m_font;
QPixmap m_icon;
QIcon m_icon;
QSize m_iconSize;
QRect m_selectionGeometry;

View file

@ -429,6 +429,7 @@ void PresentWindowsEffect::slotWindowAdded(EffectWindow *w)
winData->iconFrame = effects->effectFrame(EffectFrameUnstyled, false);
winData->iconFrame->setAlignment(Qt::AlignRight | Qt::AlignBottom);
winData->iconFrame->setIcon(w->icon());
winData->iconFrame->setIconSize(QSize(32, 32));
if (isSelectableWindow(w)) {
m_motionManager.manage(w);
rearrangeWindows();
@ -1520,6 +1521,7 @@ void PresentWindowsEffect::setActive(bool active)
winData->iconFrame = effects->effectFrame(EffectFrameUnstyled, false);
winData->iconFrame->setAlignment(Qt::AlignRight | Qt::AlignBottom);
winData->iconFrame->setIcon(w->icon());
winData->iconFrame->setIconSize(QSize(32, 32));
}
// Filter out special windows such as panels and taskbars
foreach (EffectWindow * w, effects->stackingOrder()) {

View file

@ -35,6 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <assert.h>
#include <kstartupinfo.h>
#include <KWindowSystem>
#include <QDebug>
#include <QX11Info>
@ -217,52 +218,26 @@ Group::~Group()
delete effect_group;
}
QPixmap Group::icon() const
QIcon Group::icon() const
{
if (leader_client != NULL)
return leader_client->icon();
else if (leader_wid != None) {
QPixmap ic;
Client::readIcons(leader_wid, &ic, NULL, NULL, NULL);
QIcon ic;
auto readIcon = [&ic, this](int size, bool scale = true) {
const QPixmap pix = KWindowSystem::icon(leader_wid, size, size, scale, KWindowSystem::NETWM | KWindowSystem::WMHints);
if (!pix.isNull()) {
ic.addPixmap(pix);
}
};
readIcon(16);
readIcon(32);
readIcon(48, false);
readIcon(64, false);
readIcon(128, false);
return ic;
}
return QPixmap();
}
QPixmap Group::miniIcon() const
{
if (leader_client != NULL)
return leader_client->miniIcon();
else if (leader_wid != None) {
QPixmap ic;
Client::readIcons(leader_wid, NULL, &ic, NULL, NULL);
return ic;
}
return QPixmap();
}
QPixmap Group::bigIcon() const
{
if (leader_client != NULL)
return leader_client->bigIcon();
else if (leader_wid != None) {
QPixmap ic;
Client::readIcons(leader_wid, NULL, NULL, &ic, NULL);
return ic;
}
return QPixmap();
}
QPixmap Group::hugeIcon() const
{
if (leader_client != NULL)
return leader_client->hugeIcon();
else if (leader_wid != None) {
QPixmap ic;
Client::readIcons(leader_wid, NULL, NULL, NULL, &ic);
return ic;
}
return QPixmap();
return QIcon();
}
void Group::addMember(Client* member_P)

View file

@ -42,10 +42,7 @@ public:
const Client* leaderClient() const;
Client* leaderClient();
const ClientList& members() const;
QPixmap icon() const;
QPixmap miniIcon() const;
QPixmap bigIcon() const;
QPixmap hugeIcon() const;
QIcon icon() const;
void addMember(Client* member);
void removeMember(Client* member);
void gotLeader(Client* leader);

View file

@ -760,7 +760,7 @@ WINDOW_HELPER_DEFAULT(bool, isUserResize, "resize", false)
WINDOW_HELPER_DEFAULT(QRect, iconGeometry, "iconGeometry", QRect())
WINDOW_HELPER_DEFAULT(bool, isSpecialWindow, "specialWindow", true)
WINDOW_HELPER_DEFAULT(bool, acceptsFocus, "wantsInput", true) // We don't actually know...
WINDOW_HELPER_DEFAULT(QPixmap, icon, "icon", QPixmap())
WINDOW_HELPER_DEFAULT(QIcon, icon, "icon", QIcon())
WINDOW_HELPER_DEFAULT(bool, isSkipSwitcher, "skipSwitcher", false)
WINDOW_HELPER_DEFAULT(bool, isCurrentTab, "isCurrentTab", false)
WINDOW_HELPER_DEFAULT(bool, decorationHasAlpha, "decorationHasAlpha", false)

View file

@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwineffects_export.h>
#include <kwinglobals.h>
#include <QIcon>
#include <QPair>
#include <QSet>
#include <QRect>
@ -1472,7 +1473,7 @@ class KWINEFFECTS_EXPORT EffectWindow : public QObject
* management (moving, raising,...) on them.
**/
Q_PROPERTY(bool specialWindow READ isSpecialWindow)
Q_PROPERTY(QPixmap icon READ icon)
Q_PROPERTY(QIcon icon READ icon)
/**
* Whether the window should be excluded from window switching effects.
**/
@ -1597,7 +1598,7 @@ public:
virtual void deleteProperty(long atom) const = 0;
QString caption() const;
QPixmap icon() const;
QIcon icon() const;
QString windowClass() const;
QString windowRole() const;
virtual const EffectWindowGroup* group() const = 0;
@ -2648,8 +2649,8 @@ public:
/**
* Set the icon that will appear on the left-hand size of the frame.
*/
virtual void setIcon(const QPixmap& icon) = 0;
virtual const QPixmap& icon() const = 0;
virtual void setIcon(const QIcon& icon) = 0;
virtual const QIcon& icon() const = 0;
virtual void setIconSize(const QSize& size) = 0;
virtual const QSize& iconSize() const = 0;

View file

@ -2231,7 +2231,7 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
}
if (!m_iconTexture) { // lazy creation
m_iconTexture = m_scene->createTexture(m_effectFrame->icon());
m_iconTexture = m_scene->createTexture(m_effectFrame->icon().pixmap(m_effectFrame->iconSize()));
}
m_iconTexture->bind();
m_iconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));

View file

@ -899,7 +899,7 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr
QPoint topLeft(m_effectFrame->geometry().x(), m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2);
if (!m_iconPicture) // lazy creation
m_iconPicture = new XRenderPicture(m_effectFrame->icon().toImage());
m_iconPicture = new XRenderPicture(m_effectFrame->icon().pixmap(m_effectFrame->iconSize()).toImage());
QRect geom = QRect(topLeft, m_effectFrame->iconSize());
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *m_iconPicture, fill,
effects->xrenderBufferPicture(),

View file

@ -90,7 +90,7 @@ QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize
s = requestedSize;
}
*size = s;
QPixmap icon = client->icon(s);
QPixmap icon = client->icon().pixmap(s);
if (s.width() > icon.width() || s.height() > icon.height()) {
// icon is smaller than what we requested - QML would scale it which looks bad
QPixmap temp(s);

View file

@ -350,12 +350,12 @@ QString TabBoxClientImpl::caption() const
return m_client->caption();
}
QPixmap TabBoxClientImpl::icon(const QSize& size) const
QIcon TabBoxClientImpl::icon() const
{
if (m_client->isDesktop()) {
return QIcon::fromTheme(QStringLiteral("user-desktop")).pixmap(size);
return QIcon::fromTheme(QStringLiteral("user-desktop"));
}
return m_client->icon(size);
return m_client->icon();
}
WId TabBoxClientImpl::window() const

View file

@ -90,7 +90,7 @@ public:
virtual ~TabBoxClientImpl();
virtual QString caption() const;
virtual QPixmap icon(const QSize& size = QSize(32, 32)) const;
virtual QIcon icon() const override;
virtual WId window() const;
virtual bool isMinimized() const;
virtual int x() const;

View file

@ -373,7 +373,7 @@ public:
* @param size Requested size of the icon
* @return The icon of the client
*/
virtual QPixmap icon(const QSize& size = QSize(32, 32)) const = 0;
virtual QIcon icon() const = 0;
/**
* @return The window Id of the client
*/

View file

@ -37,7 +37,6 @@ TabGroup::TabGroup(Client *c)
, m_pendingUpdates(TabGroup::None)
{
QIcon icon(c->icon());
icon.addPixmap(c->miniIcon());
m_clients << c;
c->setTabGroup(this);
c->setClientShown(true);

View file

@ -169,7 +169,7 @@ void WindowThumbnailItem::paint(QPainter *painter)
if (!client) {
return;
}
QPixmap pixmap = client->icon(boundingRect().size().toSize());
QPixmap pixmap = client->icon().pixmap(boundingRect().size().toSize());
const QSize size(boundingRect().size().toSize() - pixmap.size());
painter->drawPixmap(boundingRect().adjusted(size.width()/2.0, size.height()/2.0, -size.width()/2.0, -size.height()/2.0).toRect(),
pixmap);