blob: ff4e63de614a55f0f7de31e048c4ce92c865fd15 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include "qvsyncanimationdriver_p.h"
#include "private/qabstractanimation_p.h"
#include <private/qthread_p.h>
#include <QtGui/qevent.h>
#include <QtGui/qwidget.h>
#include <QtGui/qapplication.h>
#ifdef Q_WS_QPA
#include <qplatformglcontext_qpa.h>
#endif
#include <qdebug.h>
class QVSyncAnimationDriverPrivate : public QAnimationDriverPrivate
{
public:
QWidget *window;
bool aborted;
};
class WidgetAccessor : public QWidget
{
public:
void paint() {
QPaintEvent e(rect());
paintEvent(&e);
}
};
QVSyncAnimationDriver::QVSyncAnimationDriver(QObject *parent)
: QAnimationDriver(*(new QVSyncAnimationDriverPrivate), parent)
{
Q_D(QVSyncAnimationDriver);
d->window = 0;
d->aborted = false;
qApp->installEventFilter(this);
}
void QVSyncAnimationDriver::setWidget(QWidget *window)
{
d_func()->window = window;
}
QWidget *QVSyncAnimationDriver::widget() const
{
return d_func()->window;
}
void QVSyncAnimationDriver::started()
{
Q_D(QVSyncAnimationDriver);
if (!d->window) {
qWarning("VSyncDriver: no window to drive animation on...\n");
return;
}
QEvent *event = new QEvent(QEvent::Type(QEvent::User + 1));
QApplication::postEvent(this, event);
}
bool QVSyncAnimationDriver::event(QEvent *e)
{
Q_D(QVSyncAnimationDriver);
if (e->type() == QEvent::User + 1) {
while (isRunning() && !d->aborted && !d->threadData->quitNow) {
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QApplication::processEvents(QEventLoop::AllEvents, 1);
advance();
((WidgetAccessor *) d->window)->paint();
#ifdef Q_WS_QPA
QPlatformGLContext *ctx = d->window->platformWindow()->glContext();
ctx->swapBuffers();
#endif
}
}
return QAnimationDriver::event(e);
}
bool QVSyncAnimationDriver::eventFilter(QObject *object, QEvent *event) {
Q_D(QVSyncAnimationDriver);
if (isRunning()) {
#ifdef Q_WS_QPA
if (object == d->window && event->type() == QEvent::UpdateRequest)
return true;
else
#endif
if (object == QApplication::instance() && event->type() == QEvent::Quit) {
// If we get a close event while running, we are actually inside the processEvents()
// block and need to exit an extra level to exit the final exec().
d->aborted = true;
QApplication::quit();
} else if (object == d->window && event->type() == QEvent::Paint) {
// Since we are now blocking on vsync and we do a single fullscreen update,
// want to only respond to a single update pr 16.66 ms increment, which is
// the one we explicitly send to the window. All others we reject.
return true;
}
}
return QObject::eventFilter(object, event);
}
void QVSyncAnimationDriver::stopped()
{
// I don't need to do nothing as baseclass sets isRunning to false for us..
}
|