1 | /* |
2 | SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "kwindowinfo.h" |
8 | #include "kwindowsystem.h" |
9 | #include "kwindowsystem_debug.h" |
10 | #include "kx11extras.h" |
11 | #include "netwm.h" |
12 | |
13 | #include <config-kwindowsystem.h> |
14 | |
15 | #include "private/qtx11extras_p.h" |
16 | #include <QDebug> |
17 | #include <QRect> |
18 | |
19 | #include "kxerrorhandler_p.h" |
20 | #include <X11/Xatom.h> |
21 | #include <X11/Xlib.h> |
22 | #include <xcb/res.h> |
23 | |
24 | #include "cptr_p.h" |
25 | |
26 | static bool haveXRes() |
27 | { |
28 | static bool s_checked = false; |
29 | static bool s_haveXRes = false; |
30 | if (!s_checked) { |
31 | auto cookie = xcb_res_query_version(c: QX11Info::connection(), XCB_RES_MAJOR_VERSION, XCB_RES_MINOR_VERSION); |
32 | UniqueCPointer<xcb_res_query_version_reply_t> reply(xcb_res_query_version_reply(c: QX11Info::connection(), cookie, e: nullptr)); |
33 | s_haveXRes = reply != nullptr; |
34 | s_checked = true; |
35 | } |
36 | return s_haveXRes; |
37 | } |
38 | |
39 | class Q_DECL_HIDDEN KWindowInfoPrivate : public QSharedData |
40 | { |
41 | public: |
42 | WId window; |
43 | NET::Properties properties; |
44 | NET::Properties2 properties2; |
45 | |
46 | std::unique_ptr<NETWinInfo> m_info; |
47 | QString m_name; |
48 | QString m_iconic_name; |
49 | QRect m_geometry; |
50 | QRect m_frame_geometry; |
51 | int m_pid = -1; // real PID from XResources. Valid if > 0 |
52 | bool m_valid = false; |
53 | }; |
54 | |
55 | KWindowInfo::KWindowInfo(WId window, NET::Properties properties, NET::Properties2 properties2) |
56 | : d(new KWindowInfoPrivate) |
57 | { |
58 | d->window = window; |
59 | d->properties = properties; |
60 | d->properties2 = properties2; |
61 | |
62 | if (!KWindowSystem::isPlatformX11()) { |
63 | return; |
64 | } |
65 | |
66 | KXErrorHandler handler; |
67 | if (properties & NET::WMVisibleIconName) { |
68 | properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback |
69 | } |
70 | if (properties & NET::WMVisibleName) { |
71 | properties |= NET::WMName; // force, in case it will be used as a fallback |
72 | } |
73 | if (properties2 & NET::WM2ExtendedStrut) { |
74 | properties |= NET::WMStrut; // will be used as fallback |
75 | } |
76 | if (properties & NET::WMWindowType) { |
77 | properties2 |= NET::WM2TransientFor; // will be used when type is not set |
78 | } |
79 | if ((properties & NET::WMDesktop) && KX11Extras::mapViewport()) { |
80 | properties |= NET::WMGeometry; // for viewports, the desktop (workspace) is determined from the geometry |
81 | } |
82 | properties |= NET::XAWMState; // force to get error detection for valid() |
83 | d->m_info.reset(p: new NETWinInfo(QX11Info::connection(), d->window, QX11Info::appRootWindow(), properties, properties2)); |
84 | if (properties & NET::WMName) { |
85 | if (d->m_info->name() && d->m_info->name()[0] != '\0') { |
86 | d->m_name = QString::fromUtf8(utf8: d->m_info->name()); |
87 | } else { |
88 | d->m_name = KX11Extras::readNameProperty(window: d->window, XA_WM_NAME); |
89 | } |
90 | } |
91 | if (properties & NET::WMIconName) { |
92 | if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') { |
93 | d->m_iconic_name = QString::fromUtf8(utf8: d->m_info->iconName()); |
94 | } else { |
95 | d->m_iconic_name = KX11Extras::readNameProperty(window: d->window, XA_WM_ICON_NAME); |
96 | } |
97 | } |
98 | if (properties & (NET::WMGeometry | NET::WMFrameExtents)) { |
99 | NETRect frame; |
100 | NETRect geom; |
101 | d->m_info->kdeGeometry(frame, window&: geom); |
102 | d->m_geometry.setRect(ax: geom.pos.x, ay: geom.pos.y, aw: geom.size.width, ah: geom.size.height); |
103 | d->m_frame_geometry.setRect(ax: frame.pos.x, ay: frame.pos.y, aw: frame.size.width, ah: frame.size.height); |
104 | } |
105 | d->m_valid = !handler.error(sync: false); // no sync - NETWinInfo did roundtrips |
106 | |
107 | if (haveXRes()) { |
108 | xcb_res_client_id_spec_t specs; |
109 | specs.client = win(); |
110 | specs.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; |
111 | auto cookie = xcb_res_query_client_ids(c: QX11Info::connection(), num_specs: 1, specs: &specs); |
112 | |
113 | UniqueCPointer<xcb_res_query_client_ids_reply_t> reply(xcb_res_query_client_ids_reply(c: QX11Info::connection(), cookie, e: nullptr)); |
114 | if (reply && xcb_res_query_client_ids_ids_length(R: reply.get()) > 0) { |
115 | uint32_t pid = *xcb_res_client_id_value_value(R: (xcb_res_query_client_ids_ids_iterator(R: reply.get()).data)); |
116 | d->m_pid = pid; |
117 | } |
118 | } |
119 | } |
120 | |
121 | KWindowInfo::KWindowInfo(const KWindowInfo &other) |
122 | : d(other.d) |
123 | { |
124 | } |
125 | |
126 | KWindowInfo::~KWindowInfo() |
127 | { |
128 | } |
129 | |
130 | KWindowInfo &KWindowInfo::operator=(const KWindowInfo &other) |
131 | { |
132 | if (d != other.d) { |
133 | d = other.d; |
134 | } |
135 | return *this; |
136 | } |
137 | |
138 | bool KWindowInfo::valid(bool withdrawn_is_valid) const |
139 | { |
140 | if (!KWindowSystem::isPlatformX11()) { |
141 | return false; |
142 | } |
143 | |
144 | if (!d->m_valid) { |
145 | return false; |
146 | } |
147 | if (!withdrawn_is_valid && mappingState() == NET::Withdrawn) { |
148 | return false; |
149 | } |
150 | return true; |
151 | } |
152 | |
153 | WId KWindowInfo::win() const |
154 | { |
155 | return d->window; |
156 | } |
157 | |
158 | #define CHECK_X11 \ |
159 | if (!KWindowSystem::isPlatformX11()) { \ |
160 | qCWarning(LOG_KWINDOWSYSTEM) << "KWindowInfo is only functional when running on X11"; \ |
161 | return {}; \ |
162 | } |
163 | |
164 | NET::States KWindowInfo::state() const |
165 | { |
166 | CHECK_X11 |
167 | #if !defined(KDE_NO_WARNING_OUTPUT) |
168 | if (!(d->m_info->passedProperties() & NET::WMState)) { |
169 | qWarning() << "Pass NET::WMState to KWindowInfo" ; |
170 | } |
171 | #endif |
172 | return d->m_info->state(); |
173 | } |
174 | |
175 | bool KWindowInfo::hasState(NET::States s) const |
176 | { |
177 | CHECK_X11 |
178 | return (state() & s) == s; |
179 | } |
180 | |
181 | bool KWindowInfo::icccmCompliantMappingState() const |
182 | { |
183 | CHECK_X11 |
184 | static enum { noidea, yes, no } wm_is_1_2_compliant = noidea; |
185 | if (wm_is_1_2_compliant == noidea) { |
186 | NETRootInfo info(QX11Info::connection(), NET::Supported, NET::Properties2(), QX11Info::appScreen()); |
187 | wm_is_1_2_compliant = info.isSupported(state: NET::Hidden) ? yes : no; |
188 | } |
189 | return wm_is_1_2_compliant == yes; |
190 | } |
191 | |
192 | // see NETWM spec section 7.6 |
193 | bool KWindowInfo::isMinimized() const |
194 | { |
195 | CHECK_X11 |
196 | if (mappingState() != NET::Iconic) { |
197 | return false; |
198 | } |
199 | // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows |
200 | if ((state() & NET::Hidden) != 0 && (state() & NET::Shaded) == 0) { // shaded may have NET::Hidden too |
201 | return true; |
202 | } |
203 | // older WMs use WithdrawnState for other virtual desktops |
204 | // and IconicState only for minimized |
205 | return icccmCompliantMappingState() ? false : true; |
206 | } |
207 | |
208 | NET::MappingState KWindowInfo::mappingState() const |
209 | { |
210 | CHECK_X11 |
211 | #if !defined(KDE_NO_WARNING_OUTPUT) |
212 | if (!(d->m_info->passedProperties() & NET::XAWMState)) { |
213 | qWarning() << "Pass NET::XAWMState to KWindowInfo" ; |
214 | } |
215 | #endif |
216 | return d->m_info->mappingState(); |
217 | } |
218 | |
219 | NETExtendedStrut KWindowInfo::extendedStrut() const |
220 | { |
221 | CHECK_X11 |
222 | #if !defined(KDE_NO_WARNING_OUTPUT) |
223 | if (!(d->m_info->passedProperties2() & NET::WM2ExtendedStrut)) { |
224 | qWarning() << "Pass NET::WM2ExtendedStrut to KWindowInfo" ; |
225 | } |
226 | #endif |
227 | NETExtendedStrut ext = d->m_info->extendedStrut(); |
228 | NETStrut str = d->m_info->strut(); |
229 | if (ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 |
230 | && (str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0)) { |
231 | // build extended from simple |
232 | if (str.left != 0) { |
233 | ext.left_width = str.left; |
234 | ext.left_start = 0; |
235 | ext.left_end = XDisplayHeight(QX11Info::display(), DefaultScreen(QX11Info::display())); |
236 | } |
237 | if (str.right != 0) { |
238 | ext.right_width = str.right; |
239 | ext.right_start = 0; |
240 | ext.right_end = XDisplayHeight(QX11Info::display(), DefaultScreen(QX11Info::display())); |
241 | } |
242 | if (str.top != 0) { |
243 | ext.top_width = str.top; |
244 | ext.top_start = 0; |
245 | ext.top_end = XDisplayWidth(QX11Info::display(), DefaultScreen(QX11Info::display())); |
246 | } |
247 | if (str.bottom != 0) { |
248 | ext.bottom_width = str.bottom; |
249 | ext.bottom_start = 0; |
250 | ext.bottom_end = XDisplayWidth(QX11Info::display(), DefaultScreen(QX11Info::display())); |
251 | } |
252 | } |
253 | return ext; |
254 | } |
255 | |
256 | NET::WindowType KWindowInfo::windowType(NET::WindowTypes supported_types) const |
257 | { |
258 | CHECK_X11 |
259 | #if !defined(KDE_NO_WARNING_OUTPUT) |
260 | if (!(d->m_info->passedProperties() & NET::WMWindowType)) { |
261 | qWarning() << "Pass NET::WMWindowType to KWindowInfo" ; |
262 | } |
263 | #endif |
264 | if (!d->m_info->hasWindowType()) { // fallback, per spec recommendation |
265 | if (transientFor() != XCB_WINDOW_NONE) { // dialog |
266 | if (supported_types & NET::DialogMask) { |
267 | return NET::Dialog; |
268 | } |
269 | } else { |
270 | if (supported_types & NET::NormalMask) { |
271 | return NET::Normal; |
272 | } |
273 | } |
274 | } |
275 | return d->m_info->windowType(supported_types); |
276 | } |
277 | |
278 | QString KWindowInfo::visibleName() const |
279 | { |
280 | CHECK_X11 |
281 | #if !defined(KDE_NO_WARNING_OUTPUT) |
282 | if (!(d->m_info->passedProperties() & NET::WMVisibleName)) { |
283 | qWarning() << "Pass NET::WMVisibleName to KWindowInfo" ; |
284 | } |
285 | #endif |
286 | return d->m_info->visibleName() && d->m_info->visibleName()[0] != '\0' ? QString::fromUtf8(utf8: d->m_info->visibleName()) : name(); |
287 | } |
288 | |
289 | QString KWindowInfo::visibleNameWithState() const |
290 | { |
291 | CHECK_X11 |
292 | QString s = visibleName(); |
293 | if (isMinimized()) { |
294 | s.prepend(c: QLatin1Char('(')); |
295 | s.append(c: QLatin1Char(')')); |
296 | } |
297 | return s; |
298 | } |
299 | |
300 | QString KWindowInfo::name() const |
301 | { |
302 | CHECK_X11 |
303 | #if !defined(KDE_NO_WARNING_OUTPUT) |
304 | if (!(d->m_info->passedProperties() & NET::WMName)) { |
305 | qWarning() << "Pass NET::WMName to KWindowInfo" ; |
306 | } |
307 | #endif |
308 | return d->m_name; |
309 | } |
310 | |
311 | QString KWindowInfo::visibleIconName() const |
312 | { |
313 | CHECK_X11 |
314 | #if !defined(KDE_NO_WARNING_OUTPUT) |
315 | if (!(d->m_info->passedProperties() & NET::WMVisibleIconName)) { |
316 | qWarning() << "Pass NET::WMVisibleIconName to KWindowInfo" ; |
317 | } |
318 | #endif |
319 | if (d->m_info->visibleIconName() && d->m_info->visibleIconName()[0] != '\0') { |
320 | return QString::fromUtf8(utf8: d->m_info->visibleIconName()); |
321 | } |
322 | if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') { |
323 | return QString::fromUtf8(utf8: d->m_info->iconName()); |
324 | } |
325 | if (!d->m_iconic_name.isEmpty()) { |
326 | return d->m_iconic_name; |
327 | } |
328 | return visibleName(); |
329 | } |
330 | |
331 | QString KWindowInfo::visibleIconNameWithState() const |
332 | { |
333 | CHECK_X11 |
334 | QString s = visibleIconName(); |
335 | if (isMinimized()) { |
336 | s.prepend(c: QLatin1Char('(')); |
337 | s.append(c: QLatin1Char(')')); |
338 | } |
339 | return s; |
340 | } |
341 | |
342 | QString KWindowInfo::iconName() const |
343 | { |
344 | CHECK_X11 |
345 | #if !defined(KDE_NO_WARNING_OUTPUT) |
346 | if (!(d->m_info->passedProperties() & NET::WMIconName)) { |
347 | qWarning() << "Pass NET::WMIconName to KWindowInfo" ; |
348 | } |
349 | #endif |
350 | if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') { |
351 | return QString::fromUtf8(utf8: d->m_info->iconName()); |
352 | } |
353 | if (!d->m_iconic_name.isEmpty()) { |
354 | return d->m_iconic_name; |
355 | } |
356 | return name(); |
357 | } |
358 | |
359 | bool KWindowInfo::isOnCurrentDesktop() const |
360 | { |
361 | CHECK_X11 |
362 | return isOnDesktop(desktop: KX11Extras::currentDesktop()); |
363 | } |
364 | |
365 | bool KWindowInfo::isOnDesktop(int desktop) const |
366 | { |
367 | CHECK_X11 |
368 | #if !defined(KDE_NO_WARNING_OUTPUT) |
369 | if (!(d->m_info->passedProperties() & NET::WMDesktop)) { |
370 | qWarning() << "Pass NET::WMDesktop to KWindowInfo" ; |
371 | } |
372 | #endif |
373 | if (KX11Extras::mapViewport()) { |
374 | if (onAllDesktops()) { |
375 | return true; |
376 | } |
377 | return KX11Extras::viewportWindowToDesktop(r: d->m_geometry) == desktop; |
378 | } |
379 | return d->m_info->desktop() == desktop || d->m_info->desktop() == NET::OnAllDesktops; |
380 | } |
381 | |
382 | bool KWindowInfo::onAllDesktops() const |
383 | { |
384 | CHECK_X11 |
385 | #if !defined(KDE_NO_WARNING_OUTPUT) |
386 | if (!(d->m_info->passedProperties() & NET::WMDesktop)) { |
387 | qWarning() << "Pass NET::WMDesktop to KWindowInfo" ; |
388 | } |
389 | #endif |
390 | if (KX11Extras::mapViewport()) { |
391 | if (d->m_info->passedProperties() & NET::WMState) { |
392 | return d->m_info->state() & NET::Sticky; |
393 | } |
394 | NETWinInfo info(QX11Info::connection(), win(), QX11Info::appRootWindow(), NET::WMState, NET::Properties2()); |
395 | return info.state() & NET::Sticky; |
396 | } |
397 | return d->m_info->desktop() == NET::OnAllDesktops; |
398 | } |
399 | |
400 | int KWindowInfo::desktop() const |
401 | { |
402 | CHECK_X11 |
403 | #if !defined(KDE_NO_WARNING_OUTPUT) |
404 | if (!(d->m_info->passedProperties() & NET::WMDesktop)) { |
405 | qWarning() << "Pass NET::WMDesktop to KWindowInfo" ; |
406 | } |
407 | #endif |
408 | if (KX11Extras::mapViewport()) { |
409 | if (onAllDesktops()) { |
410 | return NET::OnAllDesktops; |
411 | } |
412 | return KX11Extras::viewportWindowToDesktop(r: d->m_geometry); |
413 | } |
414 | return d->m_info->desktop(); |
415 | } |
416 | |
417 | QStringList KWindowInfo::activities() const |
418 | { |
419 | CHECK_X11 |
420 | #if !defined(KDE_NO_WARNING_OUTPUT) |
421 | if (!(d->m_info->passedProperties2() & NET::WM2Activities)) { |
422 | qWarning() << "Pass NET::WM2Activities to KWindowInfo" ; |
423 | } |
424 | #endif |
425 | |
426 | const QStringList result = QString::fromLatin1(ba: d->m_info->activities()).split(sep: QLatin1Char(','), behavior: Qt::SkipEmptyParts); |
427 | |
428 | return result.contains(QStringLiteral(KDE_ALL_ACTIVITIES_UUID)) ? QStringList() : result; |
429 | } |
430 | |
431 | QRect KWindowInfo::geometry() const |
432 | { |
433 | CHECK_X11 |
434 | #if !defined(KDE_NO_WARNING_OUTPUT) |
435 | if (!(d->m_info->passedProperties() & NET::WMGeometry)) { |
436 | qWarning() << "Pass NET::WMGeometry to KWindowInfo" ; |
437 | } |
438 | #endif |
439 | return d->m_geometry; |
440 | } |
441 | |
442 | QRect KWindowInfo::frameGeometry() const |
443 | { |
444 | CHECK_X11 |
445 | #if !defined(KDE_NO_WARNING_OUTPUT) |
446 | if (!(d->m_info->passedProperties() & NET::WMFrameExtents)) { |
447 | qWarning() << "Pass NET::WMFrameExtents to KWindowInfo" ; |
448 | } |
449 | #endif |
450 | return d->m_frame_geometry; |
451 | } |
452 | |
453 | WId KWindowInfo::transientFor() const |
454 | { |
455 | CHECK_X11 |
456 | #if !defined(KDE_NO_WARNING_OUTPUT) |
457 | if (!(d->m_info->passedProperties2() & NET::WM2TransientFor)) { |
458 | qWarning() << "Pass NET::WM2TransientFor to KWindowInfo" ; |
459 | } |
460 | #endif |
461 | return d->m_info->transientFor(); |
462 | } |
463 | |
464 | WId KWindowInfo::groupLeader() const |
465 | { |
466 | CHECK_X11 |
467 | #if !defined(KDE_NO_WARNING_OUTPUT) |
468 | if (!(d->m_info->passedProperties2() & NET::WM2GroupLeader)) { |
469 | qWarning() << "Pass NET::WM2GroupLeader to KWindowInfo" ; |
470 | } |
471 | #endif |
472 | return d->m_info->groupLeader(); |
473 | } |
474 | |
475 | QByteArray KWindowInfo::windowClassClass() const |
476 | { |
477 | CHECK_X11 |
478 | #if !defined(KDE_NO_WARNING_OUTPUT) |
479 | if (!(d->m_info->passedProperties2() & NET::WM2WindowClass)) { |
480 | qWarning() << "Pass NET::WM2WindowClass to KWindowInfo" ; |
481 | } |
482 | #endif |
483 | return d->m_info->windowClassClass(); |
484 | } |
485 | |
486 | QByteArray KWindowInfo::windowClassName() const |
487 | { |
488 | CHECK_X11 |
489 | #if !defined(KDE_NO_WARNING_OUTPUT) |
490 | if (!(d->m_info->passedProperties2() & NET::WM2WindowClass)) { |
491 | qWarning() << "Pass NET::WM2WindowClass to KWindowInfo" ; |
492 | } |
493 | #endif |
494 | return d->m_info->windowClassName(); |
495 | } |
496 | |
497 | QByteArray KWindowInfo::windowRole() const |
498 | { |
499 | CHECK_X11 |
500 | #if !defined(KDE_NO_WARNING_OUTPUT) |
501 | if (!(d->m_info->passedProperties2() & NET::WM2WindowRole)) { |
502 | qWarning() << "Pass NET::WM2WindowRole to KWindowInfo" ; |
503 | } |
504 | #endif |
505 | return d->m_info->windowRole(); |
506 | } |
507 | |
508 | QByteArray KWindowInfo::clientMachine() const |
509 | { |
510 | CHECK_X11 |
511 | #if !defined(KDE_NO_WARNING_OUTPUT) |
512 | if (!(d->m_info->passedProperties2() & NET::WM2ClientMachine)) { |
513 | qWarning() << "Pass NET::WM2ClientMachine to KWindowInfo" ; |
514 | } |
515 | #endif |
516 | return d->m_info->clientMachine(); |
517 | } |
518 | |
519 | bool KWindowInfo::allowedActionsSupported() const |
520 | { |
521 | CHECK_X11 |
522 | static enum { noidea, yes, no } wm_supports_allowed_actions = noidea; |
523 | if (wm_supports_allowed_actions == noidea) { |
524 | NETRootInfo info(QX11Info::connection(), NET::Supported, NET::Properties2(), QX11Info::appScreen()); |
525 | wm_supports_allowed_actions = info.isSupported(property: NET::WM2AllowedActions) ? yes : no; |
526 | } |
527 | return wm_supports_allowed_actions == yes; |
528 | } |
529 | |
530 | bool KWindowInfo::actionSupported(NET::Action action) const |
531 | { |
532 | CHECK_X11 |
533 | #if !defined(KDE_NO_WARNING_OUTPUT) |
534 | if (!(d->m_info->passedProperties2() & NET::WM2AllowedActions)) { |
535 | qWarning() << "Pass NET::WM2AllowedActions to KWindowInfo" ; |
536 | } |
537 | #endif |
538 | if (allowedActionsSupported()) { |
539 | return d->m_info->allowedActions() & action; |
540 | } else { |
541 | return true; // no idea if it's supported or not -> pretend it is |
542 | } |
543 | } |
544 | |
545 | QByteArray KWindowInfo::desktopFileName() const |
546 | { |
547 | CHECK_X11 |
548 | #if !defined(KDE_NO_WARNING_OUTPUT) |
549 | if (!(d->m_info->passedProperties2() & NET::WM2DesktopFileName)) { |
550 | qWarning() << "Pass NET::WM2DesktopFileName to KWindowInfo" ; |
551 | } |
552 | #endif |
553 | return QByteArray(d->m_info->desktopFileName()); |
554 | } |
555 | |
556 | QByteArray KWindowInfo::gtkApplicationId() const |
557 | { |
558 | CHECK_X11 |
559 | #if !defined(KDE_NO_WARNING_OUTPUT) |
560 | if (!(d->m_info->passedProperties2() & NET::WM2DesktopFileName)) { |
561 | qWarning() << "Pass NET::WM2DesktopFileName to KWindowInfo" ; |
562 | } |
563 | #endif |
564 | return QByteArray(d->m_info->gtkApplicationId()); |
565 | } |
566 | |
567 | QByteArray KWindowInfo::() const |
568 | { |
569 | CHECK_X11 |
570 | #if !defined(KDE_NO_WARNING_OUTPUT) |
571 | if (!(d->m_info->passedProperties2() & NET::WM2AppMenuServiceName)) { |
572 | qWarning() << "Pass NET::WM2AppMenuServiceName to KWindowInfo" ; |
573 | } |
574 | #endif |
575 | return QByteArray(d->m_info->appMenuServiceName()); |
576 | } |
577 | |
578 | QByteArray KWindowInfo::() const |
579 | { |
580 | CHECK_X11 |
581 | #if !defined(KDE_NO_WARNING_OUTPUT) |
582 | if (!(d->m_info->passedProperties2() & NET::WM2AppMenuObjectPath)) { |
583 | qWarning() << "Pass NET::WM2AppMenuObjectPath to KWindowInfo" ; |
584 | } |
585 | #endif |
586 | return QByteArray(d->m_info->appMenuObjectPath()); |
587 | } |
588 | |
589 | int KWindowInfo::pid() const |
590 | { |
591 | CHECK_X11 |
592 | // If pid is found using the XRes extension use that instead. |
593 | // It is more reliable than the app reporting it's own PID as apps |
594 | // within an app namespace are unable to do so correctly |
595 | if (d->m_pid > 0) { |
596 | return d->m_pid; |
597 | } |
598 | |
599 | #if !defined(KDE_NO_WARNING_OUTPUT) |
600 | if (!(d->m_info->passedProperties() & NET::WMPid)) { |
601 | qWarning() << "Pass NET::WMPid to KWindowInfo" ; |
602 | } |
603 | #endif |
604 | |
605 | return d->m_info->pid(); |
606 | } |
607 | |