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
wxWindow::QtStoreWindowPointer( this, handler );
// Handle QWidget destruction signal AFTER it gets deleted
QObject::connect( this, &QObject::destroyed, this,
&wxQtEventSignalHandler::HandleDestroyedSignal );
Widget::setMouseTracking(true);
}
void HandleDestroyedSignal()
{
}
virtual Handler *GetHandler() const override
{
// Only process the signal / event if the wxWindow is not destroyed
@@ -383,42 +375,44 @@ protected:
bool touchEvent(QTouchEvent *touch)
{
wxWindow *win = wxWindow::QtRetrieveWindowPointer(this);
bool handled = false;
for (const QTouchEvent::TouchPoint& tp : touch->touchPoints())
if ( wxWindow *win = wxWindow::QtRetrieveWindowPointer(this) )
{
wxEventType evtype = wxEVT_NULL;
switch (tp.state())
for (const QTouchEvent::TouchPoint& tp : touch->touchPoints())
{
case Qt::TouchPointPressed:
evtype = wxEVT_TOUCH_BEGIN;
break;
wxEventType evtype = wxEVT_NULL;
case Qt::TouchPointMoved:
evtype = wxEVT_TOUCH_MOVE;
break;
case Qt::TouchPointReleased:
evtype = wxEVT_TOUCH_END;
break;
switch (tp.state())
{
case Qt::TouchPointPressed:
evtype = wxEVT_TOUCH_BEGIN;
break;
default:
continue;
case Qt::TouchPointMoved:
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;
@@ -448,11 +442,9 @@ protected:
void tapandholdTriggered(QTapAndHoldGesture *gesture, QEvent *event)
{
wxWindow *win = wxWindow::QtRetrieveWindowPointer( this );
if (gesture->state() == Qt::GestureFinished)
if ( wxWindow *win = wxWindow::QtRetrieveWindowPointer( this ) )
{
if ( win )
if (gesture->state() == Qt::GestureFinished)
{
wxLongPressEvent ev(win->GetId());
ev.SetPosition( wxQtConvertPoint( gesture->position().toPoint() ) );
@@ -461,15 +453,14 @@ protected:
win->ProcessWindowEvent( ev );
event->accept();
}
}
else if (gesture->state() == Qt::GestureStarted)
{
event->accept();
}
else
{
event->accept();
else if (gesture->state() == Qt::GestureStarted)
{
event->accept();
}
else
{
event->accept();
}
}
}
+2
View File
@@ -23,6 +23,8 @@ public:
long style = 0,
const wxString &name = wxASCII_STR(wxStaticTextNameStr) );
~wxStaticText();
bool Create(wxWindow *parent,
wxWindowID id,
const wxString &label,
+13 -10
View File
@@ -61,17 +61,20 @@ void wxQtPushButton::action()
bool wxQtPushButton::event(QEvent* e)
{
switch ( e->type() )
if ( GetHandler() )
{
case QEvent::EnabledChange:
case QEvent::Enter:
case QEvent::Leave:
case QEvent::FocusIn:
case QEvent::FocusOut:
GetHandler()->QtUpdateState();
break;
default:
break;
switch ( e->type() )
{
case QEvent::EnabledChange:
case QEvent::Enter:
case QEvent::Leave:
case QEvent::FocusIn:
case QEvent::FocusOut:
GetHandler()->QtUpdateState();
break;
default:
break;
}
}
return QPushButton::event(e);
+18
View File
@@ -35,6 +35,24 @@ wxStaticText::wxStaticText(wxWindow *parent,
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,
wxWindowID id,
const wxString &label,
+5 -18
View File
@@ -350,36 +350,23 @@ wxWindowQt::~wxWindowQt()
{
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;
}
// 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 )
s_capturedWindow = nullptr;
DestroyChildren(); // This also destroys scrollbars
SendDestroyEvent();
if (m_qtWindow)
QtStoreWindowPointer( GetHandle(), nullptr );
QtStoreWindowPointer( GetHandle(), nullptr );
#if wxUSE_DRAG_AND_DROP
SetDropTarget(nullptr);
#endif
DestroyChildren(); // This also destroys scrollbars
delete m_qtWindow;
}