Move OverlayWindow from Workspace to its own class

All the functionality of Overlay Window is moved to its own class
OverlayWindow. It is created and owned by class Scene, since almost
all function calls are called from this class.

REVIEW: 101866
This commit is contained in:
Arthur Arlt 2011-07-06 11:58:23 +02:00
parent c703dca4b2
commit d8072be54d
13 changed files with 251 additions and 145 deletions

View file

@ -118,7 +118,8 @@ set(kwin_KDEINIT_SRCS
group.cpp
bridge.cpp
manage.cpp
notifications.cpp
notifications.cpp
overlaywindow.cpp
activation.cpp
useractions.cpp
geometry.cpp

View file

@ -47,6 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "unmanaged.h"
#include "deleted.h"
#include "effects.h"
#include "overlaywindow.h"
#include "scene.h"
#include "scene_basic.h"
#include "scene_xrender.h"
@ -379,7 +380,7 @@ void Workspace::performCompositing()
{
#ifdef KWIN_HAVE_COMPOSITING
if (((repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
|| !overlay_visible)) { // nothing is visible anyway
|| !scene->overlayWindow()->isVisible())) { // nothing is visible anyway
vBlankPadding += 3;
scene->idle();
// Note: It would seem here we should undo suspended unredirect, but when scenes need
@ -492,94 +493,6 @@ void Workspace::stopMousePolling()
mousePollingTimer.stop();
}
bool Workspace::createOverlay()
{
assert(overlay == None);
if (!Extensions::compositeOverlayAvailable())
return false;
if (!Extensions::shapeInputAvailable()) // needed in setupOverlay()
return false;
#ifdef HAVE_XCOMPOSITE_OVERLAY
overlay = XCompositeGetOverlayWindow(display(), rootWindow());
if (overlay == None)
return false;
XResizeWindow(display(), overlay, displayWidth(), displayHeight());
return true;
#else
return false;
#endif
}
void Workspace::setupOverlay(Window w)
{
assert(overlay != None);
assert(Extensions::shapeInputAvailable());
XSetWindowBackgroundPixmap(display(), overlay, None);
overlay_shape = QRegion();
setOverlayShape(QRect(0, 0, displayWidth(), displayHeight()));
if (w != None) {
XSetWindowBackgroundPixmap(display(), w, None);
XShapeCombineRectangles(display(), w, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
}
XSelectInput(display(), overlay, VisibilityChangeMask);
}
void Workspace::showOverlay()
{
assert(overlay != None);
if (overlay_shown)
return;
XMapSubwindows(display(), overlay);
XMapWindow(display(), overlay);
overlay_shown = true;
}
void Workspace::hideOverlay()
{
assert(overlay != None);
XUnmapWindow(display(), overlay);
overlay_shown = false;
setOverlayShape(QRect(0, 0, displayWidth(), displayHeight()));
}
void Workspace::setOverlayShape(const QRegion& reg)
{
// Avoid setting the same shape again, it causes flicker (apparently it is not a no-op
// and triggers something).
if (reg == overlay_shape)
return;
QVector< QRect > rects = reg.rects();
XRectangle* xrects = new XRectangle[ rects.count()];
for (int i = 0;
i < rects.count();
++i) {
xrects[ i ].x = rects[ i ].x();
xrects[ i ].y = rects[ i ].y();
xrects[ i ].width = rects[ i ].width();
xrects[ i ].height = rects[ i ].height();
}
XShapeCombineRectangles(display(), overlay, ShapeBounding, 0, 0,
xrects, rects.count(), ShapeSet, Unsorted);
delete[] xrects;
XShapeCombineRectangles(display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
overlay_shape = reg;
}
void Workspace::destroyOverlay()
{
if (overlay == None)
return;
// reset the overlay shape
XRectangle rec = { 0, 0, displayWidth(), displayHeight() };
XShapeCombineRectangles(display(), overlay, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted);
XShapeCombineRectangles(display(), overlay, ShapeInput, 0, 0, &rec, 1, ShapeSet, Unsorted);
#ifdef HAVE_XCOMPOSITE_OVERLAY
XCompositeReleaseOverlayWindow(display(), overlay);
#endif
overlay = None;
overlay_shown = false;
}
bool Workspace::compositingActive()
{
return !m_finishingCompositing && compositing();
@ -588,7 +501,7 @@ bool Workspace::compositingActive()
// force is needed when the list of windows changes (e.g. a window goes away)
void Workspace::checkUnredirect(bool force)
{
if (!compositing() || overlay == None || !options->unredirectFullscreen)
if (!compositing() || scene->overlayWindow()->window() == None || !options->unredirectFullscreen)
return;
if (force)
forceUnredirectCheck = true;
@ -598,7 +511,7 @@ void Workspace::checkUnredirect(bool force)
void Workspace::delayedCheckUnredirect()
{
if (!compositing() || overlay == None || !options->unredirectFullscreen)
if (!compositing() || scene->overlayWindow()->window() == None || !options->unredirectFullscreen)
return;
ToplevelList list;
bool changed = forceUnredirectCheck;
@ -621,7 +534,7 @@ void Workspace::delayedCheckUnredirect()
if (c->unredirected())
reg -= c->geometry();
}
setOverlayShape(reg);
scene->overlayWindow()->setShape(reg);
}
//****************************************

View file

@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "tabbox.h"
#endif
#include "group.h"
#include "overlaywindow.h"
#include "rules.h"
#include "unmanaged.h"
#include "effects.h"
@ -445,15 +446,15 @@ bool Workspace::workspaceEvent(XEvent * e)
case Expose:
if (compositing()
&& (e->xexpose.window == rootWindow() // root window needs repainting
|| (overlay != None && e->xexpose.window == overlay))) { // overlay needs repainting
|| (scene->overlayWindow()->window() != None && e->xexpose.window == scene->overlayWindow()->window()))) { // overlay needs repainting
addRepaint(e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height);
}
break;
case VisibilityNotify:
if (compositing() && overlay != None && e->xvisibility.window == overlay) {
bool was_visible = overlay_visible;
overlay_visible = (e->xvisibility.state != VisibilityFullyObscured);
if (!was_visible && overlay_visible) {
if (compositing() && scene->overlayWindow()->window() != None && e->xvisibility.window == scene->overlayWindow()->window()) {
bool was_visible = scene->overlayWindow()->isVisible();
scene->overlayWindow()->setVisibility((e->xvisibility.state != VisibilityFullyObscured));
if (!was_visible && scene->overlayWindow()->isVisible()) {
// hack for #154825
addRepaintFull();
QTimer::singleShot(2000, this, SLOT(addRepaintFull()));

146
overlaywindow.cpp Normal file
View file

@ -0,0 +1,146 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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 "overlaywindow.h"
#include "kwinglobals.h"
#include "assert.h"
#include <QtCore/QVector>
#include <X11/extensions/shape.h>
namespace KWin {
OverlayWindow::OverlayWindow()
: m_window(None)
, m_visible(true)
, m_shown(false)
{
}
OverlayWindow::~OverlayWindow()
{
}
bool OverlayWindow::create()
{
assert(m_window == None);
if (!Extensions::compositeOverlayAvailable())
return false;
if (!Extensions::shapeInputAvailable()) // needed in setupOverlay()
return false;
#ifdef HAVE_XCOMPOSITE_OVERLAY
m_overlay = XCompositeGetOverlayWindow(display(), rootWindow());
if (m_overlay == None)
return false;
XResizeWindow(display(), m_overlay, displayWidth(), displayHeight());
return true;
#else
return false;
#endif
}
void OverlayWindow::setup(Window window)
{
assert(m_window != None);
assert(Extensions::shapeInputAvailable());
XSetWindowBackgroundPixmap(display(), m_window, None);
m_shape = QRegion();
setShape(QRect(0, 0, displayWidth(), displayHeight()));
if (window != None) {
XSetWindowBackgroundPixmap(display(), window, None);
XShapeCombineRectangles(display(), window, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
}
XSelectInput(display(), m_window, VisibilityChangeMask);
}
void OverlayWindow::show()
{
assert(m_window != None);
if (m_shown)
return;
XMapSubwindows(display(), m_window);
XMapWindow(display(), m_window);
m_shown = true;
}
void OverlayWindow::hide()
{
assert(m_window != None);
XUnmapWindow(display(), m_window);
m_shown = false;
setShape(QRect(0, 0, displayWidth(), displayHeight()));
}
void OverlayWindow::setShape(const QRegion& reg)
{
// Avoid setting the same shape again, it causes flicker (apparently it is not a no-op
// and triggers something).
if (reg == m_shape)
return;
QVector< QRect > rects = reg.rects();
XRectangle* xrects = new XRectangle[ rects.count()];
for (int i = 0;
i < rects.count();
++i) {
xrects[ i ].x = rects[ i ].x();
xrects[ i ].y = rects[ i ].y();
xrects[ i ].width = rects[ i ].width();
xrects[ i ].height = rects[ i ].height();
}
XShapeCombineRectangles(display(), m_window, ShapeBounding, 0, 0,
xrects, rects.count(), ShapeSet, Unsorted);
delete[] xrects;
XShapeCombineRectangles(display(), m_window, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
m_shape = reg;
}
bool OverlayWindow::isVisible()
{
return m_visible;
}
void OverlayWindow::setVisibility(bool visible)
{
m_visible = visible;
}
void OverlayWindow::destroy()
{
if (m_window == None)
return;
// reset the overlay shape
XRectangle rec = { 0, 0, displayWidth(), displayHeight() };
XShapeCombineRectangles(display(), m_window, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted);
XShapeCombineRectangles(display(), m_window, ShapeInput, 0, 0, &rec, 1, ShapeSet, Unsorted);
#ifdef HAVE_XCOMPOSITE_OVERLAY
XCompositeReleaseOverlayWindow(display(), m_overlay);
#endif
m_window = None;
m_shown = false;
}
Window OverlayWindow::window()
{
return m_window;
}
} // namespace KWin

53
overlaywindow.h Normal file
View file

@ -0,0 +1,53 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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/>.
*********************************************************************/
#ifndef KWIN_OVERLAYWINDOW_H
#define KWIN_OVERLAYWINDOW_H
#include <QRegion>
#include <X11/Xlib.h>
namespace KWin {
class OverlayWindow {
public:
OverlayWindow();
~OverlayWindow();
/// Creates XComposite overlay window, call initOverlay() afterwards
bool create();
/// Init overlay and the destination window in it
void setup(Window window);
void show();
void hide(); // hides and resets overlay window
void setShape(const QRegion& reg);
/// Destroys XComposite overlay window
void destroy();
Window window();
bool isVisible();
void setVisibility(bool visible);
private:
bool m_visible;
bool m_shown; // For showOverlay()
QRegion m_shape;
Window m_window;
};
} // namespace
#endif //KWIN_OVERLAYWINDOW_H

View file

@ -77,6 +77,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "deleted.h"
#include "effects.h"
#include "lanczosfilter.h"
#include "overlaywindow.h"
#include "shadow.h"
#include <kephal/screens.h>
@ -95,12 +96,14 @@ Scene::Scene(Workspace* ws)
, wspace(ws)
, has_waitSync(false)
, lanczos_filter(new LanczosFilter())
, m_overlayWindow(new OverlayWindow())
{
}
Scene::~Scene()
{
delete lanczos_filter;
delete m_overlayWindow;
}
// returns mask and possibly modified region
@ -321,6 +324,11 @@ void Scene::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, Windo
w->sceneWindow()->performPaint(mask, region, data);
}
OverlayWindow* Scene::overlayWindow()
{
return m_overlayWindow;
}
//****************************************
// Scene::Window
//****************************************

View file

@ -35,6 +35,7 @@ class Deleted;
class EffectFrameImpl;
class EffectWindowImpl;
class LanczosFilter;
class OverlayWindow;
class Shadow;
// The base class for compositing backends.
@ -95,6 +96,7 @@ public:
bool waitSyncAvailable() {
return has_waitSync;
}
OverlayWindow* overlayWindow();
public Q_SLOTS:
// opacity of a window changed
virtual void windowOpacityChanged(KWin::Toplevel* c) = 0;
@ -152,6 +154,7 @@ protected:
Workspace* wspace;
bool has_waitSync;
LanczosFilter* lanczos_filter;
OverlayWindow* m_overlayWindow;
};
// The base class for windows representations in composite backends

View file

@ -77,6 +77,7 @@ Sources and other compositing managers:
#include "client.h"
#include "deleted.h"
#include "effects.h"
#include "overlaywindow.h"
#include <math.h>

View file

@ -62,7 +62,7 @@ SceneOpenGL::~SceneOpenGL()
{
if (!init_ok) {
// TODO this probably needs to clean up whatever has been created until the failure
wspace->destroyOverlay();
m_overlayWindow->destroy();
return;
}
foreach (Window * w, windows)
@ -76,8 +76,8 @@ SceneOpenGL::~SceneOpenGL()
eglReleaseThread();
SceneOpenGL::EffectFrame::cleanup();
checkGLError("Cleanup");
if (wspace->overlayWindow()) {
wspace->destroyOverlay();
if (m_overlayWindow->window()) {
m_overlayWindow->destroy();
}
}
@ -96,13 +96,13 @@ bool SceneOpenGL::initRenderingContext()
return false;
eglBindAPI(EGL_OPENGL_ES_API);
initBufferConfigs();
if (!wspace->createOverlay()) {
if (!m_overlayWindow->create()) {
kError(1212) << "Could not get overlay window";
return false;
} else {
wspace->setupOverlay(None);
m_overlayWindow->setup(None);
}
surface = eglCreateWindowSurface(dpy, config, wspace->overlayWindow(), 0);
surface = eglCreateWindowSurface(dpy, config, m_overlayWindow->window(), 0);
const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
@ -177,8 +177,8 @@ void SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
int mask = 0;
paintScreen(&mask, &damage); // call generic implementation
ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync
if (wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long
if (m_overlayWindow->window()) // show the window only after the first pass, since
m_overlayWindow->show(); // that pass may take long
lastRenderTime = t.elapsed();
flushBuffer(mask, damage);
// do cleanup

View file

@ -128,7 +128,7 @@ SceneOpenGL::~SceneOpenGL()
{
if (!init_ok) {
// TODO this probably needs to clean up whatever has been created until the failure
wspace->destroyOverlay();
m_overlayWindow->destroy();
return;
}
foreach (Window * w, windows)
@ -137,11 +137,11 @@ SceneOpenGL::~SceneOpenGL()
cleanupGL();
glXMakeCurrent(display(), None, NULL);
glXDestroyContext(display(), ctxbuffer);
if (wspace->overlayWindow()) {
if (m_overlayWindow->window()) {
if (hasGLXVersion(1, 3))
glXDestroyWindow(display(), glxbuffer);
XDestroyWindow(display(), buffer);
wspace->destroyOverlay();
m_overlayWindow->destroy();
} else {
glXDestroyPixmap(display(), glxbuffer);
XFreeGC(display(), gcroot);
@ -196,19 +196,19 @@ bool SceneOpenGL::initBuffer()
{
if (!initBufferConfigs())
return false;
if (fbcbuffer_db != NULL && wspace->createOverlay()) {
if (fbcbuffer_db != NULL && m_overlayWindow->create()) {
// we have overlay, try to create double-buffered window in it
fbcbuffer = fbcbuffer_db;
XVisualInfo* visual = glXGetVisualFromFBConfig(display(), fbcbuffer);
XSetWindowAttributes attrs;
attrs.colormap = XCreateColormap(display(), rootWindow(), visual->visual, AllocNone);
buffer = XCreateWindow(display(), wspace->overlayWindow(), 0, 0, displayWidth(), displayHeight(),
buffer = XCreateWindow(display(), m_overlayWindow->window(), 0, 0, displayWidth(), displayHeight(),
0, visual->depth, InputOutput, visual->visual, CWColormap, &attrs);
if (hasGLXVersion(1, 3))
glxbuffer = glXCreateWindow(display(), fbcbuffer, buffer, NULL);
else
glxbuffer = buffer;
wspace->setupOverlay(buffer);
m_overlayWindow->setup(buffer);
db = true;
XFree(visual);
} else if (fbcbuffer_nondb != NULL) {
@ -458,8 +458,8 @@ void SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
#endif
glPopMatrix();
ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync
if (wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long
if (m_overlayWindow->window()) // show the window only after the first pass, since
m_overlayWindow->show(); // that pass may take long
lastRenderTime = t.elapsed();
flushBuffer(mask, damage);
// do cleanup

View file

@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "client.h"
#include "deleted.h"
#include "effects.h"
#include "overlaywindow.h"
#include "kwinxrenderutils.h"
#include <X11/extensions/Xcomposite.h>
@ -99,16 +100,16 @@ SceneXrender::SceneXrender(Workspace* ws)
return;
}
KXErrorHandler xerr;
if (wspace->createOverlay()) {
wspace->setupOverlay(None);
if (m_overlayWindow->create()) {
m_overlayWindow->setup(None);
XWindowAttributes attrs;
XGetWindowAttributes(display(), wspace->overlayWindow(), &attrs);
XGetWindowAttributes(display(), m_overlayWindow->window(), &attrs);
format = XRenderFindVisualFormat(display(), attrs.visual);
if (format == NULL) {
kError(1212) << "Failed to find XRender format for overlay window";
return;
}
front = XRenderCreatePicture(display(), wspace->overlayWindow(), format, 0, NULL);
front = XRenderCreatePicture(display(), m_overlayWindow->window(), format, 0, NULL);
} else {
// create XRender picture for the root window
format = XRenderFindVisualFormat(display(), DefaultVisual(display(), DefaultScreen(display())));
@ -132,13 +133,13 @@ SceneXrender::~SceneXrender()
{
if (!init_ok) {
// TODO this probably needs to clean up whatever has been created until the failure
wspace->destroyOverlay();
m_overlayWindow->destroy();
return;
}
XRenderFreePicture(display(), front);
XRenderFreePicture(display(), buffer);
buffer = None;
wspace->destroyOverlay();
m_overlayWindow->destroy();
foreach (Window * w, windows)
delete w;
}
@ -167,8 +168,8 @@ void SceneXrender::paint(QRegion damage, ToplevelList toplevels)
}
int mask = 0;
paintScreen(&mask, &damage);
if (wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long
if (m_overlayWindow->window()) // show the window only after the first pass, since
m_overlayWindow->show(); // that pass may take long
lastRenderTime = t.elapsed();
flushBuffer(mask, damage);
// do cleanup

View file

@ -59,6 +59,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "unmanaged.h"
#include "deleted.h"
#include "effects.h"
#include "overlaywindow.h"
#include "tilinglayout.h"
#include "scripting/scripting.h"
@ -149,9 +150,6 @@ Workspace::Workspace(bool restore)
, compositingSuspended(false)
, compositingBlocked(false)
, xrrRefreshRate(0)
, overlay(None)
, overlay_visible(true)
, overlay_shown(false)
, transSlider(NULL)
, transButton(NULL)
, forceUnredirectCheck(true)
@ -532,7 +530,7 @@ Client* Workspace::createClient(Window w, bool is_mapped)
Unmanaged* Workspace::createUnmanaged(Window w)
{
if (w == overlay)
if (w == scene->overlayWindow()->window())
return NULL;
Unmanaged* c = new Unmanaged(this);
if (!c->track(w)) {

View file

@ -535,16 +535,6 @@ public:
void addRepaint(const QRect& r);
void addRepaint(const QRegion& r);
void addRepaint(int x, int y, int w, int h);
/// Creates XComposite overlay window, call initOverlay() afterwards
bool createOverlay();
/// Init overlay and the destination window in it
void setupOverlay(Window window);
void showOverlay();
void hideOverlay(); // hides and resets overlay window
void setOverlayShape(const QRegion& reg);
/// Destroys XComposite overlay window
void destroyOverlay();
Window overlayWindow();
void checkUnredirect(bool force = false);
void checkCompositeTimer();
@ -940,10 +930,6 @@ private:
uint vBlankInterval, vBlankPadding, fpsInterval, estimatedRenderTime;
int xrrRefreshRate; // used only for compositing
QRegion repaints_region;
Window overlay; // XComposite overlay window
bool overlay_visible;
bool overlay_shown; // For showOverlay()
QRegion overlay_shape;
QSlider* transSlider;
QPushButton* transButton;
QTimer unredirectTimer;
@ -1124,11 +1110,6 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
}
inline Window Workspace::overlayWindow()
{
return overlay;
}
inline bool Workspace::rulesUpdatesDisabled() const
{
return rules_updates_disabled;