Repository: slint-ui/slint (language: rust)

Issue:
PopupWindow does not close when calling close()
### Bug Description

When calling close() on a PopupWindow, I'd expect it to close. However, nothing happens. See the provided code snippet (reproducible in SlintPad).

### Reproducible Code (if applicable)

```slint
export component Example inherits Window {
    width: 100px;
    height: 100px;

    popup := PopupWindow {
        Rectangle { background: yellow; }
        x: 20px; y: 20px; height: 50px; width: 50px;
        close-policy: no-auto-close;
        TouchArea {
            clicked => { popup.close(); }
        }
    }

    TouchArea {
        clicked => { popup.show(); }
    }
}
```


### Environment Details

- Slint Version: 1.9.1
- [Run in SlintPad](https://docs.slint.dev/latest/editor/?snippet=export+component+Example+inherits+Window+%7B%0A++++width%3A+100px%3B%0A++++height%3A+100px%3B%0A%0A++++popup+%3A%3D+PopupWindow+%7B%0A++++++++Rectangle+%7B+background%3A+yellow%3B+%7D%0A++++++++x%3A+20px%3B+y%3A+20px%3B+height%3A+50px%3B+width%3A+50px%3B%0A++++++++close-policy%3A+no-auto-close%3B%0A++++++++TouchArea+%7B%0A++++++++++++clicked+%3D%3E+%7B+popup.close%28%29%3B+%7D%0A++++++++%7D%0A++++%7D%0A%0A++++TouchArea+%7B%0A++++++++clicked+%3D%3E+%7B+popup.show%28%29%3B+%7D%0A++++%7D%0A%7D&style=native)

### Product Impact

LibrePCB; Pretty important to have closable popups ;)


Discussion / hints:
When showing the popup, we do this:

```rust
    instance.description.popup_ids.borrow_mut().insert(
        element.borrow().id.clone(),
        WindowInner::from_pub(parent_window_adapter.window()).show_popup(
            &vtable::VRc::into_dyn(inst.clone()),
            pos,
            close_policy,
            parent_item,
        ),
    );
```

and when removing we do this:

```rust
pub fn close_popup(
    element: ElementRc,
    instance: InstanceRef,
    parent_window_adapter: WindowAdapterRc,
) {
    if let Some(current_id) =
        instance.description.popup_ids.borrow_mut().remove(&element.borrow().id)
    {
        WindowInner::from_pub(parent_window_adapter.window()).close_popup(current_id);
    }
}
```

I noticed that when showing, the popup_ids inserted into belong to a *different* instance than the instance passed to `close_popup()`. So the id is never found, and `close_popup()` is never called on the `WindowInner`.
Btw I forgot to mention, I also tested with 1.8.0 and there it worked properly so it seems to be a regression. Just replace the `close-policy: no-auto-close;` by `close-on-click: false;` for compatibility with 1.8.x.

Fix patch:
diff --git a/.github/actions/install-linux-dependencies/action.yaml b/.github/actions/install-linux-dependencies/action.yaml
index 0c5159c3d68..a47c10ad5b5 100644
--- a/.github/actions/install-linux-dependencies/action.yaml
+++ b/.github/actions/install-linux-dependencies/action.yaml
@@ -27,7 +27,7 @@ runs:
           if: runner.os == 'Linux'
           run: |
               sudo apt-get update
-              sudo apt-get install libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libudev-dev libinput-dev libfontconfig-dev ${{ inputs.extra-packages }}
+              sudo apt-get install libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libxkbcommon-x11-dev libudev-dev libinput-dev libfontconfig-dev ${{ inputs.extra-packages }}
           shell: bash
         - name: Install Linux dependencies
           if: ${{ runner.os == 'Linux' && (inputs.old-ubuntu != 'true')}}
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 597fac98272..e2b3294a2c4 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -103,8 +103,6 @@ jobs:
 
     node_test:
         env:
-            DYLD_FRAMEWORK_PATH: /Users/runner/work/slint/Qt/5.15.2/clang_64/lib
-            QT_QPA_PLATFORM: offscreen
             RUSTFLAGS: -D warnings
             CARGO_PROFILE_DEV_DEBUG: 0
             CARGO_INCREMENTAL: false
@@ -118,13 +116,6 @@ jobs:
         steps:
             - uses: actions/checkout@v4
             - uses: ./.github/actions/install-linux-dependencies
-            - name: Install Qt
-              if: runner.os == 'Linux'
-              uses: jurplel/install-qt-action@v4
-              with:
-                  version: "5.15.2"
-                  setup-python: false
-                  cache: true
             - name: Upgrade LLVM for Skia build on Windows
               if: runner.os == 'Windows'
               run: choco upgrade llvm
diff --git a/internal/interpreter/eval.rs b/internal/interpreter/eval.rs
index 5ec31a46a22..304c0fff130 100644
--- a/internal/interpreter/eval.rs
+++ b/internal/interpreter/eval.rs
@@ -650,10 +650,26 @@ fn call_builtin_function(
 
             if let Expression::ElementReference(popup_window) = &arguments[0] {
                 let popup_window = popup_window.upgrade().unwrap();
+                let pop_comp = popup_window.borrow().enclosing_component.upgrade().unwrap();
+                let parent_component = pop_comp
+                    .parent_element
+                    .upgrade()
+                    .unwrap()
+                    .borrow()
+                    .enclosing_component
+                    .upgrade()
+                    .unwrap();
+                let popup_list = parent_component.popup_windows.borrow();
+                let popup =
+                    popup_list.iter().find(|p| Rc::ptr_eq(&p.component, &pop_comp)).unwrap();
+
+                generativity::make_guard!(guard);
+                let enclosing_component =
+                    enclosing_component_for_element(&popup.parent_element, component, guard);
                 crate::dynamic_item_tree::close_popup(
                     popup_window,
-                    component,
-                    component.window_adapter(),
+                    enclosing_component,
+                    enclosing_component.window_adapter(),
                 );
 
                 Value::Void


Test patch:
diff --git a/tests/cases/elements/popupwindow_close.slint b/tests/cases/elements/popupwindow_close.slint
index c4fc087d9d8..c196f830a4e 100644
--- a/tests/cases/elements/popupwindow_close.slint
+++ b/tests/cases/elements/popupwindow_close.slint
@@ -335,7 +335,7 @@ assert_eq(instance.get_click_count(), 3);
 assert_eq(instance.get_popup_clicked(), 2001);
 ```
 
-```disable-because-nodejs-runs-with-qt-and-send-mouse-click-wont-send-to-popup-qwindow
+```js
 var instance = new slint.TestCase({});
 
 assert.equal(instance.click_count, 0);
diff --git a/tests/cases/elements/popupwindow_close_policy.slint b/tests/cases/elements/popupwindow_close_policy.slint
index 21ef74da413..6a184c50fea 100644
--- a/tests/cases/elements/popupwindow_close_policy.slint
+++ b/tests/cases/elements/popupwindow_close_policy.slint
@@ -442,7 +442,7 @@ slint_testing::send_mouse_click(&instance, 15., 15.);
 assert_eq(instance.get_click_count(), 2);
 ```
 
-```disable-because-nodejs-runs-with-qt-and-send-mouse-click-wont-send-to-popup-qwindow
+```js
 var instance = new slint.TestCase({});
 
 assert.equal(instance.click_count, 0);
@@ -492,41 +492,41 @@ assert.equal(instance.click_count, 3);
 
 
 // --------- Close outside click  popup
-instance.set_popup_selector(3);
-instance.set_popup_created(false);
-instance.set_click_count(0);
+instance.popup_selector = 3;
+instance.popup_created = false;
+instance.click_count = 0;
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 1);
-assert.equal(instance.get_popup_created(), true);
-assert.equal(instance.get_popup_clicked(), 2001);
+assert.equal(instance.click_count, 1);
+assert.equal(instance.popup_created, true);
+assert.equal(instance.popup_clicked, 2001);
 
 // click inside
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_popup_clicked(), 2003);
+assert.equal(instance.popup_clicked, 2003);
 
 // Click outside to close
 slintlib.private_api.send_mouse_click(instance, 5., 5.);
-assert.equal(instance.get_click_count(), 1);
+assert.equal(instance.click_count, 1);
 // Subsequent click to verify that it was closed
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 2);
-assert.equal(instance.get_popup_clicked(), 2003);
+assert.equal(instance.click_count, 2);
+assert.equal(instance.popup_clicked, 2003);
 
 
 // --------- Close outside click popup by esc
-instance.set_popup_selector(3);
-instance.set_click_count(0);
+instance.popup_selector = 3;
+instance.click_count = 0;
 slintlib.private_api.send_mouse_click(instance, 5., 5.);
-assert.equal(instance.get_click_count(), 1);
+assert.equal(instance.click_count, 1);
 
 // click inside
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_popup_clicked(), 2005);
+assert.equal(instance.popup_clicked, 2005);
 
 // close by esc
 slintlib.private_api.send_keyboard_string_sequence(instance, "\u{001b}");
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 2);
+assert.equal(instance.click_count, 2);
 ```
 
 */
diff --git a/tests/cases/elements/popupwindow_close_policy_inherited.slint b/tests/cases/elements/popupwindow_close_policy_inherited.slint
index 63ab9890f31..cd8e30093a5 100644
--- a/tests/cases/elements/popupwindow_close_policy_inherited.slint
+++ b/tests/cases/elements/popupwindow_close_policy_inherited.slint
@@ -458,7 +458,7 @@ slint_testing::send_mouse_click(&instance, 15., 15.);
 assert_eq(instance.get_click_count(), 2);
 ```
 
-```disable-because-nodejs-runs-with-qt-and-send-mouse-click-wont-send-to-popup-qwindow
+```js
 var instance = new slint.TestCase({});
 
 assert.equal(instance.click_count, 0);
@@ -508,41 +508,41 @@ assert.equal(instance.click_count, 3);
 
 
 // --------- Close outside click  popup
-instance.set_popup_selector(3);
-instance.set_popup_created(false);
-instance.set_click_count(0);
+instance.popup_selector = 3;
+instance.popup_created = false;
+instance.click_count = 0;
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 1);
-assert.equal(instance.get_popup_created(), true);
-assert.equal(instance.get_popup_clicked(), 2001);
+assert.equal(instance.click_count, 1);
+assert.equal(instance.popup_created, true);
+assert.equal(instance.popup_clicked, 2001);
 
 // click inside
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_popup_clicked(), 2003);
+assert.equal(instance.popup_clicked, 2003);
 
 // Click outside to close
 slintlib.private_api.send_mouse_click(instance, 5., 5.);
-assert.equal(instance.get_click_count(), 1);
+assert.equal(instance.click_count, 1);
 // Subsequent click to verify that it was closed
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 2);
-assert.equal(instance.get_popup_clicked(), 2003);
+assert.equal(instance.click_count, 2);
+assert.equal(instance.popup_clicked, 2003);
 
 
 // --------- Close outside click popup by esc
-instance.set_popup_selector(3);
-instance.set_click_count(0);
+instance.popup_selector = 3;
+instance.click_count = 0;
 slintlib.private_api.send_mouse_click(instance, 5., 5.);
-assert.equal(instance.get_click_count(), 1);
+assert.equal(instance.click_count, 1);
 
 // click inside
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_popup_clicked(), 2005);
+assert.equal(instance.popup_clicked, 2005);
 
 // close by esc
 slintlib.private_api.send_keyboard_string_sequence(instance, "\u{001b}");
 slintlib.private_api.send_mouse_click(instance, 15., 15.);
-assert.equal(instance.get_click_count(), 2);
+assert.equal(instance.click_count, 2);
 ```
 
 */