wayland: Implement cursor-shape-v1
This commit is contained in:
parent
79ae56c601
commit
0ffe6ae718
9 changed files with 92 additions and 161 deletions
|
|
@ -14,7 +14,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
input::{
|
input::{
|
||||||
pointer::{CursorImageAttributes, CursorImageStatus},
|
pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus},
|
||||||
Seat,
|
Seat,
|
||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::wl_surface,
|
reexports::wayland_server::protocol::wl_surface,
|
||||||
|
|
@ -24,7 +24,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
wayland::compositor::{get_role, with_states},
|
wayland::compositor::{get_role, with_states},
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, io::Read, sync::Mutex, time::Duration};
|
use std::{collections::HashMap, io::Read, sync::Mutex};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use xcursor::{
|
use xcursor::{
|
||||||
parser::{parse_xcursor, Image},
|
parser::{parse_xcursor, Image},
|
||||||
|
|
@ -33,42 +33,6 @@ use xcursor::{
|
||||||
|
|
||||||
static FALLBACK_CURSOR_DATA: &[u8] = include_bytes!("../../../resources/cursor.rgba");
|
static FALLBACK_CURSOR_DATA: &[u8] = include_bytes!("../../../resources/cursor.rgba");
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub enum CursorShape {
|
|
||||||
Default,
|
|
||||||
ColResize,
|
|
||||||
RowResize,
|
|
||||||
Grab,
|
|
||||||
EastResize,
|
|
||||||
WestResize,
|
|
||||||
NorthResize,
|
|
||||||
SouthResize,
|
|
||||||
NorthEastResize,
|
|
||||||
NorthWestResize,
|
|
||||||
SouthEastResize,
|
|
||||||
SouthWestResize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for CursorShape {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
match self {
|
|
||||||
CursorShape::Default => "default",
|
|
||||||
CursorShape::ColResize => "col-resize",
|
|
||||||
CursorShape::RowResize => "row-resize",
|
|
||||||
CursorShape::Grab => "grabbing",
|
|
||||||
CursorShape::EastResize => "e-resize",
|
|
||||||
CursorShape::WestResize => "w-resize",
|
|
||||||
CursorShape::NorthResize => "n-resize",
|
|
||||||
CursorShape::SouthResize => "s-resize",
|
|
||||||
CursorShape::NorthEastResize => "ne-resize",
|
|
||||||
CursorShape::NorthWestResize => "nw-resize",
|
|
||||||
CursorShape::SouthEastResize => "se-resize",
|
|
||||||
CursorShape::SouthWestResize => "sw-resize",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Cursor {
|
pub struct Cursor {
|
||||||
icons: Vec<Image>,
|
icons: Vec<Image>,
|
||||||
|
|
@ -76,9 +40,10 @@ pub struct Cursor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor {
|
impl Cursor {
|
||||||
pub fn load(theme: &CursorTheme, shape: CursorShape, size: u32) -> Cursor {
|
pub fn load(theme: &CursorTheme, shape: CursorIcon, size: u32) -> Cursor {
|
||||||
let icons = load_icon(&theme, shape)
|
let icons = load_icon(theme, shape)
|
||||||
.map_err(|err| warn!(?err, "Unable to load xcursor, using fallback cursor"))
|
.map_err(|err| warn!(?err, "Unable to load xcursor, using fallback cursor"))
|
||||||
|
.or_else(|_| load_icon(theme, CursorIcon::Default))
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
vec![Image {
|
vec![Image {
|
||||||
size: 32,
|
size: 32,
|
||||||
|
|
@ -105,7 +70,7 @@ fn nearest_images(size: u32, images: &[Image]) -> impl Iterator<Item = &Image> {
|
||||||
// Follow the nominal size of the cursor to choose the nearest
|
// Follow the nominal size of the cursor to choose the nearest
|
||||||
let nearest_image = images
|
let nearest_image = images
|
||||||
.iter()
|
.iter()
|
||||||
.min_by_key(|image| (size as i32 - image.size as i32).abs())
|
.min_by_key(|image| u32::abs_diff(size, image.size))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
images.iter().filter(move |image| {
|
images.iter().filter(move |image| {
|
||||||
|
|
@ -142,7 +107,7 @@ enum Error {
|
||||||
Parse,
|
Parse,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_icon(theme: &CursorTheme, shape: CursorShape) -> Result<Vec<Image>, Error> {
|
fn load_icon(theme: &CursorTheme, shape: CursorIcon) -> Result<Vec<Image>, Error> {
|
||||||
let icon_path = theme
|
let icon_path = theme
|
||||||
.load_icon(&shape.to_string())
|
.load_icon(&shape.to_string())
|
||||||
.ok_or(Error::NoDefaultCursor)?;
|
.ok_or(Error::NoDefaultCursor)?;
|
||||||
|
|
@ -228,15 +193,29 @@ where
|
||||||
|
|
||||||
pub type CursorState = Mutex<CursorStateInner>;
|
pub type CursorState = Mutex<CursorStateInner>;
|
||||||
pub struct CursorStateInner {
|
pub struct CursorStateInner {
|
||||||
current_cursor: CursorShape,
|
current_cursor: Option<CursorIcon>,
|
||||||
pub cursors: HashMap<CursorShape, Cursor>,
|
|
||||||
|
cursor_theme: CursorTheme,
|
||||||
|
cursor_size: u32,
|
||||||
|
|
||||||
|
cursors: HashMap<CursorIcon, Cursor>,
|
||||||
current_image: Option<Image>,
|
current_image: Option<Image>,
|
||||||
image_cache: Vec<(Image, MemoryRenderBuffer)>,
|
image_cache: Vec<(Image, MemoryRenderBuffer)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CursorStateInner {
|
impl CursorStateInner {
|
||||||
pub fn set_shape(&mut self, shape: CursorShape) {
|
pub fn set_shape(&mut self, shape: CursorIcon) {
|
||||||
self.current_cursor = shape;
|
self.current_cursor = Some(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unset_shape(&mut self) {
|
||||||
|
self.current_cursor = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_named_cursor(&mut self, shape: CursorIcon) -> &Cursor {
|
||||||
|
self.cursors
|
||||||
|
.entry(shape)
|
||||||
|
.or_insert_with(|| Cursor::load(&self.cursor_theme, shape, self.cursor_size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,59 +234,12 @@ impl Default for CursorStateInner {
|
||||||
fn default() -> CursorStateInner {
|
fn default() -> CursorStateInner {
|
||||||
let (theme, size) = load_cursor_theme();
|
let (theme, size) = load_cursor_theme();
|
||||||
CursorStateInner {
|
CursorStateInner {
|
||||||
current_cursor: CursorShape::Default,
|
current_cursor: None,
|
||||||
cursors: {
|
|
||||||
let mut map = HashMap::new();
|
cursor_size: size,
|
||||||
map.insert(
|
cursor_theme: theme,
|
||||||
CursorShape::Default,
|
|
||||||
Cursor::load(&theme, CursorShape::Default, size),
|
cursors: HashMap::new(),
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::ColResize,
|
|
||||||
Cursor::load(&theme, CursorShape::ColResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::RowResize,
|
|
||||||
Cursor::load(&theme, CursorShape::RowResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::Grab,
|
|
||||||
Cursor::load(&theme, CursorShape::Grab, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::NorthResize,
|
|
||||||
Cursor::load(&theme, CursorShape::NorthResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::SouthResize,
|
|
||||||
Cursor::load(&theme, CursorShape::SouthResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::EastResize,
|
|
||||||
Cursor::load(&theme, CursorShape::EastResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::WestResize,
|
|
||||||
Cursor::load(&theme, CursorShape::WestResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::NorthEastResize,
|
|
||||||
Cursor::load(&theme, CursorShape::NorthEastResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::SouthEastResize,
|
|
||||||
Cursor::load(&theme, CursorShape::SouthEastResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::NorthWestResize,
|
|
||||||
Cursor::load(&theme, CursorShape::NorthWestResize, size),
|
|
||||||
);
|
|
||||||
map.insert(
|
|
||||||
CursorShape::SouthWestResize,
|
|
||||||
Cursor::load(&theme, CursorShape::SouthWestResize, size),
|
|
||||||
);
|
|
||||||
map
|
|
||||||
},
|
|
||||||
current_image: None,
|
current_image: None,
|
||||||
image_cache: Vec::new(),
|
image_cache: Vec::new(),
|
||||||
}
|
}
|
||||||
|
|
@ -343,19 +275,23 @@ where
|
||||||
})
|
})
|
||||||
.unwrap_or(CursorImageStatus::default_named());
|
.unwrap_or(CursorImageStatus::default_named());
|
||||||
|
|
||||||
if let CursorImageStatus::Surface(ref wl_surface) = cursor_status {
|
let seat_userdata = seat.user_data();
|
||||||
return draw_surface_cursor(renderer, wl_surface, location.to_i32_round(), scale);
|
let mut state_ref = seat_userdata.get::<CursorState>().unwrap().lock().unwrap();
|
||||||
// TODO: Handle other named cursors
|
let state = &mut *state_ref;
|
||||||
} else if draw_default && CursorImageStatus::default_named() == cursor_status {
|
|
||||||
let integer_scale = scale.x.max(scale.y).ceil() as u32;
|
|
||||||
|
|
||||||
let seat_userdata = seat.user_data();
|
let named_cursor = state.current_cursor.or(match cursor_status {
|
||||||
let mut state_ref = seat_userdata.get::<CursorState>().unwrap().lock().unwrap();
|
CursorImageStatus::Named(named_cursor) => Some(named_cursor),
|
||||||
let state = &mut *state_ref;
|
_ => None,
|
||||||
let frame = state.cursors.get(&state.current_cursor).unwrap().get_image(
|
});
|
||||||
integer_scale,
|
if let Some(current_cursor) = named_cursor {
|
||||||
Into::<Duration>::into(time).as_millis() as u32,
|
if !draw_default && current_cursor == CursorIcon::Default {
|
||||||
);
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let integer_scale = scale.x.max(scale.y).ceil() as u32;
|
||||||
|
let frame = state
|
||||||
|
.get_named_cursor(current_cursor)
|
||||||
|
.get_image(integer_scale, time.as_millis());
|
||||||
|
|
||||||
let pointer_images = &mut state.image_cache;
|
let pointer_images = &mut state.image_cache;
|
||||||
let maybe_image =
|
let maybe_image =
|
||||||
|
|
@ -396,6 +332,8 @@ where
|
||||||
),
|
),
|
||||||
hotspot,
|
hotspot,
|
||||||
)];
|
)];
|
||||||
|
} else if let CursorImageStatus::Surface(ref wl_surface) = cursor_status {
|
||||||
|
return draw_surface_cursor(renderer, wl_surface, location.to_i32_round(), scale);
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface};
|
use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::{
|
backend::render::{cursor::CursorState, SplitRenderElements},
|
||||||
cursor::{CursorShape, CursorState},
|
|
||||||
SplitRenderElements,
|
|
||||||
},
|
|
||||||
shell::{
|
shell::{
|
||||||
focus::target::PointerFocusTarget,
|
focus::target::PointerFocusTarget,
|
||||||
grabs::{ReleaseMode, ResizeEdge},
|
grabs::{ReleaseMode, ResizeEdge},
|
||||||
|
|
@ -1331,7 +1328,7 @@ impl PointerTarget<State> for CosmicStack {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
cursor_state.set_shape(CursorShape::Default);
|
cursor_state.unset_shape();
|
||||||
let _previous = p.swap_focus(None);
|
let _previous = p.swap_focus(None);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::{
|
backend::render::{cursor::CursorState, SplitRenderElements},
|
||||||
cursor::{CursorShape, CursorState},
|
|
||||||
SplitRenderElements,
|
|
||||||
},
|
|
||||||
shell::{
|
shell::{
|
||||||
focus::target::PointerFocusTarget,
|
focus::target::PointerFocusTarget,
|
||||||
grabs::{ReleaseMode, ResizeEdge},
|
grabs::{ReleaseMode, ResizeEdge},
|
||||||
|
|
@ -35,10 +32,10 @@ use smithay::{
|
||||||
input::{
|
input::{
|
||||||
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
|
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent,
|
AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent,
|
||||||
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
|
||||||
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
|
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent,
|
||||||
PointerTarget, RelativeMotionEvent,
|
GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent,
|
||||||
},
|
},
|
||||||
touch::{
|
touch::{
|
||||||
DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget,
|
DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget,
|
||||||
|
|
@ -146,17 +143,17 @@ impl Focus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor_shape(&self) -> CursorShape {
|
pub fn cursor_shape(&self) -> CursorIcon {
|
||||||
match self {
|
match self {
|
||||||
Focus::ResizeTopLeft => CursorShape::NorthWestResize,
|
Focus::ResizeTopLeft => CursorIcon::NwResize,
|
||||||
Focus::ResizeTopRight => CursorShape::NorthEastResize,
|
Focus::ResizeTopRight => CursorIcon::NeResize,
|
||||||
Focus::ResizeTop => CursorShape::NorthResize,
|
Focus::ResizeTop => CursorIcon::NResize,
|
||||||
Focus::ResizeBottomLeft => CursorShape::SouthWestResize,
|
Focus::ResizeBottomLeft => CursorIcon::SwResize,
|
||||||
Focus::ResizeBottomRight => CursorShape::SouthEastResize,
|
Focus::ResizeBottomRight => CursorIcon::SeResize,
|
||||||
Focus::ResizeBottom => CursorShape::SouthResize,
|
Focus::ResizeBottom => CursorIcon::SResize,
|
||||||
Focus::ResizeLeft => CursorShape::WestResize,
|
Focus::ResizeLeft => CursorIcon::WResize,
|
||||||
Focus::ResizeRight => CursorShape::EastResize,
|
Focus::ResizeRight => CursorIcon::EResize,
|
||||||
Focus::Header => CursorShape::Default,
|
Focus::Header => CursorIcon::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -754,7 +751,7 @@ impl PointerTarget<State> for CosmicWindow {
|
||||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||||
self.0.with_program(|p| {
|
self.0.with_program(|p| {
|
||||||
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
||||||
cursor_state.lock().unwrap().set_shape(CursorShape::Default);
|
cursor_state.lock().unwrap().unset_shape();
|
||||||
let _previous = p.swap_focus(None);
|
let _previous = p.swap_focus(None);
|
||||||
});
|
});
|
||||||
PointerTarget::leave(&self.0, seat, data, serial, time)
|
PointerTarget::leave(&self.0, seat, data, serial, time)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::{
|
backend::render::{
|
||||||
cursor::{CursorShape, CursorState},
|
cursor::CursorState, element::AsGlowRenderer, BackdropShader, IndicatorShader, Key,
|
||||||
element::AsGlowRenderer,
|
SplitRenderElements, Usage,
|
||||||
BackdropShader, IndicatorShader, Key, SplitRenderElements, Usage,
|
|
||||||
},
|
},
|
||||||
shell::{
|
shell::{
|
||||||
element::{
|
element::{
|
||||||
|
|
@ -32,7 +31,7 @@ use smithay::{
|
||||||
desktop::{layer_map_for_output, space::SpaceElement},
|
desktop::{layer_map_for_output, space::SpaceElement},
|
||||||
input::{
|
input::{
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||||
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
||||||
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
||||||
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
||||||
|
|
@ -710,7 +709,7 @@ impl MoveGrab {
|
||||||
|
|
||||||
{
|
{
|
||||||
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
||||||
cursor_state.lock().unwrap().set_shape(CursorShape::Grab);
|
cursor_state.lock().unwrap().set_shape(CursorIcon::Grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveGrab {
|
MoveGrab {
|
||||||
|
|
@ -850,7 +849,7 @@ impl Drop for MoveGrab {
|
||||||
|
|
||||||
{
|
{
|
||||||
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
||||||
cursor_state.lock().unwrap().set_shape(CursorShape::Default);
|
cursor_state.lock().unwrap().unset_shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((mapped, position)) = position {
|
if let Some((mapped, position)) = position {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::cursor::{CursorShape, CursorState},
|
backend::render::cursor::CursorState,
|
||||||
shell::{
|
shell::{
|
||||||
focus::target::PointerFocusTarget,
|
focus::target::PointerFocusTarget,
|
||||||
grabs::{GrabStartData, ReleaseMode},
|
grabs::{GrabStartData, ReleaseMode},
|
||||||
|
|
@ -14,7 +14,7 @@ use smithay::{
|
||||||
backend::input::ButtonState,
|
backend::input::ButtonState,
|
||||||
input::{
|
input::{
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
|
AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||||
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
||||||
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
||||||
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
||||||
|
|
@ -54,8 +54,8 @@ impl PointerTarget<State> for ResizeForkTarget {
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_shape(match self.orientation {
|
.set_shape(match self.orientation {
|
||||||
Orientation::Horizontal => CursorShape::RowResize,
|
Orientation::Horizontal => CursorIcon::RowResize,
|
||||||
Orientation::Vertical => CursorShape::ColResize,
|
Orientation::Vertical => CursorIcon::ColResize,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ impl PointerTarget<State> for ResizeForkTarget {
|
||||||
) {
|
) {
|
||||||
let user_data = seat.user_data();
|
let user_data = seat.user_data();
|
||||||
let cursor_state = user_data.get::<CursorState>().unwrap();
|
let cursor_state = user_data.get::<CursorState>().unwrap();
|
||||||
cursor_state.lock().unwrap().set_shape(CursorShape::Default)
|
cursor_state.lock().unwrap().unset_shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
|
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use std::{any::Any, cell::RefCell, collections::HashMap, sync::Mutex, time::Duration};
|
use std::{any::Any, cell::RefCell, collections::HashMap, sync::Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::cursor::{CursorShape, CursorState},
|
backend::render::cursor::CursorState,
|
||||||
config::{xkb_config_to_wl, Config},
|
config::{xkb_config_to_wl, Config},
|
||||||
input::{ModifiersShortcutQueue, SupressedButtons, SupressedKeys},
|
input::{ModifiersShortcutQueue, SupressedButtons, SupressedKeys},
|
||||||
state::State,
|
state::State,
|
||||||
|
|
@ -13,7 +13,7 @@ use smithay::{
|
||||||
desktop::utils::bbox_from_surface_tree,
|
desktop::utils::bbox_from_surface_tree,
|
||||||
input::{
|
input::{
|
||||||
keyboard::{LedState, XkbConfig},
|
keyboard::{LedState, XkbConfig},
|
||||||
pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus},
|
pointer::{CursorImageAttributes, CursorImageStatus},
|
||||||
Seat, SeatState,
|
Seat, SeatState,
|
||||||
},
|
},
|
||||||
output::Output,
|
output::Output,
|
||||||
|
|
@ -347,17 +347,15 @@ impl SeatExt for Seat<State> {
|
||||||
);
|
);
|
||||||
Some((buffer_geo, (hotspot.x, hotspot.y).into()))
|
Some((buffer_geo, (hotspot.x, hotspot.y).into()))
|
||||||
}
|
}
|
||||||
CursorImageStatus::Named(CursorIcon::Default) => {
|
CursorImageStatus::Named(cursor_icon) => {
|
||||||
let seat_userdata = self.user_data();
|
let seat_userdata = self.user_data();
|
||||||
seat_userdata.insert_if_missing_threadsafe(CursorState::default);
|
seat_userdata.insert_if_missing_threadsafe(CursorState::default);
|
||||||
let state = seat_userdata.get::<CursorState>().unwrap();
|
let state = seat_userdata.get::<CursorState>().unwrap();
|
||||||
let frame = state
|
let frame = state
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.cursors
|
.get_named_cursor(cursor_icon)
|
||||||
.get(&CursorShape::Default)
|
.get_image(1, time.as_millis());
|
||||||
.unwrap()
|
|
||||||
.get_image(1, Into::<Duration>::into(time).as_millis() as u32);
|
|
||||||
|
|
||||||
Some((
|
Some((
|
||||||
Rectangle::from_loc_and_size(
|
Rectangle::from_loc_and_size(
|
||||||
|
|
@ -367,10 +365,6 @@ impl SeatExt for Seat<State> {
|
||||||
(frame.xhot as i32, frame.yhot as i32).into(),
|
(frame.xhot as i32, frame.yhot as i32).into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
CursorImageStatus::Named(_) => {
|
|
||||||
// TODO: Handle for `cursor_shape_v1` protocol
|
|
||||||
None
|
|
||||||
}
|
|
||||||
CursorImageStatus::Hidden => None,
|
CursorImageStatus::Hidden => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ use smithay::{
|
||||||
wayland::{
|
wayland::{
|
||||||
alpha_modifier::AlphaModifierState,
|
alpha_modifier::AlphaModifierState,
|
||||||
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
||||||
|
cursor_shape::CursorShapeManagerState,
|
||||||
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
||||||
foreign_toplevel_list::ForeignToplevelListState,
|
foreign_toplevel_list::ForeignToplevelListState,
|
||||||
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
||||||
|
|
@ -210,6 +211,7 @@ pub struct Common {
|
||||||
pub idle_inhibit_manager_state: IdleInhibitManagerState,
|
pub idle_inhibit_manager_state: IdleInhibitManagerState,
|
||||||
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
||||||
pub shm_state: ShmState,
|
pub shm_state: ShmState,
|
||||||
|
pub cursor_shape_manager_state: CursorShapeManagerState,
|
||||||
pub wl_drm_state: WlDrmState<Option<DrmNode>>,
|
pub wl_drm_state: WlDrmState<Option<DrmNode>>,
|
||||||
pub viewporter_state: ViewporterState,
|
pub viewporter_state: ViewporterState,
|
||||||
pub kde_decoration_state: KdeDecorationState,
|
pub kde_decoration_state: KdeDecorationState,
|
||||||
|
|
@ -506,6 +508,7 @@ impl State {
|
||||||
let screencopy_state = ScreencopyState::new::<Self, _>(dh, client_is_privileged);
|
let screencopy_state = ScreencopyState::new::<Self, _>(dh, client_is_privileged);
|
||||||
let shm_state =
|
let shm_state =
|
||||||
ShmState::new::<Self>(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]);
|
ShmState::new::<Self>(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]);
|
||||||
|
let cursor_shape_manager_state = CursorShapeManagerState::new::<State>(dh);
|
||||||
let seat_state = SeatState::<Self>::new();
|
let seat_state = SeatState::<Self>::new();
|
||||||
let viewporter_state = ViewporterState::new::<Self>(dh);
|
let viewporter_state = ViewporterState::new::<Self>(dh);
|
||||||
let wl_drm_state = WlDrmState::<Option<DrmNode>>::default();
|
let wl_drm_state = WlDrmState::<Option<DrmNode>>::default();
|
||||||
|
|
@ -600,6 +603,7 @@ impl State {
|
||||||
image_source_state,
|
image_source_state,
|
||||||
screencopy_state,
|
screencopy_state,
|
||||||
shm_state,
|
shm_state,
|
||||||
|
cursor_shape_manager_state,
|
||||||
seat_state,
|
seat_state,
|
||||||
session_lock_manager_state,
|
session_lock_manager_state,
|
||||||
keyboard_shortcuts_inhibit_state,
|
keyboard_shortcuts_inhibit_state,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
state::State,
|
state::State,
|
||||||
};
|
};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
delegate_seat,
|
delegate_cursor_shape, delegate_seat,
|
||||||
input::{keyboard::LedState, pointer::CursorImageStatus, SeatHandler, SeatState},
|
input::{keyboard::LedState, pointer::CursorImageStatus, SeatHandler, SeatState},
|
||||||
};
|
};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
@ -48,3 +48,4 @@ impl SeatHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate_seat!(State);
|
delegate_seat!(State);
|
||||||
|
delegate_cursor_shape!(State);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{ffi::OsString, os::unix::io::OwnedFd, process::Stdio};
|
use std::{ffi::OsString, os::unix::io::OwnedFd, process::Stdio};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::cursor::{load_cursor_theme, Cursor, CursorShape},
|
backend::render::cursor::{load_cursor_theme, Cursor},
|
||||||
shell::{
|
shell::{
|
||||||
element::surface::SSD_HEIGHT, focus::target::KeyboardFocusTarget, grabs::ReleaseMode,
|
element::surface::SSD_HEIGHT, focus::target::KeyboardFocusTarget, grabs::ReleaseMode,
|
||||||
CosmicSurface, Shell,
|
CosmicSurface, Shell,
|
||||||
|
|
@ -15,6 +15,7 @@ use crate::{
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::drm::DrmNode,
|
backend::drm::DrmNode,
|
||||||
desktop::space::SpaceElement,
|
desktop::space::SpaceElement,
|
||||||
|
input::pointer::CursorIcon,
|
||||||
reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window},
|
reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window},
|
||||||
utils::{Logical, Point, Rectangle, Size, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, Size, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -99,7 +100,7 @@ impl State {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (theme, size) = load_cursor_theme();
|
let (theme, size) = load_cursor_theme();
|
||||||
let cursor = Cursor::load(&theme, CursorShape::Default, size);
|
let cursor = Cursor::load(&theme, CursorIcon::Default, size);
|
||||||
let image = cursor.get_image(1, 0);
|
let image = cursor.get_image(1, 0);
|
||||||
if let Err(err) = wm.set_cursor(
|
if let Err(err) = wm.set_cursor(
|
||||||
&image.pixels_rgba,
|
&image.pixels_rgba,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue