Fix Linux data-view dropdown popup parenting (#13721)

Delay opening the object-list filament dropdown on wxGTK until the editor
  window is mapped, avoiding popup creation without a valid native toplevel.
  Also set the GTK transient parent for dropdown popups created from data-view
  cell editors.
This commit is contained in:
SoftFever
2026-05-19 01:01:53 +08:00
committed by GitHub
parent dc12126b78
commit 88b4a63228
3 changed files with 36 additions and 2 deletions

View File

@@ -324,9 +324,18 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
else else
c_editor->SetSelection(atoi(data.GetText().c_str()) - 1); c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
// Open the dropdown immediately when the editor is focused.
c_editor->Bind(wxEVT_SET_FOCUS, [c_editor](wxFocusEvent& evt) { c_editor->Bind(wxEVT_SET_FOCUS, [c_editor](wxFocusEvent& evt) {
#ifdef __WXGTK__
// On wxGTK the data-view editor may receive focus before its native
// window is mapped. Opening the popup one event later avoids creating
// the GTK popup without a valid toplevel parent.
c_editor->CallAfter([c_editor]() {
if (c_editor->IsShownOnScreen())
c_editor->ForceDropdownOpen();
});
#else
c_editor->ForceDropdownOpen(); c_editor->ForceDropdownOpen();
#endif
evt.Skip(); evt.Skip();
}); });
@@ -392,4 +401,3 @@ wxSize TextRenderer::GetSize() const
return GetTextExtent(m_value); return GetTextExtent(m_value);
} }

View File

@@ -167,6 +167,30 @@ bool DropDown::HasDismissLongTime()
(now - dismissTime).total_milliseconds() >= 20; (now - dismissTime).total_milliseconds() >= 20;
} }
void DropDown::Popup(wxWindow *focus)
{
#ifdef __WXGTK__
if (!mainDropDown && m_widget) {
// Data-view cell editors can receive focus before wxGTK infers a
// native popup parent, so provide the current toplevel explicitly.
GtkWindow *transient_parent = nullptr;
for (wxWindow *win = GetParent(); win; win = win->GetParent()) {
GtkWidget *widget = static_cast<GtkWidget *>(win->GetHandle());
if (!widget)
continue;
GtkWidget *top = gtk_widget_get_toplevel(widget);
if (GTK_IS_WINDOW(top)) {
transient_parent = GTK_WINDOW(top);
break;
}
}
if (transient_parent)
gtk_window_set_transient_for(GTK_WINDOW(m_widget), transient_parent);
}
#endif
PopupWindow::Popup(focus);
}
void DropDown::paintEvent(wxPaintEvent& evt) void DropDown::paintEvent(wxPaintEvent& evt)
{ {
// depending on your system you may need to look at double-buffered dcs // depending on your system you may need to look at double-buffered dcs

View File

@@ -105,6 +105,8 @@ public:
bool HasDismissLongTime(); bool HasDismissLongTime();
void Popup(wxWindow *focus = nullptr) override;
protected: protected:
void Dismiss() override; void Dismiss() override;