window decorations
This commit is contained in:
parent
454b14bf3a
commit
d78c792f05
10 changed files with 174 additions and 54 deletions
|
|
@ -3,7 +3,7 @@
|
|||
//! eg. Usually whenever a user clicks on the app's titlebar and starts dragging, the compositors
|
||||
//! enters a MoveSurfaceGrab state.
|
||||
|
||||
use crate::State;
|
||||
use crate::{render::DecoratedWindow, State};
|
||||
use smithay::{
|
||||
desktop::Window,
|
||||
input::pointer::{
|
||||
|
|
@ -18,7 +18,7 @@ use smithay::{
|
|||
|
||||
pub struct MoveSurfaceGrab {
|
||||
pub start_data: PointerGrabStartData<State>,
|
||||
pub window: Window,
|
||||
pub window: DecoratedWindow,
|
||||
pub initial_window_location: Point<i32, Logical>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,15 +41,15 @@ impl CompositorHandler for State {
|
|||
if let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.filter(|w| w.toplevel().is_some())
|
||||
.find(|w| w.toplevel().unwrap().wl_surface() == &root)
|
||||
.filter(|w| w.window.toplevel().is_some())
|
||||
.find(|w| w.window.toplevel().unwrap().wl_surface() == &root)
|
||||
{
|
||||
window.on_commit();
|
||||
window.window.on_commit();
|
||||
}
|
||||
};
|
||||
|
||||
xdg_shell::handle_commit(&mut self.popups, &self.space, surface);
|
||||
resize_grab::handle_commit(&mut self.space, surface);
|
||||
// xdg_shell::handle_commit(&mut self.popups, &self.space, surface);
|
||||
// resize_grab::handle_commit(&mut self.space, surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl XdgActivationHandler for State {
|
|||
|
||||
{
|
||||
for element in self.space.elements() {
|
||||
match element.underlying_surface() {
|
||||
match element.window.underlying_surface() {
|
||||
WindowSurface::Wayland(wl) => {
|
||||
if *wl.wl_surface() == surface {
|
||||
raised_element = Some(element);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1
|
|||
impl XdgDecorationHandler for State {
|
||||
fn new_decoration(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(Mode::ClientSide);
|
||||
// state.decoration_mode = Some(Mode::ServerSide);
|
||||
// state.decoration_mode = Some(Mode::ClientSide);
|
||||
state.decoration_mode = Some(Mode::ServerSide);
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
|
|
@ -17,16 +17,16 @@ impl XdgDecorationHandler for State {
|
|||
mode: Mode,
|
||||
) {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(Mode::ClientSide);
|
||||
// state.decoration_mode = Some(mode);
|
||||
// state.decoration_mode = Some(Mode::ClientSide);
|
||||
state.decoration_mode = Some(mode);
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
|
||||
fn unset_mode(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(Mode::ClientSide);
|
||||
// state.decoration_mode = Some(Mode::ServerSide);
|
||||
// state.decoration_mode = Some(Mode::ClientSide);
|
||||
state.decoration_mode = Some(Mode::ServerSide);
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use smithay::{
|
|||
|
||||
use crate::{
|
||||
grabs::{MoveSurfaceGrab, ResizeSurfaceGrab},
|
||||
render::DecoratedWindow,
|
||||
state::State,
|
||||
};
|
||||
|
||||
|
|
@ -35,7 +36,8 @@ impl XdgShellHandler for State {
|
|||
|
||||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
let window = Window::new_wayland_window(surface);
|
||||
self.space.map_element(window, (0, 0), false);
|
||||
self.space
|
||||
.map_element(DecoratedWindow::new(window), (0, 0), false);
|
||||
}
|
||||
|
||||
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||
|
|
@ -69,15 +71,15 @@ impl XdgShellHandler for State {
|
|||
let window = self
|
||||
.space
|
||||
.elements()
|
||||
.filter(|w| w.toplevel().is_some())
|
||||
.find(|w| w.toplevel().unwrap().wl_surface() == wl_surface)
|
||||
.filter(|w| w.window.toplevel().is_some())
|
||||
.find(|w| w.window.toplevel().unwrap().wl_surface() == wl_surface)
|
||||
.unwrap()
|
||||
.clone();
|
||||
let initial_window_location = self.space.element_location(&window).unwrap();
|
||||
|
||||
let grab = MoveSurfaceGrab {
|
||||
start_data,
|
||||
window,
|
||||
window: window.clone(),
|
||||
initial_window_location,
|
||||
};
|
||||
|
||||
|
|
@ -102,12 +104,12 @@ impl XdgShellHandler for State {
|
|||
let window = self
|
||||
.space
|
||||
.elements()
|
||||
.filter(|w| w.toplevel().is_some())
|
||||
.find(|w| w.toplevel().unwrap().wl_surface() == wl_surface)
|
||||
.filter(|w| w.window.toplevel().is_some())
|
||||
.find(|w| w.window.toplevel().unwrap().wl_surface() == wl_surface)
|
||||
.unwrap()
|
||||
.clone();
|
||||
let initial_window_location = self.space.element_location(&window).unwrap();
|
||||
let initial_window_size = window.geometry().size;
|
||||
let initial_window_size = window.window.geometry().size;
|
||||
|
||||
surface.with_pending_state(|state| {
|
||||
state.states.set(xdg_toplevel::State::Resizing);
|
||||
|
|
@ -117,7 +119,7 @@ impl XdgShellHandler for State {
|
|||
|
||||
let grab = ResizeSurfaceGrab::start(
|
||||
start_data,
|
||||
window,
|
||||
window.window.clone(),
|
||||
edges.into(),
|
||||
Rectangle::new(initial_window_location, initial_window_size),
|
||||
);
|
||||
|
|
@ -202,8 +204,8 @@ impl State {
|
|||
let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.filter(|w| w.toplevel().is_some())
|
||||
.find(|w| w.toplevel().unwrap().wl_surface() == &root)
|
||||
.filter(|w| w.window.toplevel().is_some())
|
||||
.find(|w| w.window.toplevel().unwrap().wl_surface() == &root)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
27
src/input.rs
27
src/input.rs
|
|
@ -65,29 +65,32 @@ impl State {
|
|||
let button_state = event.state();
|
||||
|
||||
if ButtonState::Pressed == button_state && !pointer.is_grabbed() {
|
||||
let mut actv_window = None;
|
||||
if let Some((window, _loc)) = self
|
||||
.space
|
||||
.element_under(pointer.current_location())
|
||||
.map(|(w, l)| (w.clone(), l))
|
||||
{
|
||||
self.space.raise_element(&window, true);
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
if let Some(toplevel) = window.window.toplevel() {
|
||||
keyboard.set_focus(self, Some(toplevel.wl_surface().clone()), serial);
|
||||
}
|
||||
self.space.elements().for_each(|window| {
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
});
|
||||
actv_window = Some(window.clone());
|
||||
} else {
|
||||
self.space.elements().for_each(|window| {
|
||||
window.set_activated(false);
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
});
|
||||
keyboard.set_focus(self, Option::<WlSurface>::None, serial);
|
||||
}
|
||||
|
||||
self.space.elements().for_each(|window| {
|
||||
window.window.set_activated(false);
|
||||
if let Some(actv_window) = actv_window.as_ref() {
|
||||
if actv_window.window == window.window {
|
||||
window.window.set_activated(true);
|
||||
}
|
||||
}
|
||||
if let Some(toplevel) = window.window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
pointer.button(
|
||||
|
|
|
|||
128
src/render.rs
128
src/render.rs
|
|
@ -3,21 +3,137 @@ use smithay::{
|
|||
damage::OutputDamageTracker,
|
||||
element::{
|
||||
memory::MemoryRenderBufferRenderElement, solid::SolidColorRenderElement,
|
||||
surface::WaylandSurfaceRenderElement,
|
||||
surface::WaylandSurfaceRenderElement, AsRenderElements, Id, Kind,
|
||||
},
|
||||
gles::{GlesRenderer, GlesTarget},
|
||||
ImportMem,
|
||||
utils::CommitCounter,
|
||||
Color32F, ImportAll, ImportDmaWl, ImportMem, ImportMemWl, Renderer, RendererSuper,
|
||||
},
|
||||
desktop::{space::SpaceElement, Window},
|
||||
output::Output,
|
||||
render_elements,
|
||||
utils::{IsAlive, Physical, Point, Scale},
|
||||
};
|
||||
use wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode;
|
||||
|
||||
use crate::State;
|
||||
|
||||
render_elements! {
|
||||
DecorationElement<R> where R: ImportMem;
|
||||
Chrome=SolidColorRenderElement,
|
||||
Label=MemoryRenderBufferRenderElement<R>,
|
||||
pub OutputElement<R> where R: ImportMem + ImportDmaWl + ImportMemWl;
|
||||
Window=WaylandSurfaceRenderElement<R>,
|
||||
Background=SolidColorRenderElement,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct DecoratedWindow {
|
||||
pub window: Window,
|
||||
}
|
||||
|
||||
impl DecoratedWindow {
|
||||
pub fn new(window: Window) -> Self {
|
||||
Self { window }
|
||||
}
|
||||
|
||||
fn decorated(&self) -> bool {
|
||||
let mut b = false;
|
||||
if let Some(toplevel) = self.window.toplevel() {
|
||||
toplevel.with_pending_state(|f| {
|
||||
if let Some(decor) = f.decoration_mode {
|
||||
b = decor == Mode::ServerSide;
|
||||
}
|
||||
});
|
||||
}
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
impl SpaceElement for DecoratedWindow {
|
||||
fn bbox(&self) -> smithay::utils::Rectangle<i32, smithay::utils::Logical> {
|
||||
let mut bbox = self.window.bbox();
|
||||
|
||||
if self.decorated() {
|
||||
bbox.loc.x -= 5;
|
||||
bbox.loc.y -= 22;
|
||||
}
|
||||
|
||||
bbox
|
||||
}
|
||||
|
||||
fn is_in_input_region(
|
||||
&self,
|
||||
point: &smithay::utils::Point<f64, smithay::utils::Logical>,
|
||||
) -> bool {
|
||||
self.window.is_in_input_region(point)
|
||||
}
|
||||
|
||||
fn set_activate(&self, activated: bool) {
|
||||
self.window.set_activate(activated)
|
||||
}
|
||||
|
||||
fn output_enter(
|
||||
&self,
|
||||
output: &Output,
|
||||
overlap: smithay::utils::Rectangle<i32, smithay::utils::Logical>,
|
||||
) {
|
||||
self.window.output_enter(output, overlap)
|
||||
}
|
||||
|
||||
fn output_leave(&self, output: &Output) {
|
||||
self.window.output_leave(output)
|
||||
}
|
||||
}
|
||||
|
||||
impl IsAlive for DecoratedWindow {
|
||||
fn alive(&self) -> bool {
|
||||
self.window.alive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> AsRenderElements<R> for DecoratedWindow
|
||||
where
|
||||
R: Renderer + ImportDmaWl + ImportMemWl + ImportMem + ImportAll,
|
||||
<R as RendererSuper>::TextureId: Clone + Send + 'static,
|
||||
{
|
||||
type RenderElement = OutputElement<R>; // one enum, both variants
|
||||
|
||||
fn render_elements<C: From<Self::RenderElement>>(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
location: Point<i32, Physical>,
|
||||
scale: Scale<f64>,
|
||||
alpha: f32,
|
||||
) -> Vec<C> {
|
||||
let mut elements: Vec<C> = Vec::new();
|
||||
|
||||
/* Start with actual window elements */
|
||||
elements.extend(
|
||||
self.window
|
||||
.render_elements::<OutputElement<R>>(renderer, location, scale, alpha)
|
||||
.into_iter()
|
||||
.map(C::from),
|
||||
);
|
||||
|
||||
/* If the window is decorated, push a solid color */
|
||||
let decorated = self.decorated();
|
||||
if decorated {
|
||||
let mut bg_rect = self.window.geometry().to_physical_precise_round(scale);
|
||||
|
||||
bg_rect.size.w += 10;
|
||||
bg_rect.size.h += 27;
|
||||
|
||||
let background = SolidColorRenderElement::new(
|
||||
Id::new(),
|
||||
bg_rect,
|
||||
CommitCounter::default(),
|
||||
Color32F::new(1.0, 0.75, 0.26, 1.0),
|
||||
Kind::Unspecified,
|
||||
);
|
||||
|
||||
elements.push(C::from(OutputElement::Background(background)));
|
||||
}
|
||||
|
||||
elements
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
@ -30,7 +146,7 @@ impl State {
|
|||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let elem = DecorationElement::
|
||||
|
||||
smithay::desktop::space::render_output::<_, WaylandSurfaceRenderElement<GlesRenderer>, _, _>(
|
||||
smithay::desktop::space::render_output::<_, OutputElement<GlesRenderer>, _, _>(
|
||||
output,
|
||||
renderer,
|
||||
framebuffer,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::audio::SystemAudioPlayer;
|
||||
use crate::{audio::SystemAudioPlayer, render::DecoratedWindow};
|
||||
use std::{ffi::OsString, sync::Arc};
|
||||
|
||||
use smithay::{
|
||||
|
|
@ -35,7 +35,7 @@ pub struct State {
|
|||
pub socket_name: OsString,
|
||||
pub display_handle: DisplayHandle,
|
||||
|
||||
pub space: Space<Window>,
|
||||
pub space: Space<DecoratedWindow>,
|
||||
pub handle: LoopHandle<'static, Self>,
|
||||
pub popups: PopupManager,
|
||||
pub seat: Seat<Self>,
|
||||
|
|
@ -213,6 +213,7 @@ impl State {
|
|||
.element_under(pos)
|
||||
.and_then(|(window, location)| {
|
||||
window
|
||||
.window
|
||||
.surface_under(pos - location.to_f64(), WindowSurfaceType::ALL)
|
||||
.map(|(s, p)| (s, (p + location).to_f64()))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ use std::time::Duration;
|
|||
|
||||
use smithay::{
|
||||
backend::{
|
||||
renderer::{
|
||||
damage::OutputDamageTracker, element::surface::WaylandSurfaceRenderElement,
|
||||
gles::GlesRenderer,
|
||||
},
|
||||
renderer::damage::OutputDamageTracker,
|
||||
winit::{self, WinitEvent},
|
||||
},
|
||||
output::{Mode, Output, PhysicalProperties, Subpixel},
|
||||
|
|
@ -72,7 +69,7 @@ pub fn init_winit(state: &mut State) -> Result<(), Box<dyn std::error::Error>> {
|
|||
backend.submit(Some(&[damage])).unwrap();
|
||||
|
||||
state.space.elements().for_each(|window| {
|
||||
window.send_frame(
|
||||
window.window.send_frame(
|
||||
&output,
|
||||
state.start_time.elapsed(),
|
||||
Some(Duration::ZERO),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use smithay::{
|
|||
};
|
||||
use wayland_server::{Display, DisplayHandle};
|
||||
|
||||
use crate::state::State;
|
||||
use crate::{state::State, render::DecoratedWindow};
|
||||
|
||||
pub struct XWaylandState {
|
||||
pub xwm: Option<X11Wm>,
|
||||
|
|
@ -31,10 +31,11 @@ impl XwmHandler for State {
|
|||
// grant it — the window will be mapped once you set this
|
||||
window.set_mapped(true).unwrap();
|
||||
|
||||
self.space
|
||||
.map_element(Window::new_x11_window(window.clone()), (0, 0), true);
|
||||
|
||||
// insert it into your Space/window management here
|
||||
self.space.map_element(
|
||||
DecoratedWindow::new(Window::new_x11_window(window.clone())),
|
||||
(0, 0),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue