Wayland support (#141)

* Wayland implementation restructuration

* Moved previous X11 code into own module

* Moved some data into a common struct between wayland and x11

* Added glue

* Moved common unix functions into module

* Revert commits

* Update x11.rs

* Update x11.rs

* Cargo fmt

* Cargo fmt

* Initial Wayland struct and constructors

* Create Wayland window first

* Window::new constructor and removed error type

* Complete window creation

* More docs

* Fixed window creation

* Proper window creation

* Added byteorder

* Disallow resize and set_title

* Implement is_open() and get_window_handle()

* Fixed get_size() and implemented set_position()

* Wayland set_position was missing

* Added WIP update methods

* Improved update methods

* Added more prototype functions

* Get Keyboard and Mouse device

* outsource input device creation

* get proper mouse positions

* Properly get scroll wheel

* Implement HasRawWindowHandle for Wayland Window

* Implemented updaterate methods

* is active method

* More key handler methods

* Retrieve all events from keyboard and mouse

* Added more DisplayInfo methods

* Improvements for event handling

* Partial support for scaling

* Properly update buffer

* More imports

* Styling, etc.

* Merge

* More code to update the framebuffer

* Added scaling again

* Readded better event handling

* Properly render all colors as non-transparent ones

* Clear all events after being read

* update_with_buffer_stride is not WIP anymore

* Assume a connected keyboard and pointer device

* Moved keyboard and pointer from DisplayInfo into Window

* Support resizing and checking if the window is still open

* Rendering performance improvement

* Less warnings and some comments

* Byteorder now required anymore

* Not anymore resizing the ShmPool below its previous size and remove WlBuffers when told to

* Removed more magic numbers and added comments

* Proper size check of the buffer size

* Less conversions

* save the previous framebuffer size in DisplayInfo instead of seeking the fd

* Set the pixelformat statically depending on whether alpha channel is allowed or not

* Set the fd length only again when the size really changes

* Save resizability so that the size of the window doesnt get changed.

* Fix rerendering issue

* Fix rerendering issue

* Using unstable protocol to support server-side decorations

* Outsource buffer creation code

* Small improvements and comments

* Replaced usage of atomic types

* Cleanup

* Outsource Input handling into own struct

* Use mspc channels instead of Vec for input handling

* Implemented set_cursor_style()

* Proper cursorstyle into string decoding

* Implemented mouse buttons

* Scroll wheel fix

* Handle scroll events

* Updated code for new version of the wayland crate

* Reset scroll after each update

* Starting on keymap support with xkb

* Revert 19a590a

* Add missing bracket

* added missing minimum version for surface.damage_buffer()

* Fix for corrupted pointer images

* Implement scaling

* Remove comments

* Acknowledge only the last configure event when redrawing

* Assign the closure to the toplevel only once

* Own function for buffer filtering

* Dont truncate the fd anymore

* Proper damage surface

* Preventg display from getting dropped first

* custom BufferPool implementation

* Unneccessary printlns

* ack configure before committing

* set active field when keyboard focus enters/leaves the surface

* save modifiers each time they are changed

* Requires xkbcommon-sys to retrieve the keymap - will later be removed

* Prototype function to convert a key

* simplify keymap creation

* handle key event

* simplify button state evaluation

* Create wl_seat earlier so events are not getting missed

* Added key conversions and key offset

* Cargo fmt

* Update keyhandler

* Renaming

* Update xkb keys

* Input callback

* Numpad corrections

* Remove publicity from functions

* Retrieve input devices as early as possible

* TODO

* Small cleanup

* Proper key modifiers update

* Scale::FitScreen cant be implemented for now

* finish menu functions(copied from x11)

* Clean up some stuff

* unused variables

* Less warnings

* Comments and Variable naming improvements

* retrieve toplevel info now with an own method

* Constants

* Remove unused function

* Unused field

* Unused let binding

* Improve code readability

* Change note

* Comments

* Opinionated cleanup

* Comment out unused variables

Might be used later on

* Mouse buttons with boolean state

* Prototype UnixMenu functions

* Renaming

* unimplemented functions

* actually unimplemented

* Minor formatting change

* Remove unused fields

Even if they will be used later on, this would be a breaking change.
It's unnecessary to keep these around no matter what the future may
hold.

* Less unwraping now

* Feature gate x11 and wayland, both enabled by default

* Feature gate dependencies

* Menu is now is a new file for both x11 and wayland

* Feature gate everything

* Cargo fmt

* Simplify conditions

Co-Authored-By: Cole Helbling <cole.e.helbling@outlook.com>

* Missing paranthesis

Co-Authored-By: Cole Helbling <cole.e.helbling@outlook.com>

* Cargo fmt

* Proper debug message

* wayland deps

* xkb dev lib

* Update Cargo.toml

Co-Authored-By: Cole Helbling <cole.e.helbling@outlook.com>

* Update .github/workflows/ci.yml

Co-Authored-By: Cole Helbling <cole.e.helbling@outlook.com>

Co-authored-by: Antonino Siena <a.siena@gmx.de>
Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
This commit is contained in:
Antonino Siena 2020-04-05 06:49:25 +02:00 committed by GitHub
parent 3d5ae73135
commit d77e559b0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1335 additions and 154 deletions

View file

@ -28,6 +28,8 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- if: matrix.os == 'ubuntu-latest'
run: sudo apt install libwayland-cursor0 libxkbcommon-dev libwayland-dev
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:

View file

@ -39,65 +39,19 @@ features = [
"errhandlingapi"
]
[target.i686-unknown-linux-gnu.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[features]
default = ["wayland", "x11"]
x11 = ["x11-dl"]
wayland = ["wayland-client", "wayland-protocols", "wayland-cursor", "tempfile", "xkb", "xkbcommon-sys"]
[target.x86_64-unknown-linux-gnu.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.arm-unknown-linux-gnueabihf.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.armv7-unknown-linux-gnueabihf.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.aarch64-unknown-linux-gnu.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.x86_64-unknown-dragonfly.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.armv6-unknown-freebsd.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.armv7-unknown-freebsd.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.aarch64-unknown-freebsd.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.x86_64-unknown-freebsd.dependencies]
x11-dl = "2.18.3"
wayland-client = "0.25"
wayland-protocols = { version = "0.25", features = ["client"] }
tempfile = "3.1.0"
[target.'cfg(not(any(target_os = "macos", target_os = "redox", windows)))'.dependencies]
wayland-client = {version = "0.25", optional = true}
wayland-protocols = { version = "0.25", features = ["client", "unstable_protocols"], optional = true }
wayland-cursor = {version = "0.25", optional = true}
tempfile = {version = "3.1.0", optional = true}
xkb = {version = "0.2.1", optional = true}
xkbcommon-sys = {version = "0.7", optional = true}
x11-dl = {version = "2.18.3", optional = true}
[target.x86_64-unknown-redox.dependencies]
orbclient = "0.3.20"

View file

@ -2,6 +2,15 @@ use std::env;
extern crate cc;
fn main() {
if cfg!(not(any(
target_os = "macos",
target_os = "windows",
target_os = "redox"
))) && cfg!(not(any(feature = "wayland", feature = "x11")))
{
panic!("At least one of the x11 or wayland features must be enabled");
}
let env = env::var("TARGET").unwrap();
if env.contains("darwin") {
cc::Build::new()

58
src/os/unix/common.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::Result;
use crate::{Key, MenuHandle, MenuItem, MenuItemHandle, UnixMenu, UnixMenuItem};
pub struct Menu {
pub internal: UnixMenu,
}
impl Menu {
pub fn new(name: &str) -> Result<Menu> {
Ok(Menu {
internal: UnixMenu {
handle: MenuHandle(0),
item_counter: MenuItemHandle(0),
name: name.to_owned(),
items: Vec::new(),
},
})
}
pub fn add_sub_menu(&mut self, name: &str, sub_menu: &Menu) {
let handle = self.next_item_handle();
self.internal.items.push(UnixMenuItem {
label: name.to_owned(),
handle,
sub_menu: Some(Box::new(sub_menu.internal.clone())),
id: 0,
enabled: true,
key: Key::Unknown,
modifier: 0,
});
}
fn next_item_handle(&mut self) -> MenuItemHandle {
let handle = self.internal.item_counter;
self.internal.item_counter.0 += 1;
handle
}
pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle {
let item_handle = self.next_item_handle();
self.internal.items.push(UnixMenuItem {
sub_menu: None,
handle: self.internal.item_counter,
id: item.id,
label: item.label.clone(),
enabled: item.enabled,
key: item.key,
modifier: item.modifier,
});
item_handle
}
pub fn remove_item(&mut self, handle: &MenuItemHandle) {
self.internal
.items
.retain(|ref item| item.handle.0 != handle.0);
}
}

View file

@ -8,37 +8,61 @@
// turn off a gazillion warnings about X keysym names
#![allow(non_upper_case_globals)]
//mod wayland;
mod common;
mod key_mapping;
#[cfg(feature = "wayland")]
mod wayland;
#[cfg(feature = "x11")]
mod x11;
use crate::Result;
use crate::{CursorStyle, MenuHandle, UnixMenu};
use crate::{InputCallback, Key, KeyRepeat, MouseButton, MouseMode, WindowOptions};
pub use x11::Menu;
pub use common::Menu;
use std::os::raw;
// Differentiate between Wayland and X11 at run-time
pub enum Window {
#[cfg(feature = "x11")]
X11(x11::Window),
Wayland(()), //WlWindow
#[cfg(feature = "wayland")]
Wayland(wayland::Window),
}
impl Window {
#[cfg(all(feature = "x11", feature = "wayland"))]
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> {
//TODO: Try to create Wayland display first
// Try to create Wayland display first
let wl_window = wayland::Window::new(name, width, height, opts);
match wl_window {
Ok(w) => Ok(Window::Wayland(w)),
Err(_) => {
// Create X11 Window when Wayland fails
let window = Window::X11(x11::Window::new(name, width, height, opts)?);
Ok(window)
}
}
}
#[cfg(all(feature = "wayland", not(feature = "x11")))]
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> {
let wl_window = wayland::Window::new(name, width, height, opts)?;
Ok(Window::Wayland(wl_window))
}
#[cfg(all(feature = "x11", not(feature = "wayland")))]
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> {
let window = Window::X11(x11::Window::new(name, width, height, opts)?);
Ok(window)
}
pub fn set_title(&mut self, title: &str) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_title(title),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_title(title),
}
}
@ -50,199 +74,257 @@ impl Window {
buf_stride: usize,
) -> Result<()> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => {
w.update_with_buffer_stride(buffer, buf_width, buf_height, buf_stride)
}
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => {
w.update_with_buffer_stride(buffer, buf_width, buf_height, buf_stride)
}
}
}
pub fn update(&mut self) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.update(),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.update(),
}
}
pub fn get_window_handle(&self) -> *mut raw::c_void {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_window_handle(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_window_handle(),
}
}
pub fn set_background_color(&mut self, bg_color: u32) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_background_color(bg_color),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_background_color(bg_color),
}
}
pub fn set_position(&mut self, x: isize, y: isize) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_position(x, y),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_position(x, y),
}
}
pub fn get_size(&self) -> (usize, usize) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_size(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_size(),
}
}
pub fn get_mouse_pos(&self, mode: MouseMode) -> Option<(f32, f32)> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_mouse_pos(mode),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_mouse_pos(mode),
}
}
pub fn get_unscaled_mouse_pos(&self, mode: MouseMode) -> Option<(f32, f32)> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_unscaled_mouse_pos(mode),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_unscaled_mouse_pos(mode),
}
}
pub fn get_mouse_down(&self, button: MouseButton) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_mouse_down(button),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_mouse_down(button),
}
}
pub fn get_scroll_wheel(&self) -> Option<(f32, f32)> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_scroll_wheel(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_scroll_wheel(),
}
}
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_cursor_style(cursor),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_cursor_style(cursor),
}
}
pub fn set_rate(&mut self, rate: Option<std::time::Duration>) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_rate(rate),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_rate(rate),
}
}
pub fn update_rate(&mut self) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.update_rate(),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.update_rate(),
}
}
pub fn get_keys(&self) -> Option<Vec<Key>> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_keys(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_keys(),
}
}
pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_keys_pressed(repeat),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_keys_pressed(repeat),
}
}
pub fn get_keys_released(&self) -> Option<Vec<Key>> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_keys_released(),
#[cfg(feature = "wayland")]
Window::Wayland(ref _w) => unimplemented!(),
}
}
pub fn is_key_down(&self, key: Key) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.is_key_down(key),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.is_key_down(key),
}
}
pub fn set_key_repeat_delay(&mut self, delay: f32) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_key_repeat_delay(delay),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_key_repeat_delay(delay),
}
}
pub fn set_key_repeat_rate(&mut self, rate: f32) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_key_repeat_rate(rate),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_key_repeat_rate(rate),
}
}
pub fn is_key_pressed(&self, key: Key, repeat: KeyRepeat) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.is_key_pressed(key, repeat),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.is_key_pressed(key, repeat),
}
}
pub fn is_key_released(&self, key: Key) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.is_key_released(key),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.is_key_released(key),
}
}
pub fn set_input_callback(&mut self, callback: Box<dyn InputCallback>) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.set_input_callback(callback),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.set_input_callback(callback),
}
}
pub fn is_open(&self) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.is_open(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.is_open(),
}
}
pub fn is_active(&mut self) -> bool {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.is_active(),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.is_active(),
}
}
pub fn add_menu(&mut self, menu: &Menu) -> MenuHandle {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.add_menu(menu),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.add_menu(menu),
}
}
pub fn get_unix_menus(&self) -> Option<&Vec<UnixMenu>> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.get_unix_menus(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.get_unix_menus(),
}
}
pub fn remove_menu(&mut self, handle: MenuHandle) {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.remove_menu(handle),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.remove_menu(handle),
}
}
pub fn is_menu_pressed(&mut self) -> Option<usize> {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref mut w) => w.is_menu_pressed(),
Window::Wayland(ref mut _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref mut w) => w.is_menu_pressed(),
}
}
}
@ -250,8 +332,10 @@ impl Window {
unsafe impl raw_window_handle::HasRawWindowHandle for Window {
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
match *self {
#[cfg(feature = "x11")]
Window::X11(ref w) => w.raw_window_handle(),
Window::Wayland(ref _w) => unimplemented!(),
#[cfg(feature = "wayland")]
Window::Wayland(ref w) => w.raw_window_handle(),
}
}
}

1129
src/os/unix/wayland.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ use x11_dl::xlib;
use crate::error::Error;
use crate::Result;
use crate::{CursorStyle, MenuHandle, MenuItem, MenuItemHandle, UnixMenu, UnixMenuItem};
use crate::{CursorStyle, MenuHandle, UnixMenu};
use std::ffi::CString;
use std::mem;
@ -20,13 +20,14 @@ use std::ptr;
use crate::buffer_helper;
use crate::mouse_handler;
use super::common::Menu;
// NOTE: the x11-dl crate does not define Button6 or Button7
const Button6: c_uint = xlib::Button5 + 1;
const Button7: c_uint = xlib::Button5 + 2;
// We have these in C so we can always have optimize on (-O3) so they
// run fast in debug build as well. These functions should be seen as
// "system" functions that just doesn't exist in X11
// These functions are implemented in C in order to always have
// optimizations on (`-O3`), allowing debug builds to run fast as well.
extern "C" {
fn Image_upper_left(
target: *mut u32,
@ -1103,59 +1104,3 @@ impl Drop for Window {
}
}
}
pub struct Menu {
pub internal: UnixMenu,
}
impl Menu {
pub fn new(name: &str) -> Result<Menu> {
Ok(Menu {
internal: UnixMenu {
handle: MenuHandle(0),
item_counter: MenuItemHandle(0),
name: name.to_owned(),
items: Vec::new(),
},
})
}
pub fn add_sub_menu(&mut self, name: &str, sub_menu: &Menu) {
let handle = self.next_item_handle();
self.internal.items.push(UnixMenuItem {
label: name.to_owned(),
handle,
sub_menu: Some(Box::new(sub_menu.internal.clone())),
id: 0,
enabled: true,
key: Key::Unknown,
modifier: 0,
});
}
fn next_item_handle(&mut self) -> MenuItemHandle {
let handle = self.internal.item_counter;
self.internal.item_counter.0 += 1;
handle
}
pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle {
let item_handle = self.next_item_handle();
self.internal.items.push(UnixMenuItem {
sub_menu: None,
handle: self.internal.item_counter,
id: item.id,
label: item.label.clone(),
enabled: item.enabled,
key: item.key,
modifier: item.modifier,
});
item_handle
}
pub fn remove_item(&mut self, handle: &MenuItemHandle) {
self.internal
.items
.retain(|ref item| item.handle.0 != handle.0);
}
}