From c329bcfd933d7d847092e4be0462169e83191461 Mon Sep 17 00:00:00 2001 From: APTX Date: Fri, 31 Jul 2009 13:29:30 +0200 Subject: [PATCH] - Move some code from VideoWindow into a new class: VideoPlayer. --- src/seekslider.cpp | 8 ++ src/src.pro | 11 ++- src/videoplayer.cpp | 94 +++++++++++++++++++++++ src/videoplayer.h | 64 ++++++++++++++++ src/videowidget.h | 2 +- src/videowindow.cpp | 178 ++++++++++++-------------------------------- src/videowindow.h | 28 +------ 7 files changed, 227 insertions(+), 158 deletions(-) create mode 100644 src/videoplayer.cpp create mode 100644 src/videoplayer.h diff --git a/src/seekslider.cpp b/src/seekslider.cpp index 799f342..5c8770a 100644 --- a/src/seekslider.cpp +++ b/src/seekslider.cpp @@ -96,6 +96,8 @@ void SeekSlider::setMediaObject(Phonon::MediaObject *media) void SeekSlider::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + QPainter p(this); seekerTop = 0;//height() / 3; @@ -143,18 +145,24 @@ void SeekSlider::paintEvent(QPaintEvent *event) void SeekSlider::mouseMoveEvent(QMouseEvent *event) { + Q_UNUSED(event); + markerShadowPos = event->pos().x(); update(); } void SeekSlider::enterEvent(QEvent *event) { + Q_UNUSED(event); + drawMarkerShadow = true; update(); } void SeekSlider::leaveEvent(QEvent *event) { + Q_UNUSED(event); + drawMarkerShadow = false; update(); } diff --git a/src/src.pro b/src/src.pro index a4b9517..587a15f 100644 --- a/src/src.pro +++ b/src/src.pro @@ -23,7 +23,8 @@ SOURCES += main.cpp \ anidbconfigdialog.cpp \ episodevotedialog.cpp \ versiondialog.cpp \ - seekslider.cpp + seekslider.cpp \ + videoplayer.cpp HEADERS += menu.h \ videowindow.h \ videowidget.h \ @@ -34,7 +35,8 @@ HEADERS += menu.h \ episodevotedialog.h \ versiondialog.h \ constants.h \ - seekslider.h + seekslider.h \ + videoplayer.h FORMS += menu.ui \ anidbconfigdialog.ui \ episodevotedialog.ui @@ -73,3 +75,8 @@ use_anidbudpclient { message(Building without AniDBUdpClient!) DEFINES += NO_ANIDBUDPCLIENT } + +# Output Temporary files +OBJECTS_DIR = ../.tmp/obj +MOC_DIR = ../.tmp/moc +RCC_DIR = ../.tmp/rcc diff --git a/src/videoplayer.cpp b/src/videoplayer.cpp new file mode 100644 index 0000000..3cd7153 --- /dev/null +++ b/src/videoplayer.cpp @@ -0,0 +1,94 @@ +#include "videoplayer.h" + +#include "videowidget.h" + +VideoPlayer::VideoPlayer(QObject *parent, QWidget *videoWidgetParent) : Phonon::MediaObject(parent) +{ + m_mediaController = new Phonon::MediaController(this); + m_videoWidget = new VideoWidget(videoWidgetParent); // TODO + m_audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); + + Phonon::createPath(this, m_videoWidget); + Phonon::createPath(this, m_audioOutput); + + connect(m_videoWidget, SIGNAL(volumeChangeRequested(int)), this, SLOT(changeVolume(int))); +} + +void VideoPlayer::open(const Phonon::MediaSource &source) +{ + m_currentSource = source; + setCurrentSource(source); +} + +void VideoPlayer::play(const Phonon::MediaSource &file) +{ + open(file); + play(); +} + +void VideoPlayer::play() +{ + Phonon::MediaObject::play(); +} + +void VideoPlayer::togglePlay() +{ + switch(state()) + { + case Phonon::PlayingState: + Phonon::MediaObject::pause(); + break; + case Phonon::LoadingState: + case Phonon::PausedState: + case Phonon::StoppedState: + play(); + break; + default: + break; + } +} + +void VideoPlayer::volumeUp(int by) +{ + qreal volume = qBound(qreal(0), m_audioOutput->volume() + qreal(by) * 0.01, qreal(1.0)); + m_audioOutput->setVolume(volume); +} + +void VideoPlayer::volumeDown(int by) +{ + qreal volume = qBound(qreal(0), m_audioOutput->volume() - qreal(by) * 0.01, qreal(1.0)); + m_audioOutput->setVolume(volume); +} + +void VideoPlayer::changeVolume(int by) +{ + qreal volume = qBound(qreal(0), m_audioOutput->volume() + qreal(by) * 0.01, qreal(1.0)); + m_audioOutput->setVolume(volume); +} + +void VideoPlayer::skip(int msec) +{ + seek(currentTime() + qint64(msec)); +} + +void VideoPlayer::updateChapters() +{ + int chapters = m_mediaController->availableChapters(); + +qDebug() << "Chapters" << chapters; +} + +void VideoPlayer::updateSubtitles() +{ + QList subtitles = m_mediaController->availableSubtitles(); + + foreach (const Phonon::SubtitleDescription &subtitle, subtitles) + { + qDebug() << subtitle; + if (subtitle.name() == "eng") + { +qDebug() << "yep!"; + m_mediaController->setCurrentSubtitle(subtitle); + } + } +} diff --git a/src/videoplayer.h b/src/videoplayer.h new file mode 100644 index 0000000..a71b625 --- /dev/null +++ b/src/videoplayer.h @@ -0,0 +1,64 @@ +#ifndef VIDEOPLAYER_H +#define VIDEOPLAYER_H + +#ifdef KDE_PHONON +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif + +class VideoWidget; + +#define Phonon_AudioOutput Phonon::AudioOutput + +class VideoPlayer : public Phonon::MediaObject +{ + Q_OBJECT + + Q_PROPERTY(QString currentFile READ currentFile); + + Q_PROPERTY(VideoWidget *videoWidget READ videoWidget); + Q_PROPERTY(Phonon_AudioOutput *audioOutput READ audioOutput); + +public: + VideoPlayer(QObject *parent = 0, QWidget *videoWidgetParent = 0); + + Phonon::MediaController *mediaController() const { return m_mediaController;} + VideoWidget *videoWidget() const { return m_videoWidget;} + Phonon::AudioOutput *audioOutput() const { return m_audioOutput;} + + QString currentFile() const { return currentSource().fileName();} + +public slots: + void open(const Phonon::MediaSource &file); + void play(const Phonon::MediaSource &file); + void play(); + + void togglePlay(); + + void skip(int msec = 85000); + + void volumeUp(int by = 5); + void volumeDown(int by = 5); + void changeVolume(int by = 5); + + void updateChapters(); + void updateSubtitles(); + +signals: + void foo(); + +private: + Phonon::MediaController *m_mediaController; + Phonon::MediaSource m_currentSource; + VideoWidget *m_videoWidget; + Phonon::AudioOutput *m_audioOutput; +}; + +#endif // VIDEOPLAYER_H diff --git a/src/videowidget.h b/src/videowidget.h index a3b8adf..365bbc0 100644 --- a/src/videowidget.h +++ b/src/videowidget.h @@ -9,7 +9,7 @@ class VideoWidget : public Phonon::VideoWidget { -Q_OBJECT; + Q_OBJECT public: VideoWidget(QWidget *parent = 0); diff --git a/src/videowindow.cpp b/src/videowindow.cpp index 8128ba9..e2c3530 100644 --- a/src/videowindow.cpp +++ b/src/videowindow.cpp @@ -14,6 +14,7 @@ #include #include "menu.h" +#include "videoplayer.h" #include "videowidget.h" #include "aniplayer.h" #include "directoryplaylist.h" @@ -41,10 +42,7 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) #ifdef Q_WS_X11 setFocusPolicy(Qt::StrongFocus); #endif - resize(640, 480); - destroyed = menuMoving = windowMoving = m_closeOnStop = false; - m_currentFile = ""; #ifndef NO_ANIDBUDPCLIENT anidb = new AniDBUdpClient(this); @@ -53,19 +51,12 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) m_automark = 0; #endif - - mediaObject = new Phonon::MediaObject(this); - mediaController = new Phonon::MediaController(mediaObject); + videoPlayer = new VideoPlayer(this, this); #ifdef GRAPHICS_VIEW_VIDEO - videoWidget = new VideoWidget(); + videoWidget = new VideoWidget(); // TODO #else - videoWidget = new VideoWidget(this); #endif - audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); - - Phonon::createPath(mediaObject, videoWidget); - Phonon::createPath(mediaObject, audioOutput); #ifdef GRAPHICS_VIEW_VIDEO videoScene = new QGraphicsScene(this); @@ -84,7 +75,7 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) // videoView->resize(size()); #else - setCentralWidget(videoWidget); + setCentralWidget(videoPlayer->videoWidget()); #endif playlist = new DirectoryPlaylist(this); @@ -124,10 +115,10 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) addAction("skip85sec", "Skip 1:25", QKeySequence("/")); - videoWidget->addActions(actions()); + videoPlayer->videoWidget()->addActions(actions()); - connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(handleStateChange(Phonon::State,Phonon::State))); - connect(mediaController, SIGNAL(availableSubtitlesChanged()), this, SLOT(updateSubtitles())); + connect(videoPlayer, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(handleStateChange(Phonon::State,Phonon::State))); + connect(videoPlayer->mediaController(), SIGNAL(availableSubtitlesChanged()), this, SLOT(updateSubtitles())); #ifndef NO_ANIDBUDPCLIENT connect(m_actions["markWatched"], SIGNAL(triggered()), this, SLOT(markWatched())); connect(m_actions["settings"], SIGNAL(triggered()), this, SLOT(anidbSettings())); @@ -137,20 +128,19 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) connect(m_actions["open"], SIGNAL(triggered()), this, SLOT(open())); connect(m_actions["play"], SIGNAL(triggered()), this, SLOT(play())); #ifndef BROWSERPLUGIN_BUILD - connect(m_actions["togglePlay"], SIGNAL(triggered()), this, SLOT(togglePlay())); + connect(m_actions["togglePlay"], SIGNAL(triggered()), videoPlayer, SLOT(togglePlay())); connect(m_actions["togglePinMenu"], SIGNAL(toggled(bool)), this, SLOT(setPinMenu(bool))); connect(m_actions["toggleStayOnTop"], SIGNAL(toggled(bool)), this, SLOT(toggleStayOnTop())); #endif - connect(m_actions["pause"], SIGNAL(triggered()), this, SLOT(pause())); - connect(m_actions["stop"], SIGNAL(triggered()), this, SLOT(stop())); + connect(m_actions["pause"], SIGNAL(triggered()), videoPlayer, SLOT(pause())); + connect(m_actions["stop"], SIGNAL(triggered()), videoPlayer, SLOT(stop())); - connect(m_actions["volUp"], SIGNAL(triggered()), this, SLOT(volumeUp())); - connect(m_actions["volDown"], SIGNAL(triggered()), this, SLOT(volumeDown())); + connect(m_actions["volUp"], SIGNAL(triggered()), videoPlayer, SLOT(volumeUp())); + connect(m_actions["volDown"], SIGNAL(triggered()), videoPlayer, SLOT(volumeDown())); - connect(m_actions["skip85sec"], SIGNAL(triggered()), this, SLOT(skip())); + connect(m_actions["skip85sec"], SIGNAL(triggered()), videoPlayer, SLOT(skip())); - connect(videoWidget, SIGNAL(menuToggleRequested()), this, SLOT(toggleMenu())); - connect(videoWidget, SIGNAL(volumeChangeRequested(int)), this, SLOT(changeVolume(int))); + connect(videoPlayer->videoWidget(), SIGNAL(menuToggleRequested()), this, SLOT(toggleMenu())); connect(m_actions["next"], SIGNAL(triggered()), playlist, SLOT(next())); connect(m_actions["previous"], SIGNAL(triggered()), playlist, SLOT(previous())); @@ -158,18 +148,17 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) #ifndef BROWSERPLUGIN_BUILD connect(menu, SIGNAL(positionChanged()), this, SLOT(moveWithMenu())); #endif - connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), menu, SLOT(setTotalTime(qint64))); - connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64))); + connect(videoPlayer, SIGNAL(totalTimeChanged(qint64)), menu, SLOT(setTotalTime(qint64))); + connect(videoPlayer, SIGNAL(tick(qint64)), this, SLOT(tick(qint64))); - menu->oldSeekSlider()->setMediaObject(mediaObject); - menu->seekSlider()->setMediaObject(mediaObject); - menu->volumeSlider()->setAudioOutput(audioOutput); + menu->oldSeekSlider()->setMediaObject(videoPlayer); + menu->seekSlider()->setMediaObject(videoPlayer); + menu->volumeSlider()->setAudioOutput(videoPlayer->audioOutput()); #ifdef GRAPHICS_VIEW_VIDEO - videoSceneMenu->seekSlider()->setMediaObject(mediaObject); - videoSceneMenu->volumeSlider()->setAudioOutput(audioOutput); + videoSceneMenu->seekSlider()->setMediaObject(videoPlayer); + videoSceneMenu->volumeSlider()->setAudioOutput(videoPlayer->audioOutput()); #endif - menu->show(); #ifndef BROWSERPLUGIN_BUILD move(50, 50); #endif @@ -182,7 +171,6 @@ VideoWindow::VideoWindow(QWidget *parent) : QMainWindow(parent) anidb->setIdlePolicy(AniDBUdpClient::LogoutIdlePolicy); #endif - open(m_currentFile); } VideoWindow::~VideoWindow() @@ -191,7 +179,12 @@ VideoWindow::~VideoWindow() destroyed = true; // HAX - mediaObject->setCurrentSource(Phonon::MediaSource()); + videoPlayer->setCurrentSource(Phonon::MediaSource()); +} + +QString VideoWindow::currentFile() const +{ + return videoPlayer->currentFile(); } void VideoWindow::toggleMenu() @@ -213,13 +206,13 @@ void VideoWindow::open(bool closeOnStop) { QString dir; - if (m_currentFile == "") + if (videoPlayer->currentFile() == "") { dir = QDesktopServices::storageLocation(QDesktopServices::MoviesLocation); } else { - QFileInfo fileInfo(m_currentFile); + QFileInfo fileInfo(videoPlayer->currentFile()); QDir dirObj = fileInfo.absoluteDir(); while (!dirObj.exists()) dirObj = dirObj.absolutePath() + "/.."; @@ -252,8 +245,6 @@ void VideoWindow::open(const QString &file, bool closeOnStop) menu->showMessage(tr("File %1 does not exist").arg(file)); return; } - m_currentFile = file; - m_currentUrl = ""; playlist->setDirectory(fileInfo.absoluteDir()); playlist->setCurrent(playlist->indexOfFile(file)); @@ -261,7 +252,7 @@ void VideoWindow::open(const QString &file, bool closeOnStop) menu->showMessage(tr("Opening: %1").arg(file)); Phonon::MediaSource mediaSource(file); - mediaObject->setCurrentSource(mediaSource); + videoPlayer->open(mediaSource); m_closeOnStop = closeOnStop; } @@ -274,8 +265,7 @@ void VideoWindow::openUrl(const QString &urlstr) menu->showMessage(tr("Opening: %1").arg(url.toString(QUrl::RemovePassword))); Phonon::MediaSource mediaSource(url); - mediaObject->setCurrentSource(mediaSource); - m_currentUrl = url; + videoPlayer->open(mediaSource); m_closeOnStop = false; play(m_closeOnStop); @@ -283,12 +273,12 @@ void VideoWindow::openUrl(const QString &urlstr) void VideoWindow::play(bool closeOnStop) { - if ((m_currentFile == "" && !m_currentUrl.isValid()) || mediaObject->currentSource().type() == Phonon::MediaSource::Invalid) + if (videoPlayer->currentSource().type() == Phonon::MediaSource::Invalid) { open(closeOnStop); } - mediaObject->play(); + videoPlayer->play(); } void VideoWindow::play(const QString &file, bool closeOnStop) @@ -297,53 +287,6 @@ void VideoWindow::play(const QString &file, bool closeOnStop) play(closeOnStop); } -void VideoWindow::togglePlay() -{ - Phonon::State state = mediaObject->state(); - - switch(state) - { - case Phonon::PlayingState: - mediaObject->pause(); - break; - case Phonon::LoadingState: - case Phonon::PausedState: - case Phonon::StoppedState: - play(); - break; - default: - break; - } -} - -void VideoWindow::pause() -{ - mediaObject->pause(); -} - -void VideoWindow::stop() -{ - mediaObject->stop(); -} - -void VideoWindow::volumeUp(int by) -{ - qreal volume = qBound(qreal(0), audioOutput->volume() + qreal(by) * 0.01, qreal(1.0)); - audioOutput->setVolume(volume); -} - -void VideoWindow::volumeDown(int by) -{ - qreal volume = qBound(qreal(0), audioOutput->volume() - qreal(by) * 0.01, qreal(1.0)); - audioOutput->setVolume(volume); -} - -void VideoWindow::changeVolume(int by) -{ - qreal volume = qBound(qreal(0), audioOutput->volume() + qreal(by) * 0.01, qreal(1.0)); - audioOutput->setVolume(volume); -} - void VideoWindow::resizeToVideo() { #ifdef GRAPHICS_VIEW_VIDEO @@ -351,7 +294,7 @@ void VideoWindow::resizeToVideo() videoScene->setSceneRect(videoWidget->rect()); videoView->centerOn(videoWidgetProxy); #endif - resize(videoWidget->sizeHint()); + resize(videoPlayer->videoWidget()->sizeHint()); } void VideoWindow::setPinMenu(bool pinned) @@ -370,11 +313,6 @@ void VideoWindow::toggleStayOnTop() show(); } -void VideoWindow::skip(int msec) -{ - mediaObject->seek(mediaObject->currentTime() + msec); -} - void VideoWindow::about() { VersionDialog dialog(this); @@ -390,8 +328,8 @@ qDebug() << "Media changed state from" << oldstate << "to" << newstate; switch(newstate) { case Phonon::ErrorState: - //QMessageBox::warning(this, tr("Phonon error"), mediaObject->errorString()); - menu->showMessage(mediaObject->errorString()); + //QMessageBox::warning(this, tr("Phonon error"), videoPlayer->errorString()); + menu->showMessage(videoPlayer->errorString()); m_actions["play"]->setDisabled(false); m_actions["pause"]->setDisabled(true); @@ -439,12 +377,12 @@ qDebug() << "Media changed state from" << oldstate << "to" << newstate; if (!m_marked) addCommand->deleteLater(); - addCommand = new MylistAddCommand(m_currentFile, this); + addCommand = new MylistAddCommand(videoPlayer->currentFile(), this); m_marked = false; #endif break; case Phonon::PlayingState: - if (newstate == Phonon::PausedState && mediaObject->remainingTime() == 0) + if (newstate == Phonon::PausedState && videoPlayer->remainingTime() == 0) { playlist->next(); } @@ -461,7 +399,7 @@ void VideoWindow::tick(qint64 time) if (!m_automark || m_marked) return; - int percentPlayed = int(double(time) / double(mediaObject->totalTime()) * double(100)); + int percentPlayed = int(double(time) / double(videoPlayer->totalTime()) * double(100)); if (percentPlayed < m_automark) return; @@ -470,26 +408,6 @@ void VideoWindow::tick(qint64 time) #endif } -void VideoWindow::updateChapters() -{ - -} - -void VideoWindow::updateSubtitles() -{ - QList subtitles = mediaController->availableSubtitles(); - - foreach (const Phonon::SubtitleDescription &subtitle, subtitles) - { - qDebug() << subtitle; - if (subtitle.name() == "eng") - { -qDebug() << "yep!"; - mediaController->setCurrentSubtitle(subtitle); - } - } -} - void VideoWindow::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) @@ -518,7 +436,7 @@ void VideoWindow::mousePressEvent(QMouseEvent *event) menu->hide(); } #else - videoWidget->toggleFullScreen(); + videoPlayer->videoWidget()->toggleFullScreen(); event->accept(); #endif } @@ -578,10 +496,10 @@ void VideoWindow::wheelEvent(QWheelEvent *event) { // Wheel Up if (event->delta() > 0) - changeVolume(5); + videoPlayer->changeVolume(5); // Wheel Down else - changeVolume(-5); + videoPlayer->changeVolume(-5); event->accept(); } @@ -722,8 +640,8 @@ void VideoWindow::saveSettings() settings.beginGroup("settings"); settings.setValue("isMenuPinned", isMenuPinned()); - settings.setValue("currentFile", m_currentFile); - settings.setValue("volume", audioOutput->volume()); + settings.setValue("currentFile", videoPlayer->currentFile()); + settings.setValue("volume", videoPlayer->audioOutput()->volume()); settings.endGroup(); settings.beginGroup("videoWindow"); settings.setValue("geometry", saveGeometry()); @@ -754,8 +672,8 @@ void VideoWindow::loadSettings() settings.beginGroup("settings"); m_actions["togglePinMenu"]->setChecked(settings.value("isMenuPinned", true).toBool()); if (!m_closeOnStop) - m_currentFile = settings.value("currentFile", "").toString(); - audioOutput->setVolume(settings.value("volume", qreal(1.0)).toDouble()); + videoPlayer->open(settings.value("currentFile", "").toString()); + videoPlayer->audioOutput()->setVolume(settings.value("volume", qreal(1.0)).toDouble()); settings.endGroup(); settings.beginGroup("videoWindow"); restoreGeometry(settings.value("geometry", saveGeometry()).toByteArray()); @@ -796,8 +714,8 @@ bool VideoWindow::readData(QIODevice *source, const QString &format) QUrl url(m_currentUrl); Phonon::MediaSource mediaSource(url); - mediaObject->setCurrentSource(mediaSource); - mediaObject->play(); + videoPlayer->open(mediaSource); + videoPlayer->play(); return true; } diff --git a/src/videowindow.h b/src/videowindow.h index cba15f1..11a2a5d 100644 --- a/src/videowindow.h +++ b/src/videowindow.h @@ -2,10 +2,6 @@ #define VIDEOWINDOW_H #ifdef KDE_PHONON -# include -# include -# include - # include # include #else @@ -31,6 +27,7 @@ # endif #endif +class VideoPlayer; class VideoWidget; class Menu; class DirectoryPlaylist; @@ -60,7 +57,7 @@ public: VideoWindow(QWidget *parent = 0); virtual ~VideoWindow(); - inline const QString ¤tFile() const { return m_currentFile;} + QString currentFile() const; public slots: @@ -72,22 +69,11 @@ public slots: void openUrl(const QString &url); void play(bool closeOnStop = false); void play(const QString &file, bool closeOnStop = false); - void togglePlay(); - void pause(); - void stop(); - - void volumeUp(int by = 5); - void volumeDown(int by = 5); - void changeVolume(int by = 5); void resizeToVideo(); - void setPinMenu(bool pinned); - void toggleStayOnTop(); - void skip(int msec = 85000); - void about(); protected: @@ -112,9 +98,6 @@ private slots: void tick(qint64 time); - void updateChapters(); - void updateSubtitles(); - #ifndef NO_ANIDBUDPCLIENT void markWatched(); void doMarkWatched(); @@ -137,9 +120,7 @@ private: Menu *videoSceneMenu; #endif - Phonon::MediaObject *mediaObject; - Phonon::MediaController *mediaController; - VideoWidget *videoWidget; + VideoPlayer *videoPlayer; #ifdef GRAPHICS_VIEW_VIDEO QGraphicsScene *videoScene; @@ -153,9 +134,6 @@ private: QList chapterActions; QList subtitleActions; - QString m_currentFile; - QUrl m_currentUrl; - bool destroyed; bool windowMoving; bool menuMoving; -- 2.52.0