support XCP::SHAPE for Views

--views can now specify their input area under X11 and
give valuable space to underlying windows
pull/19/head
Michail Vourlakos 5 years ago
parent cf1cb1ca8e
commit 6de05c92e8

@ -30,7 +30,7 @@ set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries"
PURPOSE "Required for building the X11 based workspace")
if(X11_FOUND)
find_package(XCB MODULE REQUIRED COMPONENTS XCB RANDR EVENT)
find_package(XCB MODULE REQUIRED COMPONENTS XCB RANDR SHAPE EVENT)
set_package_properties(XCB PROPERTIES TYPE REQUIRED)
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS X11Extras)

@ -59,6 +59,8 @@ Minimum requirements:
KF5WindowSystem >= 5.38.0
Qt5X11Extras >= 5.7.0
libxcb
libxcb-randr
libxcb-shape
libSM
```

@ -163,6 +163,11 @@ int main(int argc, char **argv)
filterDebugTextOption.setFlags(QCommandLineOption::HiddenFromHelp);
filterDebugTextOption.setValueName(i18nc("command line: debug-text", "filter_debug_text"));
parser.addOption(filterDebugTextOption);
QCommandLineOption filterDebugInputMask(QStringList() << QStringLiteral("input"));
filterDebugInputMask.setDescription(QStringLiteral("Show visual window indicators for calculated input mask."));
filterDebugInputMask.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(filterDebugInputMask);
//! END: Hidden options
parser.process(app);

@ -24,6 +24,8 @@
#include <coretypes.h>
#include "panelshadows_p.h"
#include "view.h"
#include "../lattecorona.h"
#include "../wm/abstractwindowinterface.h"
// Qt
#include <QRegion>
@ -40,6 +42,8 @@ Effects::Effects(Latte::View *parent)
: QObject(parent),
m_view(parent)
{
m_corona = qobject_cast<Latte::Corona *>(m_view->corona());
init();
}
@ -235,6 +239,24 @@ void Effects::setMask(QRect area)
emit maskChanged();
}
QRect Effects::inputMask() const
{
return m_inputMask;
}
void Effects::setInputMask(QRect area)
{
if (m_inputMask == area) {
return;
}
m_inputMask = area;
m_corona->wm()->setInputMask(m_view, area);
emit inputMaskChanged();
}
void Effects::forceMaskRedraw()
{
if (m_background) {

@ -31,6 +31,7 @@
#include <Plasma/Theme>
namespace Latte {
class Corona;
class View;
}
@ -52,6 +53,7 @@ class Effects: public QObject
Q_PROPERTY(QRect mask READ mask WRITE setMask NOTIFY maskChanged)
Q_PROPERTY(QRect rect READ rect WRITE setRect NOTIFY rectChanged)
Q_PROPERTY(QRect inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged)
@ -83,6 +85,9 @@ public:
QRect mask() const;
void setMask(QRect area);
QRect inputMask() const;
void setInputMask(QRect area);
QRect rect() const;
void setRect(QRect area);
@ -110,6 +115,7 @@ signals:
void enabledBordersChanged();
void maskChanged();
void innerShadowChanged();
void inputMaskChanged();
void rectChanged();
void subtractedMaskRegionsChanged();
@ -142,8 +148,10 @@ private:
QRect m_rect;
QRect m_mask;
QRect m_inputMask;
QPointer<Latte::View> m_view;
QPointer<Latte::Corona> m_corona;
Plasma::Theme m_theme;
//only for the mask on disabled compositing, not to actually paint

@ -138,6 +138,7 @@ public:
virtual void switchToPreviousVirtualDesktop() = 0;
virtual void setFrameExtents(QWindow *view, const QMargins &margins) = 0;
virtual void setInputMask(QWindow *window, const QRect &rect) = 0;
Latte::Corona *corona();
Tracker::Schemes *schemesTracker();

@ -459,7 +459,12 @@ void WaylandInterface::setActiveEdge(QWindow *view, bool active)
void WaylandInterface::setFrameExtents(QWindow *view, const QMargins &extents)
{
//! do nothing yet until there is a wayland way to provide this
//! do nothing until there is a wayland way to provide this
}
void WaylandInterface::setInputMask(QWindow *window, const QRect &rect)
{
//! do nothins, QWindow::mask() is sufficient enough in order to define Window input mask
}
WindowInfoWrap WaylandInterface::requestInfoActive()

@ -99,6 +99,7 @@ public:
void switchToPreviousVirtualDesktop() override;
void setFrameExtents(QWindow *view, const QMargins &margins) override;
void setInputMask(QWindow *window, const QRect &rect) override;
void registerIgnoredWindow(WindowId wid) override;
void unregisterIgnoredWindow(WindowId wid) override;

@ -40,6 +40,7 @@
// X11
#include <NETWM>
#include <xcb/xcb.h>
#include <xcb/shape.h>
namespace Latte {
namespace WindowSystem {
@ -384,6 +385,56 @@ void XWindowInterface::setFrameExtents(QWindow *view, const QMargins &margins)
#endif
}
void XWindowInterface::checkShapeExtension()
{
if (!m_shapeExtensionChecked) {
xcb_connection_t *c = QX11Info::connection();
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, nullptr));
if (!version.isNull()) {
m_shapeAvailable = (version->major_version * 0x10 + version->minor_version) >= 0x11;
}
}
m_shapeExtensionChecked = true;
}
}
void XWindowInterface::setInputMask(QWindow *window, const QRect &rect)
{
if (!window || !window->isVisible()) {
return;
}
xcb_connection_t *c = QX11Info::connection();
if (!m_shapeExtensionChecked) {
checkShapeExtension();
}
if (!m_shapeAvailable) {
return;
}
if (!rect.isEmpty()) {
xcb_rectangle_t xcbrect;
xcbrect.x = qMax(SHRT_MIN, rect.x());
xcbrect.y = qMax(SHRT_MIN, rect.y());
xcbrect.width = qMin((int)USHRT_MAX, rect.width());
xcbrect.height = qMin((int)USHRT_MAX, rect.height());
// 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, window->winId(), 0, 0, 1, &xcbrect);
} else {
// delete the shape
xcb_shape_mask(c, XCB_SHAPE_SO_INTERSECT, XCB_SHAPE_SK_INPUT,
window->winId(), 0, 0, XCB_PIXMAP_NONE);
}
}
WindowInfoWrap XWindowInterface::requestInfoActive()
{

@ -83,6 +83,7 @@ public:
void switchToPreviousVirtualDesktop() override;
void setFrameExtents(QWindow *view, const QMargins &margins) override;
void setInputMask(QWindow *window, const QRect &rect) override;
private:
bool isAcceptableWindow(WindowId wid);
@ -97,6 +98,12 @@ private:
QUrl windowUrl(WindowId wid);
void checkShapeExtension();
private:
//xcb_shape
bool m_shapeExtensionChecked{false};
bool m_shapeAvailable{false};
};
}

@ -511,21 +511,11 @@ Item{
var tempLength = root.isHorizontal ? width : height;
var tempThickness = root.isHorizontal ? height : width;
var noCompositingEdit = false; //!LatteCore.WindowSystem.compositingActive && root.editMode;
if (LatteCore.WindowSystem.compositingActive || noCompositingEdit) {
if (LatteCore.WindowSystem.compositingActive) {
if (normalState) {
//console.log("entered normal state...");
//count panel length
//used when !compositing and in editMode
if (noCompositingEdit) {
tempLength = root.isHorizontal ? root.width : root.height;
} else {
tempLength = background.totals.visualLength;
}
tempLength = background.totals.visualLength;
tempThickness = thicknessNormal;
if (animations.needThickness.count > 0) {
@ -560,9 +550,7 @@ Item{
}
}
if (noCompositingEdit) {
localX = 0;
} else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) {
if (plasmoid.configuration.alignment === LatteCore.Types.Justify) {
localX = (latteView.width/2) - tempLength/2 + background.offset;
} else if (root.panelAlignment === LatteCore.Types.Left) {
localX = background.offset;
@ -590,9 +578,7 @@ Item{
}
}
if (noCompositingEdit) {
localY = 0;
} else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) {
if (plasmoid.configuration.alignment === LatteCore.Types.Justify) {
localY = (latteView.height/2) - tempLength/2 + background.offset;
} else if (root.panelAlignment === LatteCore.Types.Top) {
localY = background.offset;
@ -675,7 +661,7 @@ Item{
if (root.isVertical) {
maskThickness = maskArea.width;
}
} else if (!noCompositingEdit){
} else {
//! no compositing case
var overridesHidden = latteView.visibility.isHidden && !latteView.visibility.supportsKWinEdges;
@ -791,6 +777,60 @@ Item{
//console.log("update geometry ::: "+localGeometry);
latteView.localGeometry = localGeometry;
}
//! Input Mask
if (LatteCore.WindowSystem.isPlatformX11) {
//! This is not needed under wayland environment, mask() can be used instead
var animated = ( animations.needBothAxis.count>0
|| animations.needLength.count>0
|| animations.needThickness.count>0
|| latteView.visibility.isHidden);
if (!LatteCore.WindowSystem.compositingActive || animated || latteView.behaveAsPlasmaPanel) {
latteView.effects.inputMask = Qt.rect(0, 0, -1, -1);
} else {
var inputThickness = finalScreenEdgeMargin + metrics.totals.thickness;
var inputGeometry = Qt.rect(0, 0, root.width, root.height);
if (plasmoid.location === PlasmaCore.Types.TopEdge) {
inputGeometry.x = latteView.effects.rect.x; // from effects area
inputGeometry.y = 0;
inputGeometry.width = latteView.effects.rect.width; // from effects area
inputGeometry.height = inputThickness ;
} else if (plasmoid.location === PlasmaCore.Types.BottomEdge) {
inputGeometry.x = latteView.effects.rect.x; // from effects area
inputGeometry.y = root.height - inputThickness;
inputGeometry.width = latteView.effects.rect.width; // from effects area
inputGeometry.height = inputThickness;
} else if (plasmoid.location === PlasmaCore.Types.LeftEdge) {
inputGeometry.x = 0;
inputGeometry.y = latteView.effects.rect.y; // from effects area
inputGeometry.width = inputThickness;
inputGeometry.height = latteView.effects.rect.height; // from effects area
} else if (plasmoid.location === PlasmaCore.Types.RightEdge) {
inputGeometry.x = root.width - inputThickness;
inputGeometry.y = latteView.effects.rect.y; // from effects area
inputGeometry.width = inputThickness;
inputGeometry.height = latteView.effects.rect.height; // from effects area
}
//set the boundaries for latteView local geometry
//qBound = qMax(min, qMin(value, max)).
inputGeometry.x = Math.max(0, Math.min(inputGeometry.x, latteView.width));
inputGeometry.y = Math.max(0, Math.min(inputGeometry.y, latteView.height));
inputGeometry.width = Math.min(inputGeometry.width, latteView.width);
inputGeometry.height = Math.min(inputGeometry.height, latteView.height);
latteView.effects.inputMask = inputGeometry;
}
}
}
Loader{

@ -62,6 +62,7 @@ Item {
////BEGIN properties
property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0
property bool debugModeInputMask: Qt.application.arguments.indexOf("--input")>=0
property bool debugModeLayouter: Qt.application.arguments.indexOf("--layouter")>=0
property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0
property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0
@ -1578,4 +1579,21 @@ Item {
opacity: 0.35
}
}
Loader{
anchors.fill: parent
active: latteView && latteView.effects && root.debugModeInputMask
sourceComponent: Rectangle{
x: latteView.effects.inputMask.x
y: latteView.effects.inputMask.y
width: latteView.effects.inputMask.width
height: latteView.effects.inputMask.height
color: "purple"
border.width: 2
border.color: "purple"
opacity: 0.35
}
}
}

@ -63,4 +63,9 @@ bool QuickWindowSystem::isPlatformWayland() const
return KWindowSystem::isPlatformWayland();
}
bool QuickWindowSystem::isPlatformX11() const
{
return KWindowSystem::isPlatformX11();
}
} //end of namespace

@ -38,6 +38,7 @@ class QuickWindowSystem final : public QObject
Q_PROPERTY(bool compositingActive READ compositingActive NOTIFY compositingChanged FINAL)
Q_PROPERTY(bool isPlatformWayland READ isPlatformWayland NOTIFY isPlatformWaylandChanged FINAL)
Q_PROPERTY(bool isPlatformX11 READ isPlatformX11 NOTIFY isPlatformX11Changed FINAL)
public:
explicit QuickWindowSystem(QObject *parent = nullptr);
@ -45,10 +46,12 @@ public:
bool compositingActive() const;
bool isPlatformWayland() const;
bool isPlatformX11() const;
signals:
void compositingChanged();
void isPlatformWaylandChanged();
void isPlatformX11Changed();
private:
bool m_compositing{true};

Loading…
Cancel
Save