mirror of https://github.com/wayvr-org/wayvr.git
relative mouse, dynamic decor, refactors
This commit is contained in:
parent
16325040a5
commit
ee7be500af
|
|
@ -5,6 +5,7 @@
|
|||
<elements>
|
||||
<div flex_grow="1" height="48">
|
||||
<rectangle
|
||||
id="rect"
|
||||
flex_grow="1" height="48"
|
||||
padding="8" border="2"
|
||||
round="8"
|
||||
|
|
@ -13,7 +14,7 @@
|
|||
color="background"
|
||||
border_color="outline"
|
||||
>
|
||||
<label id="label_title" margin_left="8" color="on_background" size="22" weight="bold" />
|
||||
<label id="title" text="~title" margin_left="8" color="on_background" size="22" weight="bold" />
|
||||
<div gap="4">
|
||||
<Button macro="window_button" _release="::EditToggle">
|
||||
<sprite macro="window_button_icon" src="watch/edit.svg" />
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ pub enum SpawnPos {
|
|||
Parent(OverlaySelector),
|
||||
}
|
||||
|
||||
pub enum GlobalChange {
|
||||
Settings,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
|
||||
pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send;
|
||||
pub enum OverlayTask {
|
||||
|
|
@ -116,8 +121,7 @@ pub enum OverlayTask {
|
|||
ToggleDashboard,
|
||||
ShowHide,
|
||||
CleanupMirrors,
|
||||
SettingsChanged,
|
||||
KeyboardChanged,
|
||||
GlobalChange(GlobalChange),
|
||||
Modify(OverlaySelector, Box<ModifyOverlayTask>),
|
||||
Spawn(OverlaySelector, SpawnPos, Box<CreateOverlayTask>),
|
||||
ModifyPanel(ModifyPanelTask),
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use glam::Vec2;
|
||||
use glam::{DVec2, Vec2};
|
||||
use smithay::{
|
||||
backend::input::{Axis, AxisSource, ButtonState, Keycode},
|
||||
input::{
|
||||
keyboard::KeyboardHandle,
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle},
|
||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle, RelativeMotionEvent},
|
||||
},
|
||||
reexports::wayland_server::{self, protocol::wl_surface::WlSurface},
|
||||
utils::{Logical, Point, SerialCounter},
|
||||
|
|
@ -262,8 +262,16 @@ impl WayVRCompositor {
|
|||
.context("Failed to set keymap")
|
||||
}
|
||||
|
||||
pub fn send_mouse_move(&mut self, focus: Option<(WlSurface, Vec2)>, global_pos: Vec2) {
|
||||
pub fn send_mouse_move(
|
||||
&mut self,
|
||||
focus: Option<(WlSurface, Vec2)>,
|
||||
global_pos: DVec2,
|
||||
delta: DVec2,
|
||||
delta_unaccel: DVec2,
|
||||
) {
|
||||
let location: Point<f64, Logical> = (global_pos.x as f64, global_pos.y as f64).into();
|
||||
let delta: Point<f64, Logical> = (delta.x, delta.y).into();
|
||||
let delta_unaccel: Point<f64, Logical> = (delta_unaccel.x, delta_unaccel.y).into();
|
||||
|
||||
let focus = focus.map(|(surface, origin)| {
|
||||
let focus_location: Point<f64, Logical> = (origin.x as f64, origin.y as f64).into();
|
||||
|
|
@ -273,13 +281,22 @@ impl WayVRCompositor {
|
|||
|
||||
self.seat_pointer.motion(
|
||||
&mut self.state,
|
||||
focus,
|
||||
focus.clone(),
|
||||
&MotionEvent {
|
||||
location,
|
||||
serial: self.serial_counter.next_serial(),
|
||||
time: super::time::get_millis() as u32,
|
||||
},
|
||||
);
|
||||
self.seat_pointer.relative_motion(
|
||||
&mut self.state,
|
||||
focus,
|
||||
&RelativeMotionEvent {
|
||||
delta,
|
||||
delta_unaccel,
|
||||
utime: super::time::get_millis(),
|
||||
},
|
||||
);
|
||||
|
||||
self.seat_pointer.frame(&mut self.state);
|
||||
}
|
||||
|
|
@ -312,7 +329,44 @@ impl WayVRCompositor {
|
|||
self.seat_pointer.frame(&mut self.state);
|
||||
}
|
||||
|
||||
pub fn send_pointer_axis_wheel(&mut self, delta: super::WheelDelta) {
|
||||
pub fn send_pointer_axis_wheel_raw(&mut self, delta: super::WheelDelta) {
|
||||
let time = super::time::get_millis() as u32;
|
||||
|
||||
let v120_x = delta.x as i32;
|
||||
let v120_y = delta.y as i32;
|
||||
|
||||
if v120_x == 0 && v120_y == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
// 15 logical axis units for one wheel detent of 120 v120 units
|
||||
const AXIS_VALUE_PER_DETENT: f64 = 15.0;
|
||||
|
||||
let mut frame = AxisFrame::new(time).source(AxisSource::Wheel);
|
||||
|
||||
if v120_x != 0 {
|
||||
frame = frame
|
||||
.value(
|
||||
Axis::Horizontal,
|
||||
f64::from(v120_x) / 120.0 * AXIS_VALUE_PER_DETENT,
|
||||
)
|
||||
.v120(Axis::Horizontal, v120_x);
|
||||
}
|
||||
|
||||
if v120_y != 0 {
|
||||
frame = frame
|
||||
.value(
|
||||
Axis::Vertical,
|
||||
f64::from(v120_y) / 120.0 * AXIS_VALUE_PER_DETENT,
|
||||
)
|
||||
.v120(Axis::Vertical, v120_y);
|
||||
}
|
||||
|
||||
self.seat_pointer.axis(&mut self.state, frame);
|
||||
self.seat_pointer.frame(&mut self.state);
|
||||
}
|
||||
|
||||
pub fn send_pointer_axis_wheel_accumulated(&mut self, delta: super::WheelDelta) {
|
||||
let time = super::time::get_millis() as u32;
|
||||
|
||||
let multiplier = 32.0;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use smithay::desktop::{
|
|||
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy,
|
||||
find_popup_root_surface, get_popup_toplevel_coords,
|
||||
};
|
||||
use smithay::input::pointer::Focus;
|
||||
use smithay::input::pointer::{CursorImageStatus, Focus};
|
||||
use smithay::input::{Seat, SeatHandler, SeatState};
|
||||
use smithay::output::Output;
|
||||
use smithay::reexports::rustix::fs::{OFlags, fcntl_setfl};
|
||||
|
|
@ -24,6 +24,7 @@ use smithay::wayland::dmabuf::{
|
|||
};
|
||||
use smithay::wayland::fractional_scale::with_fractional_scale;
|
||||
use smithay::wayland::output::OutputHandler;
|
||||
use smithay::wayland::relative_pointer::RelativePointerManagerState;
|
||||
use smithay::wayland::selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
set_data_device_focus, set_data_device_selection,
|
||||
|
|
@ -45,8 +46,8 @@ use smithay::wayland::viewporter::ViewporterState;
|
|||
use smithay::{
|
||||
delegate_compositor, delegate_data_control, delegate_data_device, delegate_dmabuf,
|
||||
delegate_ext_data_control, delegate_kde_decoration, delegate_output,
|
||||
delegate_primary_selection, delegate_seat, delegate_shm, delegate_single_pixel_buffer,
|
||||
delegate_viewporter, delegate_xdg_decoration, delegate_xdg_shell,
|
||||
delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_shm,
|
||||
delegate_single_pixel_buffer, delegate_viewporter, delegate_xdg_decoration, delegate_xdg_shell,
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
|
|
@ -80,6 +81,8 @@ pub struct Application {
|
|||
#[allow(dead_code)]
|
||||
pub xdg_decoration_state: XdgDecorationState,
|
||||
pub kde_decoration_state: KdeDecorationState,
|
||||
#[allow(dead_code)]
|
||||
pub relative_pointer_state: RelativePointerManagerState,
|
||||
pub wayvr_tasks: SyncEventQueue<WayVRTask>,
|
||||
pub popup_manager: PopupManager,
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -87,6 +90,7 @@ pub struct Application {
|
|||
pub display_handle: DisplayHandle,
|
||||
pub redraw_requests: HashSet<ObjectId>,
|
||||
pub pending_frame_callbacks: HashMap<ObjectId, Vec<wl_callback::WlCallback>>,
|
||||
pub cursor_image: CursorImageStatus,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
|
|
@ -334,11 +338,8 @@ impl SeatHandler for Application {
|
|||
set_primary_focus(dh, seat, client);
|
||||
}
|
||||
|
||||
fn cursor_image(
|
||||
&mut self,
|
||||
_seat: &Seat<Self>,
|
||||
_image: smithay::input::pointer::CursorImageStatus,
|
||||
) {
|
||||
fn cursor_image(&mut self, _seat: &Seat<Self>, image: CursorImageStatus) {
|
||||
self.cursor_image = image;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -581,6 +582,13 @@ impl XdgShellHandler for Application {
|
|||
.send(WayVRTask::MinimizeRequest(client.id(), surface.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn title_changed(&mut self, surface: ToplevelSurface) {
|
||||
if let Some(client) = surface.wl_surface().client() {
|
||||
self.wayvr_tasks
|
||||
.send(WayVRTask::TitleChange(client.id(), surface.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShmHandler for Application {
|
||||
|
|
@ -683,6 +691,7 @@ delegate_ext_data_control!(Application);
|
|||
delegate_xdg_decoration!(Application);
|
||||
delegate_kde_decoration!(Application);
|
||||
delegate_single_pixel_buffer!(Application);
|
||||
delegate_relative_pointer!(Application);
|
||||
|
||||
const fn wl_transform_to_frame_transform(
|
||||
transform: wl_output::Transform,
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub const SEAT_NAME: &str = "wayvr";
|
||||
|
||||
const IGNORE_PREFIX: &str = "WayVR";
|
||||
const WATCHDOG_TIMEOUT: Duration = Duration::from_millis(5000);
|
||||
const POLL_TIMEOUT_MS: i32 = 20;
|
||||
|
|
@ -51,6 +49,8 @@ pub enum CapturedEvent {
|
|||
PointerMotion {
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dx_raw: f64,
|
||||
dy_raw: f64,
|
||||
},
|
||||
PointerAxis {
|
||||
horizontal_v120: i32,
|
||||
|
|
@ -319,10 +319,10 @@ fn worker_main(
|
|||
};
|
||||
|
||||
let mut libinput = Libinput::new_with_udev(interface);
|
||||
if libinput.udev_assign_seat(SEAT_NAME).is_err() {
|
||||
if libinput.udev_assign_seat("seat0").is_err() {
|
||||
let _ = init_tx.send(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("failed to assign libinput seat {SEAT_NAME:?}"),
|
||||
format!("failed to assign libinput seat"),
|
||||
)));
|
||||
return;
|
||||
}
|
||||
|
|
@ -550,9 +550,16 @@ fn process_libinput_event(
|
|||
Event::Pointer(PointerEvent::Motion(event)) if emit => {
|
||||
let dx = event.dx();
|
||||
let dy = event.dy();
|
||||
let dx_raw = event.dx_unaccelerated();
|
||||
let dy_raw = event.dy_unaccelerated();
|
||||
if (dx != 0.0 || dy != 0.0)
|
||||
&& event_tx
|
||||
.send(CapturedEvent::PointerMotion { dx, dy })
|
||||
.send(CapturedEvent::PointerMotion {
|
||||
dx,
|
||||
dy,
|
||||
dx_raw,
|
||||
dy_raw,
|
||||
})
|
||||
.is_err()
|
||||
{
|
||||
return ProcessResult::ReceiverGone;
|
||||
|
|
@ -805,6 +812,9 @@ fn check_key_combo(pressed: &HashSet<u16>) -> Option<KeyCombo> {
|
|||
let alt =
|
||||
pressed.contains(&KeyCode::KEY_LEFTALT.0) || pressed.contains(&KeyCode::KEY_RIGHTALT.0);
|
||||
|
||||
let ctrl =
|
||||
pressed.contains(&KeyCode::KEY_LEFTCTRL.0) || pressed.contains(&KeyCode::KEY_RIGHTCTRL.0);
|
||||
|
||||
if alt && pressed.contains(&KeyCode::KEY_F4.0) {
|
||||
return Some(KeyCombo::AltF4);
|
||||
}
|
||||
|
|
@ -813,9 +823,6 @@ fn check_key_combo(pressed: &HashSet<u16>) -> Option<KeyCombo> {
|
|||
return Some(KeyCombo::AltTab);
|
||||
}
|
||||
|
||||
let ctrl =
|
||||
pressed.contains(&KeyCode::KEY_LEFTCTRL.0) || pressed.contains(&KeyCode::KEY_RIGHTCTRL.0);
|
||||
|
||||
if ctrl && alt && pressed.contains(&KeyCode::KEY_DELETE.0) {
|
||||
return Some(KeyCombo::CtrlAltDel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use slotmap::SecondaryMap;
|
|||
use smallvec::SmallVec;
|
||||
use smithay::{
|
||||
desktop::PopupManager,
|
||||
input::{SeatState, keyboard::XkbConfig},
|
||||
input::{SeatState, keyboard::XkbConfig, pointer::CursorImageStatus},
|
||||
output::{Mode, Output},
|
||||
reexports::{
|
||||
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager as kde_decoration,
|
||||
|
|
@ -30,6 +30,7 @@ use smithay::{
|
|||
wayland::{
|
||||
compositor::{self, SurfaceData, with_states},
|
||||
dmabuf::{DmabufFeedbackBuilder, DmabufState},
|
||||
relative_pointer::RelativePointerManagerState,
|
||||
selection::{
|
||||
data_device::DataDeviceState, ext_data_control as selection_ext,
|
||||
primary_selection::PrimarySelectionState, wlr_data_control as selection_wlr,
|
||||
|
|
@ -65,19 +66,19 @@ use crate::{
|
|||
task::{OverlayTask, SpawnPos, TaskContainer, TaskType, ToggleMode},
|
||||
wayvr::{
|
||||
image_importer::ImageImporter,
|
||||
input_capture::{InputCapture, SEAT_NAME},
|
||||
input_capture::InputCapture,
|
||||
process::{KillSignal, Process},
|
||||
},
|
||||
},
|
||||
graphics::{ExtentExt, WGfxExtras},
|
||||
ipc::{event_queue::SyncEventQueue, ipc_server, signal::WayVRSignal},
|
||||
overlays::wayvr::create_wl_window_overlay,
|
||||
overlays::wayvr::{WvrCommand, create_wl_window_overlay},
|
||||
state::AppState,
|
||||
subsystem::{
|
||||
dbus::DbusConnector,
|
||||
hid::{MODS_TO_KEYS, WheelDelta},
|
||||
},
|
||||
windowing::{OverlayID, OverlaySelector},
|
||||
windowing::{OverlayID, OverlaySelector, backend::OverlayEventData},
|
||||
};
|
||||
|
||||
pub use hit_test::{WvrHitContext, WvrHitTarget, build_hit_context};
|
||||
|
|
@ -117,6 +118,7 @@ pub enum WayVRTask {
|
|||
NewToplevel(ClientId, ToplevelSurface),
|
||||
DropToplevel(ClientId, ToplevelSurface),
|
||||
MinimizeRequest(ClientId, ToplevelSurface),
|
||||
TitleChange(ClientId, ToplevelSurface),
|
||||
NewExternalProcess(ExternalProcessRequest),
|
||||
ProcessTerminationRequest(process::ProcessHandle, KillSignal),
|
||||
CloseWindowRequest(window::WindowHandle),
|
||||
|
|
@ -158,7 +160,7 @@ pub enum TickTask {
|
|||
|
||||
const KEY_REPEAT_DELAY: i32 = 200;
|
||||
const KEY_REPEAT_RATE: i32 = 50;
|
||||
const WAYVR_SCREEN_RES: [i32; 2] = [2560, 2560];
|
||||
const WAYVR_SCREEN_RES: [i32; 2] = [2560, 1440];
|
||||
|
||||
impl WvrServerState {
|
||||
pub fn new(
|
||||
|
|
@ -178,7 +180,7 @@ impl WvrServerState {
|
|||
let shm = ShmState::new::<Application>(&dh, Vec::new());
|
||||
let data_device = DataDeviceState::new::<Application>(&dh);
|
||||
let primary_selection_state = PrimarySelectionState::new::<Application>(&dh);
|
||||
let mut seat = seat_state.new_wl_seat(&dh, SEAT_NAME);
|
||||
let mut seat = seat_state.new_wl_seat(&dh, "wayvr");
|
||||
|
||||
let ext_data_control_state = selection_ext::DataControlState::new::<Application, _>(
|
||||
&dh,
|
||||
|
|
@ -194,6 +196,7 @@ impl WvrServerState {
|
|||
let xdg_decoration_state = XdgDecorationState::new::<Application>(&dh);
|
||||
let kde_decoration_state =
|
||||
KdeDecorationState::new::<Application>(&dh, kde_decoration::Mode::Server);
|
||||
let relative_pointer_state = RelativePointerManagerState::new::<Application>(&dh);
|
||||
let viewporter = ViewporterState::new::<Application>(&dh);
|
||||
|
||||
let dummy_milli_hz = 60000; /* refresh rate in millihertz */
|
||||
|
|
@ -277,12 +280,14 @@ impl WvrServerState {
|
|||
ext_data_control_state,
|
||||
xdg_decoration_state,
|
||||
kde_decoration_state,
|
||||
relative_pointer_state,
|
||||
wayvr_tasks: tasks.clone(),
|
||||
dmabuf_state,
|
||||
popup_manager: PopupManager::default(),
|
||||
viewporter,
|
||||
redraw_requests: HashSet::new(),
|
||||
pending_frame_callbacks: HashMap::new(),
|
||||
cursor_image: CursorImageStatus::default_named(),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -564,6 +569,29 @@ impl WvrServerState {
|
|||
}
|
||||
}
|
||||
}
|
||||
WayVRTask::TitleChange(client_id, toplevel) => {
|
||||
for client in &wvr_server.manager.clients {
|
||||
if client.client.id() != client_id {
|
||||
continue;
|
||||
}
|
||||
let Some(window_handle) = wvr_server.wm.find_window_handle(&toplevel)
|
||||
else {
|
||||
log::warn!("MinimizeRequest: Couldn't find matching window handle");
|
||||
continue;
|
||||
};
|
||||
if let Some(oid) = wvr_server.window_to_overlay.get(&window_handle) {
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(*oid),
|
||||
Box::new(|app, owc| {
|
||||
let _ = owc.backend.notify(
|
||||
app,
|
||||
OverlayEventData::WvrCommand(WvrCommand::ReloadTitle),
|
||||
);
|
||||
}),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
WayVRTask::ProcessTerminationRequest(process_handle, signal) => {
|
||||
if let Some(process) = wvr_server.processes.get_mut(&process_handle) {
|
||||
process.kill(signal);
|
||||
|
|
@ -728,6 +756,7 @@ impl WvrServerState {
|
|||
};
|
||||
|
||||
let mut mouse_delta = DVec2::ZERO;
|
||||
let mut mouse_delta_raw = DVec2::ZERO;
|
||||
|
||||
for ev in input_capture.drain_events() {
|
||||
match ev {
|
||||
|
|
@ -738,61 +767,29 @@ impl WvrServerState {
|
|||
let Some(mouse_index) = Self::button_to_mouse_index(button) else {
|
||||
continue;
|
||||
};
|
||||
let Some(ref hover) = self.wm.mouse else {
|
||||
continue;
|
||||
};
|
||||
let Some(window) = self.wm.windows.get(&hover.hover_window) else {
|
||||
continue;
|
||||
};
|
||||
let toplevel = window.toplevel.wl_surface().clone();
|
||||
let inner_extent = with_states(&toplevel, |states| {
|
||||
SurfaceBufWithImage::get_from_surface(states)
|
||||
.map(|s| s.image.extent_u32arr())
|
||||
.unwrap_or([1, 1])
|
||||
});
|
||||
let Some(hit_ctx) = build_hit_context(
|
||||
&toplevel,
|
||||
&self.manager.state.popup_manager,
|
||||
inner_extent,
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let pos = Vec2::new(hover.x as f32, hover.y as f32);
|
||||
let target = hit_ctx.hit_target_at(pos);
|
||||
let focus_target = self.hit_target_to_focus(
|
||||
target.unwrap_or(WvrHitTarget::Toplevel { pos }),
|
||||
hover.hover_window,
|
||||
pos,
|
||||
);
|
||||
let click_freeze = 0;
|
||||
self.send_mouse_button(
|
||||
focus_target,
|
||||
pos,
|
||||
hover.hover_window,
|
||||
mouse_index,
|
||||
pressed,
|
||||
click_freeze,
|
||||
);
|
||||
self.manager.send_pointer_button(mouse_index, pressed);
|
||||
}
|
||||
input_capture::CapturedEvent::PointerMotion { dx, dy } => {
|
||||
input_capture::CapturedEvent::PointerMotion {
|
||||
dx,
|
||||
dy,
|
||||
dx_raw,
|
||||
dy_raw,
|
||||
} => {
|
||||
mouse_delta += DVec2 { x: dx, y: dy };
|
||||
mouse_delta_raw += DVec2 {
|
||||
x: dx_raw,
|
||||
y: dy_raw,
|
||||
};
|
||||
}
|
||||
input_capture::CapturedEvent::PointerAxis {
|
||||
horizontal_v120,
|
||||
vertical_v120,
|
||||
} => {
|
||||
let Some(ref hover) = self.wm.mouse else {
|
||||
continue;
|
||||
};
|
||||
let delta = WheelDelta {
|
||||
x: horizontal_v120 as f32,
|
||||
y: vertical_v120 as f32,
|
||||
};
|
||||
self.send_mouse_scroll(
|
||||
hover.hover_window,
|
||||
Vec2::new(hover.x as f32, hover.y as f32),
|
||||
delta,
|
||||
);
|
||||
self.manager.send_pointer_axis_wheel_raw(delta);
|
||||
}
|
||||
input_capture::CapturedEvent::UngrabbedAll => {
|
||||
self.manager.release_all_keys();
|
||||
|
|
@ -806,7 +803,7 @@ impl WvrServerState {
|
|||
self.close_window(window_handle);
|
||||
}
|
||||
}
|
||||
input_capture::KeyCombo::AltTab => {}
|
||||
input_capture::KeyCombo::AltTab => self.alt_tab(),
|
||||
input_capture::KeyCombo::CtrlAltDel => { /* not exposed to us */ }
|
||||
}
|
||||
}
|
||||
|
|
@ -819,10 +816,6 @@ impl WvrServerState {
|
|||
break 'mouse_update;
|
||||
};
|
||||
|
||||
let new_x = hover.x as f64 + mouse_delta.x;
|
||||
let new_y = hover.y as f64 + mouse_delta.y;
|
||||
let new_pos = Vec2::new(new_x as f32, new_y as f32);
|
||||
|
||||
let Some(window) = self.wm.windows.get(&hover.hover_window) else {
|
||||
break 'mouse_update;
|
||||
};
|
||||
|
|
@ -837,17 +830,38 @@ impl WvrServerState {
|
|||
else {
|
||||
break 'mouse_update;
|
||||
};
|
||||
let target = hit_ctx.hit_target_at(new_pos);
|
||||
|
||||
let new_x = (hover.pos.x + mouse_delta.x).clamp(0., inner_extent[0] as f64);
|
||||
let new_y = (hover.pos.y + mouse_delta.y).clamp(0., inner_extent[1] as f64);
|
||||
let new_pos = DVec2::new(new_x, new_y);
|
||||
let new_pos_f32 = Vec2::new(new_x as f32, new_y as f32);
|
||||
|
||||
let target = hit_ctx.hit_target_at(new_pos_f32);
|
||||
let focus_target = self.hit_target_to_focus(
|
||||
target.unwrap_or(WvrHitTarget::Toplevel { pos: new_pos }),
|
||||
target.unwrap_or(WvrHitTarget::Toplevel { pos: new_pos_f32 }),
|
||||
hover.hover_window,
|
||||
new_pos_f32,
|
||||
);
|
||||
self.send_mouse_move_relative(
|
||||
focus_target,
|
||||
new_pos,
|
||||
mouse_delta,
|
||||
mouse_delta_raw,
|
||||
hover.hover_window,
|
||||
new_pos,
|
||||
);
|
||||
self.send_mouse_move(focus_target, new_pos, hover.hover_window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn alt_tab(&mut self) {
|
||||
let mut windows: Vec<_> = self.wm.windows.iter().collect();
|
||||
if windows.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
||||
fn button_to_mouse_index(button: u32) -> Option<MouseIndex> {
|
||||
match button {
|
||||
272 => Some(MouseIndex::Left),
|
||||
|
|
@ -880,57 +894,25 @@ impl WvrServerState {
|
|||
}
|
||||
|
||||
self.has_input_focus = has_focus;
|
||||
}
|
||||
|
||||
pub fn send_mouse_move(
|
||||
&mut self,
|
||||
target: PointerFocusTarget,
|
||||
global_pos: Vec2,
|
||||
hover_window: window::WindowHandle,
|
||||
) {
|
||||
if self.mouse_freeze > Instant::now() {
|
||||
return;
|
||||
if !has_focus {
|
||||
self.wm.mouse = None;
|
||||
}
|
||||
|
||||
let focus = match target {
|
||||
PointerFocusTarget::Surface { surface, origin } => Some((surface, origin)),
|
||||
PointerFocusTarget::Toplevel => {
|
||||
let surface = self
|
||||
.wm
|
||||
.windows
|
||||
.get(&hover_window)
|
||||
.map(|x| x.toplevel.wl_surface().clone());
|
||||
|
||||
surface.clone().map(|surface| (surface, Vec2::ZERO))
|
||||
}
|
||||
PointerFocusTarget::None => None,
|
||||
};
|
||||
|
||||
self.manager.send_mouse_move(focus, global_pos);
|
||||
|
||||
self.mouse_freeze = Instant::now() + Duration::from_millis(1);
|
||||
|
||||
self.wm.mouse = Some(window::MouseState {
|
||||
hover_window,
|
||||
x: global_pos.x as u32,
|
||||
y: global_pos.y as u32,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_mouse_button(
|
||||
pub fn get_focused_window(&self) -> Option<window::WindowHandle> {
|
||||
if !self.has_input_focus {
|
||||
return None;
|
||||
}
|
||||
self.wm.mouse.as_ref().map(|x| x.hover_window)
|
||||
}
|
||||
|
||||
fn get_mouse_focus(
|
||||
&mut self,
|
||||
target: PointerFocusTarget,
|
||||
global_pos: Vec2,
|
||||
hover_window: window::WindowHandle,
|
||||
index: MouseIndex,
|
||||
pressed: bool,
|
||||
click_freeze: i32,
|
||||
) {
|
||||
if pressed {
|
||||
self.mouse_freeze = Instant::now() + Duration::from_millis(click_freeze.max(0) as u64);
|
||||
}
|
||||
|
||||
let (focus, focus_keyboard) = match target {
|
||||
) -> (Option<(WlSurface, Vec2)>, Option<WlSurface>) {
|
||||
match target {
|
||||
PointerFocusTarget::Surface { surface, origin } => (Some((surface, origin)), None),
|
||||
PointerFocusTarget::Toplevel => {
|
||||
let surface = self
|
||||
|
|
@ -952,7 +934,76 @@ impl WvrServerState {
|
|||
.map(|x| x.toplevel.wl_surface().clone());
|
||||
(None, pressed.then_some(surface).flatten())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mouse_relative(&self, global_pos: DVec2, hover_window: window::WindowHandle) -> DVec2 {
|
||||
let Some(ref mouse) = self.wm.mouse else {
|
||||
return DVec2::ZERO;
|
||||
};
|
||||
if hover_window != mouse.hover_window {
|
||||
// don't twitch if we just switched windows
|
||||
return DVec2::ZERO;
|
||||
}
|
||||
global_pos - mouse.pos
|
||||
}
|
||||
|
||||
fn send_mouse_move_relative(
|
||||
&mut self,
|
||||
target: PointerFocusTarget,
|
||||
global_pos: DVec2,
|
||||
delta: DVec2,
|
||||
delta_unaccel: DVec2,
|
||||
hover_window: window::WindowHandle,
|
||||
) {
|
||||
let (focus, _) = self.get_mouse_focus(target, hover_window, false);
|
||||
|
||||
self.manager
|
||||
.send_mouse_move(focus, global_pos, delta, delta_unaccel);
|
||||
self.mouse_freeze = Instant::now() + Duration::from_millis(1);
|
||||
self.wm.mouse = Some(window::MouseState {
|
||||
hover_window,
|
||||
pos: global_pos,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_mouse_move(
|
||||
&mut self,
|
||||
target: PointerFocusTarget,
|
||||
global_pos: Vec2,
|
||||
hover_window: window::WindowHandle,
|
||||
) {
|
||||
if self.mouse_freeze > Instant::now() {
|
||||
return;
|
||||
}
|
||||
|
||||
let global_pos = DVec2::from(global_pos);
|
||||
|
||||
let (focus, _) = self.get_mouse_focus(target, hover_window, false);
|
||||
let linear_delta = self.get_mouse_relative(global_pos, hover_window);
|
||||
self.manager
|
||||
.send_mouse_move(focus, global_pos, linear_delta, linear_delta);
|
||||
self.mouse_freeze = Instant::now() + Duration::from_millis(1);
|
||||
self.wm.mouse = Some(window::MouseState {
|
||||
hover_window,
|
||||
pos: global_pos,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_mouse_button(
|
||||
&mut self,
|
||||
target: PointerFocusTarget,
|
||||
global_pos: Vec2,
|
||||
hover_window: window::WindowHandle,
|
||||
index: MouseIndex,
|
||||
pressed: bool,
|
||||
click_freeze: i32,
|
||||
) {
|
||||
if pressed {
|
||||
self.mouse_freeze = Instant::now() + Duration::from_millis(click_freeze.max(0) as u64);
|
||||
}
|
||||
|
||||
let (focus, focus_keyboard) = self.get_mouse_focus(target, hover_window, pressed);
|
||||
|
||||
if focus_keyboard.is_some() {
|
||||
self.manager.seat_keyboard.set_focus(
|
||||
|
|
@ -960,16 +1011,19 @@ impl WvrServerState {
|
|||
focus_keyboard,
|
||||
self.manager.serial_counter.next_serial(),
|
||||
);
|
||||
|
||||
self.wm.keyboard_focus = Some(hover_window);
|
||||
}
|
||||
|
||||
self.manager.send_mouse_move(focus, global_pos);
|
||||
let global_pos = DVec2::from(global_pos);
|
||||
let linear_delta = self.get_mouse_relative(global_pos, hover_window);
|
||||
|
||||
self.manager
|
||||
.send_mouse_move(focus, global_pos, linear_delta, linear_delta);
|
||||
self.wm.mouse = Some(window::MouseState {
|
||||
hover_window,
|
||||
x: global_pos.x.max(0.0) as u32,
|
||||
y: global_pos.y.max(0.0) as u32,
|
||||
pos: global_pos,
|
||||
});
|
||||
|
||||
self.manager.send_pointer_button(index, pressed);
|
||||
}
|
||||
|
||||
|
|
@ -979,13 +1033,13 @@ impl WvrServerState {
|
|||
global_pos: Vec2,
|
||||
delta: WheelDelta,
|
||||
) {
|
||||
let global_pos = DVec2::from(global_pos);
|
||||
self.wm.mouse = Some(window::MouseState {
|
||||
hover_window,
|
||||
x: global_pos.x.max(0.0) as u32,
|
||||
y: global_pos.y.max(0.0) as u32,
|
||||
pos: global_pos,
|
||||
});
|
||||
|
||||
self.manager.send_pointer_axis_wheel(delta);
|
||||
self.manager.send_pointer_axis_wheel_accumulated(delta);
|
||||
}
|
||||
|
||||
pub fn send_key(&mut self, virtual_key: u32, down: bool) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use glam::DVec2;
|
||||
use smithay::utils::{Logical, Size};
|
||||
use smithay::wayland::shell::xdg::ToplevelSurface;
|
||||
use wayvr_ipc::packet_server;
|
||||
|
|
@ -107,14 +108,14 @@ impl Window {
|
|||
#[derive(Debug)]
|
||||
pub struct MouseState {
|
||||
pub hover_window: WindowHandle,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub pos: DVec2,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WindowManager {
|
||||
pub windows: WindowVec,
|
||||
pub mouse: Option<MouseState>,
|
||||
pub keyboard_focus: Option<WindowHandle>,
|
||||
}
|
||||
|
||||
impl WindowManager {
|
||||
|
|
@ -122,6 +123,7 @@ impl WindowManager {
|
|||
Self {
|
||||
windows: WindowVec::new(),
|
||||
mouse: None,
|
||||
keyboard_focus: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ use crate::{
|
|||
backend::{
|
||||
XrBackend,
|
||||
input::{Haptics, HoverResult, PointerHit, PointerMode},
|
||||
task::{OverlayTask, PlayspaceTask, TaskType, ToggleMode},
|
||||
task::{GlobalChange, OverlayTask, PlayspaceTask, TaskType, ToggleMode},
|
||||
wayvr::{
|
||||
process::{KillSignal, ProcessHandle},
|
||||
window::WindowHandle,
|
||||
|
|
@ -532,9 +532,12 @@ impl DashInterface<AppState> for DashInterfaceLive {
|
|||
data.session.config_dirty = true;
|
||||
|
||||
match kind {
|
||||
ConfigChangeKind::OverlayConfig => data
|
||||
.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::SettingsChanged)),
|
||||
ConfigChangeKind::OverlayConfig => {
|
||||
data.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::GlobalChange(
|
||||
GlobalChange::Settings,
|
||||
)))
|
||||
}
|
||||
ConfigChangeKind::EnvironmentBlend => {
|
||||
#[cfg(feature = "openxr")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
KEYMAP_CHANGE,
|
||||
backend::{
|
||||
input::{HoverResult, PointerHit},
|
||||
task::{OverlayTask, TaskType},
|
||||
task::{GlobalChange, OverlayTask, TaskType},
|
||||
},
|
||||
gui::panel::{GuiPanel, overlay_list::OverlayList, set_list::SetList},
|
||||
overlays::keyboard::builder::create_keyboard_panel,
|
||||
|
|
@ -184,7 +184,9 @@ impl KeyboardBackend {
|
|||
self.internal_switch_keymap(new_key);
|
||||
}
|
||||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::KeyboardChanged));
|
||||
.enqueue(TaskType::Overlay(OverlayTask::GlobalChange(
|
||||
GlobalChange::Keyboard,
|
||||
)));
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,24 +4,29 @@ use glam::{Affine2, Affine3A, Quat, Vec3, vec2, vec3};
|
|||
use slotmap::Key;
|
||||
use smithay::{
|
||||
desktop::PopupManager,
|
||||
input::pointer::CursorImageStatus,
|
||||
reexports::wayland_server::Resource,
|
||||
utils::{Logical, Size},
|
||||
wayland::{compositor::with_states, shell::xdg::XdgPopupSurfaceData},
|
||||
wayland::{
|
||||
compositor::with_states,
|
||||
shell::xdg::{XdgPopupSurfaceData, XdgToplevelSurfaceData},
|
||||
},
|
||||
};
|
||||
use vulkano::{
|
||||
buffer::BufferUsage, image::view::ImageView, pipeline::graphics::color_blend::AttachmentBlend,
|
||||
};
|
||||
use wayvr_ipc::packet_client::PositionMode;
|
||||
use wgui::{
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::button::ComponentButton,
|
||||
event::EventCallback,
|
||||
event::{CallbackDataCommon, EventCallback},
|
||||
gfx::{
|
||||
cmd::WGfxClearMode,
|
||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||
},
|
||||
i18n::Translation,
|
||||
parser::Fetchable,
|
||||
widget::{EventResult, label::WidgetLabel},
|
||||
widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
|
||||
};
|
||||
use wlx_capture::frame::{MouseMeta, Transform};
|
||||
use wlx_common::{
|
||||
|
|
@ -35,7 +40,7 @@ use crate::{
|
|||
input::{self, HoverResult},
|
||||
task::{OverlayTask, TaskType},
|
||||
wayvr::{
|
||||
self, PointerFocusTarget, SurfaceBufWithImage,
|
||||
self, PointerFocusTarget, SurfaceBufWithImage, WvrServerState,
|
||||
hit_test::{
|
||||
PopupRoot, RenderedSurface, WvrHitContext, WvrHitTarget,
|
||||
collect_rendered_surface_tree, collect_rendered_surface_tree_at,
|
||||
|
|
@ -65,6 +70,7 @@ use crate::{
|
|||
|
||||
#[derive(Clone)]
|
||||
pub enum WvrCommand {
|
||||
ReloadTitle,
|
||||
CloseWindow,
|
||||
KillProcess(KillSignal),
|
||||
}
|
||||
|
|
@ -154,6 +160,7 @@ pub struct WvrWindowBackend {
|
|||
overlay_id: OverlayID,
|
||||
scale: (f32, f32),
|
||||
resizable: bool,
|
||||
had_focus: bool,
|
||||
}
|
||||
|
||||
impl WvrWindowBackend {
|
||||
|
|
@ -220,20 +227,11 @@ impl WvrWindowBackend {
|
|||
NewGuiPanelParams {
|
||||
resize_to_parent: true,
|
||||
on_custom_attrib: Some(on_custom_attrib),
|
||||
extra_vars: [("title".into(), name.as_ref().into())].into(),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
{
|
||||
let mut title = panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&panel.layout.state, "label_title")?;
|
||||
title.set_text_simple(
|
||||
&mut app.wgui_globals.get(),
|
||||
Translation::from_raw_text(&name),
|
||||
);
|
||||
}
|
||||
|
||||
panel.update_layout(app)?;
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -267,6 +265,7 @@ impl WvrWindowBackend {
|
|||
overlay_id: OverlayID::null(),
|
||||
scale,
|
||||
resizable,
|
||||
had_focus: false,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +348,67 @@ impl WvrWindowBackend {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_title(&mut self, new_title: Rc<str>) {
|
||||
let mut common = CallbackDataCommon {
|
||||
state: &self.panel.layout.state,
|
||||
alterables: &mut self.panel.layout.alterables,
|
||||
};
|
||||
|
||||
if let Ok(mut title) = self
|
||||
.panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&self.panel.layout.state, "title")
|
||||
{
|
||||
title.set_text(&mut common, Translation::from_raw_text_rc(new_title));
|
||||
}
|
||||
}
|
||||
|
||||
fn update_decor(&mut self, wvr_server: &mut WvrServerState) {
|
||||
let now_focused = wvr_server
|
||||
.get_focused_window()
|
||||
.is_some_and(|w| w == self.window);
|
||||
|
||||
if now_focused == self.had_focus {
|
||||
return;
|
||||
}
|
||||
|
||||
self.had_focus = now_focused;
|
||||
|
||||
let mut common = CallbackDataCommon {
|
||||
state: &self.panel.layout.state,
|
||||
alterables: &mut self.panel.layout.alterables,
|
||||
};
|
||||
|
||||
const COLORS: [(WguiColor, WguiColor); 2] = [
|
||||
(
|
||||
WguiColorName::Outline.to_wgui_color(),
|
||||
WguiColorName::OnBackground.to_wgui_color(),
|
||||
),
|
||||
(
|
||||
WguiColorName::Tertiary.to_wgui_color(),
|
||||
WguiColorName::Tertiary.to_wgui_color(),
|
||||
),
|
||||
];
|
||||
|
||||
let (rect_col, label_col) = COLORS[now_focused as usize];
|
||||
|
||||
if let Ok(mut rect) = self
|
||||
.panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetRectangle>(&self.panel.layout.state, "rect")
|
||||
{
|
||||
rect.set_border_color(&mut common, rect_col);
|
||||
}
|
||||
|
||||
if let Ok(mut title) = self
|
||||
.panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&self.panel.layout.state, "title")
|
||||
{
|
||||
title.set_color(&mut common, label_col, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_index_from_mode(mode: input::PointerMode) -> Option<wayvr::MouseIndex> {
|
||||
match mode {
|
||||
input::PointerMode::Left => Some(wayvr::MouseIndex::Left),
|
||||
|
|
@ -468,7 +528,6 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
|
||||
let surface_id = toplevel.wl_surface().id();
|
||||
let surfaces = collect_rendered_surface_tree(toplevel.wl_surface());
|
||||
let should_render_panel = self.panel.should_render(app)?;
|
||||
|
||||
let mut popup_roots = Vec::new();
|
||||
let mut popups = Vec::new();
|
||||
|
|
@ -505,6 +564,8 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
let mut tree_dirty = false;
|
||||
|
||||
if let Some(wvr_server) = app.wvr_server.as_mut() {
|
||||
self.update_decor(wvr_server);
|
||||
|
||||
let state = &mut wvr_server.manager.state;
|
||||
tree_dirty |= state.take_redraw_request(&surface_id);
|
||||
tree_dirty |= state.has_pending_frame_callbacks(&surface_id);
|
||||
|
|
@ -518,6 +579,7 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
}
|
||||
}
|
||||
|
||||
let should_render_panel = self.panel.should_render(app)?;
|
||||
let force_render = tree_dirty || mem::take(&mut self.just_resumed);
|
||||
|
||||
let hit_surfaces = surfaces.clone();
|
||||
|
|
@ -600,8 +662,8 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
.as_ref()
|
||||
.filter(|m| m.hover_window == self.window)
|
||||
.map(|m| MouseMeta {
|
||||
x: (m.x as f32) / (inner_extent[0] as f32),
|
||||
y: (m.y as f32) / (inner_extent[1] as f32),
|
||||
x: (m.pos.x as f32) / (inner_extent[0] as f32),
|
||||
y: (m.pos.y as f32) / (inner_extent[1] as f32),
|
||||
});
|
||||
|
||||
let dirty = self.mouse != mouse || rendered_surfaces_dirty(&self.popups, &popups);
|
||||
|
|
@ -666,13 +728,20 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
callback_surfaces.push(&popup.surface_id);
|
||||
}
|
||||
|
||||
if let Some(mouse) = self.mouse.as_ref() {
|
||||
self.pipeline.as_mut().unwrap().render_mouse(mouse, rdr)?;
|
||||
}
|
||||
|
||||
// frame callbacks for toplevel + subsurf + popup
|
||||
if let Some(wvr_server) = app.wvr_server.as_mut() {
|
||||
let state = &mut wvr_server.manager.state;
|
||||
|
||||
match state.cursor_image {
|
||||
CursorImageStatus::Hidden => {}
|
||||
CursorImageStatus::Named(_) | CursorImageStatus::Surface(_) => {
|
||||
// FIXME: properly render surface?
|
||||
if let Some(mouse) = self.mouse.as_ref() {
|
||||
self.pipeline.as_mut().unwrap().render_mouse(mouse, rdr)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(window) = wvr_server.wm.windows.get(&self.window) {
|
||||
let surface_id = window.toplevel.wl_surface().id();
|
||||
state.send_frame_callbacks_for_surface_id(&surface_id);
|
||||
|
|
@ -703,6 +772,24 @@ impl OverlayBackend for WvrWindowBackend {
|
|||
let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
|
||||
wvr_server.overlay_added(oid, self.window);
|
||||
}
|
||||
OverlayEventData::WvrCommand(WvrCommand::ReloadTitle) => {
|
||||
let wvr_server = app.wvr_server.as_mut().unwrap(); //never None
|
||||
if let Some(window) = wvr_server.wm.windows.get(&self.window) {
|
||||
let title = with_states(window.toplevel.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.title
|
||||
.clone()
|
||||
});
|
||||
if let Some(title) = title {
|
||||
self.update_title(title.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
OverlayEventData::WvrCommand(WvrCommand::CloseWindow) => {
|
||||
app.wvr_server.as_mut().unwrap().close_window(self.window);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,9 +106,15 @@ impl AppState {
|
|||
let session = AppSession::load();
|
||||
let wvr_signals = SyncEventQueue::new();
|
||||
|
||||
let wvr_server = WvrServerState::new(gfx.clone(), &gfx_extras, wvr_signals.clone())
|
||||
.log_err("Could not initialize WayVR Server")
|
||||
.ok();
|
||||
let wvr_server = {
|
||||
let mut maybe_wvr = WvrServerState::new(gfx.clone(), &gfx_extras, wvr_signals.clone())
|
||||
.log_err("Could not initialize WayVR Server")
|
||||
.ok();
|
||||
if let Some(wvr) = maybe_wvr.as_mut() {
|
||||
wvr.config_changed(&session.config);
|
||||
}
|
||||
maybe_wvr
|
||||
};
|
||||
|
||||
let (hid_provider, mut hid_error) = HidWrapper::new(session.config.input_emulation_method);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use wlx_common::{
|
|||
|
||||
use crate::{
|
||||
FRAME_COUNTER,
|
||||
backend::task::{CreateOverlayTask, OverlayTask, SpawnPos, ToggleMode},
|
||||
backend::task::{CreateOverlayTask, GlobalChange, OverlayTask, SpawnPos, ToggleMode},
|
||||
config::save_state,
|
||||
overlays::{
|
||||
anchor::{create_anchor, create_grab_help},
|
||||
|
|
@ -307,7 +307,7 @@ where
|
|||
self.restore_set = 0;
|
||||
self.sets_changed(app);
|
||||
}
|
||||
OverlayTask::SettingsChanged => {
|
||||
OverlayTask::GlobalChange(GlobalChange::Settings) => {
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id)
|
||||
&& app.session.config.enable_watch != watch.config.active_state.is_some()
|
||||
{
|
||||
|
|
@ -326,7 +326,7 @@ where
|
|||
.log_err("Could not notify SettingsChanged");
|
||||
}
|
||||
}
|
||||
OverlayTask::KeyboardChanged => {
|
||||
OverlayTask::GlobalChange(GlobalChange::Keyboard) => {
|
||||
self.overlays_changed(app)?;
|
||||
self.sets_changed(app);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ impl WidgetRectangle {
|
|||
self.params.color = color;
|
||||
common.mark_widget_dirty(self.id);
|
||||
}
|
||||
|
||||
pub fn set_border_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor) {
|
||||
self.params.border_color = color;
|
||||
common.mark_widget_dirty(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetObj for WidgetRectangle {
|
||||
|
|
|
|||
Loading…
Reference in New Issue