From 240bbdc5832a0ee1109abcf155ed565287d50e12 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Sat, 18 Jun 2022 08:49:45 -0700 Subject: [PATCH] viewer: fix mouse and compositing issues from using windows --- app/panel/audiomonitor/audiomonitor.cpp | 19 +- app/panel/audiomonitor/audiomonitor.h | 2 + app/widget/manageddisplay/manageddisplay.cpp | 45 ++- app/widget/manageddisplay/manageddisplay.h | 16 +- app/widget/viewer/viewerdisplay.cpp | 383 ++++++++++--------- app/widget/viewer/viewerdisplay.h | 35 +- 6 files changed, 280 insertions(+), 220 deletions(-) diff --git a/app/panel/audiomonitor/audiomonitor.cpp b/app/panel/audiomonitor/audiomonitor.cpp index 034ddcf9f..2b2df6a28 100644 --- a/app/panel/audiomonitor/audiomonitor.cpp +++ b/app/panel/audiomonitor/audiomonitor.cpp @@ -20,18 +20,35 @@ #include "audiomonitor.h" +#include "panel/panelmanager.h" + namespace olive { +#define super PanelWidget + AudioMonitorPanel::AudioMonitorPanel(QWidget *parent) : - PanelWidget(QStringLiteral("AudioMonitor"), parent) + super(QStringLiteral("AudioMonitor"), parent) { audio_monitor_ = new AudioMonitor(); + audio_monitor_->installEventFilter(this); + setWidget(QWidget::createWindowContainer(audio_monitor_)); Retranslate(); } +bool AudioMonitorPanel::eventFilter(QObject *o, QEvent *e) +{ + if (o == audio_monitor_ && e->type() == QEvent::FocusIn) { + // HACK: QWindow focus isn't accounted for in QApplication::focusChanged, so we handle it + // manually here. + PanelManager::instance()->FocusChanged(nullptr, this); + } + + return super::eventFilter(o, e); +} + void AudioMonitorPanel::Retranslate() { SetTitle(tr("Audio Monitor")); diff --git a/app/panel/audiomonitor/audiomonitor.h b/app/panel/audiomonitor/audiomonitor.h index 2c76d60da..b9d7b5e04 100644 --- a/app/panel/audiomonitor/audiomonitor.h +++ b/app/panel/audiomonitor/audiomonitor.h @@ -45,6 +45,8 @@ public: audio_monitor_->SetParams(params); } + virtual bool eventFilter(QObject *o, QEvent *e) override; + private: virtual void Retranslate() override; diff --git a/app/widget/manageddisplay/manageddisplay.cpp b/app/widget/manageddisplay/manageddisplay.cpp index 1a8d66c08..923d0bdee 100644 --- a/app/widget/manageddisplay/manageddisplay.cpp +++ b/app/widget/manageddisplay/manageddisplay.cpp @@ -23,18 +23,19 @@ #include #include +#include "panel/panelmanager.h" #include "render/opengl/openglrenderer.h" #include "render/rendermanager.h" namespace olive { +#define super QWidget + ManagedDisplayWidget::ManagedDisplayWidget(QWidget *parent) : QWidget(parent), color_manager_(nullptr), color_service_(nullptr) { - setContextMenuPolicy(Qt::CustomContextMenu); - QHBoxLayout* layout = new QHBoxLayout(this); layout->setSpacing(0); layout->setMargin(0); @@ -55,9 +56,7 @@ ManagedDisplayWidget::ManagedDisplayWidget(QWidget *parent) : &ManagedDisplayWidgetOpenGL::frameSwapped, this, &ManagedDisplayWidget::frameSwapped, Qt::DirectConnection); - connect(static_cast(inner_widget_), - &ManagedDisplayWidgetOpenGL::OnMouseMove, - this, &ManagedDisplayWidget::InnerWidgetMouseMove); + inner_widget_->installEventFilter(this); // Create OpenGL renderer attached_renderer_ = new OpenGLRenderer(this); @@ -279,6 +278,42 @@ void ManagedDisplayWidget::update() } } +bool ManagedDisplayWidget::eventFilter(QObject *o, QEvent *e) +{ + if (o != inner_widget_) { + return super::eventFilter(o, e); + } + + switch (e->type()) { + case QEvent::FocusIn: + // HACK: QWindow focus isn't accounted for in QApplication::focusChanged, so we handle it + // manually here. + PanelManager::instance()->FocusChanged(nullptr, this); + break; + case QEvent::ContextMenu: + { + QContextMenuEvent *ctx = static_cast(e); + emit customContextMenuRequested(ctx->pos()); + return true; + } + case QEvent::MouseButtonPress: + { + // HACK: QWindows don't seem to receive ContextMenu events on right click (only when pressing + // the menu button on the keyboard) so we handle it manually here + QMouseEvent *ev = static_cast(e); + if (ev->button() == Qt::RightButton) { + emit customContextMenuRequested(ev->pos()); + return true; + } + break; + } + default: + break; + } + + return super::eventFilter(o, e); +} + Menu* ManagedDisplayWidget::GetDisplayMenu(QMenu* parent, bool auto_connect) { QStringList displays = color_manager()->ListAvailableDisplays(); diff --git a/app/widget/manageddisplay/manageddisplay.h b/app/widget/manageddisplay/manageddisplay.h index 4d85850ec..89a952eb0 100644 --- a/app/widget/manageddisplay/manageddisplay.h +++ b/app/widget/manageddisplay/manageddisplay.h @@ -38,14 +38,11 @@ public: ManagedDisplayWidgetOpenGL() = default; signals: + // Render signals void OnInit(); - void OnPaint(); - void OnDestroy(); - void OnMouseMove(QMouseEvent* e); - protected: virtual void initializeGL() override { @@ -60,13 +57,6 @@ protected: emit OnPaint(); } - virtual void mouseMoveEvent(QMouseEvent* e) override - { - emit OnMouseMove(e); - - QOpenGLWindow::mouseMoveEvent(e); - } - private slots: void DestroyListener() { @@ -132,6 +122,8 @@ public: */ void update(); + virtual bool eventFilter(QObject *o, QEvent *e) override; + public slots: /** * @brief Replaces the color transform with a new one @@ -156,8 +148,6 @@ signals: void frameSwapped(); - void InnerWidgetMouseMove(QMouseEvent* event); - protected: /** * @brief Provides access to the color processor (nullptr if none is set) diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index 01bdee5e6..7d6d660c9 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -73,8 +73,6 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) : { connect(Core::instance(), &Core::ToolChanged, this, &ViewerDisplayWidget::ToolChanged); - connect(this, &ViewerDisplayWidget::InnerWidgetMouseMove, this, &ViewerDisplayWidget::EmitColorAtCursor); - // Initializes cursor based on tool UpdateCursor(); @@ -242,185 +240,48 @@ void ViewerDisplayWidget::IncrementSkippedFrames() Core::instance()->ShowStatusBarMessage(tr("%n skipped frame(s) detected during playback", nullptr, frames_skipped_), 10000); } -void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) +bool ViewerDisplayWidget::eventFilter(QObject *o, QEvent *e) { - if (event->button() == Qt::LeftButton && Core::instance()->tool() == Tool::kAdd - && (Core::instance()->GetSelectedAddableObject() == Tool::kAddableShape || Core::instance()->GetSelectedAddableObject() == Tool::kAddableTitle)) { + if (o != this->inner_widget()) { + return super::eventFilter(o, e); + } - add_band_start_ = event->pos(); - - add_band_ = new QRubberBand(QRubberBand::Rectangle, this); - add_band_->setGeometry(QRect(add_band_start_, add_band_start_)); - add_band_->show(); - - } else if (event->button() == Qt::LeftButton && gizmos_ - && (gizmo_last_draw_transform_inverted_ = gizmo_last_draw_transform_.inverted(), - current_gizmo_ = TryGizmoPress(gizmo_db_, gizmo_last_draw_transform_inverted_.map(event->pos())))) { - - // Handle gizmo click - gizmo_start_drag_ = event->pos(); - gizmo_last_drag_ = gizmo_start_drag_; - current_gizmo_->SetGlobals(NodeTraverser::GenerateGlobals(gizmo_params_, GenerateGizmoTime())); - - } else if (IsHandDrag(event)) { - - // Handle hand drag - hand_last_drag_pos_ = event->pos(); - hand_dragging_ = true; - emit HandDragStarted(); - setCursor(Qt::ClosedHandCursor); - - } else { - - if (event->button() == Qt::LeftButton) { - // Handle standard drag - emit DragStarted(); + switch (e->type()) { + case QEvent::MouseButtonPress: + if (OnMousePress(static_cast(e))) { + return true; } - - super::mousePressEvent(event); - - } -} - -void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event) -{ - // Handle hand dragging - if (hand_dragging_) { - - // Emit movement - emit HandDragMoved(event->x() - hand_last_drag_pos_.x(), - event->y() - hand_last_drag_pos_.y()); - - hand_last_drag_pos_ = event->pos(); - - } else if (add_band_) { - - add_band_->setGeometry(QRect(event->pos(), add_band_start_).normalized()); - - } else if (current_gizmo_) { - - // Signal movement - if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { - if (!gizmo_drag_started_) { - QPointF start = gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; - - rational gizmo_time = GetGizmoTime(); - NodeTraverser t; - t.SetCacheVideoParams(gizmo_params_); - NodeValueRow row = t.GenerateRow(gizmos_, TimeRange(gizmo_time, gizmo_time + gizmo_params_.frame_rate_as_time_base())); - - draggable->DragStart(row, start.x(), start.y(), gizmo_time); - gizmo_drag_started_ = true; - } - - QPointF v = event->pos() * gizmo_last_draw_transform_inverted_; - switch (draggable->GetDragValueBehavior()) { - case DraggableGizmo::kAbsolute: - // Above value is correct - break; - case DraggableGizmo::kDeltaFromPrevious: - v -= gizmo_last_drag_ * gizmo_last_draw_transform_inverted_; - gizmo_last_drag_ = event->pos(); - break; - case DraggableGizmo::kDeltaFromStart: - v -= gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; - break; - } - - draggable->DragMove(v.x(), v.y(), event->modifiers()); + break; + case QEvent::MouseMove: + EmitColorAtCursor(static_cast(e)); + if (OnMouseMove(static_cast(e))) { + return true; } - - } else { - - // Default behavior - super::mouseMoveEvent(event); - - } -} - -void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event) -{ - if (hand_dragging_) { - - // Handle hand drag - emit HandDragEnded(); - hand_dragging_ = false; - UpdateCursor(); - - } else if (add_band_) { - - const QRect &band_rect = add_band_->geometry(); - if (band_rect.width() > 1 && band_rect.height() > 1) { - QRectF r = GenerateDisplayTransform().inverted().mapRect(add_band_->geometry()); - emit CreateAddableAt(r); + break; + case QEvent::MouseButtonRelease: + if (OnMouseRelease(static_cast(e))) { + return true; } - - add_band_->deleteLater(); - add_band_ = nullptr; - - } else if (current_gizmo_) { - - // Handle gizmo - if (gizmo_drag_started_) { - MultiUndoCommand *command = new MultiUndoCommand(); - if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { - draggable->DragEnd(command); - } - Core::instance()->undo_stack()->pushIfHasChildren(command); - gizmo_drag_started_ = false; - } - current_gizmo_ = nullptr; - - } else { - - // Default behavior - super::mouseReleaseEvent(event); - - } -} - -void ViewerDisplayWidget::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton && gizmos_) { - QPointF ptr = TransformViewerSpaceToBufferSpace(event->pos()); - foreach (NodeGizmo *g, gizmos_->GetGizmos()) { - if (TextGizmo *text = dynamic_cast(g)) { - if (text->GetRect().contains(ptr)) { - OpenTextGizmo(text, event); - break; - } - } + break; + case QEvent::MouseButtonDblClick: + if (OnMouseDoubleClick(static_cast(e))) { + return true; } + break; + case QEvent::DragEnter: + emit DragEntered(static_cast(e)); + break; + case QEvent::DragLeave: + emit DragLeft(static_cast(e)); + break; + case QEvent::Drop: + emit Dropped(static_cast(e)); + break; + default: + break; } - super::mouseDoubleClickEvent(event); -} - -void ViewerDisplayWidget::dragEnterEvent(QDragEnterEvent *event) -{ - emit DragEntered(event); - - if (!event->isAccepted()) { - super::dragEnterEvent(event); - } -} - -void ViewerDisplayWidget::dragLeaveEvent(QDragLeaveEvent *event) -{ - emit DragLeft(event); - - if (!event->isAccepted()) { - super::dragLeaveEvent(event); - } -} - -void ViewerDisplayWidget::dropEvent(QDropEvent *event) -{ - emit Dropped(event); - - if (!event->isAccepted()) { - super::dropEvent(event); - } + return super::eventFilter(o, e); } void ViewerDisplayWidget::OnPaint() @@ -792,11 +653,17 @@ void ViewerDisplayWidget::OpenTextGizmo(TextGizmo *text, QMouseEvent *event) QTransform gizmo_transform = GenerateDisplayTransform(); ViewerTextEditor *text_edit = new ViewerTextEditor(gizmo_transform.m11(), this); + + text_edit->setWindowFlags(text_edit->windowFlags() | Qt::Tool | Qt::FramelessWindowHint); + text_edit->setAttribute(Qt::WA_NoSystemBackground); + text_edit->setAttribute(Qt::WA_TranslucentBackground); + Html::HtmlToDoc(text_edit->document(), text->GetHtml()); text_edit->setProperty("gizmo", reinterpret_cast(text)); - QRectF transformed_geom = gizmo_transform.map(text->GetRect()).boundingRect(); - text_edit->setGeometry(transformed_geom.toRect()); + QRect transformed_geom = gizmo_transform.map(text->GetRect()).boundingRect().toRect(); + + text_edit->setGeometry(QRect(mapToGlobal(transformed_geom.topLeft()), mapToGlobal(transformed_geom.bottomRight()))); ViewerTextEditorToolBar *toolbar = new ViewerTextEditorToolBar(this); @@ -843,6 +710,172 @@ void ViewerDisplayWidget::OpenTextGizmo(TextGizmo *text, QMouseEvent *event) }); } +bool ViewerDisplayWidget::OnMousePress(QMouseEvent *event) +{ + if (IsHandDrag(event)) { + + // Handle hand drag + hand_last_drag_pos_ = event->pos(); + hand_dragging_ = true; + emit HandDragStarted(); + setCursor(Qt::ClosedHandCursor); + + return true; + + } else if (event->button() == Qt::LeftButton) { + + if (Core::instance()->tool() == Tool::kAdd + && (Core::instance()->GetSelectedAddableObject() == Tool::kAddableShape || Core::instance()->GetSelectedAddableObject() == Tool::kAddableTitle)) { + + add_band_start_ = event->pos(); + + add_band_ = new QRubberBand(QRubberBand::Rectangle, this); + add_band_->setGeometry(QRect(add_band_start_, add_band_start_)); + add_band_->show(); + + } else if (gizmos_ + && (gizmo_last_draw_transform_inverted_ = gizmo_last_draw_transform_.inverted(), + current_gizmo_ = TryGizmoPress(gizmo_db_, gizmo_last_draw_transform_inverted_.map(event->pos())))) { + + // Handle gizmo click + gizmo_start_drag_ = event->pos(); + gizmo_last_drag_ = gizmo_start_drag_; + current_gizmo_->SetGlobals(NodeTraverser::GenerateGlobals(gizmo_params_, GenerateGizmoTime())); + + } else { + + // Handle standard drag + emit DragStarted(); + + } + + return true; + + } + + return false; +} + +bool ViewerDisplayWidget::OnMouseMove(QMouseEvent *event) +{ + // Handle hand dragging + if (hand_dragging_) { + + // Emit movement + emit HandDragMoved(event->x() - hand_last_drag_pos_.x(), + event->y() - hand_last_drag_pos_.y()); + + hand_last_drag_pos_ = event->pos(); + + return true; + + } else if (add_band_) { + + add_band_->setGeometry(QRect(event->pos(), add_band_start_).normalized()); + + return true; + + } else if (current_gizmo_) { + + // Signal movement + if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { + if (!gizmo_drag_started_) { + QPointF start = gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; + + rational gizmo_time = GetGizmoTime(); + NodeTraverser t; + t.SetCacheVideoParams(gizmo_params_); + NodeValueRow row = t.GenerateRow(gizmos_, TimeRange(gizmo_time, gizmo_time + gizmo_params_.frame_rate_as_time_base())); + + draggable->DragStart(row, start.x(), start.y(), gizmo_time); + gizmo_drag_started_ = true; + } + + QPointF v = event->pos() * gizmo_last_draw_transform_inverted_; + switch (draggable->GetDragValueBehavior()) { + case DraggableGizmo::kAbsolute: + // Above value is correct + break; + case DraggableGizmo::kDeltaFromPrevious: + v -= gizmo_last_drag_ * gizmo_last_draw_transform_inverted_; + gizmo_last_drag_ = event->pos(); + break; + case DraggableGizmo::kDeltaFromStart: + v -= gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; + break; + } + + draggable->DragMove(v.x(), v.y(), event->modifiers()); + + return true; + } + + } + + return false; +} + +bool ViewerDisplayWidget::OnMouseRelease(QMouseEvent *e) +{ + if (hand_dragging_) { + + // Handle hand drag + emit HandDragEnded(); + hand_dragging_ = false; + UpdateCursor(); + + return true; + + } else if (add_band_) { + + const QRect &band_rect = add_band_->geometry(); + if (band_rect.width() > 1 && band_rect.height() > 1) { + QRectF r = GenerateDisplayTransform().inverted().mapRect(add_band_->geometry()); + emit CreateAddableAt(r); + } + + add_band_->deleteLater(); + add_band_ = nullptr; + + return true; + + } else if (current_gizmo_) { + + // Handle gizmo + if (gizmo_drag_started_) { + MultiUndoCommand *command = new MultiUndoCommand(); + if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { + draggable->DragEnd(command); + } + Core::instance()->undo_stack()->pushIfHasChildren(command); + gizmo_drag_started_ = false; + } + current_gizmo_ = nullptr; + + return true; + + } + + return false; +} + +bool ViewerDisplayWidget::OnMouseDoubleClick(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && gizmos_) { + QPointF ptr = TransformViewerSpaceToBufferSpace(event->pos()); + foreach (NodeGizmo *g, gizmos_->GetGizmos()) { + if (TextGizmo *text = dynamic_cast(g)) { + if (text->GetRect().contains(ptr)) { + OpenTextGizmo(text, event); + return true; + } + } + } + } + + return false; +} + void ViewerDisplayWidget::EmitColorAtCursor(QMouseEvent *e) { // Do this no matter what, emits signal to any pixel samplers diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index 629a682aa..2b1491f5e 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -130,6 +130,8 @@ public: return &timer_; } + virtual bool eventFilter(QObject *o, QEvent *e) override; + public slots: /** * @brief Set the transformation matrix to draw with @@ -215,30 +217,6 @@ signals: void CreateAddableAt(const QRectF &rect); -protected: - /** - * @brief Override the mouse press event for the DragStarted() signal and gizmos - */ - virtual void mousePressEvent(QMouseEvent* event) override; - - /** - * @brief Override mouse move to signal for the pixel sampler and gizmos - */ - virtual void mouseMoveEvent(QMouseEvent* event) override; - - /** - * @brief Override mouse release event for gizmos - */ - virtual void mouseReleaseEvent(QMouseEvent* event) override; - - virtual void mouseDoubleClickEvent(QMouseEvent *event) override; - - virtual void dragEnterEvent(QDragEnterEvent* event) override; - - virtual void dragLeaveEvent(QDragLeaveEvent* event) override; - - virtual void dropEvent(QDropEvent* event) override; - protected slots: /** * @brief Paint function to display the texture (received in SetTexture()) on screen. @@ -278,6 +256,13 @@ private: void OpenTextGizmo(TextGizmo *text, QMouseEvent *event = nullptr); + bool OnMousePress(QMouseEvent *e); + bool OnMouseMove(QMouseEvent *e); + bool OnMouseRelease(QMouseEvent *e); + bool OnMouseDoubleClick(QMouseEvent *e); + + void EmitColorAtCursor(QMouseEvent* e); + /** * @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL(). */ @@ -390,8 +375,6 @@ private: bool queue_starved_; private slots: - void EmitColorAtCursor(QMouseEvent* e); - void UpdateFromQueue(); void TextEditChanged();