wxQt: Fix Qt objects destruction

Fix crashes start to appear when porting to Qt version 6.x
This commit is contained in:
ali kettab
2025-03-12 09:11:02 +01:00
committed by AliKet
parent 8a3f68e064
commit 7eea971ca4
5 changed files with 79 additions and 78 deletions
+41 -50
View File
@@ -83,17 +83,9 @@ public:
// Set immediately as it is used to check if wxWindow is alive // Set immediately as it is used to check if wxWindow is alive
wxWindow::QtStoreWindowPointer( this, handler ); wxWindow::QtStoreWindowPointer( this, handler );
// Handle QWidget destruction signal AFTER it gets deleted
QObject::connect( this, &QObject::destroyed, this,
&wxQtEventSignalHandler::HandleDestroyedSignal );
Widget::setMouseTracking(true); Widget::setMouseTracking(true);
} }
void HandleDestroyedSignal()
{
}
virtual Handler *GetHandler() const override virtual Handler *GetHandler() const override
{ {
// Only process the signal / event if the wxWindow is not destroyed // Only process the signal / event if the wxWindow is not destroyed
@@ -383,42 +375,44 @@ protected:
bool touchEvent(QTouchEvent *touch) bool touchEvent(QTouchEvent *touch)
{ {
wxWindow *win = wxWindow::QtRetrieveWindowPointer(this);
bool handled = false; bool handled = false;
for (const QTouchEvent::TouchPoint& tp : touch->touchPoints()) if ( wxWindow *win = wxWindow::QtRetrieveWindowPointer(this) )
{ {
wxEventType evtype = wxEVT_NULL; for (const QTouchEvent::TouchPoint& tp : touch->touchPoints())
switch (tp.state())
{ {
case Qt::TouchPointPressed: wxEventType evtype = wxEVT_NULL;
evtype = wxEVT_TOUCH_BEGIN;
break;
case Qt::TouchPointMoved: switch (tp.state())
evtype = wxEVT_TOUCH_MOVE; {
break; case Qt::TouchPointPressed:
case Qt::TouchPointReleased: evtype = wxEVT_TOUCH_BEGIN;
evtype = wxEVT_TOUCH_END; break;
break;
default: case Qt::TouchPointMoved:
continue; evtype = wxEVT_TOUCH_MOVE;
break;
case Qt::TouchPointReleased:
evtype = wxEVT_TOUCH_END;
break;
default:
continue;
}
wxMultiTouchEvent evt(win->GetId(), evtype);
// Use screen position as the event might originate from a different
// Qt window than this one.
wxPoint2DDouble pt = wxQtConvertPointF(tp.screenPos().toPoint());
wxPoint ref = pt.GetFloor();
evt.SetPosition(win->ScreenToClient(ref) + (pt - ref));
evt.SetSequenceId(wxTouchSequenceId(wxUIntToPtr((unsigned)tp.id())));
// Qt doesn't provide the primary point flag
handled |= win->ProcessWindowEvent(evt);
} }
wxMultiTouchEvent evt(win->GetId(), evtype);
// Use screen position as the event might originate from a different
// Qt window than this one.
wxPoint2DDouble pt = wxQtConvertPointF(tp.screenPos().toPoint());
wxPoint ref = pt.GetFloor();
evt.SetPosition(win->ScreenToClient(ref) + (pt - ref));
evt.SetSequenceId(wxTouchSequenceId(wxUIntToPtr((unsigned)tp.id())));
// Qt doesn't provide the primary point flag
handled |= win->ProcessWindowEvent(evt);
} }
return handled; return handled;
@@ -448,11 +442,9 @@ protected:
void tapandholdTriggered(QTapAndHoldGesture *gesture, QEvent *event) void tapandholdTriggered(QTapAndHoldGesture *gesture, QEvent *event)
{ {
wxWindow *win = wxWindow::QtRetrieveWindowPointer( this ); if ( wxWindow *win = wxWindow::QtRetrieveWindowPointer( this ) )
if (gesture->state() == Qt::GestureFinished)
{ {
if ( win ) if (gesture->state() == Qt::GestureFinished)
{ {
wxLongPressEvent ev(win->GetId()); wxLongPressEvent ev(win->GetId());
ev.SetPosition( wxQtConvertPoint( gesture->position().toPoint() ) ); ev.SetPosition( wxQtConvertPoint( gesture->position().toPoint() ) );
@@ -461,15 +453,14 @@ protected:
win->ProcessWindowEvent( ev ); win->ProcessWindowEvent( ev );
event->accept(); event->accept();
} }
else if (gesture->state() == Qt::GestureStarted)
} {
else if (gesture->state() == Qt::GestureStarted) event->accept();
{ }
event->accept(); else
} {
else event->accept();
{ }
event->accept();
} }
} }
+2
View File
@@ -23,6 +23,8 @@ public:
long style = 0, long style = 0,
const wxString &name = wxASCII_STR(wxStaticTextNameStr) ); const wxString &name = wxASCII_STR(wxStaticTextNameStr) );
~wxStaticText();
bool Create(wxWindow *parent, bool Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
const wxString &label, const wxString &label,
+13 -10
View File
@@ -61,17 +61,20 @@ void wxQtPushButton::action()
bool wxQtPushButton::event(QEvent* e) bool wxQtPushButton::event(QEvent* e)
{ {
switch ( e->type() ) if ( GetHandler() )
{ {
case QEvent::EnabledChange: switch ( e->type() )
case QEvent::Enter: {
case QEvent::Leave: case QEvent::EnabledChange:
case QEvent::FocusIn: case QEvent::Enter:
case QEvent::FocusOut: case QEvent::Leave:
GetHandler()->QtUpdateState(); case QEvent::FocusIn:
break; case QEvent::FocusOut:
default: GetHandler()->QtUpdateState();
break; break;
default:
break;
}
} }
return QPushButton::event(e); return QPushButton::event(e);
+18
View File
@@ -35,6 +35,24 @@ wxStaticText::wxStaticText(wxWindow *parent,
Create( parent, id, label, pos, size, style, name ); Create( parent, id, label, pos, size, style, name );
} }
wxStaticText::~wxStaticText()
{
// Dissociate the buddy before QLabel get destroyed to avoid this assertion:
//
// ASSERT failure in QLabel: "Called object is not of the correct type (class
// destructor may have already run)", file...
//
// Explanation:
// ------------
// When setBuddy() is called to set the buddy (see Create() below), Qt (internally)
// connects the QLabel to the QObject::destroyed() signal to be notified of the
// buddy's destruction and to dissociate it. Since the QLabel and its buddy are
// the same object, setBuddy() will be called on an already destroyed object, producing
// the aforementioned assertion message.
GetQLabel()->setBuddy( nullptr );
}
bool wxStaticText::Create(wxWindow *parent, bool wxStaticText::Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
const wxString &label, const wxString &label,
+5 -18
View File
@@ -350,36 +350,23 @@ wxWindowQt::~wxWindowQt()
{ {
if ( !m_qtWindow ) if ( !m_qtWindow )
{ {
wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::~wxWindow %s m_qtWindow is null"), GetName()); // Pseudo windows don't have a valid m_qtWindow, so just return.
return; return;
} }
// Delete only if the qt widget was created or assigned to this base class
wxLogTrace(TRACE_QT_WINDOW, wxT("wxWindow::~wxWindow %s m_qtWindow=%p"), GetName(), m_qtWindow);
if ( !IsBeingDeleted() )
{
SendDestroyEvent();
}
// Avoid processing pending events which quite often would lead to crashes after this.
QCoreApplication::removePostedEvents(m_qtWindow);
// Block signals because the handlers access members of a derived class.
m_qtWindow->blockSignals(true);
if ( s_capturedWindow == this ) if ( s_capturedWindow == this )
s_capturedWindow = nullptr; s_capturedWindow = nullptr;
DestroyChildren(); // This also destroys scrollbars SendDestroyEvent();
if (m_qtWindow) QtStoreWindowPointer( GetHandle(), nullptr );
QtStoreWindowPointer( GetHandle(), nullptr );
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
SetDropTarget(nullptr); SetDropTarget(nullptr);
#endif #endif
DestroyChildren(); // This also destroys scrollbars
delete m_qtWindow; delete m_qtWindow;
} }