63a866d98c
This change makes the WindowItem track the opacity and schedule a repaint. It further decouples the legacy scene from code window abstractions. It's an API breaking change. WindowPaintData no longer can make windows more opaque. It only provides additional opacity factor.
279 lines
7.8 KiB
C++
279 lines
7.8 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "windowitem.h"
|
|
#include "decorationitem.h"
|
|
#include "deleted.h"
|
|
#include "internalwindow.h"
|
|
#include "shadowitem.h"
|
|
#include "surfaceitem_internal.h"
|
|
#include "surfaceitem_wayland.h"
|
|
#include "surfaceitem_x11.h"
|
|
#include "wayland_server.h"
|
|
#include "window.h"
|
|
#include "workspace.h"
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
WindowItem::WindowItem(Window *window, Item *parent)
|
|
: Item(parent)
|
|
, m_window(window)
|
|
{
|
|
connect(window, &Window::decorationChanged, this, &WindowItem::updateDecorationItem);
|
|
updateDecorationItem();
|
|
|
|
connect(window, &Window::shadowChanged, this, &WindowItem::updateShadowItem);
|
|
updateShadowItem();
|
|
|
|
connect(window, &Window::frameGeometryChanged, this, &WindowItem::updatePosition);
|
|
updatePosition();
|
|
|
|
if (waylandServer()) {
|
|
connect(waylandServer(), &WaylandServer::lockStateChanged, this, &WindowItem::updateVisibility);
|
|
}
|
|
connect(window, &Window::minimizedChanged, this, &WindowItem::updateVisibility);
|
|
connect(window, &Window::hiddenChanged, this, &WindowItem::updateVisibility);
|
|
connect(window, &Window::activitiesChanged, this, &WindowItem::updateVisibility);
|
|
connect(window, &Window::desktopChanged, this, &WindowItem::updateVisibility);
|
|
connect(workspace(), &Workspace::currentActivityChanged, this, &WindowItem::updateVisibility);
|
|
connect(workspace(), &Workspace::currentDesktopChanged, this, &WindowItem::updateVisibility);
|
|
updateVisibility();
|
|
|
|
connect(window, &Window::opacityChanged, this, &WindowItem::updateOpacity);
|
|
updateOpacity();
|
|
|
|
connect(window, &Window::windowClosed, this, &WindowItem::handleWindowClosed);
|
|
}
|
|
|
|
WindowItem::~WindowItem()
|
|
{
|
|
}
|
|
|
|
SurfaceItem *WindowItem::surfaceItem() const
|
|
{
|
|
return m_surfaceItem.data();
|
|
}
|
|
|
|
DecorationItem *WindowItem::decorationItem() const
|
|
{
|
|
return m_decorationItem.data();
|
|
}
|
|
|
|
ShadowItem *WindowItem::shadowItem() const
|
|
{
|
|
return m_shadowItem.data();
|
|
}
|
|
|
|
Window *WindowItem::window() const
|
|
{
|
|
return m_window;
|
|
}
|
|
|
|
void WindowItem::refVisible(int reason)
|
|
{
|
|
if (reason & PAINT_DISABLED_BY_HIDDEN) {
|
|
m_forceVisibleByHiddenCount++;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_DELETE) {
|
|
m_forceVisibleByDeleteCount++;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_DESKTOP) {
|
|
m_forceVisibleByDesktopCount++;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_MINIMIZE) {
|
|
m_forceVisibleByMinimizeCount++;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_ACTIVITY) {
|
|
m_forceVisibleByActivityCount++;
|
|
}
|
|
updateVisibility();
|
|
}
|
|
|
|
void WindowItem::unrefVisible(int reason)
|
|
{
|
|
if (reason & PAINT_DISABLED_BY_HIDDEN) {
|
|
Q_ASSERT(m_forceVisibleByHiddenCount > 0);
|
|
m_forceVisibleByHiddenCount--;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_DELETE) {
|
|
Q_ASSERT(m_forceVisibleByDeleteCount > 0);
|
|
m_forceVisibleByDeleteCount--;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_DESKTOP) {
|
|
Q_ASSERT(m_forceVisibleByDesktopCount > 0);
|
|
m_forceVisibleByDesktopCount--;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_MINIMIZE) {
|
|
Q_ASSERT(m_forceVisibleByMinimizeCount > 0);
|
|
m_forceVisibleByMinimizeCount--;
|
|
}
|
|
if (reason & PAINT_DISABLED_BY_ACTIVITY) {
|
|
Q_ASSERT(m_forceVisibleByActivityCount > 0);
|
|
m_forceVisibleByActivityCount--;
|
|
}
|
|
updateVisibility();
|
|
}
|
|
|
|
void WindowItem::handleWindowClosed(Window *original, Deleted *deleted)
|
|
{
|
|
Q_UNUSED(original)
|
|
m_window = deleted;
|
|
}
|
|
|
|
bool WindowItem::computeVisibility() const
|
|
{
|
|
if (waylandServer() && waylandServer()->isScreenLocked()) {
|
|
return m_window->isLockScreen() || m_window->isInputMethod();
|
|
}
|
|
if (m_window->isDeleted()) {
|
|
if (m_forceVisibleByDeleteCount == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!m_window->isOnCurrentDesktop()) {
|
|
if (m_forceVisibleByDesktopCount == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!m_window->isOnCurrentActivity()) {
|
|
if (m_forceVisibleByActivityCount == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
if (m_window->isMinimized()) {
|
|
if (m_forceVisibleByMinimizeCount == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
if (m_window->isHiddenInternal()) {
|
|
if (m_forceVisibleByHiddenCount == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void WindowItem::updateVisibility()
|
|
{
|
|
setVisible(computeVisibility());
|
|
}
|
|
|
|
void WindowItem::updatePosition()
|
|
{
|
|
setPosition(m_window->pos());
|
|
}
|
|
|
|
void WindowItem::updateSurfaceItem(SurfaceItem *surfaceItem)
|
|
{
|
|
m_surfaceItem.reset(surfaceItem);
|
|
|
|
if (m_surfaceItem) {
|
|
connect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility);
|
|
connect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition);
|
|
connect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition);
|
|
|
|
updateSurfacePosition();
|
|
updateSurfaceVisibility();
|
|
} else {
|
|
disconnect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility);
|
|
disconnect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition);
|
|
disconnect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition);
|
|
}
|
|
}
|
|
|
|
void WindowItem::updateSurfacePosition()
|
|
{
|
|
const QRect bufferGeometry = m_window->bufferGeometry();
|
|
const QRect frameGeometry = m_window->frameGeometry();
|
|
|
|
m_surfaceItem->setPosition(bufferGeometry.topLeft() - frameGeometry.topLeft());
|
|
}
|
|
|
|
void WindowItem::updateSurfaceVisibility()
|
|
{
|
|
m_surfaceItem->setVisible(!m_window->isShade());
|
|
}
|
|
|
|
void WindowItem::updateShadowItem()
|
|
{
|
|
Shadow *shadow = m_window->shadow();
|
|
if (shadow) {
|
|
if (!m_shadowItem || m_shadowItem->shadow() != shadow) {
|
|
m_shadowItem.reset(new ShadowItem(shadow, m_window, this));
|
|
}
|
|
if (m_decorationItem) {
|
|
m_shadowItem->stackBefore(m_decorationItem.data());
|
|
} else if (m_surfaceItem) {
|
|
m_shadowItem->stackBefore(m_decorationItem.data());
|
|
}
|
|
} else {
|
|
m_shadowItem.reset();
|
|
}
|
|
}
|
|
|
|
void WindowItem::updateDecorationItem()
|
|
{
|
|
if (m_window->isDeleted() || m_window->isZombie()) {
|
|
return;
|
|
}
|
|
if (m_window->decoration()) {
|
|
m_decorationItem.reset(new DecorationItem(m_window->decoration(), m_window, this));
|
|
if (m_shadowItem) {
|
|
m_decorationItem->stackAfter(m_shadowItem.data());
|
|
} else if (m_surfaceItem) {
|
|
m_decorationItem->stackBefore(m_surfaceItem.data());
|
|
}
|
|
} else {
|
|
m_decorationItem.reset();
|
|
}
|
|
}
|
|
|
|
void WindowItem::updateOpacity()
|
|
{
|
|
setOpacity(m_window->opacity());
|
|
}
|
|
|
|
WindowItemX11::WindowItemX11(Window *window, Item *parent)
|
|
: WindowItem(window, parent)
|
|
{
|
|
initialize();
|
|
|
|
// Xwayland windows and Wayland surfaces are associated asynchronously.
|
|
connect(window, &Window::surfaceChanged, this, &WindowItemX11::initialize);
|
|
}
|
|
|
|
void WindowItemX11::initialize()
|
|
{
|
|
switch (kwinApp()->operationMode()) {
|
|
case Application::OperationModeX11:
|
|
updateSurfaceItem(new SurfaceItemX11(window(), this));
|
|
break;
|
|
case Application::OperationModeXwayland:
|
|
if (!window()->surface()) {
|
|
updateSurfaceItem(nullptr);
|
|
} else {
|
|
updateSurfaceItem(new SurfaceItemXwayland(window(), this));
|
|
}
|
|
break;
|
|
case Application::OperationModeWaylandOnly:
|
|
Q_UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
WindowItemWayland::WindowItemWayland(Window *window, Item *parent)
|
|
: WindowItem(window, parent)
|
|
{
|
|
updateSurfaceItem(new SurfaceItemWayland(window->surface(), window, this));
|
|
}
|
|
|
|
WindowItemInternal::WindowItemInternal(InternalWindow *window, Item *parent)
|
|
: WindowItem(window, parent)
|
|
{
|
|
updateSurfaceItem(new SurfaceItemInternal(window, this));
|
|
}
|
|
|
|
} // namespace KWin
|