Skip to content

Commit

Permalink
dock: Destory display at SurfaceAboutToBeDestroyed
Browse files Browse the repository at this point in the history
When the dock is floating, SurfaceAboutToBeDestroyed event arrives
earlier than ~ScopeWidget(). Let's delete at the event.
On the other hand, if it's docked, ~ScopeWidget() arrives earlier than
SurfaceAboutToBeDestroyed. I need to remove the event filter not to
access the released object from the surface event filter.
  • Loading branch information
norihiro committed Aug 15, 2023
1 parent f390ec8 commit b4df405
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
34 changes: 34 additions & 0 deletions src/SurfaceEventFilter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once
#include <QObject>

template<typename QTDisplay_class> class SurfaceEventFilter : public QObject {
QTDisplay_class *w;

public:
SurfaceEventFilter(QTDisplay_class *w_) : w(w_) {}

protected:
bool eventFilter(QObject *obj, QEvent *event) override
{
bool result = QObject::eventFilter(obj, event);
QPlatformSurfaceEvent *surfaceEvent;

switch (event->type()) {
case QEvent::PlatformSurface:
surfaceEvent = static_cast<QPlatformSurfaceEvent *>(event);

switch (surfaceEvent->surfaceEventType()) {
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
w->DestroyDisplay();
break;
default:
break;
}
break;
default:
break;
}

return result;
}
};
38 changes: 34 additions & 4 deletions src/scope-widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "scope-widget.hpp"
#include "scope-widget-properties.hpp"
#include "obsgui-helper.hpp"
#include "SurfaceEventFilter.hpp"

#define N_SRC SCOPE_WIDGET_N_SRC

Expand Down Expand Up @@ -42,6 +43,8 @@ struct scope_widget_s
// last drawn coordinates for each rect
src_rect_s src_rect[N_SRC];
int i_mouse_last, i_src_menu;

bool destroying;
};

static obs_source_t *create_scope_source_roi(const char *id, obs_data_t *settings, const char *name)
Expand Down Expand Up @@ -146,7 +149,8 @@ static void draw(void *param, uint32_t cx, uint32_t cy)
pthread_mutex_unlock(&data->mutex);
}

ScopeWidget::ScopeWidget(QWidget *parent) : QWidget(parent), eventFilter(BuildEventFilter())
ScopeWidget::ScopeWidget(QWidget *parent)
: QWidget(parent), eventFilter(BuildEventFilter()), surfaceEventFilter(new SurfaceEventFilter(this))
{
properties = NULL;
setAttribute(Qt::WA_PaintOnScreen);
Expand All @@ -164,15 +168,17 @@ ScopeWidget::ScopeWidget(QWidget *parent) : QWidget(parent), eventFilter(BuildEv
data->src_shown = (1 << N_SRC) - 1;
data->i_mouse_last = -1;
data->i_src_menu = -1;

windowHandle()->installEventFilter(surfaceEventFilter.get());
}

ScopeWidget::~ScopeWidget()
{
windowHandle()->removeEventFilter(surfaceEventFilter.get());
removeEventFilter(eventFilter.get());

if (data) {
obs_display_destroy(data->disp);
data->disp = NULL;
DestroyDisplay();

pthread_mutex_lock(&data->mutex);
for (int i = 0; i < N_SRC; i++)
Expand Down Expand Up @@ -217,9 +223,16 @@ void ScopeWidget::CreateDisplay()
if (data->disp || !windowHandle() || !windowHandle()->isExposed())
return;

if (data->destroying)
return;

blog(LOG_INFO, "ScopeWidget::CreateDisplay %p", this);

QSize size = GetPixelSize(this);
if (size.width() <= 0 || size.height() <= 0) {
blog(LOG_WARNING, "ScopeWidget::CreateDisplay: Not creating obs_display because the size is zero.");
return;
}
gs_init_data info = {};
info.cx = size.width();
info.cy = size.height();
Expand All @@ -238,13 +251,30 @@ void ScopeWidget::CreateDisplay()
obs_display_add_draw_callback(data->disp, draw, data);
}

void ScopeWidget::DestroyDisplay()
{
if (!data) {
blog(LOG_ERROR, "ScopeWidget::DestroyDisplay() accessing released object");
return;
}

obs_display_destroy(data->disp);
data->disp = NULL;
data->destroying = true;
}

void ScopeWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);

if (!isVisible())
return;

CreateDisplay();

QSize size = GetPixelSize(this);
obs_display_resize(data->disp, size.width(), size.height());
if (data->disp && size.width() > 0 && size.height() > 0)
obs_display_resize(data->disp, size.width(), size.height());
}

void ScopeWidget::paintEvent(QPaintEvent *)
Expand Down
5 changes: 4 additions & 1 deletion src/scope-widget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
#define SCOPE_WIDGET_N_SRC 6

class OBSEventFilter;
template<typename QTDisplay_class> class SurfaceEventFilter;

class ScopeWidget : public QWidget {
Q_OBJECT

struct scope_widget_s *data;
class ScopeWidgetProperties *properties;
std::unique_ptr<OBSEventFilter> eventFilter;
std::unique_ptr<SurfaceEventFilter<ScopeWidget>> surfaceEventFilter;

void CreateDisplay();
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
class QPaintEngine *paintEngine() const override;
Expand All @@ -35,6 +36,8 @@ public slots:
public:
ScopeWidget(QWidget *parent);
~ScopeWidget();
void CreateDisplay();
void DestroyDisplay();
static void default_properties(obs_data_t *);
void save_properties(obs_data_t *);
void load_properties(obs_data_t *);
Expand Down

0 comments on commit b4df405

Please sign in to comment.