forked from quickshell/quickshell
		
	hyprland/surface: add visibleMask
This commit is contained in:
		
							parent
							
								
									cdaff2967f
								
							
						
					
					
						commit
						b289bfa504
					
				
					 6 changed files with 230 additions and 36 deletions
				
			
		| 
						 | 
					@ -34,7 +34,7 @@
 | 
				
			||||||
    This protocol exposes hyprland-specific wl_surface properties.
 | 
					    This protocol exposes hyprland-specific wl_surface properties.
 | 
				
			||||||
  </description>
 | 
					  </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <interface name="hyprland_surface_manager_v1" version="1">
 | 
					  <interface name="hyprland_surface_manager_v1" version="2">
 | 
				
			||||||
    <description summary="manager for hyprland surface objects">
 | 
					    <description summary="manager for hyprland surface objects">
 | 
				
			||||||
      This interface allows a client to create hyprland surface objects.
 | 
					      This interface allows a client to create hyprland surface objects.
 | 
				
			||||||
    </description>
 | 
					    </description>
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@
 | 
				
			||||||
    </enum>
 | 
					    </enum>
 | 
				
			||||||
  </interface>
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <interface name="hyprland_surface_v1" version="1">
 | 
					  <interface name="hyprland_surface_v1" version="2">
 | 
				
			||||||
    <description summary="hyprland-specific wl_surface properties">
 | 
					    <description summary="hyprland-specific wl_surface properties">
 | 
				
			||||||
      This interface allows access to hyprland-specific properties of a wl_surface.
 | 
					      This interface allows access to hyprland-specific properties of a wl_surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,5 +96,31 @@
 | 
				
			||||||
      <entry name="no_surface" value="0" summary="wl_surface was destroyed"/>
 | 
					      <entry name="no_surface" value="0" summary="wl_surface was destroyed"/>
 | 
				
			||||||
      <entry name="out_of_range" value="1" summary="given opacity was not in the range 0.0 - 1.0 (inclusive)"/>
 | 
					      <entry name="out_of_range" value="1" summary="given opacity was not in the range 0.0 - 1.0 (inclusive)"/>
 | 
				
			||||||
    </enum>
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_visible_region" since="2">
 | 
				
			||||||
 | 
					      <description summary="set the visible region of the surface">
 | 
				
			||||||
 | 
					        This request sets the region of the surface that contains visible content.
 | 
				
			||||||
 | 
					        Visible content refers to content that has an alpha value greater than zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The visible region is an optimization hint for the compositor that lets it
 | 
				
			||||||
 | 
					        avoid drawing parts of the surface that are not visible. Setting a visible region
 | 
				
			||||||
 | 
					        that does not contain all content in the surface may result in missing content
 | 
				
			||||||
 | 
					        not being drawn.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The visible region is specified in buffer-local coordinates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The compositor ignores the parts of the visible region that fall outside of the surface.
 | 
				
			||||||
 | 
					        When all parts of the region fall outside of the buffer geometry, the compositor may
 | 
				
			||||||
 | 
					        avoid rendering the surface entirely.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial value for the visible region is empty. Setting the
 | 
				
			||||||
 | 
					        visible region has copy semantics, and the wl_region object can be destroyed immediately.
 | 
				
			||||||
 | 
					        A NULL wl_region causes the visible region to be set to empty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Does not take effect until wl_surface.commit is called.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <arg name="region" type="object" interface="wl_region" allow-null="true"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
  </interface>
 | 
					  </interface>
 | 
				
			||||||
</protocol>
 | 
					</protocol>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,13 +7,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::hyprland::surface::impl {
 | 
					namespace qs::hyprland::surface::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HyprlandSurfaceManager::HyprlandSurfaceManager(): QWaylandClientExtensionTemplate(1) {
 | 
					HyprlandSurfaceManager::HyprlandSurfaceManager(): QWaylandClientExtensionTemplate(2) {
 | 
				
			||||||
	this->initialize();
 | 
						this->initialize();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HyprlandSurface*
 | 
					HyprlandSurface*
 | 
				
			||||||
HyprlandSurfaceManager::createHyprlandExtension(QtWaylandClient::QWaylandWindow* surface) {
 | 
					HyprlandSurfaceManager::createHyprlandExtension(QtWaylandClient::QWaylandWindow* surface) {
 | 
				
			||||||
	return new HyprlandSurface(this->get_hyprland_surface(surface->surface()));
 | 
						return new HyprlandSurface(this->get_hyprland_surface(surface->surface()), surface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HyprlandSurfaceManager* HyprlandSurfaceManager::instance() {
 | 
					HyprlandSurfaceManager* HyprlandSurfaceManager::instance() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,17 +1,20 @@
 | 
				
			||||||
#include "qml.hpp"
 | 
					#include "qml.hpp"
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/qhighdpiscaling_p.h>
 | 
				
			||||||
#include <private/qwaylandwindow_p.h>
 | 
					#include <private/qwaylandwindow_p.h>
 | 
				
			||||||
#include <qlogging.h>
 | 
					#include <qlogging.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qqmlinfo.h>
 | 
					#include <qqmlinfo.h>
 | 
				
			||||||
 | 
					#include <qregion.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					#include <qvariant.h>
 | 
				
			||||||
#include <qwindow.h>
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../../../core/region.hpp"
 | 
				
			||||||
#include "../../../window/proxywindow.hpp"
 | 
					#include "../../../window/proxywindow.hpp"
 | 
				
			||||||
#include "../../../window/windowinterface.hpp"
 | 
					#include "../../../window/windowinterface.hpp"
 | 
				
			||||||
#include "../../util.hpp"
 | 
					 | 
				
			||||||
#include "manager.hpp"
 | 
					#include "manager.hpp"
 | 
				
			||||||
#include "surface.hpp"
 | 
					#include "surface.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +43,15 @@ HyprlandWindow::HyprlandWindow(ProxyWindowBase* window): QObject(nullptr), proxy
 | 
				
			||||||
	    &HyprlandWindow::onWindowConnected
 | 
						    &HyprlandWindow::onWindowConnected
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(window, &ProxyWindowBase::polished, this, &HyprlandWindow::onWindowPolished);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(
 | 
				
			||||||
 | 
						    window,
 | 
				
			||||||
 | 
						    &ProxyWindowBase::devicePixelRatioChanged,
 | 
				
			||||||
 | 
						    this,
 | 
				
			||||||
 | 
						    &HyprlandWindow::updateVisibleMask
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QObject::connect(window, &QObject::destroyed, this, &HyprlandWindow::onProxyWindowDestroyed);
 | 
						QObject::connect(window, &QObject::destroyed, this, &HyprlandWindow::onProxyWindowDestroyed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (window->backingWindow()) {
 | 
						if (window->backingWindow()) {
 | 
				
			||||||
| 
						 | 
					@ -60,14 +72,76 @@ void HyprlandWindow::setOpacity(qreal opacity) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->mOpacity = opacity;
 | 
						this->mOpacity = opacity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->surface) {
 | 
						if (this->surface && this->proxyWindow) {
 | 
				
			||||||
		this->surface->setOpacity(opacity);
 | 
							this->pendingPolish.opacity = true;
 | 
				
			||||||
		qs::wayland::util::scheduleCommit(this->proxyWindow);
 | 
							this->proxyWindow->schedulePolish();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	emit this->opacityChanged();
 | 
						emit this->opacityChanged();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PendingRegion* HyprlandWindow::visibleMask() const { return this->mVisibleMask; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandWindow::setVisibleMask(PendingRegion* mask) {
 | 
				
			||||||
 | 
						if (mask == this->mVisibleMask) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->mVisibleMask) {
 | 
				
			||||||
 | 
							QObject::disconnect(this->mVisibleMask, nullptr, this, nullptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mVisibleMask = mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mask) {
 | 
				
			||||||
 | 
							QObject::connect(mask, &QObject::destroyed, this, &HyprlandWindow::onVisibleMaskDestroyed);
 | 
				
			||||||
 | 
							QObject::connect(mask, &PendingRegion::changed, this, &HyprlandWindow::updateVisibleMask);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->updateVisibleMask();
 | 
				
			||||||
 | 
						emit this->visibleMaskChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandWindow::onVisibleMaskDestroyed() {
 | 
				
			||||||
 | 
						this->mVisibleMask = nullptr;
 | 
				
			||||||
 | 
						this->updateVisibleMask();
 | 
				
			||||||
 | 
						emit this->visibleMaskChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandWindow::updateVisibleMask() {
 | 
				
			||||||
 | 
						if (!this->surface || !this->proxyWindow) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->pendingPolish.visibleMask = true;
 | 
				
			||||||
 | 
						this->proxyWindow->schedulePolish();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandWindow::onWindowPolished() {
 | 
				
			||||||
 | 
						if (!this->surface) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->pendingPolish.opacity) {
 | 
				
			||||||
 | 
							this->surface->setOpacity(this->mOpacity);
 | 
				
			||||||
 | 
							this->pendingPolish.opacity = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->pendingPolish.visibleMask) {
 | 
				
			||||||
 | 
							QRegion mask;
 | 
				
			||||||
 | 
							if (this->mVisibleMask != nullptr) {
 | 
				
			||||||
 | 
								mask =
 | 
				
			||||||
 | 
								    this->mVisibleMask->applyTo(QRect(0, 0, this->mWindow->width(), this->mWindow->height()));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto dpr = this->proxyWindow->devicePixelRatio();
 | 
				
			||||||
 | 
							if (dpr != 1.0) {
 | 
				
			||||||
 | 
								mask = QHighDpi::scale(mask, dpr);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (mask.isEmpty() && this->mVisibleMask) {
 | 
				
			||||||
 | 
								mask = QRect(-1, -1, 1, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this->surface->setVisibleRegion(mask);
 | 
				
			||||||
 | 
							this->pendingPolish.visibleMask = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HyprlandWindow::onWindowConnected() {
 | 
					void HyprlandWindow::onWindowConnected() {
 | 
				
			||||||
	this->mWindow = this->proxyWindow->backingWindow();
 | 
						this->mWindow = this->proxyWindow->backingWindow();
 | 
				
			||||||
	// disconnected by destructor
 | 
						// disconnected by destructor
 | 
				
			||||||
| 
						 | 
					@ -86,11 +160,24 @@ void HyprlandWindow::onWindowVisibleChanged() {
 | 
				
			||||||
		if (!this->mWindow->handle()) {
 | 
							if (!this->mWindow->handle()) {
 | 
				
			||||||
			this->mWindow->create();
 | 
								this->mWindow->create();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this->mWaylandWindow = dynamic_cast<QWaylandWindow*>(this->mWindow->handle());
 | 
						auto* window = dynamic_cast<QWaylandWindow*>(this->mWindow->handle());
 | 
				
			||||||
 | 
						if (window == this->mWaylandWindow) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->mWaylandWindow) {
 | 
						if (this->mWaylandWindow) {
 | 
				
			||||||
			// disconnected by destructor
 | 
							QObject::disconnect(this->mWaylandWindow, nullptr, this, nullptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mWaylandWindow = window;
 | 
				
			||||||
 | 
						if (!window) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(
 | 
				
			||||||
 | 
						    this->mWaylandWindow,
 | 
				
			||||||
 | 
						    &QObject::destroyed,
 | 
				
			||||||
 | 
						    this,
 | 
				
			||||||
 | 
						    &HyprlandWindow::onWaylandWindowDestroyed
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QObject::connect(
 | 
						QObject::connect(
 | 
				
			||||||
	    this->mWaylandWindow,
 | 
						    this->mWaylandWindow,
 | 
				
			||||||
| 
						 | 
					@ -110,8 +197,8 @@ void HyprlandWindow::onWindowVisibleChanged() {
 | 
				
			||||||
		this->onWaylandSurfaceCreated();
 | 
							this->onWaylandSurfaceCreated();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
}
 | 
					void HyprlandWindow::onWaylandWindowDestroyed() { this->mWaylandWindow = nullptr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HyprlandWindow::onWaylandSurfaceCreated() {
 | 
					void HyprlandWindow::onWaylandSurfaceCreated() {
 | 
				
			||||||
	auto* manager = impl::HyprlandSurfaceManager::instance();
 | 
						auto* manager = impl::HyprlandSurfaceManager::instance();
 | 
				
			||||||
| 
						 | 
					@ -122,12 +209,26 @@ void HyprlandWindow::onWaylandSurfaceCreated() {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto v = this->mWaylandWindow->property("hyprland_window_ext");
 | 
				
			||||||
 | 
						if (v.canConvert<HyprlandWindow*>()) {
 | 
				
			||||||
 | 
							auto* windowExt = v.value<HyprlandWindow*>();
 | 
				
			||||||
 | 
							if (windowExt != this && windowExt->surface) {
 | 
				
			||||||
 | 
								this->surface.swap(windowExt->surface);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!this->surface) {
 | 
				
			||||||
		auto* ext = manager->createHyprlandExtension(this->mWaylandWindow);
 | 
							auto* ext = manager->createHyprlandExtension(this->mWaylandWindow);
 | 
				
			||||||
		this->surface = std::unique_ptr<impl::HyprlandSurface>(ext);
 | 
							this->surface = std::unique_ptr<impl::HyprlandSurface>(ext);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->mOpacity != 1.0) {
 | 
						this->mWaylandWindow->setProperty("hyprland_window_ext", QVariant::fromValue(this));
 | 
				
			||||||
		this->surface->setOpacity(this->mOpacity);
 | 
					
 | 
				
			||||||
		qs::wayland::util::scheduleCommit(this->proxyWindow);
 | 
						this->pendingPolish.opacity = this->mOpacity != 1.0;
 | 
				
			||||||
 | 
						this->pendingPolish.visibleMask = this->mVisibleMask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->pendingPolish.opacity || this->pendingPolish.visibleMask) {
 | 
				
			||||||
 | 
							this->proxyWindow->schedulePolish();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,8 +245,9 @@ void HyprlandWindow::onProxyWindowDestroyed() {
 | 
				
			||||||
	// Deleting it when the proxy window is deleted will cause a full opacity frame between the destruction of the
 | 
						// Deleting it when the proxy window is deleted will cause a full opacity frame between the destruction of the
 | 
				
			||||||
	// hyprland_surface_v1 and wl_surface objects.
 | 
						// hyprland_surface_v1 and wl_surface objects.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->surface == nullptr) {
 | 
					 | 
				
			||||||
	this->proxyWindow = nullptr;
 | 
						this->proxyWindow = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->surface == nullptr) {
 | 
				
			||||||
		this->deleteLater();
 | 
							this->deleteLater();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
#include <qwindow.h>
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../../../core/region.hpp"
 | 
				
			||||||
#include "../../../window/proxywindow.hpp"
 | 
					#include "../../../window/proxywindow.hpp"
 | 
				
			||||||
#include "surface.hpp"
 | 
					#include "surface.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,11 +32,18 @@ namespace qs::hyprland::surface {
 | 
				
			||||||
/// [hyprland-surface-v1]: https://github.com/hyprwm/hyprland-protocols/blob/main/protocols/hyprland-surface-v1.xml
 | 
					/// [hyprland-surface-v1]: https://github.com/hyprwm/hyprland-protocols/blob/main/protocols/hyprland-surface-v1.xml
 | 
				
			||||||
class HyprlandWindow: public QObject {
 | 
					class HyprlandWindow: public QObject {
 | 
				
			||||||
	Q_OBJECT;
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
	/// A multiplier for the window's overall opacity, ranging from 1.0 to 0.0. Overall opacity includes the opacity of
 | 
						/// A multiplier for the window's overall opacity, ranging from 1.0 to 0.0. Overall opacity includes the opacity of
 | 
				
			||||||
	/// both the window content *and* visual effects such as blur that apply to it.
 | 
						/// both the window content *and* visual effects such as blur that apply to it.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
	/// Default: 1.0
 | 
						/// Default: 1.0
 | 
				
			||||||
	Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged);
 | 
						Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged);
 | 
				
			||||||
 | 
						/// A hint to the compositor that only certain regions of the surface should be rendered.
 | 
				
			||||||
 | 
						/// This can be used to avoid rendering large empty regions of a window which can increase
 | 
				
			||||||
 | 
						/// performance, especially if the window is blurred. The mask should include all pixels
 | 
				
			||||||
 | 
						/// of the window that do not have an alpha value of 0.
 | 
				
			||||||
 | 
						Q_PROPERTY(PendingRegion* visibleMask READ visibleMask WRITE setVisibleMask NOTIFY visibleMaskChanged);
 | 
				
			||||||
 | 
						// clang-format on
 | 
				
			||||||
	QML_ELEMENT;
 | 
						QML_ELEMENT;
 | 
				
			||||||
	QML_UNCREATABLE("HyprlandWindow can only be used as an attached object.");
 | 
						QML_UNCREATABLE("HyprlandWindow can only be used as an attached object.");
 | 
				
			||||||
	QML_ATTACHED(HyprlandWindow);
 | 
						QML_ATTACHED(HyprlandWindow);
 | 
				
			||||||
| 
						 | 
					@ -48,17 +56,25 @@ public:
 | 
				
			||||||
	[[nodiscard]] qreal opacity() const;
 | 
						[[nodiscard]] qreal opacity() const;
 | 
				
			||||||
	void setOpacity(qreal opacity);
 | 
						void setOpacity(qreal opacity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] PendingRegion* visibleMask() const;
 | 
				
			||||||
 | 
						virtual void setVisibleMask(PendingRegion* mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static HyprlandWindow* qmlAttachedProperties(QObject* object);
 | 
						static HyprlandWindow* qmlAttachedProperties(QObject* object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
	void opacityChanged();
 | 
						void opacityChanged();
 | 
				
			||||||
 | 
						void visibleMaskChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private slots:
 | 
					private slots:
 | 
				
			||||||
	void onWindowConnected();
 | 
						void onWindowConnected();
 | 
				
			||||||
	void onWindowVisibleChanged();
 | 
						void onWindowVisibleChanged();
 | 
				
			||||||
 | 
						void onWaylandWindowDestroyed();
 | 
				
			||||||
	void onWaylandSurfaceCreated();
 | 
						void onWaylandSurfaceCreated();
 | 
				
			||||||
	void onWaylandSurfaceDestroyed();
 | 
						void onWaylandSurfaceDestroyed();
 | 
				
			||||||
	void onProxyWindowDestroyed();
 | 
						void onProxyWindowDestroyed();
 | 
				
			||||||
 | 
						void onVisibleMaskDestroyed();
 | 
				
			||||||
 | 
						void onWindowPolished();
 | 
				
			||||||
 | 
						void updateVisibleMask();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void disconnectWaylandWindow();
 | 
						void disconnectWaylandWindow();
 | 
				
			||||||
| 
						 | 
					@ -67,7 +83,13 @@ private:
 | 
				
			||||||
	QWindow* mWindow = nullptr;
 | 
						QWindow* mWindow = nullptr;
 | 
				
			||||||
	QtWaylandClient::QWaylandWindow* mWaylandWindow = nullptr;
 | 
						QtWaylandClient::QWaylandWindow* mWaylandWindow = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool opacity : 1 = false;
 | 
				
			||||||
 | 
							bool visibleMask : 1 = false;
 | 
				
			||||||
 | 
						} pendingPolish;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	qreal mOpacity = 1.0;
 | 
						qreal mOpacity = 1.0;
 | 
				
			||||||
 | 
						PendingRegion* mVisibleMask = nullptr;
 | 
				
			||||||
	std::unique_ptr<impl::HyprlandSurface> surface;
 | 
						std::unique_ptr<impl::HyprlandSurface> surface;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,53 @@
 | 
				
			||||||
#include "surface.hpp"
 | 
					#include "surface.hpp"
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/qwaylanddisplay_p.h>
 | 
				
			||||||
 | 
					#include <private/qwaylandintegration_p.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qregion.h>
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
#include <qwayland-hyprland-surface-v1.h>
 | 
					#include <qwayland-hyprland-surface-v1.h>
 | 
				
			||||||
 | 
					#include <wayland-client-protocol.h>
 | 
				
			||||||
#include <wayland-hyprland-surface-v1-client-protocol.h>
 | 
					#include <wayland-hyprland-surface-v1-client-protocol.h>
 | 
				
			||||||
#include <wayland-util.h>
 | 
					#include <wayland-util.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::hyprland::surface::impl {
 | 
					namespace qs::hyprland::surface::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HyprlandSurface::HyprlandSurface(::hyprland_surface_v1* surface)
 | 
					HyprlandSurface::HyprlandSurface(
 | 
				
			||||||
    : QtWayland::hyprland_surface_v1(surface) {}
 | 
					    ::hyprland_surface_v1* surface,
 | 
				
			||||||
 | 
					    QtWaylandClient::QWaylandWindow* backer
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					    : QtWayland::hyprland_surface_v1(surface)
 | 
				
			||||||
 | 
					    , backer(backer)
 | 
				
			||||||
 | 
					    , backerSurface(backer->surface()) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HyprlandSurface::~HyprlandSurface() { this->destroy(); }
 | 
					HyprlandSurface::~HyprlandSurface() { this->destroy(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool HyprlandSurface::surfaceEq(wl_surface* surface) const {
 | 
				
			||||||
 | 
						return surface == this->backerSurface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HyprlandSurface::setOpacity(qreal opacity) {
 | 
					void HyprlandSurface::setOpacity(qreal opacity) {
 | 
				
			||||||
	this->set_opacity(wl_fixed_from_double(opacity));
 | 
						this->set_opacity(wl_fixed_from_double(opacity));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandSurface::setVisibleRegion(const QRegion& region) {
 | 
				
			||||||
 | 
						if (this->version() < HYPRLAND_SURFACE_V1_SET_VISIBLE_REGION_SINCE_VERSION) {
 | 
				
			||||||
 | 
							qWarning() << "Cannot set hyprland surface visible region: compositor does not support "
 | 
				
			||||||
 | 
							              "hyprland_surface_v1.set_visible_region";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (region.isEmpty()) {
 | 
				
			||||||
 | 
							this->set_visible_region(nullptr);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							static const auto* waylandIntegration = QtWaylandClient::QWaylandIntegration::instance();
 | 
				
			||||||
 | 
							auto* display = waylandIntegration->display();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* wlRegion = display->createRegion(region);
 | 
				
			||||||
 | 
							this->set_visible_region(wlRegion);
 | 
				
			||||||
 | 
							wl_region_destroy(wlRegion); // NOLINT(misc-include-cleaner)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace qs::hyprland::surface::impl
 | 
					} // namespace qs::hyprland::surface::impl
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,31 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/qwaylandwindow_p.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qregion.h>
 | 
				
			||||||
#include <qtclasshelpermacros.h>
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
#include <qwayland-hyprland-surface-v1.h>
 | 
					#include <qwayland-hyprland-surface-v1.h>
 | 
				
			||||||
 | 
					#include <wayland-client-protocol.h>
 | 
				
			||||||
#include <wayland-hyprland-surface-v1-client-protocol.h>
 | 
					#include <wayland-hyprland-surface-v1-client-protocol.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::hyprland::surface::impl {
 | 
					namespace qs::hyprland::surface::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HyprlandSurface: public QtWayland::hyprland_surface_v1 {
 | 
					class HyprlandSurface: public QtWayland::hyprland_surface_v1 {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	explicit HyprlandSurface(::hyprland_surface_v1* surface);
 | 
						explicit HyprlandSurface(::hyprland_surface_v1* surface, QtWaylandClient::QWaylandWindow* backer);
 | 
				
			||||||
	~HyprlandSurface() override;
 | 
						~HyprlandSurface() override;
 | 
				
			||||||
	Q_DISABLE_COPY_MOVE(HyprlandSurface);
 | 
						Q_DISABLE_COPY_MOVE(HyprlandSurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool surfaceEq(wl_surface* surface) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setOpacity(qreal opacity);
 | 
						void setOpacity(qreal opacity);
 | 
				
			||||||
 | 
						void setVisibleRegion(const QRegion& region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QtWaylandClient::QWaylandWindow* backer;
 | 
				
			||||||
 | 
						wl_surface* backerSurface = nullptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace qs::hyprland::surface::impl
 | 
					} // namespace qs::hyprland::surface::impl
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue