Changeset View
Standalone View
applets/appmenu/plugin/appmenumodel.cpp
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | |||||
64 | 64 | | |||
65 | }; | 65 | }; | ||
66 | 66 | | |||
67 | AppMenuModel::AppMenuModel(QObject *parent) | 67 | AppMenuModel::AppMenuModel(QObject *parent) | ||
68 | : QAbstractListModel(parent), | 68 | : QAbstractListModel(parent), | ||
69 | m_serviceWatcher(new QDBusServiceWatcher(this)) | 69 | m_serviceWatcher(new QDBusServiceWatcher(this)) | ||
70 | { | 70 | { | ||
71 | connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &AppMenuModel::onActiveWindowChanged); | 71 | connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &AppMenuModel::onActiveWindowChanged); | ||
72 | connect(KWindowSystem::self() | ||||
73 | , static_cast<void (KWindowSystem::*)(WId)>(&KWindowSystem::windowChanged) | ||||
74 | , this | ||||
75 | , &AppMenuModel::onWindowChanged); | ||||
76 | | ||||
72 | connect(this, &AppMenuModel::modelNeedsUpdate, this, [this] { | 77 | connect(this, &AppMenuModel::modelNeedsUpdate, this, [this] { | ||
73 | if (!m_updatePending) { | 78 | if (!m_updatePending) { | ||
74 | m_updatePending = true; | 79 | m_updatePending = true; | ||
75 | QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); | 80 | QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); | ||
76 | } | 81 | } | ||
77 | }); | 82 | }); | ||
83 | | ||||
84 | connect(this, &AppMenuModel::screenGeometryChanged, this, [this] { | ||||
85 | onWindowChanged(m_currentWindowId); | ||||
86 | }); | ||||
davidedmundson: this emit keyword is confusing, you're calling a slot.
| |||||
87 | | ||||
78 | onActiveWindowChanged(KWindowSystem::activeWindow()); | 88 | onActiveWindowChanged(KWindowSystem::activeWindow()); | ||
79 | 89 | | |||
80 | m_serviceWatcher->setConnection(QDBusConnection::sessionBus()); | 90 | m_serviceWatcher->setConnection(QDBusConnection::sessionBus()); | ||
81 | //if our current DBus connection gets lost, close the menu | 91 | //if our current DBus connection gets lost, close the menu | ||
82 | //we'll select the new menu when the focus changes | 92 | //we'll select the new menu when the focus changes | ||
83 | connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &serviceName) | 93 | connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &serviceName) | ||
84 | { | 94 | { | ||
85 | if (serviceName == m_serviceName) { | 95 | if (serviceName == m_serviceName) { | ||
Show All 9 Lines | |||||
95 | { | 105 | { | ||
96 | return m_menuAvailable; | 106 | return m_menuAvailable; | ||
97 | } | 107 | } | ||
98 | 108 | | |||
99 | void AppMenuModel::setMenuAvailable(bool set) | 109 | void AppMenuModel::setMenuAvailable(bool set) | ||
100 | { | 110 | { | ||
101 | if (m_menuAvailable != set) { | 111 | if (m_menuAvailable != set) { | ||
102 | m_menuAvailable = set; | 112 | m_menuAvailable = set; | ||
113 | setMenuHidden(false); | ||||
103 | emit menuAvailableChanged(); | 114 | emit menuAvailableChanged(); | ||
104 | } | 115 | } | ||
105 | } | 116 | } | ||
106 | 117 | | |||
118 | bool AppMenuModel::menuHidden() const | ||||
119 | { | ||||
120 | return m_menuHidden; | ||||
121 | } | ||||
122 | | ||||
123 | void AppMenuModel::setMenuHidden(bool hide) | ||||
124 | { | ||||
125 | if (m_menuHidden != hide) { | ||||
126 | m_menuHidden = hide; | ||||
127 | emit menuHiddenChanged(); | ||||
128 | } | ||||
129 | } | ||||
130 | | ||||
131 | QRect AppMenuModel::screenGeometry() const | ||||
132 | { | ||||
133 | return m_screenGeometry; | ||||
134 | } | ||||
135 | | ||||
136 | void AppMenuModel::setScreenGeometry(QRect geometry) | ||||
137 | { | ||||
138 | if (m_screenGeometry == geometry) { | ||||
139 | return; | ||||
140 | } | ||||
141 | | ||||
142 | m_screenGeometry = geometry; | ||||
143 | emit screenGeometryChanged(); | ||||
144 | } | ||||
145 | | ||||
107 | int AppMenuModel::rowCount(const QModelIndex &parent) const | 146 | int AppMenuModel::rowCount(const QModelIndex &parent) const | ||
108 | { | 147 | { | ||
109 | Q_UNUSED(parent); | 148 | Q_UNUSED(parent); | ||
110 | if (!m_menuAvailable || !m_menu) { | 149 | if (!m_menuAvailable || !m_menu) { | ||
111 | return 0; | 150 | return 0; | ||
112 | } | 151 | } | ||
113 | 152 | | |||
114 | return m_menu->actions().count(); | 153 | return m_menu->actions().count(); | ||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | 175 | if (KWindowSystem::isPlatformX11()) { | |||
182 | 221 | | |||
183 | KWindowInfo info(id, NET::WMState | NET::WMWindowType, NET::WM2TransientFor); | 222 | KWindowInfo info(id, NET::WMState | NET::WMWindowType, NET::WM2TransientFor); | ||
184 | if (info.hasState(NET::SkipTaskbar) || | 223 | if (info.hasState(NET::SkipTaskbar) || | ||
185 | info.windowType(NET::UtilityMask) == NET::Utility || | 224 | info.windowType(NET::UtilityMask) == NET::Utility || | ||
186 | info.windowType(NET::DesktopMask) == NET::Desktop) { | 225 | info.windowType(NET::DesktopMask) == NET::Desktop) { | ||
187 | return; | 226 | return; | ||
188 | } | 227 | } | ||
189 | 228 | | |||
229 | m_currentWindowId = id; | ||||
davidedmundson: why move this? | |||||
this patch depends on https://phabricator.kde.org/D16715 that has moved it... The m_currentWindowId needs to be set only for windows that create correctly their menus. mvourlakos: this patch depends on https://phabricator.kde.org/D16715 that has moved it...
the reason is… | |||||
230 | | ||||
190 | WId transientId = info.transientFor(); | 231 | WId transientId = info.transientFor(); | ||
191 | // lok at transient windows first | 232 | // lok at transient windows first | ||
192 | while (transientId) { | 233 | while (transientId) { | ||
193 | if (updateMenuFromWindowIfHasMenu(transientId)) { | 234 | if (updateMenuFromWindowIfHasMenu(transientId)) { | ||
235 | setMenuHidden(false); | ||||
194 | return; | 236 | return; | ||
195 | } | 237 | } | ||
196 | transientId = KWindowInfo(transientId, nullptr, NET::WM2TransientFor).transientFor(); | 238 | transientId = KWindowInfo(transientId, nullptr, NET::WM2TransientFor).transientFor(); | ||
197 | } | 239 | } | ||
198 | 240 | | |||
199 | if (updateMenuFromWindowIfHasMenu(id)) { | 241 | if (updateMenuFromWindowIfHasMenu(id)) { | ||
242 | setMenuHidden(false); | ||||
200 | return; | 243 | return; | ||
201 | } | 244 | } | ||
202 | 245 | | |||
203 | // monitor whether an app menu becomes available later | 246 | // monitor whether an app menu becomes available later | ||
204 | // this can happen when an app starts, shows its window, and only later announces global menu (e.g. Firefox) | 247 | // this can happen when an app starts, shows its window, and only later announces global menu (e.g. Firefox) | ||
205 | qApp->installNativeEventFilter(this); | 248 | qApp->installNativeEventFilter(this); | ||
206 | m_currentWindowId = id; | 249 | m_delayedMenuWindowId = id; | ||
207 | 250 | | |||
208 | //no menu found, set it to unavailable | 251 | //no menu found, set it to unavailable | ||
209 | setMenuAvailable(false); | 252 | setMenuAvailable(false); | ||
210 | emit modelNeedsUpdate(); | 253 | emit modelNeedsUpdate(); | ||
211 | } | 254 | } | ||
212 | #endif | 255 | #endif | ||
213 | 256 | | |||
214 | } | 257 | } | ||
215 | 258 | | |||
259 | void AppMenuModel::onWindowChanged(WId id) | ||||
260 | { | ||||
261 | if (m_currentWindowId == id) { | ||||
262 | KWindowInfo info(id, NET::WMState | NET::WMGeometry); | ||||
263 | const bool contained = m_screenGeometry.isNull() || m_screenGeometry.contains(info.geometry().center()); | ||||
can we make this m_screenGeometry.isNull || m_screenGeom.contains(...) so that a user can not set a screen geometry to get windows on all screens davidedmundson: can we make this
m_screenGeometry.isNull || m_screenGeom.contains(...)
so that a user can… | |||||
you mean? setMenuHidden(info.isMinimized() || m_screenGeometry.isNull() || !m_screenGeometry.contains(info.geometry().center())); mvourlakos: you mean?
```
setMenuHidden(info.isMinimized() || m_screenGeometry.isNull() || ! | |||||
I mean const bool contained = m_screenGeometry.isNull() || m_screenGeometry.contains(info.geometry().center()) setMenuHidden(info.isMinimized() || !contained) davidedmundson: I mean
const bool contained = m_screenGeometry.isNull() || m_screenGeometry.contains(info. | |||||
264 | | ||||
265 | setMenuHidden(info.isMinimized() || !contained); | ||||
266 | } | ||||
267 | } | ||||
216 | 268 | | |||
217 | QHash<int, QByteArray> AppMenuModel::roleNames() const | 269 | QHash<int, QByteArray> AppMenuModel::roleNames() const | ||
218 | { | 270 | { | ||
219 | QHash<int, QByteArray> roleNames; | 271 | QHash<int, QByteArray> roleNames; | ||
220 | roleNames[MenuRole] = QByteArrayLiteral("activeMenu"); | 272 | roleNames[MenuRole] = QByteArrayLiteral("activeMenu"); | ||
221 | roleNames[ActionRole] = QByteArrayLiteral("activeActions"); | 273 | roleNames[ActionRole] = QByteArrayLiteral("activeActions"); | ||
222 | return roleNames; | 274 | return roleNames; | ||
223 | } | 275 | } | ||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Line(s) | 367 | if (!KWindowSystem::isPlatformX11() || eventType != "xcb_generic_event_t") { | |||
316 | return false; | 368 | return false; | ||
317 | } | 369 | } | ||
318 | 370 | | |||
319 | #if HAVE_X11 | 371 | #if HAVE_X11 | ||
320 | auto e = static_cast<xcb_generic_event_t *>(message); | 372 | auto e = static_cast<xcb_generic_event_t *>(message); | ||
321 | const uint8_t type = e->response_type & ~0x80; | 373 | const uint8_t type = e->response_type & ~0x80; | ||
322 | if (type == XCB_PROPERTY_NOTIFY) { | 374 | if (type == XCB_PROPERTY_NOTIFY) { | ||
323 | auto *event = reinterpret_cast<xcb_property_notify_event_t *>(e); | 375 | auto *event = reinterpret_cast<xcb_property_notify_event_t *>(e); | ||
324 | if (event->window == m_currentWindowId) { | 376 | if (event->window == m_delayedMenuWindowId) { | ||
325 | 377 | | |||
326 | auto serviceNameAtom = s_atoms.value(s_x11AppMenuServiceNamePropertyName); | 378 | auto serviceNameAtom = s_atoms.value(s_x11AppMenuServiceNamePropertyName); | ||
327 | auto objectPathAtom = s_atoms.value(s_x11AppMenuObjectPathPropertyName); | 379 | auto objectPathAtom = s_atoms.value(s_x11AppMenuObjectPathPropertyName); | ||
328 | 380 | | |||
329 | if (serviceNameAtom != XCB_ATOM_NONE && objectPathAtom != XCB_ATOM_NONE) { // shouldn't happen | 381 | if (serviceNameAtom != XCB_ATOM_NONE && objectPathAtom != XCB_ATOM_NONE) { // shouldn't happen | ||
330 | if (event->atom == serviceNameAtom || event->atom == objectPathAtom) { | 382 | if (event->atom == serviceNameAtom || event->atom == objectPathAtom) { | ||
331 | // see if we now have a menu | 383 | // see if we now have a menu | ||
332 | onActiveWindowChanged(KWindowSystem::activeWindow()); | 384 | onActiveWindowChanged(KWindowSystem::activeWindow()); | ||
Show All 11 Lines |
this emit keyword is confusing, you're calling a slot.