mirror of https://github.com/wayvr-org/wayvr.git
wvr_server: constrain popups to output bounds
This commit is contained in:
parent
ea6a6dc6e7
commit
e378749619
|
|
@ -3,7 +3,7 @@ use smithay::backend::allocator::dmabuf::Dmabuf;
|
|||
use smithay::backend::renderer::{BufferType, buffer_type};
|
||||
use smithay::desktop::{
|
||||
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy,
|
||||
find_popup_root_surface,
|
||||
find_popup_root_surface, get_popup_toplevel_coords,
|
||||
};
|
||||
use smithay::input::pointer::Focus;
|
||||
use smithay::input::{Seat, SeatHandler, SeatState};
|
||||
|
|
@ -16,12 +16,19 @@ use smithay::reexports::wayland_server::Resource;
|
|||
use smithay::reexports::wayland_server::backend::ObjectId;
|
||||
use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_callback, wl_output, wl_seat};
|
||||
use smithay::reexports::wayland_server::{self, DisplayHandle};
|
||||
use smithay::utils::{Logical, Rectangle, Serial, Size};
|
||||
use smithay::wayland::buffer::BufferHandler;
|
||||
use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes, send_surface_state};
|
||||
use smithay::wayland::dmabuf::{
|
||||
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf,
|
||||
};
|
||||
use smithay::wayland::fractional_scale::with_fractional_scale;
|
||||
use smithay::wayland::output::OutputHandler;
|
||||
use smithay::wayland::selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
set_data_device_focus, set_data_device_selection,
|
||||
};
|
||||
use smithay::wayland::selection::{self, SelectionHandler};
|
||||
use smithay::wayland::selection::{
|
||||
ext_data_control as selection_ext,
|
||||
primary_selection::{PrimarySelectionHandler, PrimarySelectionState, set_primary_focus},
|
||||
|
|
@ -29,6 +36,9 @@ use smithay::wayland::selection::{
|
|||
};
|
||||
use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState};
|
||||
use smithay::wayland::shell::xdg::decoration::{XdgDecorationHandler, XdgDecorationState};
|
||||
use smithay::wayland::shell::xdg::{
|
||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||
};
|
||||
use smithay::wayland::shm::{ShmHandler, ShmState, with_buffer_contents};
|
||||
use smithay::wayland::single_pixel_buffer::get_single_pixel_buffer;
|
||||
use smithay::wayland::viewporter::ViewporterState;
|
||||
|
|
@ -43,24 +53,13 @@ use std::fs::File;
|
|||
use std::io::Write;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use smithay::utils::Serial;
|
||||
use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes, send_surface_state};
|
||||
|
||||
use smithay::wayland::selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
set_data_device_focus, set_data_device_selection,
|
||||
};
|
||||
use smithay::wayland::selection::{self, SelectionHandler};
|
||||
use smithay::wayland::shell::xdg::{
|
||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||
};
|
||||
use wayland_server::Client;
|
||||
use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
|
||||
use wayland_server::protocol::wl_surface::WlSurface;
|
||||
|
||||
use crate::backend::wayvr::image_importer::ImageImporter;
|
||||
use crate::backend::wayvr::{SurfaceBufWithImage, time};
|
||||
use crate::backend::wayvr::{SurfaceBufWithImage, WAYVR_SCREEN_RES, time};
|
||||
use crate::graphics::ExtentExt;
|
||||
use crate::ipc::event_queue::SyncEventQueue;
|
||||
|
||||
use super::WayVRTask;
|
||||
|
|
@ -168,6 +167,46 @@ impl Application {
|
|||
pub fn take_redraw_request(&mut self, surface_id: &ObjectId) -> bool {
|
||||
self.redraw_requests.remove(surface_id)
|
||||
}
|
||||
|
||||
fn output_logical_size(&self) -> Size<i32, Logical> {
|
||||
self.output
|
||||
.current_mode()
|
||||
.map(|mode| Size::new(mode.size.w, mode.size.h))
|
||||
.unwrap_or_else(|| Size::new(WAYVR_SCREEN_RES[0], WAYVR_SCREEN_RES[1]))
|
||||
}
|
||||
|
||||
fn surface_logical_size(surface: &WlSurface) -> Option<Size<i32, Logical>> {
|
||||
smithay::wayland::compositor::with_states(surface, |states| {
|
||||
SurfaceBufWithImage::get_from_surface(states).map(|buf| {
|
||||
let extent = buf.image.extent_u32arr();
|
||||
let scale = buf.scale.max(1) as u32;
|
||||
|
||||
Size::new((extent[0] / scale) as i32, (extent[1] / scale) as i32)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn constrain_popup(&self, popup: &PopupSurface) {
|
||||
let popup_kind = PopupKind::Xdg(popup.clone());
|
||||
|
||||
let Ok(root_surface) = find_popup_root_surface(&popup_kind) else {
|
||||
log::warn!(
|
||||
"constrain_popup: could not find popup root surface {:?}",
|
||||
popup.wl_surface().id()
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let root_size =
|
||||
Self::surface_logical_size(&root_surface).unwrap_or_else(|| self.output_logical_size());
|
||||
|
||||
let mut target = Rectangle::from_size(root_size);
|
||||
target.loc -= get_popup_toplevel_coords(&popup_kind);
|
||||
|
||||
popup.with_pending_state(|state| {
|
||||
state.geometry = state.positioner.get_unconstrained_geometry(target);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl compositor::CompositorHandler for Application {
|
||||
|
|
@ -398,6 +437,8 @@ impl XdgShellHandler for Application {
|
|||
}
|
||||
|
||||
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||
self.constrain_popup(&surface);
|
||||
|
||||
let _ = self
|
||||
.popup_manager
|
||||
.track_popup(PopupKind::Xdg(surface))
|
||||
|
|
@ -466,11 +507,17 @@ impl XdgShellHandler for Application {
|
|||
|
||||
fn reposition_request(
|
||||
&mut self,
|
||||
_surface: PopupSurface,
|
||||
_positioner: PositionerState,
|
||||
_token: u32,
|
||||
surface: PopupSurface,
|
||||
positioner: PositionerState,
|
||||
token: u32,
|
||||
) {
|
||||
// Handle popup reposition here
|
||||
surface.with_pending_state(|state| {
|
||||
state.geometry = positioner.get_geometry();
|
||||
state.positioner = positioner;
|
||||
});
|
||||
|
||||
self.constrain_popup(&surface);
|
||||
surface.send_repositioned(token);
|
||||
}
|
||||
|
||||
// If the app wants to be fullscreen, make it think that it's fullscreen.
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ pub enum TickTask {
|
|||
|
||||
const KEY_REPEAT_DELAY: i32 = 200;
|
||||
const KEY_REPEAT_RATE: i32 = 50;
|
||||
const WAYVR_SCREEN_RES: [i32; 2] = [2560, 1440];
|
||||
|
||||
impl WvrServerState {
|
||||
pub fn new(
|
||||
|
|
@ -191,7 +192,7 @@ impl WvrServerState {
|
|||
|
||||
let mode = Mode {
|
||||
refresh: dummy_milli_hz,
|
||||
size: (2560, 1440).into(), //logical size in pixels
|
||||
size: (WAYVR_SCREEN_RES[0], WAYVR_SCREEN_RES[1]).into(), //logical size in pixels
|
||||
};
|
||||
|
||||
let _global = output.create_global::<Application>(&dh);
|
||||
|
|
|
|||
Loading…
Reference in New Issue