diff --git a/wlx-overlay-s/src/assets/edit/flip180.svg b/wlx-overlay-s/src/assets/edit/flip180.svg
new file mode 100644
index 0000000..7705399
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/flip180.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/flip270.svg b/wlx-overlay-s/src/assets/edit/flip270.svg
new file mode 100644
index 0000000..c91dfe6
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/flip270.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/flip90.svg b/wlx-overlay-s/src/assets/edit/flip90.svg
new file mode 100644
index 0000000..1b39320
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/flip90.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/flipped.svg b/wlx-overlay-s/src/assets/edit/flipped.svg
new file mode 100644
index 0000000..ecf153a
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/flipped.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/grabbable.svg b/wlx-overlay-s/src/assets/edit/grabbable.svg
index ab36417..81ee4cd 100644
--- a/wlx-overlay-s/src/assets/edit/grabbable.svg
+++ b/wlx-overlay-s/src/assets/edit/grabbable.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/wlx-overlay-s/src/assets/edit/normal.svg b/wlx-overlay-s/src/assets/edit/normal.svg
new file mode 100644
index 0000000..484ad8a
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/normal.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/rotate180.svg b/wlx-overlay-s/src/assets/edit/rotate180.svg
new file mode 100644
index 0000000..b946ed8
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/rotate180.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/rotate270.svg b/wlx-overlay-s/src/assets/edit/rotate270.svg
new file mode 100644
index 0000000..73cb40b
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/rotate270.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/edit/rotate90.svg b/wlx-overlay-s/src/assets/edit/rotate90.svg
new file mode 100644
index 0000000..74a4f57
--- /dev/null
+++ b/wlx-overlay-s/src/assets/edit/rotate90.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/wlx-overlay-s/src/assets/gui/edit.xml b/wlx-overlay-s/src/assets/gui/edit.xml
index 111579d..10bdbbf 100644
--- a/wlx-overlay-s/src/assets/gui/edit.xml
+++ b/wlx-overlay-s/src/assets/gui/edit.xml
@@ -45,6 +45,7 @@
+
@@ -77,6 +78,19 @@
+
@@ -98,4 +112,4 @@
-
\ No newline at end of file
+
diff --git a/wlx-overlay-s/src/gui/panel/helper.rs b/wlx-overlay-s/src/gui/panel/helper.rs
index 92b7db7..a9c85fe 100644
--- a/wlx-overlay-s/src/gui/panel/helper.rs
+++ b/wlx-overlay-s/src/gui/panel/helper.rs
@@ -1,7 +1,7 @@
use regex::Regex;
use std::{
fs,
- io::{BufRead, BufReader, Read},
+ io::{BufRead, BufReader},
process::Child,
sync::{
Arc, LazyLock,
diff --git a/wlx-overlay-s/src/gui/panel/mod.rs b/wlx-overlay-s/src/gui/panel/mod.rs
index 4761a13..b461750 100644
--- a/wlx-overlay-s/src/gui/panel/mod.rs
+++ b/wlx-overlay-s/src/gui/panel/mod.rs
@@ -56,6 +56,7 @@ pub struct GuiPanel
{
context: WguiContext,
timestep: Timestep,
has_focus: [bool; 2],
+ last_content_size: Vec2,
}
pub type OnCustomIdFunc = Box<
@@ -175,6 +176,7 @@ impl GuiPanel {
gui_scale: params.gui_scale,
initialized: false,
has_focus: [false, false],
+ last_content_size: Vec2::ZERO,
})
}
@@ -206,6 +208,7 @@ impl GuiPanel {
gui_scale: params.gui_scale,
initialized: false,
has_focus: [false, false],
+ last_content_size: Vec2::ZERO,
})
}
@@ -238,7 +241,6 @@ impl OverlayBackend for GuiPanel {
if self.layout.content_size.x * self.layout.content_size.y != 0.0 {
self.update_layout()?;
self.interaction_transform = Some(ui_transform([
- //TODO: dynamic
self.layout.content_size.x as _,
self.layout.content_size.y as _,
]));
@@ -275,6 +277,17 @@ impl OverlayBackend for GuiPanel {
return Ok(ShouldRender::Unable);
}
+ if !self
+ .last_content_size
+ .abs_diff_eq(self.layout.content_size, 0.1 /* pixels */)
+ {
+ self.interaction_transform = Some(ui_transform([
+ self.layout.content_size.x as _,
+ self.layout.content_size.y as _,
+ ]));
+ self.last_content_size = self.layout.content_size;
+ }
+
Ok(if self.layout.check_toggle_needs_redraw() {
ShouldRender::Should
} else {
diff --git a/wlx-overlay-s/src/overlays/edit/mod.rs b/wlx-overlay-s/src/overlays/edit/mod.rs
index b05cc29..8fd0b07 100644
--- a/wlx-overlay-s/src/overlays/edit/mod.rs
+++ b/wlx-overlay-s/src/overlays/edit/mod.rs
@@ -14,6 +14,7 @@ use wgui::{
parser::Fetchable,
widget::EventResult,
};
+use wlx_capture::frame::Transform;
use crate::{
attrib_value,
@@ -24,6 +25,7 @@ use crate::{
gui::panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS},
overlays::edit::{
lock::InteractLockHandler,
+ mouse::new_mouse_tab_handler,
pos::{PosTabState, new_pos_tab_handler},
sprite_tab::SpriteTabHandler,
stereo::new_stereo_tab_handler,
@@ -42,6 +44,7 @@ use crate::{
};
mod lock;
+mod mouse;
mod pos;
mod sprite_tab;
mod stereo;
@@ -66,6 +69,7 @@ struct EditModeState {
lock: InteractLockHandler,
pos: SpriteTabHandler,
stereo: SpriteTabHandler,
+ mouse: SpriteTabHandler,
}
type EditModeWrapPanel = GuiPanel;
@@ -264,6 +268,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result {
lock: InteractLockHandler::default(),
pos: SpriteTabHandler::default(),
stereo: SpriteTabHandler::default(),
+ mouse: SpriteTabHandler::default(),
};
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, attribs, _app| {
@@ -323,6 +328,16 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result {
Ok(EventResult::Consumed)
})
}
+ "::EditModeSetMouse" => {
+ let key = args.next().unwrap().to_owned();
+ Box::new(move |common, _data, app, state| {
+ let sel = OverlaySelector::Id(*state.id.borrow());
+ let task = state.mouse.button_clicked(common, &key);
+ app.tasks
+ .enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
+ Ok(EventResult::Consumed)
+ })
+ }
"::EditModeDeletePress" => Box::new(move |_common, _data, _app, state| {
state.delete.pressed = Instant::now();
// TODO: animate to light up button after 2s
@@ -361,9 +376,12 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result {
panel.state.pos = new_pos_tab_handler(&mut panel)?;
panel.state.stereo = new_stereo_tab_handler(&mut panel)?;
+ panel.state.mouse = new_mouse_tab_handler(&mut panel)?;
panel.state.lock = InteractLockHandler::new(&mut panel)?;
- panel.state.tabs =
- ButtonPaneTabSwitcher::new(&mut panel, &["none", "pos", "alpha", "curve", "stereo"])?;
+ panel.state.tabs = ButtonPaneTabSwitcher::new(
+ &mut panel,
+ &["none", "pos", "alpha", "curve", "stereo", "mouse"],
+ )?;
set_up_checkbox(&mut panel, "additive_box", cb_assign_additive)?;
set_up_slider(&mut panel, "lerp_slider", cb_assign_lerp)?;
@@ -435,6 +453,19 @@ fn reset_panel(
.set_tab_visible(&mut common, "stereo", false);
}
+ if let Some(mouse) = attrib_value!(
+ owc.backend.get_attrib(BackendAttrib::MouseTransform),
+ BackendAttribValue::MouseTransform
+ ) {
+ panel.state.tabs.set_tab_visible(&mut common, "mouse", true);
+ panel.state.mouse.reset(&mut common, &mouse);
+ } else {
+ panel
+ .state
+ .tabs
+ .set_tab_visible(&mut common, "mouse", false);
+ }
+
panel.layout.process_alterables(alterables)?;
Ok(())
diff --git a/wlx-overlay-s/src/overlays/edit/mouse.rs b/wlx-overlay-s/src/overlays/edit/mouse.rs
new file mode 100644
index 0000000..6c008c3
--- /dev/null
+++ b/wlx-overlay-s/src/overlays/edit/mouse.rs
@@ -0,0 +1,72 @@
+use wlx_capture::frame::Transform;
+
+use crate::{
+ overlays::edit::{
+ EditModeWrapPanel,
+ sprite_tab::{SpriteTabHandler, SpriteTabKey},
+ },
+ windowing::backend::BackendAttribValue,
+};
+
+static MOUSE_NAMES: [&str; 9] = [
+ "default",
+ "normal",
+ "rotate90",
+ "rotate180",
+ "rotate270",
+ "flipped",
+ "flip90",
+ "flip180",
+ "flip270",
+];
+
+pub fn new_mouse_tab_handler(
+ panel: &mut EditModeWrapPanel,
+) -> anyhow::Result> {
+ SpriteTabHandler::new(
+ panel,
+ "mouse",
+ &MOUSE_NAMES,
+ Box::new(|_common, state| {
+ let mouse_transform = state.clone();
+ Box::new(move |app, owc| {
+ owc.backend
+ .set_attrib(app, BackendAttribValue::MouseTransform(mouse_transform));
+ })
+ }),
+ None,
+ )
+}
+
+impl SpriteTabKey for Transform {
+ fn to_tab_key(&self) -> &'static str {
+ match self {
+ Transform::Undefined => "default",
+ Transform::Normal => "normal",
+ Transform::Rotated90 => "rotate90",
+ Transform::Rotated180 => "rotate180",
+ Transform::Rotated270 => "rotate270",
+ Transform::Flipped => "flipped",
+ Transform::Flipped90 => "flip90",
+ Transform::Flipped180 => "flip180",
+ Transform::Flipped270 => "flip270",
+ }
+ }
+
+ fn from_tab_key(key: &str) -> Self {
+ match key {
+ "default" => Transform::Undefined,
+ "normal" => Transform::Normal,
+ "rotate90" => Transform::Rotated90,
+ "rotate180" => Transform::Rotated180,
+ "rotate270" => Transform::Rotated270,
+ "flipped" => Transform::Flipped,
+ "flip90" => Transform::Flipped90,
+ "flip180" => Transform::Flipped180,
+ "flip270" => Transform::Flipped270,
+ _ => {
+ panic!("cannot translate to mouse transform: {key}")
+ }
+ }
+ }
+}
diff --git a/wlx-overlay-s/src/overlays/edit/stereo.rs b/wlx-overlay-s/src/overlays/edit/stereo.rs
index f873f90..658b115 100644
--- a/wlx-overlay-s/src/overlays/edit/stereo.rs
+++ b/wlx-overlay-s/src/overlays/edit/stereo.rs
@@ -45,7 +45,7 @@ impl SpriteTabKey for StereoMode {
"topbottom" => StereoMode::TopBottom,
"bottomtop" => StereoMode::BottomTop,
_ => {
- panic!("cannot translate to positioning: {key}")
+ panic!("cannot translate to stereo mode: {key}")
}
}
}
diff --git a/wlx-overlay-s/src/overlays/screen/backend.rs b/wlx-overlay-s/src/overlays/screen/backend.rs
index 06febfd..170c1a2 100644
--- a/wlx-overlay-s/src/overlays/screen/backend.rs
+++ b/wlx-overlay-s/src/overlays/screen/backend.rs
@@ -16,7 +16,7 @@ use crate::{
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
windowing::backend::{
BackendAttrib, BackendAttribValue, FrameMeta, OverlayBackend, OverlayEventData,
- RenderResources, ShouldRender, StereoMode,
+ RenderResources, ShouldRender, StereoMode, ui_transform,
},
};
@@ -47,6 +47,10 @@ pub struct ScreenBackend {
mouse_transform: Affine2,
interaction_transform: Option,
stereo: Option,
+ pub(super) logical_pos: Vec2,
+ pub(super) logical_size: Vec2,
+ pub(super) mouse_transform_original: Transform,
+ mouse_transform_override: Transform,
}
impl ScreenBackend {
@@ -63,49 +67,61 @@ impl ScreenBackend {
mouse_transform: Affine2::ZERO,
interaction_transform: None,
stereo: None,
+ logical_pos: Vec2::ZERO,
+ logical_size: Vec2::ZERO,
+ mouse_transform_original: Transform::Undefined,
+ mouse_transform_override: Transform::Undefined,
}
}
- pub(super) fn set_mouse_transform(&mut self, pos: Vec2, size: Vec2, transform: Transform) {
+ pub(super) fn apply_mouse_transform_with_override(&mut self, override_transform: Transform) {
+ let size = self.logical_size;
+ let pos = self.logical_pos;
+
+ let transform = match override_transform {
+ Transform::Undefined => self.mouse_transform_original,
+ other => other,
+ };
+
self.mouse_transform = match transform {
- Transform::Rotated90 | Transform::Flipped90 => Affine2::from_cols(
+ Transform::Normal | Transform::Undefined => {
+ Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos)
+ }
+ Transform::Rotated90 => Affine2::from_cols(
vec2(0., size.y),
vec2(-size.x, 0.),
vec2(pos.x + size.x, pos.y),
),
- Transform::Rotated180 | Transform::Flipped180 => Affine2::from_cols(
+ Transform::Rotated180 => Affine2::from_cols(
vec2(-size.x, 0.),
vec2(0., -size.y),
vec2(pos.x + size.x, pos.y + size.y),
),
- Transform::Rotated270 | Transform::Flipped270 => Affine2::from_cols(
+ Transform::Rotated270 => Affine2::from_cols(
vec2(0., -size.y),
vec2(size.x, 0.),
vec2(pos.x, pos.y + size.y),
),
- _ => Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos),
+ Transform::Flipped => Affine2::from_cols(
+ vec2(-size.x, 0.),
+ vec2(0., size.y),
+ vec2(pos.x + size.x, pos.y),
+ ),
+ Transform::Flipped90 => {
+ Affine2::from_cols(vec2(0., size.y), vec2(size.x, 0.), vec2(pos.x, pos.y))
+ }
+ Transform::Flipped180 => Affine2::from_cols(
+ vec2(size.x, 0.),
+ vec2(0., -size.y),
+ vec2(pos.x, pos.y + size.y),
+ ),
+ Transform::Flipped270 => Affine2::from_cols(
+ vec2(0., -size.y),
+ vec2(-size.x, 0.),
+ vec2(pos.x + size.x, pos.y + size.y),
+ ),
};
}
-
- pub(super) fn set_interaction_transform(&mut self, res: Vec2, transform: Transform) {
- let center = Vec2 { x: 0.5, y: 0.5 };
- self.interaction_transform = Some(match transform {
- Transform::Rotated90 | Transform::Flipped90 => {
- Affine2::from_cols(Vec2::NEG_Y * (res.x / res.y), Vec2::NEG_X, center)
- }
- Transform::Rotated180 | Transform::Flipped180 => {
- Affine2::from_cols(Vec2::NEG_X, Vec2::NEG_Y * (-res.x / res.y), center)
- }
- Transform::Rotated270 | Transform::Flipped270 => {
- Affine2::from_cols(Vec2::Y * (res.x / res.y), Vec2::X, center)
- }
- _ if res.y > res.x => {
- // Xorg upright screens
- Affine2::from_cols(Vec2::X * (res.y / res.x), Vec2::NEG_Y, center)
- }
- _ => Affine2::from_cols(Vec2::X, Vec2::NEG_Y * (res.x / res.y), center),
- });
- }
}
impl OverlayBackend for ScreenBackend {
@@ -175,17 +191,14 @@ impl OverlayBackend for ScreenBackend {
.is_some_and(|old| old.extent[..2] != meta.extent[..2])
{
pipeline.set_extent(app, [meta.extent[0] as _, meta.extent[1] as _])?;
- self.set_interaction_transform(
- meta.extent.extent_vec2(),
- frame.get_transform(),
- );
+ self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
}
} else {
let pipeline =
ScreenPipeline::new(&meta, app, self.stereo.unwrap_or(StereoMode::None))?;
meta.extent[2] = pipeline.get_depth();
self.pipeline = Some(pipeline);
- self.set_interaction_transform(meta.extent.extent_vec2(), frame.get_transform());
+ self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
}
self.meta = Some(meta);
@@ -281,6 +294,9 @@ impl OverlayBackend for ScreenBackend {
fn get_attrib(&self, attrib: BackendAttrib) -> Option {
match attrib {
BackendAttrib::Stereo => self.stereo.map(|s| BackendAttribValue::Stereo(s)),
+ BackendAttrib::MouseTransform => Some(BackendAttribValue::MouseTransform(
+ self.mouse_transform_override,
+ )),
_ => None,
}
}
@@ -299,6 +315,11 @@ impl OverlayBackend for ScreenBackend {
false
}
}
+ BackendAttribValue::MouseTransform(new) => {
+ self.mouse_transform_override = new;
+ self.apply_mouse_transform_with_override(new);
+ true
+ }
_ => false,
}
}
diff --git a/wlx-overlay-s/src/overlays/screen/wl.rs b/wlx-overlay-s/src/overlays/screen/wl.rs
index 6530d45..771a103 100644
--- a/wlx-overlay-s/src/overlays/screen/wl.rs
+++ b/wlx-overlay-s/src/overlays/screen/wl.rs
@@ -1,6 +1,7 @@
use glam::vec2;
use wlx_capture::{
WlxCapture,
+ frame::Transform,
wayland::{WlxClient, WlxOutput},
wlr_dmabuf::WlrDmabufCapture,
wlr_screencopy::WlrScreencopyCapture,
@@ -124,15 +125,14 @@ pub fn create_screens_wayland(wl: &mut WlxClient, app: &mut AppState) -> ScreenC
&mut pw_tokens,
app,
) {
- let logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
- let logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
- let transform = output.transform;
-
- backend.set_mouse_transform(logical_pos, logical_size, transform);
+ backend.logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
+ backend.logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
+ backend.mouse_transform_original = output.transform;
+ backend.apply_mouse_transform_with_override(Transform::Undefined);
let window_config = create_screen_from_backend(
output.name.clone(),
- transform,
+ output.transform,
&app.session,
Box::new(backend),
);
diff --git a/wlx-overlay-s/src/overlays/screen/x11.rs b/wlx-overlay-s/src/overlays/screen/x11.rs
index 70cb369..c3f9ee8 100644
--- a/wlx-overlay-s/src/overlays/screen/x11.rs
+++ b/wlx-overlay-s/src/overlays/screen/x11.rs
@@ -103,11 +103,9 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result anyhow::Result