shell: Refactor move_request, consider sticky windows
This commit is contained in:
parent
775e0ccbdc
commit
769b7d6996
8 changed files with 247 additions and 191 deletions
|
|
@ -1,10 +1,7 @@
|
||||||
use super::{CosmicMapped, CosmicSurface, CosmicWindow};
|
use super::CosmicSurface;
|
||||||
use crate::{
|
use crate::{
|
||||||
shell::{
|
shell::{
|
||||||
focus::FocusDirection,
|
focus::FocusDirection, grabs::ReleaseMode, layout::tiling::NodeDesc, Direction, Shell,
|
||||||
grabs::{MoveGrab, ReleaseMode},
|
|
||||||
layout::tiling::NodeDesc,
|
|
||||||
Direction, Shell, Trigger,
|
|
||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
utils::iced::{IcedElement, Program},
|
utils::iced::{IcedElement, Program},
|
||||||
|
|
@ -38,8 +35,8 @@ use smithay::{
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||||
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
||||||
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
|
||||||
GrabStartData as PointerGrabStartData, MotionEvent, PointerTarget, RelativeMotionEvent,
|
PointerTarget, RelativeMotionEvent,
|
||||||
},
|
},
|
||||||
Seat,
|
Seat,
|
||||||
},
|
},
|
||||||
|
|
@ -659,6 +656,7 @@ impl Program for CosmicStackInternal {
|
||||||
&seat,
|
&seat,
|
||||||
serial,
|
serial,
|
||||||
ReleaseMode::NoMouseButtons,
|
ReleaseMode::NoMouseButtons,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -713,20 +711,20 @@ impl Program for CosmicStackInternal {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cursor = seat
|
let mut cursor = seat
|
||||||
.get_pointer()
|
.get_pointer()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.current_location()
|
.current_location()
|
||||||
.to_i32_round();
|
.to_i32_round();
|
||||||
cursor.y -= TAB_HEIGHT;
|
cursor.y -= TAB_HEIGHT;
|
||||||
Shell::menu_request(
|
Shell::menu_request(
|
||||||
state,
|
state,
|
||||||
&surface,
|
&surface,
|
||||||
&seat,
|
&seat,
|
||||||
serial,
|
serial,
|
||||||
cursor - position.as_logical(),
|
cursor - position.as_logical(),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1172,60 +1170,18 @@ impl PointerTarget<State> for CosmicStack {
|
||||||
.0
|
.0
|
||||||
.with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned())
|
.with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned())
|
||||||
{
|
{
|
||||||
if let Some(stack_mapped) =
|
let seat = seat.clone();
|
||||||
data.common.shell.element_for_surface(&surface)
|
if let Some(surface) = surface.wl_surface() {
|
||||||
{
|
let _ = data.common.event_loop_handle.insert_idle(move |state| {
|
||||||
if let Some(workspace) = data.common.shell.space_for(stack_mapped) {
|
Shell::move_request(
|
||||||
// TODO: Unify this somehow with Shell::move_request/Workspace::move_request
|
state,
|
||||||
let button = 0x110; // BTN_LEFT
|
&surface,
|
||||||
let pos = event.location.as_global();
|
&seat,
|
||||||
let start_data = PointerGrabStartData {
|
None,
|
||||||
focus: None,
|
|
||||||
button,
|
|
||||||
location: pos.as_logical(),
|
|
||||||
};
|
|
||||||
let mapped = CosmicMapped::from(CosmicWindow::new(
|
|
||||||
surface,
|
|
||||||
self.0.loop_handle(),
|
|
||||||
data.common.theme.clone(),
|
|
||||||
));
|
|
||||||
let elem_geo =
|
|
||||||
workspace.element_geometry(stack_mapped).unwrap();
|
|
||||||
let indicator_thickness =
|
|
||||||
data.common.theme.cosmic().active_hint as u8;
|
|
||||||
let was_tiled = workspace.is_tiled(stack_mapped);
|
|
||||||
|
|
||||||
self.remove_idx(dragged_out);
|
|
||||||
mapped.configure();
|
|
||||||
|
|
||||||
let grab = MoveGrab::new(
|
|
||||||
start_data,
|
|
||||||
mapped,
|
|
||||||
seat,
|
|
||||||
pos,
|
|
||||||
pos.to_i32_round() - Point::from((elem_geo.size.w / 2, 24)),
|
|
||||||
indicator_thickness,
|
|
||||||
was_tiled,
|
|
||||||
ReleaseMode::NoMouseButtons,
|
ReleaseMode::NoMouseButtons,
|
||||||
data.common.event_loop_handle.clone(),
|
true,
|
||||||
);
|
)
|
||||||
if grab.is_tiling_grab() {
|
});
|
||||||
data.common.shell.set_overview_mode(
|
|
||||||
Some(Trigger::Pointer(button)),
|
|
||||||
data.common.event_loop_handle.clone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let seat = seat.clone();
|
|
||||||
data.common.event_loop_handle.insert_idle(move |state| {
|
|
||||||
seat.get_pointer().unwrap().set_grab(
|
|
||||||
state,
|
|
||||||
grab,
|
|
||||||
event.serial,
|
|
||||||
smithay::input::pointer::Focus::Clear,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,7 @@ impl Program for CosmicWindowInternal {
|
||||||
&seat,
|
&seat,
|
||||||
serial,
|
serial,
|
||||||
ReleaseMode::NoMouseButtons,
|
ReleaseMode::NoMouseButtons,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ pub fn window_items(
|
||||||
let _ = handle.insert_idle(move |state| {
|
let _ = handle.insert_idle(move |state| {
|
||||||
if let Some(surface) = move_clone.wl_surface() {
|
if let Some(surface) = move_clone.wl_surface() {
|
||||||
let seat = state.common.last_active_seat().clone();
|
let seat = state.common.last_active_seat().clone();
|
||||||
Shell::move_request(state, &surface, &seat, None, ReleaseMode::Click);
|
Shell::move_request(state, &surface, &seat, None, ReleaseMode::Click, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})),
|
})),
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
CosmicMappedRenderElement,
|
CosmicMappedRenderElement,
|
||||||
},
|
},
|
||||||
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
CosmicMapped, CosmicSurface,
|
CosmicMapped, CosmicSurface, ManagedLayer,
|
||||||
},
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
};
|
};
|
||||||
|
|
@ -61,7 +61,7 @@ pub struct MoveGrabState {
|
||||||
window_offset: Point<i32, Logical>,
|
window_offset: Point<i32, Logical>,
|
||||||
indicator_thickness: u8,
|
indicator_thickness: u8,
|
||||||
start: Instant,
|
start: Instant,
|
||||||
tiling: bool,
|
previous: ManagedLayer,
|
||||||
stacking_indicator: Option<(StackHover, Point<i32, Logical>)>,
|
stacking_indicator: Option<(StackHover, Point<i32, Logical>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ impl MoveGrabState {
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
let scale = if self.tiling {
|
let scale = if self.previous == ManagedLayer::Tiling {
|
||||||
0.6 + ((1.0
|
0.6 + ((1.0
|
||||||
- (Instant::now().duration_since(self.start).as_millis() as f64
|
- (Instant::now().duration_since(self.start).as_millis() as f64
|
||||||
/ RESCALE_ANIMATION_DURATION)
|
/ RESCALE_ANIMATION_DURATION)
|
||||||
|
|
@ -225,7 +225,7 @@ pub struct MoveGrab {
|
||||||
seat: Seat<State>,
|
seat: Seat<State>,
|
||||||
cursor_output: Output,
|
cursor_output: Output,
|
||||||
window_outputs: HashSet<Output>,
|
window_outputs: HashSet<Output>,
|
||||||
tiling: bool,
|
previous: ManagedLayer,
|
||||||
release: ReleaseMode,
|
release: ReleaseMode,
|
||||||
// SAFETY: This is only used on drop which will always be on the main thread
|
// SAFETY: This is only used on drop which will always be on the main thread
|
||||||
evlh: NotSend<LoopHandle<'static, State>>,
|
evlh: NotSend<LoopHandle<'static, State>>,
|
||||||
|
|
@ -290,7 +290,7 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tiling {
|
if self.previous == ManagedLayer::Tiling {
|
||||||
let indicator_location = state
|
let indicator_location = state
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
|
|
@ -458,7 +458,7 @@ impl MoveGrab {
|
||||||
initial_cursor_location: Point<f64, Global>,
|
initial_cursor_location: Point<f64, Global>,
|
||||||
initial_window_location: Point<i32, Global>,
|
initial_window_location: Point<i32, Global>,
|
||||||
indicator_thickness: u8,
|
indicator_thickness: u8,
|
||||||
was_tiled: bool,
|
previous_layer: ManagedLayer,
|
||||||
release: ReleaseMode,
|
release: ReleaseMode,
|
||||||
evlh: LoopHandle<'static, State>,
|
evlh: LoopHandle<'static, State>,
|
||||||
) -> MoveGrab {
|
) -> MoveGrab {
|
||||||
|
|
@ -475,7 +475,7 @@ impl MoveGrab {
|
||||||
indicator_thickness,
|
indicator_thickness,
|
||||||
start: Instant::now(),
|
start: Instant::now(),
|
||||||
stacking_indicator: None,
|
stacking_indicator: None,
|
||||||
tiling: was_tiled,
|
previous: previous_layer,
|
||||||
};
|
};
|
||||||
|
|
||||||
*seat
|
*seat
|
||||||
|
|
@ -495,14 +495,14 @@ impl MoveGrab {
|
||||||
seat: seat.clone(),
|
seat: seat.clone(),
|
||||||
window_outputs: outputs,
|
window_outputs: outputs,
|
||||||
cursor_output: output,
|
cursor_output: output,
|
||||||
tiling: was_tiled,
|
previous: previous_layer,
|
||||||
release,
|
release,
|
||||||
evlh: NotSend(evlh),
|
evlh: NotSend(evlh),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_tiling_grab(&self) -> bool {
|
pub fn is_tiling_grab(&self) -> bool {
|
||||||
self.tiling
|
self.previous == ManagedLayer::Tiling
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -512,7 +512,7 @@ impl Drop for MoveGrab {
|
||||||
let output = self.seat.active_output();
|
let output = self.seat.active_output();
|
||||||
let seat = self.seat.clone();
|
let seat = self.seat.clone();
|
||||||
let window_outputs = self.window_outputs.drain().collect::<HashSet<_>>();
|
let window_outputs = self.window_outputs.drain().collect::<HashSet<_>>();
|
||||||
let tiling = self.tiling;
|
let previous = self.previous;
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
|
|
||||||
let _ = self.evlh.0.insert_idle(move |state| {
|
let _ = self.evlh.0.insert_idle(move |state| {
|
||||||
|
|
@ -533,39 +533,58 @@ impl Drop for MoveGrab {
|
||||||
grab_state.window.output_leave(old_output);
|
grab_state.window.output_leave(old_output);
|
||||||
}
|
}
|
||||||
for (window, _) in grab_state.window.windows() {
|
for (window, _) in grab_state.window.windows() {
|
||||||
state
|
|
||||||
.common
|
|
||||||
.shell
|
|
||||||
.toplevel_info_state
|
|
||||||
.toplevel_enter_workspace(&window, &workspace_handle);
|
|
||||||
state
|
state
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
.toplevel_info_state
|
.toplevel_info_state
|
||||||
.toplevel_enter_output(&window, &output);
|
.toplevel_enter_output(&window, &output);
|
||||||
|
if previous != ManagedLayer::Sticky {
|
||||||
|
state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.toplevel_info_state
|
||||||
|
.toplevel_enter_workspace(&window, &workspace_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tiling {
|
match previous {
|
||||||
let (window, location) = state
|
ManagedLayer::Tiling => {
|
||||||
.common
|
let (window, location) = state
|
||||||
.shell
|
.common
|
||||||
.active_space_mut(&output)
|
.shell
|
||||||
.tiling_layer
|
.active_space_mut(&output)
|
||||||
.drop_window(grab_state.window);
|
.tiling_layer
|
||||||
Some((window, location.to_global(&output)))
|
.drop_window(grab_state.window);
|
||||||
} else {
|
Some((window, location.to_global(&output)))
|
||||||
grab_state.window.set_geometry(Rectangle::from_loc_and_size(
|
}
|
||||||
window_location,
|
ManagedLayer::Floating => {
|
||||||
grab_state.window.geometry().size.as_global(),
|
grab_state.window.set_geometry(Rectangle::from_loc_and_size(
|
||||||
));
|
window_location,
|
||||||
let workspace = state.common.shell.active_space_mut(&output);
|
grab_state.window.geometry().size.as_global(),
|
||||||
workspace.floating_layer.map_internal(
|
));
|
||||||
grab_state.window,
|
let workspace = state.common.shell.active_space_mut(&output);
|
||||||
Some(window_location.to_local(&workspace.output)),
|
workspace.floating_layer.map_internal(
|
||||||
None,
|
grab_state.window,
|
||||||
);
|
Some(window_location.to_local(&workspace.output)),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
Some((window.clone(), window_location))
|
Some((window.clone(), window_location))
|
||||||
|
}
|
||||||
|
ManagedLayer::Sticky => {
|
||||||
|
grab_state.window.set_geometry(Rectangle::from_loc_and_size(
|
||||||
|
window_location,
|
||||||
|
grab_state.window.geometry().size.as_global(),
|
||||||
|
));
|
||||||
|
let set = state.common.shell.workspaces.sets.get_mut(&output).unwrap();
|
||||||
|
set.sticky_layer.map_internal(
|
||||||
|
grab_state.window,
|
||||||
|
Some(window_location.to_local(&output)),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
Some((window.clone(), window_location))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
||||||
171
src/shell/mod.rs
171
src/shell/mod.rs
|
|
@ -26,7 +26,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
wayland_server::{protocol::wl_surface::WlSurface, Client, DisplayHandle},
|
wayland_server::{protocol::wl_surface::WlSurface, Client, DisplayHandle},
|
||||||
},
|
},
|
||||||
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, Serial, Size, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::with_states,
|
compositor::with_states,
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
|
|
@ -73,10 +73,12 @@ use self::{
|
||||||
swap_indicator::{swap_indicator, SwapIndicator},
|
swap_indicator::{swap_indicator, SwapIndicator},
|
||||||
CosmicWindow,
|
CosmicWindow,
|
||||||
},
|
},
|
||||||
focus::target::KeyboardFocusTarget,
|
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
grabs::{tab_items, window_items, Item, MenuGrab, ReleaseMode, ResizeEdge, ResizeGrab},
|
grabs::{
|
||||||
|
tab_items, window_items, Item, MenuGrab, MoveGrab, ReleaseMode, ResizeEdge, ResizeGrab,
|
||||||
|
},
|
||||||
layout::{
|
layout::{
|
||||||
floating::ResizeState,
|
floating::{FloatingLayout, ResizeState},
|
||||||
tiling::{NodeDesc, ResizeForkGrab, TilingLayout},
|
tiling::{NodeDesc, ResizeForkGrab, TilingLayout},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -2098,52 +2100,179 @@ impl Shell {
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
serial: impl Into<Option<Serial>>,
|
serial: impl Into<Option<Serial>>,
|
||||||
release: ReleaseMode,
|
release: ReleaseMode,
|
||||||
|
move_out_of_stack: bool,
|
||||||
) {
|
) {
|
||||||
let serial = serial.into();
|
let serial = serial.into();
|
||||||
if let Some(start_data) = check_grab_preconditions(&seat, surface, serial, release) {
|
|
||||||
if let Some(mapped) = state.common.shell.element_for_wl_surface(surface).cloned() {
|
|
||||||
if let Some(workspace) = state.common.shell.space_for_mut(&mapped) {
|
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
let (window, _) = mapped
|
|
||||||
|
if let Some(mut start_data) = check_grab_preconditions(&seat, surface, serial, release) {
|
||||||
|
if let Some(mut old_mapped) =
|
||||||
|
state.common.shell.element_for_wl_surface(surface).cloned()
|
||||||
|
{
|
||||||
|
let seats = state.common.seats().cloned().collect::<Vec<_>>();
|
||||||
|
for workspace in state.common.shell.workspaces.spaces_mut() {
|
||||||
|
for seat in seats.iter() {
|
||||||
|
let mut stack = workspace.focus_stack.get_mut(seat);
|
||||||
|
stack.remove(&old_mapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (window, _) = old_mapped
|
||||||
.windows()
|
.windows()
|
||||||
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface))
|
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let mapped = if move_out_of_stack {
|
||||||
|
let new_mapped: CosmicMapped = CosmicWindow::new(
|
||||||
|
window.clone(),
|
||||||
|
state.common.event_loop_handle.clone(),
|
||||||
|
state.common.theme.clone(),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
start_data.focus = Some((new_mapped.clone().into(), Point::from((0, 0))));
|
||||||
|
new_mapped
|
||||||
|
} else {
|
||||||
|
old_mapped.clone()
|
||||||
|
};
|
||||||
|
|
||||||
let button = start_data.button;
|
let button = start_data.button;
|
||||||
let active_hint = state.common.theme.cosmic().active_hint as u8;
|
let active_hint = state.common.theme.cosmic().active_hint as u8;
|
||||||
if let Some(grab) = workspace.move_request(
|
let pointer = seat.get_pointer().unwrap();
|
||||||
&window,
|
let pos = pointer.current_location().as_global();
|
||||||
&seat,
|
|
||||||
&output,
|
let (initial_window_location, layer, workspace_handle) =
|
||||||
start_data,
|
if let Some(workspace) = state.common.shell.space_for_mut(&old_mapped) {
|
||||||
active_hint as u8,
|
if workspace
|
||||||
release,
|
.fullscreen
|
||||||
state.common.event_loop_handle.clone(),
|
.as_ref()
|
||||||
) {
|
.is_some_and(|f| f.surface == window)
|
||||||
let handle = workspace.handle;
|
{
|
||||||
|
let _ = workspace.remove_fullscreen(); // We are moving this window, we don't need to send it back to it's original workspace
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut initial_window_location = workspace
|
||||||
|
.element_geometry(&old_mapped)
|
||||||
|
.unwrap()
|
||||||
|
.loc
|
||||||
|
.to_global(&output);
|
||||||
|
|
||||||
|
if mapped.maximized_state.lock().unwrap().is_some() {
|
||||||
|
// If surface is maximized then unmaximize it
|
||||||
|
let new_size = workspace.unmaximize_request(&mapped);
|
||||||
|
let ratio = pos.to_local(&output).x / output.geometry().size.w as f64;
|
||||||
|
|
||||||
|
initial_window_location = new_size
|
||||||
|
.map(|size| (pos.x - (size.w as f64 * ratio), pos.y).into())
|
||||||
|
.unwrap_or_else(|| pos)
|
||||||
|
.to_i32_round();
|
||||||
|
}
|
||||||
|
|
||||||
|
let layer = if mapped == old_mapped {
|
||||||
|
let was_floating = workspace.floating_layer.unmap(&mapped);
|
||||||
|
let was_tiled = workspace.tiling_layer.unmap_as_placeholder(&mapped);
|
||||||
|
assert!(was_floating != was_tiled.is_some());
|
||||||
|
was_tiled.is_some()
|
||||||
|
} else {
|
||||||
|
workspace
|
||||||
|
.tiling_layer
|
||||||
|
.mapped()
|
||||||
|
.any(|(_, m, _)| m == &old_mapped)
|
||||||
|
}
|
||||||
|
.then_some(ManagedLayer::Tiling)
|
||||||
|
.unwrap_or(ManagedLayer::Floating);
|
||||||
|
|
||||||
|
(initial_window_location, layer, workspace.handle)
|
||||||
|
} else if let Some(sticky_layer) = state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.get_mut(&output)
|
||||||
|
.filter(|set| set.sticky_layer.mapped().any(|m| m == &old_mapped))
|
||||||
|
.map(|set| &mut set.sticky_layer)
|
||||||
|
{
|
||||||
|
let mut initial_window_location = sticky_layer
|
||||||
|
.element_geometry(&old_mapped)
|
||||||
|
.unwrap()
|
||||||
|
.loc
|
||||||
|
.to_global(&output);
|
||||||
|
|
||||||
|
if let Some(state) = mapped.maximized_state.lock().unwrap().take() {
|
||||||
|
// If surface is maximized then unmaximize it
|
||||||
|
mapped.set_maximized(false);
|
||||||
|
let new_size = state.original_geometry.size.as_logical();
|
||||||
|
sticky_layer.map_internal(
|
||||||
|
mapped.clone(),
|
||||||
|
Some(state.original_geometry.loc),
|
||||||
|
Some(new_size),
|
||||||
|
);
|
||||||
|
|
||||||
|
let ratio = pos.to_local(&output).x / output.geometry().size.w as f64;
|
||||||
|
initial_window_location =
|
||||||
|
Point::<f64, _>::from((pos.x - (new_size.w as f64 * ratio), pos.y))
|
||||||
|
.to_i32_round();
|
||||||
|
}
|
||||||
|
|
||||||
|
if mapped == old_mapped {
|
||||||
|
sticky_layer.unmap(&mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
initial_window_location,
|
||||||
|
ManagedLayer::Sticky,
|
||||||
|
state.common.shell.active_space(&output).handle,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
state
|
state
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
.toplevel_info_state
|
.toplevel_info_state
|
||||||
.toplevel_leave_workspace(&window, &handle);
|
.toplevel_leave_workspace(&window, &workspace_handle);
|
||||||
state
|
state
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
.toplevel_info_state
|
.toplevel_info_state
|
||||||
.toplevel_leave_output(&window, &output);
|
.toplevel_leave_output(&window, &output);
|
||||||
|
|
||||||
|
if move_out_of_stack {
|
||||||
|
old_mapped.stack_ref_mut().unwrap().remove_window(&window);
|
||||||
|
state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.workspaces
|
||||||
|
.space_for_handle_mut(&workspace_handle)
|
||||||
|
.unwrap()
|
||||||
|
.refresh(&state.common.shell.xdg_activation_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
let grab = MoveGrab::new(
|
||||||
|
start_data,
|
||||||
|
mapped,
|
||||||
|
seat,
|
||||||
|
pos,
|
||||||
|
initial_window_location,
|
||||||
|
active_hint as u8,
|
||||||
|
layer,
|
||||||
|
release,
|
||||||
|
state.common.event_loop_handle.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
if grab.is_tiling_grab() {
|
if grab.is_tiling_grab() {
|
||||||
state.common.shell.set_overview_mode(
|
state.common.shell.set_overview_mode(
|
||||||
Some(Trigger::Pointer(button)),
|
Some(Trigger::Pointer(button)),
|
||||||
state.common.event_loop_handle.clone(),
|
state.common.event_loop_handle.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
seat.get_pointer().unwrap().set_grab(
|
seat.get_pointer().unwrap().set_grab(
|
||||||
state,
|
state,
|
||||||
grab,
|
grab,
|
||||||
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
||||||
Focus::Clear,
|
Focus::Clear,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use crate::{
|
||||||
BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer,
|
BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer,
|
||||||
},
|
},
|
||||||
shell::{
|
shell::{
|
||||||
grabs::MoveGrab,
|
|
||||||
layout::{floating::FloatingLayout, tiling::TilingLayout},
|
layout::{floating::FloatingLayout, tiling::TilingLayout},
|
||||||
OverviewMode, ANIMATION_DURATION,
|
OverviewMode, ANIMATION_DURATION,
|
||||||
},
|
},
|
||||||
|
|
@ -21,7 +20,6 @@ use crate::{
|
||||||
xwayland::XWaylandState,
|
xwayland::XWaylandState,
|
||||||
};
|
};
|
||||||
|
|
||||||
use calloop::LoopHandle;
|
|
||||||
use cosmic::theme::CosmicTheme;
|
use cosmic::theme::CosmicTheme;
|
||||||
use id_tree::Tree;
|
use id_tree::Tree;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
@ -37,7 +35,7 @@ use smithay::{
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
desktop::{layer_map_for_output, space::SpaceElement},
|
desktop::{layer_map_for_output, space::SpaceElement},
|
||||||
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
input::Seat,
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::{
|
reexports::{
|
||||||
wayland_server::{protocol::wl_surface::WlSurface, Client, Resource},
|
wayland_server::{protocol::wl_surface::WlSurface, Client, Resource},
|
||||||
|
|
@ -151,6 +149,7 @@ pub struct ManagedState {
|
||||||
pub enum ManagedLayer {
|
pub enum ManagedLayer {
|
||||||
Tiling,
|
Tiling,
|
||||||
Floating,
|
Floating,
|
||||||
|
Sticky,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
@ -678,62 +677,6 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_request(
|
|
||||||
&mut self,
|
|
||||||
window: &CosmicSurface,
|
|
||||||
seat: &Seat<State>,
|
|
||||||
output: &Output,
|
|
||||||
start_data: PointerGrabStartData<State>,
|
|
||||||
indicator_thickness: u8,
|
|
||||||
release: ReleaseMode,
|
|
||||||
evlh: LoopHandle<'static, State>,
|
|
||||||
) -> Option<MoveGrab> {
|
|
||||||
let pointer = seat.get_pointer().unwrap();
|
|
||||||
let pos = pointer.current_location().as_global();
|
|
||||||
|
|
||||||
if self
|
|
||||||
.fullscreen
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|f| &f.surface == window)
|
|
||||||
{
|
|
||||||
let _ = self.remove_fullscreen(); // We are moving this window, we don't need to send it back to it's original workspace
|
|
||||||
}
|
|
||||||
|
|
||||||
let mapped = self.element_for_surface(&window)?.clone();
|
|
||||||
let mut initial_window_location = self
|
|
||||||
.element_geometry(&mapped)
|
|
||||||
.unwrap()
|
|
||||||
.loc
|
|
||||||
.to_global(&self.output);
|
|
||||||
|
|
||||||
if mapped.maximized_state.lock().unwrap().is_some() {
|
|
||||||
// If surface is maximized then unmaximize it
|
|
||||||
let new_size = self.unmaximize_request(window);
|
|
||||||
let ratio = pos.to_local(&self.output).x / output.geometry().size.w as f64;
|
|
||||||
|
|
||||||
initial_window_location = new_size
|
|
||||||
.map(|size| (pos.x - (size.w as f64 * ratio), pos.y).into())
|
|
||||||
.unwrap_or_else(|| pos)
|
|
||||||
.to_i32_round();
|
|
||||||
}
|
|
||||||
|
|
||||||
let was_floating = self.floating_layer.unmap(&mapped);
|
|
||||||
let was_tiled = self.tiling_layer.unmap_as_placeholder(&mapped);
|
|
||||||
assert!(was_floating != was_tiled.is_some());
|
|
||||||
|
|
||||||
Some(MoveGrab::new(
|
|
||||||
start_data,
|
|
||||||
mapped,
|
|
||||||
seat,
|
|
||||||
pos,
|
|
||||||
initial_window_location,
|
|
||||||
indicator_thickness,
|
|
||||||
was_tiled.is_some(),
|
|
||||||
release,
|
|
||||||
evlh,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn toggle_tiling(&mut self, seat: &Seat<State>) {
|
pub fn toggle_tiling(&mut self, seat: &Seat<State>) {
|
||||||
if self.tiling_enabled {
|
if self.tiling_enabled {
|
||||||
for window in self
|
for window in self
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ impl XdgShellHandler for State {
|
||||||
&seat,
|
&seat,
|
||||||
serial,
|
serial,
|
||||||
ReleaseMode::NoMouseButtons,
|
ReleaseMode::NoMouseButtons,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -412,7 +412,14 @@ impl XwmHandler for State {
|
||||||
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, _button: u32) {
|
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, _button: u32) {
|
||||||
if let Some(wl_surface) = window.wl_surface() {
|
if let Some(wl_surface) = window.wl_surface() {
|
||||||
let seat = self.common.last_active_seat().clone();
|
let seat = self.common.last_active_seat().clone();
|
||||||
Shell::move_request(self, &wl_surface, &seat, None, ReleaseMode::NoMouseButtons)
|
Shell::move_request(
|
||||||
|
self,
|
||||||
|
&wl_surface,
|
||||||
|
&seat,
|
||||||
|
None,
|
||||||
|
ReleaseMode::NoMouseButtons,
|
||||||
|
false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue