7fffe99328
Due to being a compositor, kwin has to conform to some certain interfaces. It means a lot of virtual functions and function tables to integrate with C APIs. Naturally, we not always want to use every argument in such functions. Since we get -Wunused-parameter from -Wall, we have to plumb those unused arguments in order to suppress compiler warnings at the moment. However, I don't think that extra work is worth it. We cannot change or alter prototypes in any way to fix the warning the desired way. Q_UNUSED and similar macros are not good indicators of whether an argument is used too, we tend to overlook putting or removing those macros. I've also noticed that Q_UNUSED are not used to guide us with the removal no longer needed parameters. Therefore, I think it's worth adding -Wno-unused-parameter compiler option to stop the compiler producing warnings about unused parameters. It changes nothing except that we don't need to put Q_UNUSED anymore, which can be really cumbersome sometimes. Note that it doesn't affect unused variables, you'll still get a -Wunused-variable compiler warning if a variable is unused.
279 lines
7.9 KiB
C++
279 lines
7.9 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::lockScreenOverlayChanged, 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.get();
|
|
}
|
|
|
|
DecorationItem *WindowItem::decorationItem() const
|
|
{
|
|
return m_decorationItem.get();
|
|
}
|
|
|
|
ShadowItem *WindowItem::shadowItem() const
|
|
{
|
|
return m_shadowItem.get();
|
|
}
|
|
|
|
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)
|
|
{
|
|
m_window = deleted;
|
|
}
|
|
|
|
bool WindowItem::computeVisibility() const
|
|
{
|
|
if (waylandServer() && waylandServer()->isScreenLocked()) {
|
|
return m_window->isLockScreen() || m_window->isInputMethod() || m_window->isLockScreenOverlay();
|
|
}
|
|
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 QRectF bufferGeometry = m_window->bufferGeometry();
|
|
const QRectF 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.get());
|
|
} else if (m_surfaceItem) {
|
|
m_shadowItem->stackBefore(m_decorationItem.get());
|
|
}
|
|
} 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.get());
|
|
} else if (m_surfaceItem) {
|
|
m_decorationItem->stackBefore(m_surfaceItem.get());
|
|
}
|
|
} 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
|