mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
Fix DropDown submenus on Linux/Wayland (#13563)
Hovering a group item (e.g. "Generic" in the filament list) now opens its submenu correctly. The dropdown stays usable while moving the cursor between the parent list and the submenu, and dismisses normally when the user clicks outside.
This commit is contained in:
@@ -563,6 +563,34 @@ void DropDown::messureSize()
|
|||||||
subDropDown->text_off = text_off;
|
subDropDown->text_off = text_off;
|
||||||
subDropDown->use_content_width = true;
|
subDropDown->use_content_width = true;
|
||||||
subDropDown->Create(GetParent());
|
subDropDown->Create(GetParent());
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
// Orca: Keep the wx parent as the combobox so wxPopupTransientWindow installs
|
||||||
|
// its capture handlers on the main dropdown, but make the native GTK
|
||||||
|
// popup transient for the currently open popup to satisfy Wayland's
|
||||||
|
// xdg-shell rule that a popup's parent must be the topmost mapped popup.
|
||||||
|
gtk_window_set_transient_for(GTK_WINDOW(subDropDown->GetHandle()), GTK_WINDOW(GetHandle()));
|
||||||
|
// Orca: On Wayland, while the sub holds an xdg_popup grab, motion events for
|
||||||
|
// the cursor over main may not be delivered (Mutter drops motion
|
||||||
|
// outside the grabbing surface). Poll on idle and synthesize a
|
||||||
|
// mouseMove on main so its hover highlight tracks and it can dismiss
|
||||||
|
// the sub when the cursor leaves the parent (group) item.
|
||||||
|
DropDown* sub = subDropDown;
|
||||||
|
sub->Bind(wxEVT_IDLE, [sub](wxIdleEvent& e) {
|
||||||
|
e.Skip();
|
||||||
|
if (!sub->IsShown() || !sub->mainDropDown->IsShown())
|
||||||
|
return;
|
||||||
|
wxPoint screen_pt = wxGetMousePosition();
|
||||||
|
if (sub->GetScreenRect().Contains(screen_pt) || !sub->mainDropDown->GetScreenRect().Contains(screen_pt))
|
||||||
|
return;
|
||||||
|
wxPoint main_pt = sub->mainDropDown->ScreenToClient(screen_pt);
|
||||||
|
wxMouseEvent ev(wxEVT_MOTION);
|
||||||
|
ev.SetEventObject(sub->mainDropDown);
|
||||||
|
ev.m_x = main_pt.x;
|
||||||
|
ev.m_y = main_pt.y;
|
||||||
|
sub->mainDropDown->mouseMove(ev);
|
||||||
|
e.RequestMore();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
subDropDown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
subDropDown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
||||||
e.SetEventObject(this);
|
e.SetEventObject(this);
|
||||||
e.SetId(GetId());
|
e.SetId(GetId());
|
||||||
@@ -759,6 +787,15 @@ void DropDown::Dismiss()
|
|||||||
PopupWindow::Dismiss();
|
PopupWindow::Dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DropDown::ShouldDismissOnTopWindowDeactivate()
|
||||||
|
{
|
||||||
|
// On Wayland, mapping a chained xdg_popup with grab makes the parent
|
||||||
|
// toplevel inactive, which would otherwise cascade-dismiss the whole
|
||||||
|
// chain. Skip when our chain peer is shown.
|
||||||
|
return !((mainDropDown && mainDropDown->IsShown()) ||
|
||||||
|
(subDropDown && subDropDown->IsShown()));
|
||||||
|
}
|
||||||
|
|
||||||
void DropDown::OnDismiss()
|
void DropDown::OnDismiss()
|
||||||
{
|
{
|
||||||
if (mainDropDown) {
|
if (mainDropDown) {
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ protected:
|
|||||||
|
|
||||||
void OnDismiss() override;
|
void OnDismiss() override;
|
||||||
|
|
||||||
|
bool ShouldDismissOnTopWindowDeactivate() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(wxPaintEvent& evt);
|
void paintEvent(wxPaintEvent& evt);
|
||||||
void paintNow();
|
void paintNow();
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ void PopupWindow::OnMouseEvent2(wxMouseEvent &evt)
|
|||||||
void PopupWindow::topWindowActiavate(wxActivateEvent &event)
|
void PopupWindow::topWindowActiavate(wxActivateEvent &event)
|
||||||
{
|
{
|
||||||
event.Skip();
|
event.Skip();
|
||||||
if (!event.GetActive() && IsShown()) DismissAndNotify();
|
if (!event.GetActive() && IsShown() && ShouldDismissOnTopWindowDeactivate())
|
||||||
|
DismissAndNotify();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ public:
|
|||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
void BindUnfocusEvent();
|
void BindUnfocusEvent();
|
||||||
#endif
|
#endif
|
||||||
|
protected:
|
||||||
|
// Orca: Hook so derived classes (e.g. DropDown chains) can skip auto-dismissal
|
||||||
|
// when the toplevel deactivates as a side effect of their own popup grab
|
||||||
|
// (notably on Wayland, where mapping a chained xdg_popup with grab makes
|
||||||
|
// the parent toplevel briefly inactive).
|
||||||
|
virtual bool ShouldDismissOnTopWindowDeactivate() { return true; }
|
||||||
private:
|
private:
|
||||||
#ifdef __WXOSX__
|
#ifdef __WXOSX__
|
||||||
void OnMouseEvent2(wxMouseEvent &evt);
|
void OnMouseEvent2(wxMouseEvent &evt);
|
||||||
|
|||||||
Reference in New Issue
Block a user