forked from vitrine/wmaker
Porting WINGs widgets to Rust will require using some WINGs abstractions. One of them is the base widget type, which is implemented by giving all widgets a common layout (with the first two fields always being the same basic types).
58 lines
1.9 KiB
Rust
58 lines
1.9 KiB
Rust
//! Common WINGs widget fields.
|
|
//!
|
|
//! WINGs widgets all have a [`WINGsP::WMView`] object that tracks common attributes
|
|
//! like size and location and a [`WINGsP::W_Class`] field that identifies the widget
|
|
//! type (button, list, etc.). This module provides access to these fields.
|
|
//!
|
|
//! ## Rust rewrite notes
|
|
//!
|
|
//! The original WINGs implementation uses casting and a common layout for
|
|
//! "primitive" widget structs, such that the first two fields are always a
|
|
//! `W_Class` and a `*mut WMView`. We rely on this convention when implementing
|
|
//! [`Widget`] for widgets that are defined in C.
|
|
use crate::WINGsP;
|
|
use std::{
|
|
ptr::NonNull,
|
|
};
|
|
|
|
/// Base WINGs widget type.
|
|
///
|
|
/// All primitive widgets (like buttons and lists) should implement this.
|
|
pub trait Widget {
|
|
fn class(&self) -> WINGsP::W_Class;
|
|
fn view(&self) -> NonNull<WINGsP::WMView>;
|
|
}
|
|
|
|
/// Common widget header fields. It should be safe to cast opaque WINGs widget
|
|
/// structs defined in C to this type to access these fields. Before writing
|
|
/// code that casts anything to this, double-check the widget definition!
|
|
#[repr(C)]
|
|
struct WidgetLike {
|
|
class: WINGsP::W_Class,
|
|
view: *mut WINGsP::WMView,
|
|
}
|
|
|
|
/// Casts `$widget` to [`WidgetLike`]. Provided for convenience.
|
|
///
|
|
/// ## Safety
|
|
///
|
|
/// The caller of this macro is responsible for ensuring that the layout of `$widget` is compatible
|
|
/// with `WidgetLike`.
|
|
macro_rules! impl_widget {
|
|
($widget:ty) => {
|
|
impl Widget for $widget {
|
|
fn class(&self) -> crate::WINGsP::W_Class {
|
|
unsafe { ::std::mem::transmute::<&$widget, &WidgetLike>(self).class }
|
|
}
|
|
|
|
fn view(&self) -> ::std::ptr::NonNull<WINGsP::WMView> {
|
|
let widget = unsafe { ::std::mem::transmute::<&$widget, &WidgetLike>(self) };
|
|
NonNull::new(widget.view).expect("WMView field of widget struct cannot be null")
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
impl_widget!(WINGsP::WMWindow);
|
|
impl_widget!(WINGsP::WMFrame);
|