File indexing completed on 2024-11-10 04:57:45
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org> 0006 SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "group.h" 0012 #include "effect/effecthandler.h" 0013 #include "workspace.h" 0014 #include "x11window.h" 0015 0016 #include <KX11Extras> 0017 #include <QDebug> 0018 0019 namespace KWin 0020 { 0021 0022 //******************************************** 0023 // Group 0024 //******************************************** 0025 0026 Group::Group(xcb_window_t leader_P) 0027 : leader_client(nullptr) 0028 , leader_wid(leader_P) 0029 , leader_info(nullptr) 0030 , user_time(-1U) 0031 , refcount(0) 0032 { 0033 if (leader_P != XCB_WINDOW_NONE) { 0034 leader_client = workspace()->findClient(Predicate::WindowMatch, leader_P); 0035 leader_info = std::make_unique<NETWinInfo>(kwinApp()->x11Connection(), leader_P, kwinApp()->x11RootWindow(), 0036 NET::Properties(), NET::WM2StartupId); 0037 } 0038 effect_group = std::make_unique<EffectWindowGroup>(this); 0039 workspace()->addGroup(this); 0040 } 0041 0042 Group::~Group() = default; 0043 0044 QIcon Group::icon() const 0045 { 0046 if (leader_client != nullptr) { 0047 return leader_client->icon(); 0048 } else if (leader_wid != XCB_WINDOW_NONE) { 0049 QIcon ic; 0050 NETWinInfo info(kwinApp()->x11Connection(), leader_wid, kwinApp()->x11RootWindow(), NET::WMIcon, NET::WM2IconPixmap); 0051 auto readIcon = [&ic, &info, this](int size, bool scale = true) { 0052 const QPixmap pix = KX11Extras::icon(leader_wid, size, size, scale, KX11Extras::NETWM | KX11Extras::WMHints, &info); 0053 if (!pix.isNull()) { 0054 ic.addPixmap(pix); 0055 } 0056 }; 0057 readIcon(16); 0058 readIcon(32); 0059 readIcon(48, false); 0060 readIcon(64, false); 0061 readIcon(128, false); 0062 return ic; 0063 } 0064 return QIcon(); 0065 } 0066 0067 void Group::addMember(X11Window *member_P) 0068 { 0069 _members.append(member_P); 0070 // qDebug() << "GROUPADD:" << this << ":" << member_P; 0071 // qDebug() << kBacktrace(); 0072 } 0073 0074 void Group::removeMember(X11Window *member_P) 0075 { 0076 // qDebug() << "GROUPREMOVE:" << this << ":" << member_P; 0077 // qDebug() << kBacktrace(); 0078 Q_ASSERT(_members.contains(member_P)); 0079 _members.removeAll(member_P); 0080 // there are cases when automatic deleting of groups must be delayed, 0081 // e.g. when removing a member and doing some operation on the possibly 0082 // other members of the group (which would be however deleted already 0083 // if there were no other members) 0084 if (refcount == 0 && _members.isEmpty()) { 0085 workspace()->removeGroup(this); 0086 delete this; 0087 } 0088 } 0089 0090 void Group::ref() 0091 { 0092 ++refcount; 0093 } 0094 0095 void Group::deref() 0096 { 0097 if (--refcount == 0 && _members.isEmpty()) { 0098 workspace()->removeGroup(this); 0099 delete this; 0100 } 0101 } 0102 0103 void Group::gotLeader(X11Window *leader_P) 0104 { 0105 Q_ASSERT(leader_P->window() == leader_wid); 0106 leader_client = leader_P; 0107 } 0108 0109 void Group::lostLeader() 0110 { 0111 Q_ASSERT(!_members.contains(leader_client)); 0112 leader_client = nullptr; 0113 if (_members.isEmpty()) { 0114 workspace()->removeGroup(this); 0115 delete this; 0116 } 0117 } 0118 0119 } // namespace