Add outputOnly property to PlasmaCore.Dialog
The outputOnly property allows to specify that the dialog should not accept any input. Thus it's an output only window which supports click through. This is obviously platform specific and so far it is only implemented for the X11 platform using the shape extension. The input shape needs to be set once the window is visible and thus the functionality is bound to the visible changed signal. The code ensures that the required shape extension version is present and only fetches it once. REVIEW: 115139
This commit is contained in:
parent
e4d4f5fc1c
commit
bdc2ad2a84
@ -57,7 +57,7 @@ set_package_properties(KActivities PROPERTIES DESCRIPTION "The KActivities libra
|
|||||||
|
|
||||||
#optional features
|
#optional features
|
||||||
find_package(X11 MODULE)
|
find_package(X11 MODULE)
|
||||||
find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE)
|
find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE)
|
||||||
set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding"
|
set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding"
|
||||||
URL "http://xcb.freedesktop.org"
|
URL "http://xcb.freedesktop.org"
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
|
@ -8,6 +8,10 @@ if(XCB_XCB_FOUND AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND)
|
|||||||
${XCB_COMPOSITE_INCLUDE_DIR}
|
${XCB_COMPOSITE_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
if(XCB_XCB_FOUND AND XCB_SHAPE_FOUND)
|
||||||
|
add_definitions(-DHAVE_XCB_SHAPE=1)
|
||||||
|
include_directories(${XCB_SHAPE_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
set(corebindings_SRCS
|
set(corebindings_SRCS
|
||||||
corebindingsplugin.cpp
|
corebindingsplugin.cpp
|
||||||
@ -49,6 +53,9 @@ if(X11_FOUND)
|
|||||||
${XCB_COMPOSITE_LIBRARY}
|
${XCB_COMPOSITE_LIBRARY}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
if(XCB_SHAPE_FOUND)
|
||||||
|
target_link_libraries(corebindingsplugin ${XCB_SHAPE_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(OPENGL_FOUND)
|
if(OPENGL_FOUND)
|
||||||
target_link_libraries(corebindingsplugin ${OPENGL_gl_LIBRARY})
|
target_link_libraries(corebindingsplugin ${OPENGL_gl_LIBRARY})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright 2011 Marco Martin <mart@kde.org> *
|
* Copyright 2011 Marco Martin <mart@kde.org> *
|
||||||
* Copyright 2013 Sebastian Kügler <sebas@kde.org> *
|
* Copyright 2013 Sebastian Kügler <sebas@kde.org> *
|
||||||
|
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@ -38,11 +39,17 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if HAVE_XCB_SHAPE
|
||||||
|
#include <QX11Info>
|
||||||
|
#include <xcb/shape.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
DialogProxy::DialogProxy(QQuickItem *parent)
|
DialogProxy::DialogProxy(QQuickItem *parent)
|
||||||
: QQuickWindow(parent ? parent->window() : 0),
|
: QQuickWindow(parent ? parent->window() : 0),
|
||||||
m_location(Plasma::Types::BottomEdge),
|
m_location(Plasma::Types::BottomEdge),
|
||||||
m_type(Normal),
|
m_type(Normal),
|
||||||
m_hideOnWindowDeactivate(false)
|
m_hideOnWindowDeactivate(false),
|
||||||
|
m_outputOnly(false)
|
||||||
{
|
{
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setAlphaBufferSize(8);
|
format.setAlphaBufferSize(8);
|
||||||
@ -58,6 +65,8 @@ DialogProxy::DialogProxy(QQuickItem *parent)
|
|||||||
|
|
||||||
connect(this, &QWindow::xChanged, [=](){m_syncTimer->start(150);});
|
connect(this, &QWindow::xChanged, [=](){m_syncTimer->start(150);});
|
||||||
connect(this, &QWindow::yChanged, [=](){m_syncTimer->start(150);});
|
connect(this, &QWindow::yChanged, [=](){m_syncTimer->start(150);});
|
||||||
|
connect(this, &QWindow::visibleChanged, this, &DialogProxy::updateInputShape);
|
||||||
|
connect(this, &DialogProxy::outputOnlyChanged, this, &DialogProxy::updateInputShape);
|
||||||
// connect(this, &QWindow::visibleChanged, this, &DialogProxy::onVisibleChanged);
|
// connect(this, &QWindow::visibleChanged, this, &DialogProxy::onVisibleChanged);
|
||||||
//HACK: this property is invoked due to the initialization that gets done to contentItem() in the getter
|
//HACK: this property is invoked due to the initialization that gets done to contentItem() in the getter
|
||||||
property("data");
|
property("data");
|
||||||
@ -485,5 +494,58 @@ void DialogProxy::setHideOnWindowDeactivate(bool hide)
|
|||||||
emit hideOnWindowDeactivateChanged();
|
emit hideOnWindowDeactivateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DialogProxy::isOutputOnly() const
|
||||||
|
{
|
||||||
|
return m_outputOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogProxy::setOutputOnly(bool outputOnly)
|
||||||
|
{
|
||||||
|
if (m_outputOnly == outputOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_outputOnly = outputOnly;
|
||||||
|
emit outputOnlyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogProxy::updateInputShape()
|
||||||
|
{
|
||||||
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if HAVE_XCB_SHAPE
|
||||||
|
if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
|
||||||
|
xcb_connection_t *c = QX11Info::connection();
|
||||||
|
static bool s_shapeExtensionChecked = false;
|
||||||
|
static bool s_shapeAvailable = false;
|
||||||
|
if (!s_shapeExtensionChecked) {
|
||||||
|
xcb_prefetch_extension_data(c, &xcb_shape_id);
|
||||||
|
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, &xcb_shape_id);
|
||||||
|
if (extension->present) {
|
||||||
|
// query version
|
||||||
|
auto cookie = xcb_shape_query_version(c);
|
||||||
|
QScopedPointer<xcb_shape_query_version_reply_t, QScopedPointerPodDeleter> version(xcb_shape_query_version_reply(c, cookie, Q_NULLPTR));
|
||||||
|
if (!version.isNull()) {
|
||||||
|
s_shapeAvailable = (version->major_version * 0x10 + version->minor_version) >= 0x11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_shapeExtensionChecked = true;
|
||||||
|
}
|
||||||
|
if (!s_shapeAvailable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_outputOnly) {
|
||||||
|
// set input shape, so that it doesn't accept any input events
|
||||||
|
xcb_shape_rectangles(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT,
|
||||||
|
XCB_CLIP_ORDERING_UNSORTED, winId(), 0, 0, 0, NULL);
|
||||||
|
} else {
|
||||||
|
// delete the shape
|
||||||
|
xcb_shape_mask(c, XCB_SHAPE_SO_INTERSECT, XCB_SHAPE_SK_INPUT,
|
||||||
|
winId(), 0, 0, XCB_PIXMAP_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#include "dialog.moc"
|
#include "dialog.moc"
|
||||||
|
|
||||||
|
@ -79,6 +79,16 @@ class DialogProxy : public QQuickWindow
|
|||||||
**/
|
**/
|
||||||
Q_PROPERTY(bool hideOnWindowDeactivate READ hideOnWindowDeactivate WRITE setHideOnWindowDeactivate NOTIFY hideOnWindowDeactivateChanged)
|
Q_PROPERTY(bool hideOnWindowDeactivate READ hideOnWindowDeactivate WRITE setHideOnWindowDeactivate NOTIFY hideOnWindowDeactivateChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the dialog is output only. Default value is @c false. If it is @c true
|
||||||
|
* the dialog does not accept input and all pointer events are not accepted, thus the dialog
|
||||||
|
* is click through.
|
||||||
|
*
|
||||||
|
* This property is currently only supported on the X11 platform. On any other platform the
|
||||||
|
* property has no effect.
|
||||||
|
**/
|
||||||
|
Q_PROPERTY(bool outputOnly READ isOutputOnly WRITE setOutputOnly NOTIFY outputOnlyChanged)
|
||||||
|
|
||||||
Q_CLASSINFO("DefaultProperty", "mainItem")
|
Q_CLASSINFO("DefaultProperty", "mainItem")
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -123,12 +133,18 @@ public:
|
|||||||
bool hideOnWindowDeactivate() const;
|
bool hideOnWindowDeactivate() const;
|
||||||
void setHideOnWindowDeactivate(bool hide);
|
void setHideOnWindowDeactivate(bool hide);
|
||||||
|
|
||||||
|
void setOutputOnly(bool outputOnly);
|
||||||
|
bool isOutputOnly() const;
|
||||||
|
|
||||||
|
void updateInputShape();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void mainItemChanged();
|
void mainItemChanged();
|
||||||
void locationChanged();
|
void locationChanged();
|
||||||
void visualParentChanged();
|
void visualParentChanged();
|
||||||
void typeChanged();
|
void typeChanged();
|
||||||
void hideOnWindowDeactivateChanged();
|
void hideOnWindowDeactivateChanged();
|
||||||
|
void outputOnlyChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void syncMainItemToSize();
|
void syncMainItemToSize();
|
||||||
@ -158,6 +174,7 @@ private:
|
|||||||
QRect m_cachedGeometry;
|
QRect m_cachedGeometry;
|
||||||
WindowType m_type;
|
WindowType m_type;
|
||||||
bool m_hideOnWindowDeactivate;
|
bool m_hideOnWindowDeactivate;
|
||||||
|
bool m_outputOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user