tree: implement workspace dragging
This commit is contained in:
parent
132986df2a
commit
1dd20fb87b
8 changed files with 235 additions and 7 deletions
|
|
@ -558,6 +558,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
status: Default::default(),
|
status: Default::default(),
|
||||||
scroll: Default::default(),
|
scroll: Default::default(),
|
||||||
pointer_positions: Default::default(),
|
pointer_positions: Default::default(),
|
||||||
|
pointer_down: Default::default(),
|
||||||
lock_surface: Default::default(),
|
lock_surface: Default::default(),
|
||||||
hardware_cursor: Default::default(),
|
hardware_cursor: Default::default(),
|
||||||
update_render_data_scheduled: Cell::new(false),
|
update_render_data_scheduled: Cell::new(false),
|
||||||
|
|
|
||||||
|
|
@ -882,8 +882,10 @@ impl ConfigProxyHandler {
|
||||||
Some(l) => l.to_ref(),
|
Some(l) => l.to_ref(),
|
||||||
};
|
};
|
||||||
let config = WsMoveConfig {
|
let config = WsMoveConfig {
|
||||||
|
make_visible_always: false,
|
||||||
make_visible_if_empty: true,
|
make_visible_if_empty: true,
|
||||||
source_is_destroyed: false,
|
source_is_destroyed: false,
|
||||||
|
before: None,
|
||||||
};
|
};
|
||||||
move_ws_to_output(&link, &output, config);
|
move_ws_to_output(&link, &output, config);
|
||||||
ws.desired_output.set(output.global.output_id.clone());
|
ws.desired_output.set(output.global.output_id.clone());
|
||||||
|
|
|
||||||
|
|
@ -779,6 +779,10 @@ impl WlSeatGlobal {
|
||||||
self.pointer_owner.start_tile_drag(self, tl);
|
self.pointer_owner.start_tile_drag(self, tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn start_workspace_drag(self: &Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||||
|
self.pointer_owner.start_workspace_drag(self, ws);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cancel_dnd(self: &Rc<Self>) {
|
pub fn cancel_dnd(self: &Rc<Self>) {
|
||||||
self.pointer_owner.cancel_dnd(self);
|
self.pointer_owner.cancel_dnd(self);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ use {
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, ContainerSplit, ContainingNode, FindTreeUsecase, FoundNode, Node,
|
move_ws_to_output, ContainerNode, ContainerSplit, ContainingNode, FindTreeUsecase,
|
||||||
PlaceholderNode, TddType, ToplevelNode, WorkspaceNode,
|
FoundNode, Node, PlaceholderNode, TddType, ToplevelNode, WorkspaceDragDestination,
|
||||||
|
WorkspaceNode, WsMoveConfig,
|
||||||
},
|
},
|
||||||
utils::{clonecell::CloneCell, smallmap::SmallMap},
|
utils::{clonecell::CloneCell, smallmap::SmallMap},
|
||||||
},
|
},
|
||||||
|
|
@ -210,6 +211,10 @@ impl PointerOwnerHolder {
|
||||||
pub fn start_tile_drag(&self, seat: &Rc<WlSeatGlobal>, tl: &Rc<dyn ToplevelNode>) {
|
pub fn start_tile_drag(&self, seat: &Rc<WlSeatGlobal>, tl: &Rc<dyn ToplevelNode>) {
|
||||||
self.owner.get().start_tile_drag(seat, tl);
|
self.owner.get().start_tile_drag(seat, tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn start_workspace_drag(&self, seat: &Rc<WlSeatGlobal>, ws: &Rc<WorkspaceNode>) {
|
||||||
|
self.owner.get().start_workspace_drag(seat, ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait PointerOwner {
|
trait PointerOwner {
|
||||||
|
|
@ -264,6 +269,11 @@ trait PointerOwner {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
let _ = tl;
|
let _ = tl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_workspace_drag(&self, seat: &Rc<WlSeatGlobal>, ws: &Rc<WorkspaceNode>) {
|
||||||
|
let _ = seat;
|
||||||
|
let _ = ws;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimplePointerOwner<T> {
|
struct SimplePointerOwner<T> {
|
||||||
|
|
@ -477,6 +487,10 @@ impl<T: SimplePointerOwnerUsecase> PointerOwner for SimpleGrabPointerOwner<T> {
|
||||||
fn start_tile_drag(&self, seat: &Rc<WlSeatGlobal>, tl: &Rc<dyn ToplevelNode>) {
|
fn start_tile_drag(&self, seat: &Rc<WlSeatGlobal>, tl: &Rc<dyn ToplevelNode>) {
|
||||||
self.usecase.start_tile_drag(self, seat, tl);
|
self.usecase.start_tile_drag(self, seat, tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_workspace_drag(&self, seat: &Rc<WlSeatGlobal>, ws: &Rc<WorkspaceNode>) {
|
||||||
|
self.usecase.start_workspace_drag(self, seat, ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerOwner for DndPointerOwner {
|
impl PointerOwner for DndPointerOwner {
|
||||||
|
|
@ -646,6 +660,17 @@ trait SimplePointerOwnerUsecase: Sized + Clone + 'static {
|
||||||
let _ = seat;
|
let _ = seat;
|
||||||
let _ = tl;
|
let _ = tl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_workspace_drag(
|
||||||
|
&self,
|
||||||
|
grab: &SimpleGrabPointerOwner<Self>,
|
||||||
|
seat: &Rc<WlSeatGlobal>,
|
||||||
|
ws: &Rc<WorkspaceNode>,
|
||||||
|
) {
|
||||||
|
let _ = grab;
|
||||||
|
let _ = seat;
|
||||||
|
let _ = ws;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefaultPointerUsecase {
|
impl DefaultPointerUsecase {
|
||||||
|
|
@ -762,6 +787,22 @@ impl SimplePointerOwnerUsecase for DefaultPointerUsecase {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_workspace_drag(
|
||||||
|
&self,
|
||||||
|
grab: &SimpleGrabPointerOwner<Self>,
|
||||||
|
seat: &Rc<WlSeatGlobal>,
|
||||||
|
ws: &Rc<WorkspaceNode>,
|
||||||
|
) {
|
||||||
|
self.start_ui_drag(
|
||||||
|
grab,
|
||||||
|
seat,
|
||||||
|
WorkspaceDragUsecase {
|
||||||
|
ws: ws.clone(),
|
||||||
|
destination: Default::default(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait NodeSelectorUsecase: Sized + 'static {
|
trait NodeSelectorUsecase: Sized + 'static {
|
||||||
|
|
@ -1283,3 +1324,56 @@ impl UiDragUsecase for TileDragUsecase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WorkspaceDragUsecase {
|
||||||
|
ws: Rc<WorkspaceNode>,
|
||||||
|
destination: Cell<Option<WorkspaceDragDestination>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiDragUsecase for WorkspaceDragUsecase {
|
||||||
|
fn node_seat_state(&self) -> &NodeSeatState {
|
||||||
|
self.ws.node_seat_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left_button_up(&self, _seat: &Rc<WlSeatGlobal>) {
|
||||||
|
let Some(dest) = self.destination.take() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ws = self.ws.clone();
|
||||||
|
let output = dest.output.clone();
|
||||||
|
if ws.is_dummy || output.is_dummy {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let link = match &*ws.output_link.borrow() {
|
||||||
|
None => return,
|
||||||
|
Some(l) => l.to_ref(),
|
||||||
|
};
|
||||||
|
let config = WsMoveConfig {
|
||||||
|
make_visible_always: true,
|
||||||
|
make_visible_if_empty: true,
|
||||||
|
source_is_destroyed: false,
|
||||||
|
before: dest.before.clone(),
|
||||||
|
};
|
||||||
|
move_ws_to_output(&link, &output, config);
|
||||||
|
ws.desired_output.set(output.global.output_id.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_changes(&self, seat: &Rc<WlSeatGlobal>) -> Option<Rect> {
|
||||||
|
let (x, y) = seat.pointer_cursor.position();
|
||||||
|
let dest =
|
||||||
|
seat.state
|
||||||
|
.root
|
||||||
|
.workspace_drag_destination(self.ws.id, x.round_down(), y.round_down());
|
||||||
|
match dest {
|
||||||
|
None => {
|
||||||
|
self.destination.take();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Some(d) => {
|
||||||
|
let hl = d.highlight;
|
||||||
|
self.destination.set(Some(d));
|
||||||
|
Some(hl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ impl ConnectorHandler {
|
||||||
status: self.state.status.clone(),
|
status: self.state.status.clone(),
|
||||||
scroll: Default::default(),
|
scroll: Default::default(),
|
||||||
pointer_positions: Default::default(),
|
pointer_positions: Default::default(),
|
||||||
|
pointer_down: Default::default(),
|
||||||
lock_surface: Default::default(),
|
lock_surface: Default::default(),
|
||||||
hardware_cursor: Default::default(),
|
hardware_cursor: Default::default(),
|
||||||
jay_outputs: Default::default(),
|
jay_outputs: Default::default(),
|
||||||
|
|
@ -231,8 +232,10 @@ impl ConnectorHandler {
|
||||||
&& ws.desired_output.get() == output_id)
|
&& ws.desired_output.get() == output_id)
|
||||||
|| ws_to_move.is_empty();
|
|| ws_to_move.is_empty();
|
||||||
let config = WsMoveConfig {
|
let config = WsMoveConfig {
|
||||||
|
make_visible_always: false,
|
||||||
make_visible_if_empty: make_visible,
|
make_visible_if_empty: make_visible,
|
||||||
source_is_destroyed: false,
|
source_is_destroyed: false,
|
||||||
|
before: None,
|
||||||
};
|
};
|
||||||
move_ws_to_output(&ws, &on, config);
|
move_ws_to_output(&ws, &on, config);
|
||||||
}
|
}
|
||||||
|
|
@ -304,8 +307,10 @@ impl ConnectorHandler {
|
||||||
ws.visible_on_desired_output.set(ws.visible.get());
|
ws.visible_on_desired_output.set(ws.visible.get());
|
||||||
}
|
}
|
||||||
let config = WsMoveConfig {
|
let config = WsMoveConfig {
|
||||||
|
make_visible_always: false,
|
||||||
make_visible_if_empty: ws.visible.get(),
|
make_visible_if_empty: ws.visible.get(),
|
||||||
source_is_destroyed: true,
|
source_is_destroyed: true,
|
||||||
|
before: None,
|
||||||
};
|
};
|
||||||
move_ws_to_output(&ws, &target, config);
|
move_ws_to_output(&ws, &target, config);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
walker::NodeVisitor, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
walker::NodeVisitor, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId,
|
||||||
OutputNode, StackedNode, TileDragDestination,
|
OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
||||||
|
WorkspaceNodeId,
|
||||||
},
|
},
|
||||||
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
||||||
},
|
},
|
||||||
|
|
@ -98,6 +99,21 @@ impl DisplayNode {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn workspace_drag_destination(
|
||||||
|
&self,
|
||||||
|
source: WorkspaceNodeId,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
) -> Option<WorkspaceDragDestination> {
|
||||||
|
for output in self.outputs.lock().values() {
|
||||||
|
let pos = output.node_absolute_position();
|
||||||
|
if pos.contains(x, y) {
|
||||||
|
return output.workspace_drag_destination(source, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for DisplayNode {
|
impl Node for DisplayNode {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ use {
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
walker::NodeVisitor, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node,
|
walker::NodeVisitor, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node,
|
||||||
NodeId, StackedNode, TddType, TileDragDestination, WorkspaceNode,
|
NodeId, StackedNode, TddType, TileDragDestination, WorkspaceDragDestination,
|
||||||
|
WorkspaceNode, WorkspaceNodeId,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
||||||
|
|
@ -73,6 +74,7 @@ pub struct OutputNode {
|
||||||
pub status: CloneCell<Rc<String>>,
|
pub status: CloneCell<Rc<String>>,
|
||||||
pub scroll: Scroller,
|
pub scroll: Scroller,
|
||||||
pub pointer_positions: CopyHashMap<PointerType, (i32, i32)>,
|
pub pointer_positions: CopyHashMap<PointerType, (i32, i32)>,
|
||||||
|
pub pointer_down: CopyHashMap<SeatId, (i32, i32)>,
|
||||||
pub lock_surface: CloneCell<Option<Rc<ExtSessionLockSurfaceV1>>>,
|
pub lock_surface: CloneCell<Option<Rc<ExtSessionLockSurfaceV1>>>,
|
||||||
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
|
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
|
||||||
pub hardware_cursor_needs_render: Cell<bool>,
|
pub hardware_cursor_needs_render: Cell<bool>,
|
||||||
|
|
@ -858,6 +860,9 @@ impl OutputNode {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
if let PointerType::Seat(s) = id {
|
||||||
|
self.pointer_down.set(s, (x, y));
|
||||||
|
}
|
||||||
let (x, y) = self.non_exclusive_rect_rel.get().translate(x, y);
|
let (x, y) = self.non_exclusive_rect_rel.get().translate(x, y);
|
||||||
if y >= self.state.theme.sizes.title_height.get() {
|
if y >= self.state.theme.sizes.title_height.get() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1020,6 +1025,64 @@ impl OutputNode {
|
||||||
};
|
};
|
||||||
c.tile_drag_destination(source, rect, x_abs, y_abs)
|
c.tile_drag_destination(source, rect, x_abs, y_abs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn workspace_drag_destination(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
source: WorkspaceNodeId,
|
||||||
|
x_abs: i32,
|
||||||
|
y_abs: i32,
|
||||||
|
) -> Option<WorkspaceDragDestination> {
|
||||||
|
let rect = self.non_exclusive_rect.get();
|
||||||
|
if !rect.contains(x_abs, y_abs) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let th = self.state.theme.sizes.title_height.get();
|
||||||
|
if y_abs - rect.y1() > th + 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let rd = &*self.render_data.borrow();
|
||||||
|
let (x, _) = rect.translate(x_abs, y_abs);
|
||||||
|
let mut prev_is_source = false;
|
||||||
|
let mut prev_center = 0;
|
||||||
|
for t in &rd.titles {
|
||||||
|
if t.ws.id == source {
|
||||||
|
prev_is_source = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let center = (t.x1 + t.x2) / 2;
|
||||||
|
if x < center {
|
||||||
|
return if prev_is_source {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(WorkspaceDragDestination {
|
||||||
|
highlight: Rect::new_sized(
|
||||||
|
rect.x1() + prev_center,
|
||||||
|
rect.y1(),
|
||||||
|
center - prev_center,
|
||||||
|
th,
|
||||||
|
)?,
|
||||||
|
output: self.clone(),
|
||||||
|
before: Some(t.ws.clone()),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
prev_center = center;
|
||||||
|
prev_is_source = false;
|
||||||
|
}
|
||||||
|
if prev_is_source {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return Some(WorkspaceDragDestination {
|
||||||
|
highlight: Rect::new_sized(
|
||||||
|
rect.x1() + prev_center,
|
||||||
|
rect.y1(),
|
||||||
|
rect.x2() - prev_center,
|
||||||
|
th,
|
||||||
|
)?,
|
||||||
|
output: self.clone(),
|
||||||
|
before: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputTitle {
|
pub struct OutputTitle {
|
||||||
|
|
@ -1214,7 +1277,11 @@ impl Node for OutputNode {
|
||||||
state: KeyState,
|
state: KeyState,
|
||||||
_serial: u32,
|
_serial: u32,
|
||||||
) {
|
) {
|
||||||
if state != KeyState::Pressed || button != BTN_LEFT {
|
if button != BTN_LEFT {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if state != KeyState::Pressed {
|
||||||
|
self.pointer_down.remove(&seat.id());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.button(PointerType::Seat(seat.id()));
|
self.button(PointerType::Seat(seat.id()));
|
||||||
|
|
@ -1258,6 +1325,10 @@ impl Node for OutputNode {
|
||||||
self.state.tree_changed();
|
self.state.tree_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_on_leave(&self, seat: &WlSeatGlobal) {
|
||||||
|
self.pointer_down.remove(&seat.id());
|
||||||
|
}
|
||||||
|
|
||||||
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
self.pointer_move(PointerType::Seat(seat.id()), x, y);
|
self.pointer_move(PointerType::Seat(seat.id()), x, y);
|
||||||
}
|
}
|
||||||
|
|
@ -1269,6 +1340,22 @@ impl Node for OutputNode {
|
||||||
|
|
||||||
fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
self.pointer_move(PointerType::Seat(seat.id()), x, y);
|
self.pointer_move(PointerType::Seat(seat.id()), x, y);
|
||||||
|
if let Some((down_x, down_y)) = self.pointer_down.get(&seat.id()) {
|
||||||
|
const DRAG_DIST: i32 = 10;
|
||||||
|
let dx = x.round_down() - down_x;
|
||||||
|
let dy = y.round_down() - down_y;
|
||||||
|
if dx * dx + dy * dy > DRAG_DIST * DRAG_DIST {
|
||||||
|
let rd = self.render_data.borrow_mut();
|
||||||
|
for title in &rd.titles {
|
||||||
|
if down_x >= title.x1 && down_x < title.x2 {
|
||||||
|
let ws = title.ws.clone();
|
||||||
|
drop(rd);
|
||||||
|
seat.start_workspace_drag(&ws);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, _time_usec: u64) {
|
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, _time_usec: u64) {
|
||||||
|
|
|
||||||
|
|
@ -379,8 +379,10 @@ impl ContainingNode for WorkspaceNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WsMoveConfig {
|
pub struct WsMoveConfig {
|
||||||
|
pub make_visible_always: bool,
|
||||||
pub make_visible_if_empty: bool,
|
pub make_visible_if_empty: bool,
|
||||||
pub source_is_destroyed: bool,
|
pub source_is_destroyed: bool,
|
||||||
|
pub before: Option<Rc<WorkspaceNode>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_ws_to_output(
|
pub fn move_ws_to_output(
|
||||||
|
|
@ -390,8 +392,19 @@ pub fn move_ws_to_output(
|
||||||
) {
|
) {
|
||||||
let source = ws.output.get();
|
let source = ws.output.get();
|
||||||
ws.set_output(&target);
|
ws.set_output(&target);
|
||||||
target.workspaces.add_last_existing(&ws);
|
'link: {
|
||||||
if config.make_visible_if_empty && target.workspace.is_none() && !target.is_dummy {
|
if let Some(before) = config.before {
|
||||||
|
if let Some(link) = &*before.output_link.borrow() {
|
||||||
|
link.prepend_existing(ws);
|
||||||
|
break 'link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.workspaces.add_last_existing(&ws);
|
||||||
|
}
|
||||||
|
let make_visible = !target.is_dummy
|
||||||
|
&& (config.make_visible_always
|
||||||
|
|| (config.make_visible_if_empty && target.workspace.is_none()));
|
||||||
|
if make_visible {
|
||||||
target.show_workspace(&ws);
|
target.show_workspace(&ws);
|
||||||
} else {
|
} else {
|
||||||
ws.set_visible(false);
|
ws.set_visible(false);
|
||||||
|
|
@ -423,3 +436,9 @@ pub fn move_ws_to_output(
|
||||||
target.state.damage(target.global.pos.get());
|
target.state.damage(target.global.pos.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WorkspaceDragDestination {
|
||||||
|
pub highlight: Rect,
|
||||||
|
pub output: Rc<OutputNode>,
|
||||||
|
pub before: Option<Rc<WorkspaceNode>>,
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue