mirror of https://github.com/wayvr-org/wayvr.git
wip: grabbable resize corner
This commit is contained in:
parent
137570f548
commit
4f76a4abfb
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="white" d="M3 21v-2h16V3h2v16q0 .825-.587 1.413T19 21zm12-4q-.825 0-1.412-.587T13 15t.588-1.412T15 13t1.413.588T17 15t-.587 1.413T15 17M5 12v-2h3.6L3 4.4L4.4 3L10 8.6V5h2v7z"/></svg>
|
||||||
|
After Width: | Height: | Size: 392 B |
|
|
@ -126,6 +126,9 @@
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
|
<Button id="resize_corner" macro="button_style" tooltip="EDIT_MODE.RESIZE" _press="::EditModeResizeStart" _release="::EditModeResizeStop" border_color="~color_accent_translucent" color="~color_accent_50" color2="~color_accent_10">
|
||||||
|
<sprite width="48" height="48" src="edit/resize-corner.svg" />
|
||||||
|
</Button>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</elements>
|
</elements>
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,8 @@ impl WvrServerState {
|
||||||
let window_handle = wvr_server.wm.create_window(
|
let window_handle = wvr_server.wm.create_window(
|
||||||
toplevel.clone(),
|
toplevel.clone(),
|
||||||
process_handle,
|
process_handle,
|
||||||
|
min_size,
|
||||||
|
max_size,
|
||||||
fallback_size.w as _,
|
fallback_size.w as _,
|
||||||
fallback_size.h as _,
|
fallback_size.h as _,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ use crate::{backend::wayvr::process, gen_id};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
|
pub min_size: Size<i32, Logical>,
|
||||||
|
pub max_size: Size<i32, Logical>,
|
||||||
pub size_x: u32,
|
pub size_x: u32,
|
||||||
pub size_y: u32,
|
pub size_y: u32,
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
|
|
@ -16,8 +18,15 @@ pub struct Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
const fn new(toplevel: Rc<ToplevelSurface>, process: process::ProcessHandle) -> Self {
|
const fn new(
|
||||||
|
toplevel: Rc<ToplevelSurface>,
|
||||||
|
process: process::ProcessHandle,
|
||||||
|
min_size: Size<i32, Logical>,
|
||||||
|
max_size: Size<i32, Logical>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
min_size,
|
||||||
|
max_size,
|
||||||
size_x: 0,
|
size_x: 0,
|
||||||
size_y: 0,
|
size_y: 0,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
|
@ -26,6 +35,10 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resizable(&self) -> bool {
|
||||||
|
self.min_size != self.max_size
|
||||||
|
}
|
||||||
|
|
||||||
pub fn configure_size(&mut self, size: Option<Size<i32, Logical>>, bounds: Size<i32, Logical>) {
|
pub fn configure_size(&mut self, size: Option<Size<i32, Logical>>, bounds: Size<i32, Logical>) {
|
||||||
self.toplevel.with_pending_state(|state| {
|
self.toplevel.with_pending_state(|state| {
|
||||||
state.bounds = Some(bounds);
|
state.bounds = Some(bounds);
|
||||||
|
|
@ -93,10 +106,12 @@ impl WindowManager {
|
||||||
&mut self,
|
&mut self,
|
||||||
toplevel: Rc<ToplevelSurface>,
|
toplevel: Rc<ToplevelSurface>,
|
||||||
process: process::ProcessHandle,
|
process: process::ProcessHandle,
|
||||||
|
min_size: Size<i32, Logical>,
|
||||||
|
max_size: Size<i32, Logical>,
|
||||||
size_x: u32,
|
size_x: u32,
|
||||||
size_y: u32,
|
size_y: u32,
|
||||||
) -> WindowHandle {
|
) -> WindowHandle {
|
||||||
let mut window = Window::new(toplevel, process);
|
let mut window = Window::new(toplevel, process, min_size, max_size);
|
||||||
window.remember_committed_size(Size::new(size_x as i32, size_y as i32));
|
window.remember_committed_size(Size::new(size_x as i32, size_y as i32));
|
||||||
self.windows.add(window)
|
self.windows.add(window)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,14 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::vec2;
|
use glam::{Vec2, vec2};
|
||||||
use slotmap::Key;
|
use slotmap::Key;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
|
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
|
||||||
event::EventCallback,
|
event::{CallbackDataCommon, EventCallback, StyleSetRequest},
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
parser::Fetchable,
|
parser::Fetchable,
|
||||||
|
taffy::Display,
|
||||||
widget::EventResult,
|
widget::EventResult,
|
||||||
};
|
};
|
||||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue, MouseTransform, StereoMode};
|
use wlx_common::overlays::{BackendAttrib, BackendAttribValue, MouseTransform, StereoMode};
|
||||||
|
|
@ -59,6 +60,7 @@ struct EditModeState {
|
||||||
pos: SpriteTabHandler<PosTabState>,
|
pos: SpriteTabHandler<PosTabState>,
|
||||||
stereo: SpriteTabHandler<StereoMode>,
|
stereo: SpriteTabHandler<StereoMode>,
|
||||||
mouse: SpriteTabHandler<MouseTransform>,
|
mouse: SpriteTabHandler<MouseTransform>,
|
||||||
|
resize_uv: Option<Vec2>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type EditModeWrapPanel = GuiPanel<EditModeState>;
|
type EditModeWrapPanel = GuiPanel<EditModeState>;
|
||||||
|
|
@ -94,6 +96,7 @@ impl EditWrapperManager {
|
||||||
owc.backend = Box::new(EditModeBackendWrapper {
|
owc.backend = Box::new(EditModeBackendWrapper {
|
||||||
inner: ManuallyDrop::new(inner),
|
inner: ManuallyDrop::new(inner),
|
||||||
panel: ManuallyDrop::new(panel),
|
panel: ManuallyDrop::new(panel),
|
||||||
|
last_extent: [0, 0],
|
||||||
last_render: Instant::now(),
|
last_render: Instant::now(),
|
||||||
can_render_inner: false,
|
can_render_inner: false,
|
||||||
});
|
});
|
||||||
|
|
@ -135,6 +138,7 @@ pub struct EditModeBackendWrapper {
|
||||||
panel: ManuallyDrop<EditModeWrapPanel>,
|
panel: ManuallyDrop<EditModeWrapPanel>,
|
||||||
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
inner: ManuallyDrop<Box<dyn OverlayBackend>>,
|
||||||
|
|
||||||
|
last_extent: [u32; 2],
|
||||||
last_render: Instant,
|
last_render: Instant,
|
||||||
can_render_inner: bool,
|
can_render_inner: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +217,8 @@ impl OverlayBackend for EditModeBackendWrapper {
|
||||||
rdr.cmd_bufs.reverse();
|
rdr.cmd_bufs.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.last_extent = rdr.extent;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<crate::windowing::backend::FrameMeta> {
|
fn frame_meta(&mut self) -> Option<crate::windowing::backend::FrameMeta> {
|
||||||
|
|
@ -225,7 +231,23 @@ impl OverlayBackend for EditModeBackendWrapper {
|
||||||
) -> HoverResult {
|
) -> HoverResult {
|
||||||
// pass through hover events to force pipewire to capture frames for us
|
// pass through hover events to force pipewire to capture frames for us
|
||||||
let _ = self.inner.on_hover(app, hit);
|
let _ = self.inner.on_hover(app, hit);
|
||||||
self.panel.on_hover(app, hit)
|
let res = self.panel.on_hover(app, hit);
|
||||||
|
|
||||||
|
if let Some(start_uv) = self.panel.state.resize_uv.as_mut() {
|
||||||
|
let extent_f32 = vec2(self.last_extent[0] as f32, self.last_extent[1] as f32);
|
||||||
|
|
||||||
|
if start_uv.length_squared() > 10.0 {
|
||||||
|
// at first this is raw position in pixels, transform to UV here
|
||||||
|
*start_uv /= extent_f32;
|
||||||
|
} else {
|
||||||
|
// actually do resize
|
||||||
|
let new_res = extent_f32 * hit.uv / *start_uv;
|
||||||
|
let new_extent = [new_res.x as u32, new_res.y as u32];
|
||||||
|
log::warn!("NEW SIZE: {new_extent:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
fn on_left(&mut self, app: &mut crate::state::AppState, pointer: usize) {
|
fn on_left(&mut self, app: &mut crate::state::AppState, pointer: usize) {
|
||||||
self.inner.on_left(app, pointer);
|
self.inner.on_left(app, pointer);
|
||||||
|
|
@ -271,6 +293,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||||
pos: SpriteTabHandler::default(),
|
pos: SpriteTabHandler::default(),
|
||||||
stereo: SpriteTabHandler::default(),
|
stereo: SpriteTabHandler::default(),
|
||||||
mouse: SpriteTabHandler::default(),
|
mouse: SpriteTabHandler::default(),
|
||||||
|
resize_uv: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let anim_mult = app.wgui_theme.animation_mult;
|
let anim_mult = app.wgui_theme.animation_mult;
|
||||||
|
|
@ -407,6 +430,20 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||||
)));
|
)));
|
||||||
Ok(EventResult::Consumed)
|
Ok(EventResult::Consumed)
|
||||||
}),
|
}),
|
||||||
|
"::EditModeResizeStart" => Box::new(move |_common, data, app, state| {
|
||||||
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
|
return Ok(EventResult::Pass);
|
||||||
|
}
|
||||||
|
state.resize_uv = data.metadata.get_mouse_pos_absolute();
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}),
|
||||||
|
"::EditModeResizeStop" => Box::new(move |_common, data, app, state| {
|
||||||
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
|
return Ok(EventResult::Pass);
|
||||||
|
}
|
||||||
|
state.resize_uv = None;
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -564,6 +601,27 @@ fn reset_panel(
|
||||||
c.set_checked(&mut com, adjust_mouse);
|
c.set_checked(&mut com, adjust_mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let resizable = attrib_value!(
|
||||||
|
owc.backend.get_attrib(BackendAttrib::Resizable),
|
||||||
|
BackendAttribValue::Resizable
|
||||||
|
)
|
||||||
|
.unwrap_or(false);
|
||||||
|
let c = panel
|
||||||
|
.parser_state
|
||||||
|
.fetch_component_as::<ComponentButton>("resize_corner")?;
|
||||||
|
let common = CallbackDataCommon {
|
||||||
|
state: &panel.layout.state,
|
||||||
|
alterables: &mut panel.layout.alterables,
|
||||||
|
};
|
||||||
|
common.alterables.set_style(
|
||||||
|
c.get_rect(),
|
||||||
|
StyleSetRequest::Display(if resizable {
|
||||||
|
Display::Block
|
||||||
|
} else {
|
||||||
|
Display::None
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,13 @@ pub fn create_wl_window_overlay(
|
||||||
-0.95
|
-0.95
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let resizable = app
|
||||||
|
.wvr_server
|
||||||
|
.as_mut()
|
||||||
|
.and_then(|wvr| wvr.wm.windows.get(&window))
|
||||||
|
.map(|w| w.resizable())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
Ok(OverlayWindowConfig {
|
Ok(OverlayWindowConfig {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
default_state: OverlayWindowState {
|
default_state: OverlayWindowState {
|
||||||
|
|
@ -113,6 +120,7 @@ pub fn create_wl_window_overlay(
|
||||||
window,
|
window,
|
||||||
icon,
|
icon,
|
||||||
(scale, curve_scale),
|
(scale, curve_scale),
|
||||||
|
resizable,
|
||||||
)?))
|
)?))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +183,7 @@ pub struct WvrWindowBackend {
|
||||||
scrolling: bool,
|
scrolling: bool,
|
||||||
overlay_id: OverlayID,
|
overlay_id: OverlayID,
|
||||||
scale: (f32, f32),
|
scale: (f32, f32),
|
||||||
|
resizable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WvrWindowBackend {
|
impl WvrWindowBackend {
|
||||||
|
|
@ -184,6 +193,7 @@ impl WvrWindowBackend {
|
||||||
window: wayvr::window::WindowHandle,
|
window: wayvr::window::WindowHandle,
|
||||||
icon: Arc<str>,
|
icon: Arc<str>,
|
||||||
scale: (f32, f32),
|
scale: (f32, f32),
|
||||||
|
resizable: bool,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let subsurface_pipeline = app.gfx.create_pipeline(
|
let subsurface_pipeline = app.gfx.create_pipeline(
|
||||||
app.gfx_extras.shaders.get("vert_quad").unwrap(), // want panic
|
app.gfx_extras.shaders.get("vert_quad").unwrap(), // want panic
|
||||||
|
|
@ -285,6 +295,7 @@ impl WvrWindowBackend {
|
||||||
scrolling: false,
|
scrolling: false,
|
||||||
overlay_id: OverlayID::null(),
|
overlay_id: OverlayID::null(),
|
||||||
scale,
|
scale,
|
||||||
|
resizable,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,6 +311,13 @@ impl WvrWindowBackend {
|
||||||
if (scale_delta - 1.0).abs() > f32::EPSILON
|
if (scale_delta - 1.0).abs() > f32::EPSILON
|
||||||
|| (curve_scale_delta - 1.0).abs() > f32::EPSILON
|
|| (curve_scale_delta - 1.0).abs() > f32::EPSILON
|
||||||
{
|
{
|
||||||
|
self.resizable = app
|
||||||
|
.wvr_server
|
||||||
|
.as_mut()
|
||||||
|
.and_then(|wvr| wvr.wm.windows.get(&self.window))
|
||||||
|
.map(|w| w.resizable())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||||
OverlaySelector::Id(self.overlay_id),
|
OverlaySelector::Id(self.overlay_id),
|
||||||
Box::new(move |_app, owc| {
|
Box::new(move |_app, owc| {
|
||||||
|
|
@ -978,6 +996,8 @@ impl OverlayBackend for WvrWindowBackend {
|
||||||
BackendAttrib::StereoAdjustMouse => Some(BackendAttribValue::StereoAdjustMouse(
|
BackendAttrib::StereoAdjustMouse => Some(BackendAttribValue::StereoAdjustMouse(
|
||||||
self.stereo_adjust_mouse,
|
self.stereo_adjust_mouse,
|
||||||
)),
|
)),
|
||||||
|
BackendAttrib::Resizable => Some(BackendAttribValue::Resizable(self.resizable)),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ pub enum BackendAttrib {
|
||||||
StereoAdjustMouse,
|
StereoAdjustMouse,
|
||||||
MouseTransform,
|
MouseTransform,
|
||||||
Icon,
|
Icon,
|
||||||
|
Resizable,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
|
@ -36,9 +37,12 @@ pub enum BackendAttribValue {
|
||||||
MouseTransform(MouseTransform),
|
MouseTransform(MouseTransform),
|
||||||
#[serde(skip_serializing, skip_deserializing)]
|
#[serde(skip_serializing, skip_deserializing)]
|
||||||
Icon(Arc<str>),
|
Icon(Arc<str>),
|
||||||
|
#[serde(skip_serializing, skip_deserializing)]
|
||||||
|
Resizable(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendAttribValue {
|
impl BackendAttribValue {
|
||||||
|
/// Used to determine if value should be saved
|
||||||
pub fn is_default(&self) -> bool {
|
pub fn is_default(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Stereo(val) => *val == StereoMode::default(),
|
Self::Stereo(val) => *val == StereoMode::default(),
|
||||||
|
|
@ -46,6 +50,7 @@ impl BackendAttribValue {
|
||||||
Self::StereoAdjustMouse(val) => !*val,
|
Self::StereoAdjustMouse(val) => !*val,
|
||||||
Self::MouseTransform(val) => *val == MouseTransform::default(),
|
Self::MouseTransform(val) => *val == MouseTransform::default(),
|
||||||
Self::Icon(_) => false,
|
Self::Icon(_) => false,
|
||||||
|
Self::Resizable(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue