| 1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
| 2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
| 3 | |
| 4 | #pragma once |
| 5 | #include <tuple> |
| 6 | #include "slint_properties_internal.h" |
| 7 | |
| 8 | namespace slint::private_api { |
| 9 | |
| 10 | /// A Callback stores a function pointer with no parameters and no return value. |
| 11 | /// It's possible to set that pointer via set_handler() and it can be invoked via call(). This is |
| 12 | /// used to implement callbacks in the `.slint` language. |
| 13 | template<typename = void()> |
| 14 | struct Callback; |
| 15 | /// A Callback stores a function pointer with \a Arg parameters and a return value of type \a Ret. |
| 16 | /// It's possible to set that pointer via set_handler() and it can be invoked via call(). This is |
| 17 | /// used to implement callbacks in the `.slint` language. |
| 18 | template<typename Ret, typename... Arg> |
| 19 | struct Callback<Ret(Arg...)> |
| 20 | { |
| 21 | /// Constructs an empty callback that contains no handler. |
| 22 | Callback() { cbindgen_private::slint_callback_init(out: &inner); } |
| 23 | /// Destructs the callback. |
| 24 | ~Callback() { cbindgen_private::slint_callback_drop(handle: &inner); } |
| 25 | Callback(const Callback &) = delete; |
| 26 | Callback(Callback &&) = delete; |
| 27 | Callback &operator=(const Callback &) = delete; |
| 28 | |
| 29 | /// Sets a new handler \a binding for this callback, that will be invoked when call() is called. |
| 30 | template<typename F> |
| 31 | void set_handler(F binding) const |
| 32 | { |
| 33 | cbindgen_private::slint_callback_set_handler( |
| 34 | sig: &inner, |
| 35 | binding: [](void *user_data, const void *arg, void *ret) { |
| 36 | *reinterpret_cast<Ret *>(ret) = |
| 37 | std::apply(*reinterpret_cast<F *>(user_data), |
| 38 | *reinterpret_cast<const Tuple *>(arg)); |
| 39 | }, |
| 40 | user_data: new F(std::move(binding)), |
| 41 | drop_user_data: [](void *user_data) { delete reinterpret_cast<F *>(user_data); }); |
| 42 | } |
| 43 | |
| 44 | /// Invokes a previously set handler with the parameters \a arg and returns the return value of |
| 45 | /// the handler. |
| 46 | Ret call(const Arg &...arg) const |
| 47 | { |
| 48 | Ret r {}; |
| 49 | Tuple tuple { arg... }; |
| 50 | cbindgen_private::slint_callback_call(sig: &inner, arg: &tuple, ret: &r); |
| 51 | return r; |
| 52 | } |
| 53 | |
| 54 | private: |
| 55 | using Tuple = std::tuple<Arg...>; |
| 56 | cbindgen_private::CallbackOpaque inner; |
| 57 | }; |
| 58 | |
| 59 | /// A Callback stores a function pointer with \a Arg parameters and no return value. |
| 60 | /// It's possible to set that pointer via set_handler() and it can be invoked via call(). This is |
| 61 | /// used to implement callbacks in the `.slint` language. |
| 62 | template<typename... Arg> |
| 63 | struct Callback<void(Arg...)> |
| 64 | { |
| 65 | /// Constructs an empty callback that contains no handler. |
| 66 | Callback() { cbindgen_private::slint_callback_init(out: &inner); } |
| 67 | /// Destructs the callback. |
| 68 | ~Callback() { cbindgen_private::slint_callback_drop(handle: &inner); } |
| 69 | Callback(const Callback &) = delete; |
| 70 | Callback(Callback &&) = delete; |
| 71 | Callback &operator=(const Callback &) = delete; |
| 72 | |
| 73 | /// Sets a new handler \a binding for this callback, that will be invoked when call() is called. |
| 74 | template<typename F> |
| 75 | void set_handler(F binding) const |
| 76 | { |
| 77 | cbindgen_private::slint_callback_set_handler( |
| 78 | sig: &inner, |
| 79 | binding: [](void *user_data, const void *arg, void *) { |
| 80 | std::apply(*reinterpret_cast<F *>(user_data), |
| 81 | *reinterpret_cast<const Tuple *>(arg)); |
| 82 | }, |
| 83 | user_data: new F(std::move(binding)), |
| 84 | drop_user_data: [](void *user_data) { delete reinterpret_cast<F *>(user_data); }); |
| 85 | } |
| 86 | |
| 87 | /// Invokes a previously set handler with the parameters \a arg. |
| 88 | void call(const Arg &...arg) const |
| 89 | { |
| 90 | Tuple tuple { arg... }; |
| 91 | cbindgen_private::slint_callback_call(sig: &inner, arg: &tuple, ret: reinterpret_cast<void *>(0x1)); |
| 92 | } |
| 93 | |
| 94 | private: |
| 95 | using Tuple = std::tuple<Arg...>; |
| 96 | cbindgen_private::CallbackOpaque inner; |
| 97 | }; |
| 98 | |
| 99 | template<typename A, typename R> |
| 100 | struct CallbackSignatureHelper |
| 101 | { |
| 102 | using Result = R(A); |
| 103 | }; |
| 104 | template<typename R> |
| 105 | struct CallbackSignatureHelper<void, R> |
| 106 | { |
| 107 | using Result = R(); |
| 108 | }; |
| 109 | template<typename A, typename R = void> |
| 110 | using CallbackHelper = Callback<typename CallbackSignatureHelper<A, R>::Result>; |
| 111 | |
| 112 | } // namespace slint |
| 113 | |