mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-29 03:02:06 +00:00
C++: adapt to menu bar API change
The MenuVTable is now a VRc (and it was a Box before)
This commit is contained in:
parent
19bc3c8f82
commit
ab674f33fb
6 changed files with 95 additions and 70 deletions
|
|
@ -3,11 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
// In C++17, it is conditionally supported, but still valid for all compiler we care
|
||||
# pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
#endif
|
||||
|
||||
#include "slint_internal.h"
|
||||
#include "slint_platform_internal.h"
|
||||
#include "slint_qt_internal.h"
|
||||
|
|
@ -44,23 +39,16 @@ inline cbindgen_private::Rect convert_anonymous_rect(std::tuple<float, float, fl
|
|||
return cbindgen_private::Rect { .x = x, .y = y, .width = w, .height = h };
|
||||
}
|
||||
|
||||
inline void dealloc(const ItemTreeVTable *, uint8_t *ptr, [[maybe_unused]] vtable::Layout layout)
|
||||
inline void dealloc(const ItemTreeVTable *vtable, uint8_t *ptr,
|
||||
[[maybe_unused]] vtable::Layout layout)
|
||||
{
|
||||
#ifdef __cpp_sized_deallocation
|
||||
::operator delete(reinterpret_cast<void *>(ptr), layout.size,
|
||||
static_cast<std::align_val_t>(layout.align));
|
||||
#elif !defined(__APPLE__) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14
|
||||
::operator delete(reinterpret_cast<void *>(ptr), static_cast<std::align_val_t>(layout.align));
|
||||
#else
|
||||
::operator delete(reinterpret_cast<void *>(ptr));
|
||||
#endif
|
||||
vtable::dealloc(vtable, ptr, layout);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline vtable::Layout drop_in_place(ItemTreeRef item_tree)
|
||||
{
|
||||
reinterpret_cast<T *>(item_tree.instance)->~T();
|
||||
return vtable::Layout { sizeof(T), alignof(T) };
|
||||
return vtable::drop_in_place<ItemTreeVTable, T>(item_tree);
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN)
|
||||
|
|
@ -184,6 +172,19 @@ item_layout_info(VT *itemvtable, ItemType *item_ptr, cbindgen_private::Orientati
|
|||
|
||||
namespace private_api {
|
||||
|
||||
template<typename T>
|
||||
union MaybeUninitialized {
|
||||
T value;
|
||||
~MaybeUninitialized() { }
|
||||
MaybeUninitialized() { }
|
||||
T take()
|
||||
{
|
||||
T result = std::move(value);
|
||||
value.~T();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
inline void setup_popup_menu_from_menu_item_tree(
|
||||
const ItemTreeRc &menu_item_tree,
|
||||
Property<std::shared_ptr<Model<cbindgen_private::MenuEntry>>> &entries,
|
||||
|
|
@ -193,26 +194,23 @@ inline void setup_popup_menu_from_menu_item_tree(
|
|||
{
|
||||
using cbindgen_private::MenuEntry;
|
||||
using cbindgen_private::MenuVTable;
|
||||
auto shared = std::make_shared<vtable::VBox<MenuVTable>>(nullptr, nullptr);
|
||||
cbindgen_private::slint_menus_create_wrapper(&menu_item_tree, &*shared);
|
||||
MaybeUninitialized<vtable::VRc<MenuVTable>> maybe;
|
||||
cbindgen_private::slint_menus_create_wrapper(&menu_item_tree, &maybe.value);
|
||||
auto shared = maybe.take();
|
||||
entries.set_binding([shared] {
|
||||
vtable::VRefMut<MenuVTable> ref { shared->vtable, shared->instance };
|
||||
SharedVector<MenuEntry> entries_sv;
|
||||
shared->vtable->sub_menu(ref, nullptr, &entries_sv);
|
||||
shared.vtable()->sub_menu(shared.borrow(), nullptr, &entries_sv);
|
||||
std::vector<MenuEntry> entries_vec(entries_sv.begin(), entries_sv.end());
|
||||
return std::make_shared<VectorModel<MenuEntry>>(std::move(entries_vec));
|
||||
});
|
||||
sub_menu.set_handler([shared](const auto &entry) {
|
||||
vtable::VRefMut<MenuVTable> ref { shared->vtable, shared->instance };
|
||||
SharedVector<MenuEntry> entries_sv;
|
||||
shared->vtable->sub_menu(ref, &entry, &entries_sv);
|
||||
shared.vtable()->sub_menu(shared.borrow(), &entry, &entries_sv);
|
||||
std::vector<MenuEntry> entries_vec(entries_sv.begin(), entries_sv.end());
|
||||
return std::make_shared<VectorModel<MenuEntry>>(std::move(entries_vec));
|
||||
});
|
||||
activated.set_handler([shared](const auto &entry) {
|
||||
vtable::VRefMut<MenuVTable> ref { shared->vtable, shared->instance };
|
||||
shared->vtable->activate(ref, &entry);
|
||||
});
|
||||
activated.set_handler(
|
||||
[shared](const auto &entry) { shared.vtable()->activate(shared.borrow(), &entry); });
|
||||
}
|
||||
|
||||
inline SharedString translate(const SharedString &original, const SharedString &context,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,39 @@ namespace private_api {
|
|||
using ItemTreeRc = vtable::VRc<cbindgen_private::ItemTreeVTable>;
|
||||
using slint::LogicalPosition;
|
||||
|
||||
template<typename Component, typename SubMenu, typename Activated>
|
||||
struct MenuWrapper
|
||||
{
|
||||
Component component;
|
||||
SubMenu submenu;
|
||||
Activated activated;
|
||||
static cbindgen_private::MenuVTable static_vtable;
|
||||
};
|
||||
|
||||
template<typename Component, typename SubMenu, typename Activated>
|
||||
inline cbindgen_private::MenuVTable MenuWrapper<Component, SubMenu, Activated>::static_vtable {
|
||||
.sub_menu =
|
||||
[](auto data, const cbindgen_private::MenuEntry *entry,
|
||||
slint::SharedVector<cbindgen_private::MenuEntry> *result) {
|
||||
auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance);
|
||||
auto model = wrapper->submenu(wrapper->component, entry);
|
||||
result->clear();
|
||||
if (model) {
|
||||
auto count = model->row_count();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
result->push_back(*model->row_data(i));
|
||||
}
|
||||
}
|
||||
},
|
||||
.activate =
|
||||
[](auto data, const cbindgen_private::MenuEntry *entry) {
|
||||
auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance);
|
||||
wrapper->activated(wrapper->component, *entry);
|
||||
},
|
||||
.drop_in_place = vtable::drop_in_place<cbindgen_private::MenuVTable, MenuWrapper>,
|
||||
.dealloc = vtable::dealloc<cbindgen_private::MenuVTable>,
|
||||
};
|
||||
|
||||
class WindowAdapterRc
|
||||
{
|
||||
public:
|
||||
|
|
@ -62,35 +95,10 @@ public:
|
|||
if (!supports_native_menu_bar()) {
|
||||
return;
|
||||
}
|
||||
struct MenuWrapper
|
||||
{
|
||||
Component component;
|
||||
SubMenu submenu;
|
||||
Activated activated;
|
||||
};
|
||||
static cbindgen_private::MenuVTable menu_vtable = {
|
||||
.drop = [](auto data) { delete reinterpret_cast<MenuWrapper *>(data.instance); },
|
||||
.sub_menu =
|
||||
[](auto data, const cbindgen_private::MenuEntry *entry,
|
||||
slint::SharedVector<cbindgen_private::MenuEntry> *result) {
|
||||
auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance);
|
||||
auto model = wrapper->submenu(wrapper->component, entry);
|
||||
result->clear();
|
||||
if (model) {
|
||||
auto count = model->row_count();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
result->push_back(*model->row_data(i));
|
||||
}
|
||||
}
|
||||
},
|
||||
.activate =
|
||||
[](auto data, const cbindgen_private::MenuEntry *entry) {
|
||||
auto wrapper = reinterpret_cast<MenuWrapper *>(data.instance);
|
||||
wrapper->activated(wrapper->component, *entry);
|
||||
},
|
||||
};
|
||||
auto instance = new MenuWrapper { component, std::move(submenu), std::move(activated) };
|
||||
cbindgen_private::slint_windowrc_setup_native_menu_bar(&inner, &menu_vtable, instance);
|
||||
using Wrapper = MenuWrapper<Component, SubMenu, Activated>;
|
||||
auto instance = vtable::VRc<cbindgen_private::MenuVTable, Wrapper>::make(
|
||||
Wrapper { component, std::move(submenu), std::move(activated) });
|
||||
cbindgen_private::slint_windowrc_setup_native_menu_bar(&inner, &instance.into_dyn());
|
||||
}
|
||||
|
||||
bool text_input_focused() const { return slint_windowrc_get_text_input_focused(&inner); }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@
|
|||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
// In C++17, it is conditionally supported, but still valid for all compiler we care
|
||||
# pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
#endif
|
||||
|
||||
namespace vtable {
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -242,4 +247,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename VTable>
|
||||
inline void dealloc(const VTable *, uint8_t *ptr, [[maybe_unused]] Layout layout)
|
||||
{
|
||||
#ifdef __cpp_sized_deallocation
|
||||
::operator delete(reinterpret_cast<void *>(ptr), layout.size,
|
||||
static_cast<std::align_val_t>(layout.align));
|
||||
#elif !defined(__APPLE__) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14
|
||||
::operator delete(reinterpret_cast<void *>(ptr), static_cast<std::align_val_t>(layout.align));
|
||||
#else
|
||||
::operator delete(reinterpret_cast<void *>(ptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename VTable, typename T>
|
||||
inline Layout drop_in_place(VRefMut<VTable> item_tree)
|
||||
{
|
||||
reinterpret_cast<T *>(item_tree.instance)->~T();
|
||||
return vtable::Layout { sizeof(T), alignof(T) };
|
||||
}
|
||||
|
||||
} // namespace vtable
|
||||
|
|
|
|||
|
|
@ -3737,12 +3737,10 @@ fn compile_builtin_function_call(
|
|||
if ({window}.supports_native_menu_bar()) {{
|
||||
auto item_tree = {item_tree_id}::create(self);
|
||||
auto item_tree_dyn = item_tree.into_dyn();
|
||||
vtable::VBox<slint::cbindgen_private::MenuVTable> box{{}};
|
||||
slint::cbindgen_private::slint_menus_create_wrapper(&item_tree_dyn, &box);
|
||||
slint::cbindgen_private::slint_windowrc_setup_native_menu_bar(&{window}.handle(), const_cast<slint::cbindgen_private::MenuVTable*>(box.vtable), box.instance);
|
||||
// The ownership of the VBox is transferred to slint_windowrc_setup_native_menu_bar
|
||||
box.instance = nullptr;
|
||||
box.vtable = nullptr;
|
||||
slint::private_api::MaybeUninitialized<vtable::VRc<slint::cbindgen_private::MenuVTable>> maybe;
|
||||
slint::cbindgen_private::slint_menus_create_wrapper(&item_tree_dyn, &maybe.value);
|
||||
auto vrc = maybe.take();
|
||||
slint::cbindgen_private::slint_windowrc_setup_native_menu_bar(&{window}.handle(), &vrc);
|
||||
}} else {{
|
||||
auto item_tree = {item_tree_id}::create(self);
|
||||
auto item_tree_dyn = item_tree.into_dyn();
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ use vtable::{VRef, VRefMut};
|
|||
#[vtable::vtable]
|
||||
#[repr(C)]
|
||||
pub struct MenuVTable {
|
||||
/// destructor
|
||||
drop: extern "C" fn(VRefMut<MenuVTable>),
|
||||
/// Return the list of items for the sub menu (or the main menu of parent is None)
|
||||
sub_menu: extern "C" fn(VRef<MenuVTable>, Option<&MenuEntry>, &mut SharedVector<MenuEntry>),
|
||||
/// Handler when the menu entry is activated
|
||||
|
|
@ -243,9 +241,9 @@ pub mod ffi {
|
|||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn slint_menus_create_wrapper(
|
||||
menu_tree: &ItemTreeRc,
|
||||
result: *mut vtable::VBox<MenuVTable>,
|
||||
result: *mut vtable::VRc<MenuVTable>,
|
||||
) {
|
||||
let b = vtable::VBox::<MenuVTable>::new(MenuFromItemTree::new(menu_tree.clone()));
|
||||
core::ptr::write(result, b);
|
||||
let vrc = vtable::VRc::into_dyn(vtable::VRc::new(MenuFromItemTree::new(menu_tree.clone())));
|
||||
core::ptr::write(result, vrc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1494,7 +1494,6 @@ pub mod ffi {
|
|||
use crate::graphics::Size;
|
||||
use crate::graphics::{IntSize, Rgba8Pixel};
|
||||
use crate::SharedVector;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
/// This enum describes a low-level access to specific graphics APIs used
|
||||
/// by the renderer.
|
||||
|
|
@ -1847,13 +1846,12 @@ pub mod ffi {
|
|||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn slint_windowrc_setup_native_menu_bar(
|
||||
handle: *const WindowAdapterRcOpaque,
|
||||
vtable: NonNull<MenuVTable>,
|
||||
menu_instance: NonNull<c_void>,
|
||||
menu_instance: &vtable::VRc<MenuVTable>,
|
||||
) {
|
||||
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
|
||||
window_adapter
|
||||
.internal(crate::InternalToken)
|
||||
.map(|x| x.setup_menubar(vtable::VBox::from_raw(vtable, menu_instance.cast())));
|
||||
.map(|x| x.setup_menubar(menu_instance.clone()));
|
||||
}
|
||||
|
||||
/// Return the default-font-size property of the WindowItem
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue