cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
607 lines
18 KiB
C++
607 lines
18 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
*/
|
|
|
|
#include "kwindowinfo.h"
|
|
#include "kwindowsystem.h"
|
|
#include "kwindowsystem_debug.h"
|
|
#include "kx11extras.h"
|
|
#include "netwm.h"
|
|
|
|
#include <config-kwindowsystem.h>
|
|
|
|
#include "private/qtx11extras_p.h"
|
|
#include <QDebug>
|
|
#include <QRect>
|
|
|
|
#include "kxerrorhandler_p.h"
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xlib.h>
|
|
#include <xcb/res.h>
|
|
|
|
#include "cptr_p.h"
|
|
|
|
static bool haveXRes()
|
|
{
|
|
static bool s_checked = false;
|
|
static bool s_haveXRes = false;
|
|
if (!s_checked) {
|
|
auto cookie = xcb_res_query_version(QX11Info::connection(), XCB_RES_MAJOR_VERSION, XCB_RES_MINOR_VERSION);
|
|
UniqueCPointer<xcb_res_query_version_reply_t> reply(xcb_res_query_version_reply(QX11Info::connection(), cookie, nullptr));
|
|
s_haveXRes = reply != nullptr;
|
|
s_checked = true;
|
|
}
|
|
return s_haveXRes;
|
|
}
|
|
|
|
class Q_DECL_HIDDEN KWindowInfoPrivate : public QSharedData
|
|
{
|
|
public:
|
|
WId window;
|
|
NET::Properties properties;
|
|
NET::Properties2 properties2;
|
|
|
|
std::unique_ptr<NETWinInfo> m_info;
|
|
QString m_name;
|
|
QString m_iconic_name;
|
|
QRect m_geometry;
|
|
QRect m_frame_geometry;
|
|
int m_pid = -1; // real PID from XResources. Valid if > 0
|
|
bool m_valid = false;
|
|
};
|
|
|
|
KWindowInfo::KWindowInfo(WId window, NET::Properties properties, NET::Properties2 properties2)
|
|
: d(new KWindowInfoPrivate)
|
|
{
|
|
d->window = window;
|
|
d->properties = properties;
|
|
d->properties2 = properties2;
|
|
|
|
if (!KWindowSystem::isPlatformX11()) {
|
|
return;
|
|
}
|
|
|
|
KXErrorHandler handler;
|
|
if (properties & NET::WMVisibleIconName) {
|
|
properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback
|
|
}
|
|
if (properties & NET::WMVisibleName) {
|
|
properties |= NET::WMName; // force, in case it will be used as a fallback
|
|
}
|
|
if (properties2 & NET::WM2ExtendedStrut) {
|
|
properties |= NET::WMStrut; // will be used as fallback
|
|
}
|
|
if (properties & NET::WMWindowType) {
|
|
properties2 |= NET::WM2TransientFor; // will be used when type is not set
|
|
}
|
|
if ((properties & NET::WMDesktop) && KX11Extras::mapViewport()) {
|
|
properties |= NET::WMGeometry; // for viewports, the desktop (workspace) is determined from the geometry
|
|
}
|
|
properties |= NET::XAWMState; // force to get error detection for valid()
|
|
d->m_info.reset(new NETWinInfo(QX11Info::connection(), d->window, QX11Info::appRootWindow(), properties, properties2));
|
|
if (properties & NET::WMName) {
|
|
if (d->m_info->name() && d->m_info->name()[0] != '\0') {
|
|
d->m_name = QString::fromUtf8(d->m_info->name());
|
|
} else {
|
|
d->m_name = KX11Extras::readNameProperty(d->window, XA_WM_NAME);
|
|
}
|
|
}
|
|
if (properties & NET::WMIconName) {
|
|
if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') {
|
|
d->m_iconic_name = QString::fromUtf8(d->m_info->iconName());
|
|
} else {
|
|
d->m_iconic_name = KX11Extras::readNameProperty(d->window, XA_WM_ICON_NAME);
|
|
}
|
|
}
|
|
if (properties & (NET::WMGeometry | NET::WMFrameExtents)) {
|
|
NETRect frame;
|
|
NETRect geom;
|
|
d->m_info->kdeGeometry(frame, geom);
|
|
d->m_geometry.setRect(geom.pos.x, geom.pos.y, geom.size.width, geom.size.height);
|
|
d->m_frame_geometry.setRect(frame.pos.x, frame.pos.y, frame.size.width, frame.size.height);
|
|
}
|
|
d->m_valid = !handler.error(false); // no sync - NETWinInfo did roundtrips
|
|
|
|
if (haveXRes()) {
|
|
xcb_res_client_id_spec_t specs;
|
|
specs.client = win();
|
|
specs.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
|
|
auto cookie = xcb_res_query_client_ids(QX11Info::connection(), 1, &specs);
|
|
|
|
UniqueCPointer<xcb_res_query_client_ids_reply_t> reply(xcb_res_query_client_ids_reply(QX11Info::connection(), cookie, nullptr));
|
|
if (reply && xcb_res_query_client_ids_ids_length(reply.get()) > 0) {
|
|
uint32_t pid = *xcb_res_client_id_value_value((xcb_res_query_client_ids_ids_iterator(reply.get()).data));
|
|
d->m_pid = pid;
|
|
}
|
|
}
|
|
}
|
|
|
|
KWindowInfo::KWindowInfo(const KWindowInfo &other)
|
|
: d(other.d)
|
|
{
|
|
}
|
|
|
|
KWindowInfo::~KWindowInfo()
|
|
{
|
|
}
|
|
|
|
KWindowInfo &KWindowInfo::operator=(const KWindowInfo &other)
|
|
{
|
|
if (d != other.d) {
|
|
d = other.d;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool KWindowInfo::valid(bool withdrawn_is_valid) const
|
|
{
|
|
if (!KWindowSystem::isPlatformX11()) {
|
|
return false;
|
|
}
|
|
|
|
if (!d->m_valid) {
|
|
return false;
|
|
}
|
|
if (!withdrawn_is_valid && mappingState() == NET::Withdrawn) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
WId KWindowInfo::win() const
|
|
{
|
|
return d->window;
|
|
}
|
|
|
|
#define CHECK_X11 \
|
|
if (!KWindowSystem::isPlatformX11()) { \
|
|
qCWarning(LOG_KWINDOWSYSTEM) << "KWindowInfo is only functional when running on X11"; \
|
|
return {}; \
|
|
}
|
|
|
|
NET::States KWindowInfo::state() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMState)) {
|
|
qWarning() << "Pass NET::WMState to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->state();
|
|
}
|
|
|
|
bool KWindowInfo::hasState(NET::States s) const
|
|
{
|
|
CHECK_X11
|
|
return (state() & s) == s;
|
|
}
|
|
|
|
bool KWindowInfo::icccmCompliantMappingState() const
|
|
{
|
|
CHECK_X11
|
|
static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
|
|
if (wm_is_1_2_compliant == noidea) {
|
|
NETRootInfo info(QX11Info::connection(), NET::Supported, NET::Properties2(), QX11Info::appScreen());
|
|
wm_is_1_2_compliant = info.isSupported(NET::Hidden) ? yes : no;
|
|
}
|
|
return wm_is_1_2_compliant == yes;
|
|
}
|
|
|
|
// see NETWM spec section 7.6
|
|
bool KWindowInfo::isMinimized() const
|
|
{
|
|
CHECK_X11
|
|
if (mappingState() != NET::Iconic) {
|
|
return false;
|
|
}
|
|
// NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
|
|
if ((state() & NET::Hidden) != 0 && (state() & NET::Shaded) == 0) { // shaded may have NET::Hidden too
|
|
return true;
|
|
}
|
|
// older WMs use WithdrawnState for other virtual desktops
|
|
// and IconicState only for minimized
|
|
return icccmCompliantMappingState() ? false : true;
|
|
}
|
|
|
|
NET::MappingState KWindowInfo::mappingState() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::XAWMState)) {
|
|
qWarning() << "Pass NET::XAWMState to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->mappingState();
|
|
}
|
|
|
|
NETExtendedStrut KWindowInfo::extendedStrut() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2ExtendedStrut)) {
|
|
qWarning() << "Pass NET::WM2ExtendedStrut to KWindowInfo";
|
|
}
|
|
#endif
|
|
NETExtendedStrut ext = d->m_info->extendedStrut();
|
|
NETStrut str = d->m_info->strut();
|
|
if (ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
|
|
&& (str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0)) {
|
|
// build extended from simple
|
|
if (str.left != 0) {
|
|
ext.left_width = str.left;
|
|
ext.left_start = 0;
|
|
ext.left_end = XDisplayHeight(QX11Info::display(), DefaultScreen(QX11Info::display()));
|
|
}
|
|
if (str.right != 0) {
|
|
ext.right_width = str.right;
|
|
ext.right_start = 0;
|
|
ext.right_end = XDisplayHeight(QX11Info::display(), DefaultScreen(QX11Info::display()));
|
|
}
|
|
if (str.top != 0) {
|
|
ext.top_width = str.top;
|
|
ext.top_start = 0;
|
|
ext.top_end = XDisplayWidth(QX11Info::display(), DefaultScreen(QX11Info::display()));
|
|
}
|
|
if (str.bottom != 0) {
|
|
ext.bottom_width = str.bottom;
|
|
ext.bottom_start = 0;
|
|
ext.bottom_end = XDisplayWidth(QX11Info::display(), DefaultScreen(QX11Info::display()));
|
|
}
|
|
}
|
|
return ext;
|
|
}
|
|
|
|
NET::WindowType KWindowInfo::windowType(NET::WindowTypes supported_types) const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMWindowType)) {
|
|
qWarning() << "Pass NET::WMWindowType to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (!d->m_info->hasWindowType()) { // fallback, per spec recommendation
|
|
if (transientFor() != XCB_WINDOW_NONE) { // dialog
|
|
if (supported_types & NET::DialogMask) {
|
|
return NET::Dialog;
|
|
}
|
|
} else {
|
|
if (supported_types & NET::NormalMask) {
|
|
return NET::Normal;
|
|
}
|
|
}
|
|
}
|
|
return d->m_info->windowType(supported_types);
|
|
}
|
|
|
|
QString KWindowInfo::visibleName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMVisibleName)) {
|
|
qWarning() << "Pass NET::WMVisibleName to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->visibleName() && d->m_info->visibleName()[0] != '\0' ? QString::fromUtf8(d->m_info->visibleName()) : name();
|
|
}
|
|
|
|
QString KWindowInfo::visibleNameWithState() const
|
|
{
|
|
CHECK_X11
|
|
QString s = visibleName();
|
|
if (isMinimized()) {
|
|
s.prepend(QLatin1Char('('));
|
|
s.append(QLatin1Char(')'));
|
|
}
|
|
return s;
|
|
}
|
|
|
|
QString KWindowInfo::name() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMName)) {
|
|
qWarning() << "Pass NET::WMName to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_name;
|
|
}
|
|
|
|
QString KWindowInfo::visibleIconName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMVisibleIconName)) {
|
|
qWarning() << "Pass NET::WMVisibleIconName to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (d->m_info->visibleIconName() && d->m_info->visibleIconName()[0] != '\0') {
|
|
return QString::fromUtf8(d->m_info->visibleIconName());
|
|
}
|
|
if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') {
|
|
return QString::fromUtf8(d->m_info->iconName());
|
|
}
|
|
if (!d->m_iconic_name.isEmpty()) {
|
|
return d->m_iconic_name;
|
|
}
|
|
return visibleName();
|
|
}
|
|
|
|
QString KWindowInfo::visibleIconNameWithState() const
|
|
{
|
|
CHECK_X11
|
|
QString s = visibleIconName();
|
|
if (isMinimized()) {
|
|
s.prepend(QLatin1Char('('));
|
|
s.append(QLatin1Char(')'));
|
|
}
|
|
return s;
|
|
}
|
|
|
|
QString KWindowInfo::iconName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMIconName)) {
|
|
qWarning() << "Pass NET::WMIconName to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (d->m_info->iconName() && d->m_info->iconName()[0] != '\0') {
|
|
return QString::fromUtf8(d->m_info->iconName());
|
|
}
|
|
if (!d->m_iconic_name.isEmpty()) {
|
|
return d->m_iconic_name;
|
|
}
|
|
return name();
|
|
}
|
|
|
|
bool KWindowInfo::isOnCurrentDesktop() const
|
|
{
|
|
CHECK_X11
|
|
return isOnDesktop(KX11Extras::currentDesktop());
|
|
}
|
|
|
|
bool KWindowInfo::isOnDesktop(int desktop) const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMDesktop)) {
|
|
qWarning() << "Pass NET::WMDesktop to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (KX11Extras::mapViewport()) {
|
|
if (onAllDesktops()) {
|
|
return true;
|
|
}
|
|
return KX11Extras::viewportWindowToDesktop(d->m_geometry) == desktop;
|
|
}
|
|
return d->m_info->desktop() == desktop || d->m_info->desktop() == NET::OnAllDesktops;
|
|
}
|
|
|
|
bool KWindowInfo::onAllDesktops() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMDesktop)) {
|
|
qWarning() << "Pass NET::WMDesktop to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (KX11Extras::mapViewport()) {
|
|
if (d->m_info->passedProperties() & NET::WMState) {
|
|
return d->m_info->state() & NET::Sticky;
|
|
}
|
|
NETWinInfo info(QX11Info::connection(), win(), QX11Info::appRootWindow(), NET::WMState, NET::Properties2());
|
|
return info.state() & NET::Sticky;
|
|
}
|
|
return d->m_info->desktop() == NET::OnAllDesktops;
|
|
}
|
|
|
|
int KWindowInfo::desktop() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMDesktop)) {
|
|
qWarning() << "Pass NET::WMDesktop to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (KX11Extras::mapViewport()) {
|
|
if (onAllDesktops()) {
|
|
return NET::OnAllDesktops;
|
|
}
|
|
return KX11Extras::viewportWindowToDesktop(d->m_geometry);
|
|
}
|
|
return d->m_info->desktop();
|
|
}
|
|
|
|
QStringList KWindowInfo::activities() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2Activities)) {
|
|
qWarning() << "Pass NET::WM2Activities to KWindowInfo";
|
|
}
|
|
#endif
|
|
|
|
const QStringList result = QString::fromLatin1(d->m_info->activities()).split(QLatin1Char(','), Qt::SkipEmptyParts);
|
|
|
|
return result.contains(QStringLiteral(KDE_ALL_ACTIVITIES_UUID)) ? QStringList() : result;
|
|
}
|
|
|
|
QRect KWindowInfo::geometry() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMGeometry)) {
|
|
qWarning() << "Pass NET::WMGeometry to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_geometry;
|
|
}
|
|
|
|
QRect KWindowInfo::frameGeometry() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMFrameExtents)) {
|
|
qWarning() << "Pass NET::WMFrameExtents to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_frame_geometry;
|
|
}
|
|
|
|
WId KWindowInfo::transientFor() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2TransientFor)) {
|
|
qWarning() << "Pass NET::WM2TransientFor to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->transientFor();
|
|
}
|
|
|
|
WId KWindowInfo::groupLeader() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2GroupLeader)) {
|
|
qWarning() << "Pass NET::WM2GroupLeader to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->groupLeader();
|
|
}
|
|
|
|
QByteArray KWindowInfo::windowClassClass() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2WindowClass)) {
|
|
qWarning() << "Pass NET::WM2WindowClass to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->windowClassClass();
|
|
}
|
|
|
|
QByteArray KWindowInfo::windowClassName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2WindowClass)) {
|
|
qWarning() << "Pass NET::WM2WindowClass to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->windowClassName();
|
|
}
|
|
|
|
QByteArray KWindowInfo::windowRole() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2WindowRole)) {
|
|
qWarning() << "Pass NET::WM2WindowRole to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->windowRole();
|
|
}
|
|
|
|
QByteArray KWindowInfo::clientMachine() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2ClientMachine)) {
|
|
qWarning() << "Pass NET::WM2ClientMachine to KWindowInfo";
|
|
}
|
|
#endif
|
|
return d->m_info->clientMachine();
|
|
}
|
|
|
|
bool KWindowInfo::allowedActionsSupported() const
|
|
{
|
|
CHECK_X11
|
|
static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
|
|
if (wm_supports_allowed_actions == noidea) {
|
|
NETRootInfo info(QX11Info::connection(), NET::Supported, NET::Properties2(), QX11Info::appScreen());
|
|
wm_supports_allowed_actions = info.isSupported(NET::WM2AllowedActions) ? yes : no;
|
|
}
|
|
return wm_supports_allowed_actions == yes;
|
|
}
|
|
|
|
bool KWindowInfo::actionSupported(NET::Action action) const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2AllowedActions)) {
|
|
qWarning() << "Pass NET::WM2AllowedActions to KWindowInfo";
|
|
}
|
|
#endif
|
|
if (allowedActionsSupported()) {
|
|
return d->m_info->allowedActions() & action;
|
|
} else {
|
|
return true; // no idea if it's supported or not -> pretend it is
|
|
}
|
|
}
|
|
|
|
QByteArray KWindowInfo::desktopFileName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2DesktopFileName)) {
|
|
qWarning() << "Pass NET::WM2DesktopFileName to KWindowInfo";
|
|
}
|
|
#endif
|
|
return QByteArray(d->m_info->desktopFileName());
|
|
}
|
|
|
|
QByteArray KWindowInfo::gtkApplicationId() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2DesktopFileName)) {
|
|
qWarning() << "Pass NET::WM2DesktopFileName to KWindowInfo";
|
|
}
|
|
#endif
|
|
return QByteArray(d->m_info->gtkApplicationId());
|
|
}
|
|
|
|
QByteArray KWindowInfo::applicationMenuServiceName() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2AppMenuServiceName)) {
|
|
qWarning() << "Pass NET::WM2AppMenuServiceName to KWindowInfo";
|
|
}
|
|
#endif
|
|
return QByteArray(d->m_info->appMenuServiceName());
|
|
}
|
|
|
|
QByteArray KWindowInfo::applicationMenuObjectPath() const
|
|
{
|
|
CHECK_X11
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties2() & NET::WM2AppMenuObjectPath)) {
|
|
qWarning() << "Pass NET::WM2AppMenuObjectPath to KWindowInfo";
|
|
}
|
|
#endif
|
|
return QByteArray(d->m_info->appMenuObjectPath());
|
|
}
|
|
|
|
int KWindowInfo::pid() const
|
|
{
|
|
CHECK_X11
|
|
// If pid is found using the XRes extension use that instead.
|
|
// It is more reliable than the app reporting it's own PID as apps
|
|
// within an app namespace are unable to do so correctly
|
|
if (d->m_pid > 0) {
|
|
return d->m_pid;
|
|
}
|
|
|
|
#if !defined(KDE_NO_WARNING_OUTPUT)
|
|
if (!(d->m_info->passedProperties() & NET::WMPid)) {
|
|
qWarning() << "Pass NET::WMPid to KWindowInfo";
|
|
}
|
|
#endif
|
|
|
|
return d->m_info->pid();
|
|
}
|