Guard against re-entering in wxOSX wxDropSource::DoDragDrop() At least when using CEF, repeatedly starting drag-and-drop operation may result in stack overflow. Messages processed by CEF are handled when wxEVT_IDLE is triggered and the problematic scenario is when: 1. Cocoa calls OSXDefaultModeObserverCallBack() 2. wxEVT_IDLE is triggered. 3. wxWebViewChromium::OnIdle() is called. 4. CefDoMessageLoopWork() performs various jobs for CEF. If DoDragDrop() is invoked during CefDoMessageLoopWork(), and there is a recursive call to it, then the previous DoDragDrop() can't return anymore, and will, in turn, prevent CefDoMessageLoopWork() from returning to the caller. Prevent recursively re-entering this function to avoid this. See #24520. Co-authored-by: Vadim Zeitlin <va...@wxwidgets.org>
Allow wxDropSource::DoDragDrop() without mouse event in wxOSX DoDragDrop() may be called not only in response to a mouse event, but also, when using CEF, from external code. Synthesize an artificial event in this case instead of failing with an assert. See #24520.
| ... | ... | @@ -18,6 +18,7 @@ |
| 18 | 18 | #include "wx/dnd.h"
|
| 19 | 19 | #include "wx/clipbrd.h"
|
| 20 | 20 | #include "wx/filename.h"
|
| 21 | +#include "wx/recguard.h"
|
|
| 21 | 22 | |
| 22 | 23 | #ifndef WX_PRECOMP
|
| 23 | 24 | #include "wx/app.h"
|
| ... | ... | @@ -483,17 +484,39 @@ typedef NSString* NSPasteboardType; |
| 483 | 484 | |
| 484 | 485 | wxDragResult wxDropSource::DoDragDrop(int flags)
|
| 485 | 486 | {
|
| 487 | + static wxRecursionGuardFlag s_inDragDrop = 0;
|
|
| 488 | + |
|
| 486 | 489 | wxASSERT_MSG( m_data, wxT("Drop source: no data") );
|
| 487 | 490 | |
| 488 | 491 | wxDragResult result = wxDragNone;
|
| 489 | 492 | if ((m_data == nullptr) || (m_data->GetFormatCount() == 0))
|
| 490 | 493 | return result;
|
| 491 | 494 | |
| 495 | + wxRecursionGuard guard(s_inDragDrop);
|
|
| 496 | + if (guard.IsInside())
|
|
| 497 | + return wxDragNone;
|
|
| 498 | + |
|
| 492 | 499 | NSView* view = m_window->GetPeer()->GetWXWidget();
|
| 493 | 500 | if (view)
|
| 494 | 501 | {
|
| 495 | 502 | NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent();
|
| 496 | - wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event.");
|
|
| 503 | + |
|
| 504 | + // Drag and drop operation can be started from an external mouse event
|
|
| 505 | + // handler, this happens at least when using CEF, so synthesize the
|
|
| 506 | + // mouse event if we don't have one.
|
|
| 507 | + if (theEvent == nil)
|
|
| 508 | + {
|
|
| 509 | + NSPoint mouse_location = [NSEvent mouseLocation];
|
|
| 510 | + theEvent = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDragged
|
|
| 511 | + location:mouse_location
|
|
| 512 | + modifierFlags:0
|
|
| 513 | + timestamp: 0
|
|
| 514 | + windowNumber: [NSWindow windowNumberAtPoint:mouse_location belowWindowWithWindowNumber:0]
|
|
| 515 | + context:nil
|
|
| 516 | + eventNumber: 0
|
|
| 517 | + clickCount: 0
|
|
| 518 | + pressure: 1.0];
|
|
| 519 | + }
|
|
| 497 | 520 | |
| 498 | 521 | gCurrentSource = this;
|
| 499 | 522 | |
| ... | ... | @@ -560,7 +583,6 @@ wxDragResult wxDropSource::DoDragDrop(int flags) |
| 560 | 583 | gCurrentSource = nullptr;
|
| 561 | 584 | }
|
| 562 | 585 | |
| 563 | - |
|
| 564 | 586 | return result;
|
| 565 | 587 | }
|
| 566 | 588 |
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help