mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-28 03:21:28 +08:00
wxQt: Fix Qt objects destruction
Fix crashes start to appear when porting to Qt version 6.x
This commit is contained in:
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user