Fix rendering errors of close window button in Present Windows

Hiding and Showing the close window button all the time can result in
the window not having a proper content. To fix this issue we keep the
window around, but just don't show it. For this the CloseWindowView
inherits from QObject and delegates the needed calls to the nested
QQuickView.
This commit is contained in:
Martin Gräßlin 2013-10-25 12:57:34 +02:00
parent bf9219bd9a
commit 5d5673ebc0
2 changed files with 80 additions and 28 deletions

View file

@ -41,6 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QDesktopWidget>
#include <QGraphicsObject>
#include <QTimer>
@ -400,8 +401,12 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region
}
winData->textFrame->render(region, 0.9 * data.opacity() * m_decalOpacity, 0.75);
}
} else
} else {
if (w == m_closeWindow && m_closeView && !m_closeView->isVisible()) {
data.setOpacity(0);
}
effects->paintWindow(w, mask, region, data);
}
} else
effects->paintWindow(w, mask, region, data);
}
@ -522,8 +527,9 @@ bool PresentWindowsEffect::borderActivated(ElectricBorder border)
void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
{
QMouseEvent* me = static_cast< QMouseEvent* >(e);
if (m_closeView && m_closeView->geometry().contains(me->pos())) {
if (!m_closeView->isVisible()) {
if (m_closeView) {
const bool contains = m_closeView->geometry().contains(me->pos());
if (!m_closeView->isVisible() && contains) {
updateCloseWindow();
}
if (m_closeView->isVisible()) {
@ -531,7 +537,10 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
// const QPointF scenePos = m_closeView->mapToScene(widgetPos);
QMouseEvent event(me->type(), widgetPos, me->pos(), me->button(), me->buttons(), me->modifiers());
m_closeView->windowInputMouseEvent(&event);
return;
if (contains) {
// filter out
return;
}
}
}
// Which window are we hovering over? Always trigger as we don't always get move events before clicking
@ -1945,15 +1954,17 @@ void PresentWindowsEffect::screenCountChanged()
/************************************************
* CloseWindowView
************************************************/
CloseWindowView::CloseWindowView(QWindow *parent)
: QQuickView(parent)
CloseWindowView::CloseWindowView(QObject *parent)
: QObject(parent)
, m_armTimer(new QElapsedTimer())
, m_window(new QQuickView())
, m_visible(false)
{
setFlags(Qt::X11BypassWindowManagerHint);
setColor(Qt::transparent);
m_window->setFlags(Qt::X11BypassWindowManagerHint);
m_window->setColor(Qt::transparent);
setSource(QUrl(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/presentwindows/main.qml"))));
if (QObject *item = rootObject()->findChild<QObject*>(QStringLiteral("closeButton"))) {
m_window->setSource(QUrl(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/presentwindows/main.qml"))));
if (QObject *item = m_window->rootObject()->findChild<QObject*>(QStringLiteral("closeButton"))) {
connect(item, SIGNAL(clicked()), SIGNAL(requestClose()));
}
@ -1963,17 +1974,12 @@ CloseWindowView::CloseWindowView(QWindow *parent)
void CloseWindowView::windowInputMouseEvent(QMouseEvent *e)
{
if (e->type() == QEvent::MouseMove) {
mouseMoveEvent(e);
qApp->sendEvent(m_window.data(), e);
} else if (!m_armTimer->hasExpired(350)) {
// 50ms until the window is elevated (seen!) and 300ms more to be "realized" by the user.
return;
} else if (e->type() == QEvent::MouseButtonPress) {
mousePressEvent(e);
} else if (e->type() == QEvent::MouseButtonDblClick) {
mouseDoubleClickEvent(e);
} else if (e->type() == QEvent::MouseButtonRelease) {
mouseReleaseEvent(e);
}
qApp->sendEvent(m_window.data(), e);
}
void CloseWindowView::disarm()
@ -1981,12 +1987,46 @@ void CloseWindowView::disarm()
m_armTimer->restart();
}
void CloseWindowView::hideEvent(QHideEvent *event)
bool CloseWindowView::isVisible() const
{
const QPoint globalPos = mapToGlobal(QPoint(-1,-1));
QMouseEvent me(QEvent::MouseMove, QPoint(-1,-1), globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
mouseMoveEvent(&me);
QQuickView::hideEvent(event);
return m_visible;
}
void CloseWindowView::show()
{
m_visible = true;
m_window->show();
}
void CloseWindowView::hide()
{
m_visible = false;
QEvent event(QEvent::Leave);
qApp->sendEvent(m_window.data(), &event);
}
#define DELEGATE(type, name) \
type CloseWindowView::name() const \
{ \
return m_window->name(); \
}
DELEGATE(int, width)
DELEGATE(int, height)
DELEGATE(QSize, size)
DELEGATE(QRect, geometry)
DELEGATE(WId, winId)
#undef DELEGATE
void CloseWindowView::setGeometry(const QRect &geometry)
{
m_window->setGeometry(geometry);
}
QPoint CloseWindowView::mapFromGlobal(const QPoint &pos) const
{
return m_window->mapFromGlobal(pos);
}
} // namespace

View file

@ -25,28 +25,40 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "presentwindows_proxy.h"
#include <kwineffects.h>
#include <QQuickView>
class QElapsedTimer;
class QQuickView;
namespace KWin
{
class CloseWindowView : public QQuickView
class CloseWindowView : public QObject
{
Q_OBJECT
public:
explicit CloseWindowView(QWindow *parent = 0);
explicit CloseWindowView(QObject *parent = 0);
void windowInputMouseEvent(QMouseEvent* e);
void disarm();
void show();
void hide();
bool isVisible() const;
// delegate to QWindow
int width() const;
int height() const;
QSize size() const;
QRect geometry() const;
WId winId() const;
void setGeometry(const QRect &geometry);
QPoint mapFromGlobal(const QPoint &pos) const;
Q_SIGNALS:
void requestClose();
protected:
void hideEvent(QHideEvent *event);
private:
QScopedPointer<QElapsedTimer> m_armTimer;
QScopedPointer<QQuickView> m_window;
bool m_visible;
};
/**