floating mouse tiling: add corner tiling, implement designs
This commit is contained in:
parent
fc2173d028
commit
3837e56382
2 changed files with 121 additions and 68 deletions
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
backend::render::{
|
backend::render::{
|
||||||
cursor::{CursorShape, CursorState},
|
cursor::{CursorShape, CursorState},
|
||||||
element::AsGlowRenderer,
|
element::AsGlowRenderer,
|
||||||
IndicatorShader, Key, Usage,
|
BackdropShader, IndicatorShader, Key, Usage,
|
||||||
},
|
},
|
||||||
shell::{
|
shell::{
|
||||||
element::{
|
element::{
|
||||||
|
|
@ -147,21 +147,36 @@ impl MoveGrabState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let snapping_indicator = match &self.snapping_zone {
|
let snapping_indicator = match &self.snapping_zone {
|
||||||
Some(t) => vec![IndicatorShader::element(
|
Some(t) => {
|
||||||
renderer,
|
let base_color = theme.palette.neutral_9;
|
||||||
Key::Window(Usage::SnappingIndicator, self.window.clone()),
|
let overlay_geometry = t.overlay_geometry(non_exclusive_geometry);
|
||||||
t.overlay_geometry(non_exclusive_geometry),
|
vec![
|
||||||
4,
|
CosmicMappedRenderElement::from(IndicatorShader::element(
|
||||||
8,
|
renderer,
|
||||||
0.5,
|
Key::Window(Usage::SnappingIndicator, self.window.clone()),
|
||||||
output_scale.x,
|
overlay_geometry,
|
||||||
[
|
3,
|
||||||
active_window_hint.red,
|
theme.radius_s()[0] as u8, // TODO: Fix once shaders support 4 corner radii customization
|
||||||
active_window_hint.green,
|
1.0,
|
||||||
active_window_hint.blue,
|
output_scale.x,
|
||||||
],
|
[
|
||||||
)
|
active_window_hint.red,
|
||||||
.into()],
|
active_window_hint.green,
|
||||||
|
active_window_hint.blue,
|
||||||
|
],
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
CosmicMappedRenderElement::from(BackdropShader::element(
|
||||||
|
renderer,
|
||||||
|
Key::Window(Usage::SnappingIndicator, self.window.clone()),
|
||||||
|
t.overlay_geometry(non_exclusive_geometry),
|
||||||
|
theme.radius_s()[0], // TODO: Fix once shaders support 4 corner radii customization
|
||||||
|
0.4,
|
||||||
|
[base_color.red, base_color.green, base_color.blue],
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
]
|
||||||
|
}
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -227,40 +242,48 @@ unsafe impl<T> Send for NotSend<T> {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum SnappingZone {
|
pub enum SnappingZone {
|
||||||
TopMaxim,
|
Maximize,
|
||||||
TopSnap,
|
Top,
|
||||||
|
TopLeft,
|
||||||
Left,
|
Left,
|
||||||
Right,
|
BottomLeft,
|
||||||
Bottom,
|
Bottom,
|
||||||
|
BottomRight,
|
||||||
|
Right,
|
||||||
|
TopRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SNAPPING_RANGE: i32 = 12;
|
const SNAP_RANGE: i32 = 32;
|
||||||
|
const SNAP_RANGE_TOP: i32 = 24;
|
||||||
|
|
||||||
impl SnappingZone {
|
impl SnappingZone {
|
||||||
pub fn contains(
|
pub fn contains(
|
||||||
&self,
|
&self,
|
||||||
point: Point<i32, Logical>,
|
point: Point<i32, Local>,
|
||||||
non_exclusive_geometry: Rectangle<i32, Logical>,
|
output_geometry: Rectangle<i32, Local>,
|
||||||
output_geometry: Rectangle<i32, Logical>,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if !output_geometry.contains(point) {
|
if !output_geometry.contains(point) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let top_zone_32 = point.y < output_geometry.loc.y + SNAP_RANGE;
|
||||||
|
let top_zone_56 = point.y < output_geometry.loc.y + SNAP_RANGE + SNAP_RANGE_TOP;
|
||||||
|
let left_zone = point.x < output_geometry.loc.x + SNAP_RANGE;
|
||||||
|
let right_zone = point.x > output_geometry.loc.x + output_geometry.size.w - SNAP_RANGE;
|
||||||
|
let bottom_zone = point.y > output_geometry.loc.y + output_geometry.size.h - SNAP_RANGE;
|
||||||
|
let left_6th = point.x < output_geometry.loc.x + (output_geometry.size.w / 6);
|
||||||
|
let right_6th = point.x > output_geometry.loc.x + (output_geometry.size.w * 5 / 6);
|
||||||
|
let top_4th = point.y < output_geometry.loc.y + (output_geometry.size.h / 4);
|
||||||
|
let bottom_4th = point.y > output_geometry.loc.y + (output_geometry.size.h * 3 / 4);
|
||||||
match self {
|
match self {
|
||||||
SnappingZone::TopMaxim => point.y < non_exclusive_geometry.loc.y + SNAPPING_RANGE,
|
SnappingZone::Maximize => top_zone_32 && !left_6th && !right_6th,
|
||||||
SnappingZone::TopSnap => {
|
SnappingZone::Top => top_zone_56 && !top_zone_32 && !left_6th && !right_6th,
|
||||||
point.y < non_exclusive_geometry.loc.y + SNAPPING_RANGE * 2
|
SnappingZone::TopLeft => (top_zone_56 && left_6th) || (left_zone && top_4th),
|
||||||
&& point.y >= non_exclusive_geometry.loc.y + SNAPPING_RANGE
|
SnappingZone::Left => left_zone && !top_4th && !bottom_4th,
|
||||||
}
|
SnappingZone::BottomLeft => (bottom_zone && left_6th) || (left_zone && bottom_4th),
|
||||||
SnappingZone::Bottom => {
|
SnappingZone::Bottom => bottom_zone && !left_6th && !right_6th,
|
||||||
point.y
|
SnappingZone::BottomRight => (bottom_zone && right_6th) || (right_zone && bottom_4th),
|
||||||
> non_exclusive_geometry.loc.y + non_exclusive_geometry.size.h - SNAPPING_RANGE
|
SnappingZone::Right => right_zone && !top_4th && !bottom_4th,
|
||||||
}
|
SnappingZone::TopRight => (top_zone_56 && right_6th) || (right_zone && top_4th),
|
||||||
SnappingZone::Left => point.x < non_exclusive_geometry.loc.x + SNAPPING_RANGE,
|
|
||||||
SnappingZone::Right => {
|
|
||||||
point.x
|
|
||||||
> non_exclusive_geometry.loc.x + non_exclusive_geometry.size.w - SNAPPING_RANGE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn overlay_geometry(
|
pub fn overlay_geometry(
|
||||||
|
|
@ -268,11 +291,23 @@ impl SnappingZone {
|
||||||
non_exclusive_geometry: Rectangle<i32, Logical>,
|
non_exclusive_geometry: Rectangle<i32, Logical>,
|
||||||
) -> Rectangle<i32, Local> {
|
) -> Rectangle<i32, Local> {
|
||||||
match self {
|
match self {
|
||||||
SnappingZone::TopMaxim => non_exclusive_geometry.as_local(),
|
SnappingZone::Maximize => non_exclusive_geometry.as_local(),
|
||||||
SnappingZone::TopSnap => TiledCorners::Top.relative_geometry(non_exclusive_geometry),
|
SnappingZone::Top => TiledCorners::Top.relative_geometry(non_exclusive_geometry),
|
||||||
|
SnappingZone::TopLeft => {
|
||||||
|
TiledCorners::TopLeft.relative_geometry(non_exclusive_geometry)
|
||||||
|
}
|
||||||
SnappingZone::Left => TiledCorners::Left.relative_geometry(non_exclusive_geometry),
|
SnappingZone::Left => TiledCorners::Left.relative_geometry(non_exclusive_geometry),
|
||||||
SnappingZone::Right => TiledCorners::Right.relative_geometry(non_exclusive_geometry),
|
SnappingZone::BottomLeft => {
|
||||||
|
TiledCorners::BottomLeft.relative_geometry(non_exclusive_geometry)
|
||||||
|
}
|
||||||
SnappingZone::Bottom => TiledCorners::Bottom.relative_geometry(non_exclusive_geometry),
|
SnappingZone::Bottom => TiledCorners::Bottom.relative_geometry(non_exclusive_geometry),
|
||||||
|
SnappingZone::BottomRight => {
|
||||||
|
TiledCorners::BottomRight.relative_geometry(non_exclusive_geometry)
|
||||||
|
}
|
||||||
|
SnappingZone::Right => TiledCorners::Right.relative_geometry(non_exclusive_geometry),
|
||||||
|
SnappingZone::TopRight => {
|
||||||
|
TiledCorners::TopRight.relative_geometry(non_exclusive_geometry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -377,24 +412,27 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
|
|
||||||
// Check for overlapping with zones
|
// Check for overlapping with zones
|
||||||
if grab_state.previous == ManagedLayer::Floating {
|
if grab_state.previous == ManagedLayer::Floating {
|
||||||
let non_exclusive_geometry = {
|
let output_geometry = current_output.geometry().to_local(¤t_output);
|
||||||
let layers = layer_map_for_output(¤t_output);
|
|
||||||
layers.non_exclusive_zone()
|
|
||||||
};
|
|
||||||
let total_geometry = current_output.geometry().as_logical();
|
|
||||||
grab_state.snapping_zone = vec![
|
grab_state.snapping_zone = vec![
|
||||||
SnappingZone::TopMaxim,
|
SnappingZone::Maximize,
|
||||||
SnappingZone::TopSnap,
|
SnappingZone::Top,
|
||||||
|
SnappingZone::TopLeft,
|
||||||
SnappingZone::Left,
|
SnappingZone::Left,
|
||||||
SnappingZone::Right,
|
SnappingZone::BottomLeft,
|
||||||
SnappingZone::Bottom,
|
SnappingZone::Bottom,
|
||||||
|
SnappingZone::BottomRight,
|
||||||
|
SnappingZone::Right,
|
||||||
|
SnappingZone::TopRight,
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&x| {
|
.find(|&x| {
|
||||||
x.contains(
|
x.contains(
|
||||||
handle.current_location().to_i32_floor(),
|
handle
|
||||||
non_exclusive_geometry,
|
.current_location()
|
||||||
total_geometry,
|
.as_global()
|
||||||
|
.to_local(¤t_output)
|
||||||
|
.to_i32_floor(),
|
||||||
|
output_geometry,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
@ -667,23 +705,37 @@ impl Drop for MoveGrab {
|
||||||
|
|
||||||
if previous == ManagedLayer::Floating {
|
if previous == ManagedLayer::Floating {
|
||||||
if let Some(sz) = grab_state.snapping_zone {
|
if let Some(sz) = grab_state.snapping_zone {
|
||||||
if sz == SnappingZone::TopMaxim {
|
if sz == SnappingZone::Maximize {
|
||||||
state.common.shell.maximize_toggle(&window, &seat);
|
state.common.shell.maximize_toggle(&window, &seat);
|
||||||
} else {
|
} else {
|
||||||
let direction = match sz {
|
let directions = match sz {
|
||||||
SnappingZone::TopSnap => Direction::Up,
|
SnappingZone::Maximize => vec![],
|
||||||
SnappingZone::Bottom => Direction::Down,
|
SnappingZone::Top => vec![Direction::Up],
|
||||||
SnappingZone::Left => Direction::Left,
|
SnappingZone::TopLeft => {
|
||||||
SnappingZone::Right => Direction::Right,
|
vec![Direction::Up, Direction::Left]
|
||||||
_ => Direction::Up,
|
}
|
||||||
|
SnappingZone::Left => vec![Direction::Left],
|
||||||
|
SnappingZone::BottomLeft => {
|
||||||
|
vec![Direction::Down, Direction::Left]
|
||||||
|
}
|
||||||
|
SnappingZone::Bottom => vec![Direction::Down],
|
||||||
|
SnappingZone::BottomRight => {
|
||||||
|
vec![Direction::Down, Direction::Right]
|
||||||
|
}
|
||||||
|
SnappingZone::Right => vec![Direction::Right],
|
||||||
|
SnappingZone::TopRight => {
|
||||||
|
vec![Direction::Up, Direction::Right]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
workspace.floating_layer.move_element(
|
for direction in directions {
|
||||||
direction,
|
workspace.floating_layer.move_element(
|
||||||
&seat,
|
direction,
|
||||||
ManagedLayer::Floating,
|
&seat,
|
||||||
theme,
|
ManagedLayer::Floating,
|
||||||
&window,
|
&theme,
|
||||||
);
|
&window,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -899,13 +899,14 @@ impl FloatingLayout {
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
layer: ManagedLayer,
|
layer: ManagedLayer,
|
||||||
theme: cosmic::Theme,
|
theme: &cosmic::Theme,
|
||||||
element: &CosmicMapped,
|
element: &CosmicMapped,
|
||||||
) -> MoveResult {
|
) -> MoveResult {
|
||||||
match element.handle_move(direction) {
|
match element.handle_move(direction) {
|
||||||
StackMoveResult::Handled => MoveResult::Done,
|
StackMoveResult::Handled => MoveResult::Done,
|
||||||
StackMoveResult::MoveOut(surface, loop_handle) => {
|
StackMoveResult::MoveOut(surface, loop_handle) => {
|
||||||
let mapped: CosmicMapped = CosmicWindow::new(surface, loop_handle, theme).into();
|
let mapped: CosmicMapped =
|
||||||
|
CosmicWindow::new(surface, loop_handle, theme.clone()).into();
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
let pos = self.space.element_geometry(element).unwrap().loc
|
let pos = self.space.element_geometry(element).unwrap().loc
|
||||||
+ match direction {
|
+ match direction {
|
||||||
|
|
@ -1084,7 +1085,7 @@ impl FloatingLayout {
|
||||||
return MoveResult::None;
|
return MoveResult::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.move_element(direction, seat, layer, theme, &focused.clone())
|
self.move_element(direction, seat, layer, &theme, &focused.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
|
pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue