Move non-Compositor functions out of composite.cpp source file

Summary:
Compositing today is ubiquitous. There is no reason to keep compositing
specific functions of Toplevel, Client and Workspace classes in the
composite.cpp source file. Instead let these definitions be separated.

Test Plan: Compiles

Reviewers: #kwin, zzag

Reviewed By: #kwin, zzag

Subscribers: zzag, kwin

Tags: #kwin

Maniphest Tasks: T11071

Differential Revision: https://phabricator.kde.org/D21654
This commit is contained in:
Roman Gilg 2019-06-22 12:00:56 +02:00
parent 4dd4ca8f1c
commit 994fafa912
4 changed files with 279 additions and 289 deletions

View file

@ -704,6 +704,23 @@ void Client::hideClient(bool hide)
updateVisibility();
}
bool Client::setupCompositing()
{
if (!Toplevel::setupCompositing()){
return false;
}
updateVisibility(); // for internalKeep()
return true;
}
void Client::finishCompositing(ReleaseReason releaseReason)
{
Toplevel::finishCompositing(releaseReason);
updateVisibility();
// for safety in case KWin is just resizing the window
resetHaveResizeEffect();
}
/**
* Returns whether the window is minimizable or not
**/

View file

@ -20,37 +20,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "composite.h"
#include "dbusinterface.h"
#include "utils.h"
#include <QTextStream>
#include "workspace.h"
#include "client.h"
#include "unmanaged.h"
#include "decorations/decoratedclient.h"
#include "deleted.h"
#include "effects.h"
#include "overlaywindow.h"
#include "platform.h"
#include "scene.h"
#include "screens.h"
#include "shadow.h"
#include "useractions.h"
#include "xcbutils.h"
#include "platform.h"
#include "shell_client.h"
#include "unmanaged.h"
#include "useractions.h"
#include "utils.h"
#include "wayland_server.h"
#include "decorations/decoratedclient.h"
#include "workspace.h"
#include "xcbutils.h"
#include <kwingltexture.h>
#include <KWayland/Server/surface_interface.h>
#include <stdio.h>
#include <QtConcurrentRun>
#include <QFutureWatcher>
#include <QMenu>
#include <QTimerEvent>
#include <QDateTime>
#include <QOpenGLContext>
#include <QQuickWindow>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KPluginLoader>
@ -58,9 +48,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KNotification>
#include <KSelectionWatcher>
#include <QDateTime>
#include <QFutureWatcher>
#include <QMenu>
#include <QOpenGLContext>
#include <QQuickWindow>
#include <QtConcurrentRun>
#include <QTextStream>
#include <QTimerEvent>
#include <xcb/composite.h>
#include <xcb/damage.h>
#include <cstdio>
Q_DECLARE_METATYPE(KWin::Compositor::SuspendReason)
namespace KWin
@ -918,275 +919,4 @@ bool Compositor::isOverlayWindowVisible() const
return m_scene->overlayWindow()->isVisible();
}
/*****************************************************
* Workspace
****************************************************/
bool Workspace::compositing() const
{
return m_compositor && m_compositor->hasScene();
}
//****************************************
// Toplevel
//****************************************
bool Toplevel::setupCompositing()
{
if (!compositing())
return false;
if (damage_handle != XCB_NONE)
return false;
if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) {
damage_handle = xcb_generate_id(connection());
xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
}
damage_region = QRegion(0, 0, width(), height());
effect_window = new EffectWindowImpl(this);
Compositor::self()->scene()->addToplevel(this);
return true;
}
void Toplevel::finishCompositing(ReleaseReason releaseReason)
{
if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE)
return;
if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data
discardWindowPixmap();
delete effect_window;
}
if (damage_handle != XCB_NONE &&
releaseReason != ReleaseReason::Destroyed) {
xcb_damage_destroy(connection(), damage_handle);
}
damage_handle = XCB_NONE;
damage_region = QRegion();
repaints_region = QRegion();
effect_window = NULL;
}
void Toplevel::discardWindowPixmap()
{
addDamageFull();
if (effectWindow() != NULL && effectWindow()->sceneWindow() != NULL)
effectWindow()->sceneWindow()->pixmapDiscarded();
}
void Toplevel::damageNotifyEvent()
{
m_isDamaged = true;
// Note: The rect is supposed to specify the damage extents,
// but we don't know it at this point. No one who connects
// to this signal uses the rect however.
emit damaged(this, QRect());
}
bool Toplevel::compositing() const
{
if (!Workspace::self()) {
return false;
}
return Workspace::self()->compositing();
}
void Client::damageNotifyEvent()
{
if (syncRequest.isPending && isResize()) {
emit damaged(this, QRect());
m_isDamaged = true;
return;
}
if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead
if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now
setReadyForPainting();
setupWindowManagementInterface();
}
}
Toplevel::damageNotifyEvent();
}
bool Toplevel::resetAndFetchDamage()
{
if (!m_isDamaged)
return false;
if (damage_handle == XCB_NONE) {
m_isDamaged = false;
return true;
}
xcb_connection_t *conn = connection();
// Create a new region and copy the damage region to it,
// resetting the damaged state.
xcb_xfixes_region_t region = xcb_generate_id(conn);
xcb_xfixes_create_region(conn, region, 0, 0);
xcb_damage_subtract(conn, damage_handle, 0, region);
// Send a fetch-region request and destroy the region
m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region);
xcb_xfixes_destroy_region(conn, region);
m_isDamaged = false;
m_damageReplyPending = true;
return m_damageReplyPending;
}
void Toplevel::getDamageRegionReply()
{
if (!m_damageReplyPending)
return;
m_damageReplyPending = false;
// Get the fetch-region reply
xcb_xfixes_fetch_region_reply_t *reply =
xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, 0);
if (!reply)
return;
// Convert the reply to a QRegion
int count = xcb_xfixes_fetch_region_rectangles_length(reply);
QRegion region;
if (count > 1 && count < 16) {
xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply);
QVector<QRect> qrects;
qrects.reserve(count);
for (int i = 0; i < count; i++)
qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
region.setRects(qrects.constData(), count);
} else
region += QRect(reply->extents.x, reply->extents.y,
reply->extents.width, reply->extents.height);
damage_region += region;
repaints_region += region;
free(reply);
}
void Toplevel::addDamageFull()
{
if (!compositing())
return;
damage_region = rect();
repaints_region |= rect();
emit damaged(this, rect());
}
void Toplevel::resetDamage()
{
damage_region = QRegion();
}
void Toplevel::addRepaint(const QRect& r)
{
if (!compositing()) {
return;
}
repaints_region += r;
emit needsRepaint();
}
void Toplevel::addRepaint(int x, int y, int w, int h)
{
QRect r(x, y, w, h);
addRepaint(r);
}
void Toplevel::addRepaint(const QRegion& r)
{
if (!compositing()) {
return;
}
repaints_region += r;
emit needsRepaint();
}
void Toplevel::addLayerRepaint(const QRect& r)
{
if (!compositing()) {
return;
}
layer_repaints_region += r;
emit needsRepaint();
}
void Toplevel::addLayerRepaint(int x, int y, int w, int h)
{
QRect r(x, y, w, h);
addLayerRepaint(r);
}
void Toplevel::addLayerRepaint(const QRegion& r)
{
if (!compositing())
return;
layer_repaints_region += r;
emit needsRepaint();
}
void Toplevel::addRepaintFull()
{
repaints_region = visibleRect().translated(-pos());
emit needsRepaint();
}
void Toplevel::resetRepaints()
{
repaints_region = QRegion();
layer_repaints_region = QRegion();
}
void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h)
{
addWorkspaceRepaint(QRect(x, y, w, h));
}
void Toplevel::addWorkspaceRepaint(const QRect& r2)
{
if (!compositing())
return;
Compositor::self()->addRepaint(r2);
}
//****************************************
// Client
//****************************************
bool Client::setupCompositing()
{
if (!Toplevel::setupCompositing()){
return false;
}
updateVisibility(); // for internalKeep()
return true;
}
void Client::finishCompositing(ReleaseReason releaseReason)
{
Toplevel::finishCompositing(releaseReason);
updateVisibility();
// for safety in case KWin is just resizing the window
resetHaveResizeEffect();
}
} // namespace

View file

@ -17,7 +17,6 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "toplevel.h"
#ifdef KWIN_BUILD_ACTIVITIES
@ -26,9 +25,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "atoms.h"
#include "client.h"
#include "client_machine.h"
#include "composite.h"
#include "effects.h"
#include "screens.h"
#include "shadow.h"
#include "workspace.h"
#include "xcbutils.h"
#include <KWayland/Server/surface_interface.h>
@ -256,6 +257,243 @@ void Toplevel::setOpacity(double new_opacity)
}
}
bool Toplevel::setupCompositing()
{
if (!compositing())
return false;
if (damage_handle != XCB_NONE)
return false;
if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) {
damage_handle = xcb_generate_id(connection());
xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
}
damage_region = QRegion(0, 0, width(), height());
effect_window = new EffectWindowImpl(this);
Compositor::self()->scene()->addToplevel(this);
return true;
}
void Toplevel::finishCompositing(ReleaseReason releaseReason)
{
if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE)
return;
if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data
discardWindowPixmap();
delete effect_window;
}
if (damage_handle != XCB_NONE &&
releaseReason != ReleaseReason::Destroyed) {
xcb_damage_destroy(connection(), damage_handle);
}
damage_handle = XCB_NONE;
damage_region = QRegion();
repaints_region = QRegion();
effect_window = NULL;
}
void Toplevel::discardWindowPixmap()
{
addDamageFull();
if (effectWindow() != NULL && effectWindow()->sceneWindow() != NULL)
effectWindow()->sceneWindow()->pixmapDiscarded();
}
void Toplevel::damageNotifyEvent()
{
m_isDamaged = true;
// Note: The rect is supposed to specify the damage extents,
// but we don't know it at this point. No one who connects
// to this signal uses the rect however.
emit damaged(this, QRect());
}
bool Toplevel::compositing() const
{
if (!Workspace::self()) {
return false;
}
return Workspace::self()->compositing();
}
void Client::damageNotifyEvent()
{
if (syncRequest.isPending && isResize()) {
emit damaged(this, QRect());
m_isDamaged = true;
return;
}
if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead
if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now
setReadyForPainting();
setupWindowManagementInterface();
}
}
Toplevel::damageNotifyEvent();
}
bool Toplevel::resetAndFetchDamage()
{
if (!m_isDamaged)
return false;
if (damage_handle == XCB_NONE) {
m_isDamaged = false;
return true;
}
xcb_connection_t *conn = connection();
// Create a new region and copy the damage region to it,
// resetting the damaged state.
xcb_xfixes_region_t region = xcb_generate_id(conn);
xcb_xfixes_create_region(conn, region, 0, 0);
xcb_damage_subtract(conn, damage_handle, 0, region);
// Send a fetch-region request and destroy the region
m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region);
xcb_xfixes_destroy_region(conn, region);
m_isDamaged = false;
m_damageReplyPending = true;
return m_damageReplyPending;
}
void Toplevel::getDamageRegionReply()
{
if (!m_damageReplyPending)
return;
m_damageReplyPending = false;
// Get the fetch-region reply
xcb_xfixes_fetch_region_reply_t *reply =
xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, 0);
if (!reply)
return;
// Convert the reply to a QRegion
int count = xcb_xfixes_fetch_region_rectangles_length(reply);
QRegion region;
if (count > 1 && count < 16) {
xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply);
QVector<QRect> qrects;
qrects.reserve(count);
for (int i = 0; i < count; i++)
qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
region.setRects(qrects.constData(), count);
} else
region += QRect(reply->extents.x, reply->extents.y,
reply->extents.width, reply->extents.height);
damage_region += region;
repaints_region += region;
free(reply);
}
void Toplevel::addDamageFull()
{
if (!compositing())
return;
damage_region = rect();
repaints_region |= rect();
emit damaged(this, rect());
}
void Toplevel::resetDamage()
{
damage_region = QRegion();
}
void Toplevel::addRepaint(const QRect& r)
{
if (!compositing()) {
return;
}
repaints_region += r;
emit needsRepaint();
}
void Toplevel::addRepaint(int x, int y, int w, int h)
{
QRect r(x, y, w, h);
addRepaint(r);
}
void Toplevel::addRepaint(const QRegion& r)
{
if (!compositing()) {
return;
}
repaints_region += r;
emit needsRepaint();
}
void Toplevel::addLayerRepaint(const QRect& r)
{
if (!compositing()) {
return;
}
layer_repaints_region += r;
emit needsRepaint();
}
void Toplevel::addLayerRepaint(int x, int y, int w, int h)
{
QRect r(x, y, w, h);
addLayerRepaint(r);
}
void Toplevel::addLayerRepaint(const QRegion& r)
{
if (!compositing())
return;
layer_repaints_region += r;
emit needsRepaint();
}
void Toplevel::addRepaintFull()
{
repaints_region = visibleRect().translated(-pos());
emit needsRepaint();
}
void Toplevel::resetRepaints()
{
repaints_region = QRegion();
layer_repaints_region = QRegion();
}
void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h)
{
addWorkspaceRepaint(QRect(x, y, w, h));
}
void Toplevel::addWorkspaceRepaint(const QRect& r2)
{
if (!compositing())
return;
Compositor::self()->addRepaint(r2);
}
void Toplevel::setReadyForPainting()
{
if (!ready_for_painting) {

View file

@ -1748,6 +1748,11 @@ Toplevel *Workspace::findInternal(QWindow *w) const
}
}
bool Workspace::compositing() const
{
return m_compositor && m_compositor->hasScene();
}
void Workspace::markXStackingOrderAsDirty()
{
m_xStackingDirty = true;