Skip to content

Commit

Permalink
menu: Add stack tab specific menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed Dec 12, 2023
1 parent 7f027fb commit 8643645
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 47 deletions.
3 changes: 2 additions & 1 deletion resources/i18n/en/cosmic_comp.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ window-menu-resize = Resize
window-menu-move-prev-workspace = Move to previous workspace
window-menu-move-next-workspace = Move to next workspace
window-menu-stack = Create window stack
window-menu-unstack = Unstack windows
window-menu-unstack-all = Unstack windows
window-menu-unstack = Unstack window
window-menu-always-on-top = Always on top
window-menu-always-on-visible-ws = Always on visible workspace
window-menu-close = Close
Expand Down
36 changes: 36 additions & 0 deletions src/shell/element/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ impl CosmicStack {
pub enum Message {
DragStart,
Menu,
TabMenu(usize),
PotentialTabDragStart(usize),
Activate(usize),
Close(usize),
Expand Down Expand Up @@ -709,6 +710,40 @@ impl Program for CosmicStackInternal {
&seat,
serial,
cursor - position.as_logical(),
true,
);
}
}
});
}
}
}
Message::TabMenu(idx) => {
if let Some((seat, serial)) = self.last_seat.lock().unwrap().clone() {
if let Some(surface) = self.windows.lock().unwrap()[idx].wl_surface() {
loop_handle.insert_idle(move |state| {
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 position = workspace
.element_geometry(&mapped)
.unwrap()
.loc
.to_global(&workspace.output);
let mut cursor = seat
.get_pointer()
.unwrap()
.current_location()
.to_i32_round();
cursor.y -= TAB_HEIGHT;
Shell::menu_request(
state,
&surface,
&seat,
serial,
cursor - position.as_logical(),
false,
);
}
}
Expand Down Expand Up @@ -763,6 +798,7 @@ impl Program for CosmicStackInternal {
user_data.get::<Id>().unwrap().clone(),
)
.on_press(Message::PotentialTabDragStart(i))
.on_right_click(Message::TabMenu(i))
.on_close(Message::Close(i))
}),
active,
Expand Down
18 changes: 18 additions & 0 deletions src/shell/element/stack/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub struct Tab<Message: TabMessage> {
font: Font,
close_message: Option<Message>,
press_message: Option<Message>,
right_click_message: Option<Message>,
rule_theme: TabRuleTheme,
background_theme: TabBackgroundTheme,
active: bool,
Expand All @@ -135,6 +136,7 @@ impl<Message: TabMessage> Tab<Message> {
font: cosmic::font::FONT,
close_message: None,
press_message: None,
right_click_message: None,
rule_theme: TabRuleTheme::Default,
background_theme: TabBackgroundTheme::Default,
active: false,
Expand All @@ -146,6 +148,11 @@ impl<Message: TabMessage> Tab<Message> {
self
}

pub fn on_right_click(mut self, message: Message) -> Self {
self.right_click_message = Some(message);
self
}

pub fn on_close(mut self, message: Message) -> Self {
self.close_message = Some(message);
self
Expand Down Expand Up @@ -238,6 +245,7 @@ impl<Message: TabMessage> Tab<Message> {
background: self.background_theme.into(),
elements: items,
press_message: self.press_message,
right_click_message: self.right_click_message,
}
}
}
Expand All @@ -256,6 +264,7 @@ pub(super) struct TabInternal<'a, Message: TabMessage, Renderer> {
background: theme::Container,
elements: Vec<Element<'a, Message, Renderer>>,
press_message: Option<Message>,
right_click_message: Option<Message>,
}

impl<'a, Message, Renderer> Widget<Message, Renderer> for TabInternal<'a, Message, Renderer>
Expand Down Expand Up @@ -382,6 +391,15 @@ where
return event::Status::Captured;
}
}
if matches!(
event,
event::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right))
) {
if let Some(message) = self.right_click_message.clone() {
shell.publish(message);
return event::Status::Captured;
}
}
if matches!(
event,
event::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
Expand Down
1 change: 1 addition & 0 deletions src/shell/element/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ impl Program for CosmicWindowInternal {
&seat,
serial,
cursor - position.as_logical(),
false,
);
}
}
Expand Down
73 changes: 69 additions & 4 deletions src/shell/grabs/menu/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ use smithay::wayland::seat::WaylandFocus;
use crate::{
config::{Action, StaticConfig},
fl,
shell::{element::CosmicMapped, grabs::ReleaseMode, Shell},
shell::{
element::{CosmicMapped, CosmicWindow},
grabs::ReleaseMode,
CosmicSurface, Shell,
},
state::{Common, State},
utils::screenshot::screenshot_window,
utils::{prelude::SeatExt, screenshot::screenshot_window},
};

use super::{Item, ResizeEdge};
Expand Down Expand Up @@ -99,6 +103,66 @@ fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
}
}

pub fn tab_items(
stack: &CosmicMapped,
tab: &CosmicSurface,
is_tiled: bool,
config: &StaticConfig,
) -> impl Iterator<Item = Item> {
let unstack_clone_stack = stack.clone();
let unstack_clone_tab = tab.clone();
let screenshot_clone = tab.clone();
let close_clone = tab.clone();

vec![
Item::new(fl!("window-menu-unstack"), move |handle| {
let mut mapped = unstack_clone_stack.clone();
let surface = unstack_clone_tab.clone();
let _ = handle.insert_idle(move |state| {
mapped.stack_ref_mut().unwrap().remove_window(&surface);
let mapped: CosmicMapped = CosmicWindow::new(
surface,
state.common.event_loop_handle.clone(),
state.common.theme.clone(),
)
.into();

let seat = state.common.last_active_seat().clone();
let output = seat.active_output();
let workspace = state.common.shell.workspaces.active_mut(&output);
if is_tiled {
for mapped in workspace
.mapped()
.filter(|m| m.maximized_state.lock().unwrap().is_some())
.cloned()
.collect::<Vec<_>>()
.into_iter()
{
workspace.unmaximize_request(&mapped.active_window());
}
let focus_stack = workspace.focus_stack.get(&seat);
workspace
.tiling_layer
.map(mapped, Some(focus_stack.iter()), None, false);
} else {
workspace.floating_layer.map(mapped, None)
}
});
}),
Item::Separator,
Item::new(fl!("window-menu-screenshot"), move |handle| {
let tab = screenshot_clone.clone();
let _ = handle.insert_idle(move |state| screenshot_window(state, &tab));
}),
Item::Separator,
Item::new(fl!("window-menu-close"), move |_handle| {
close_clone.close();
})
.shortcut(config.get_shortcut_for_action(&Action::Close)),
]
.into_iter()
}

pub fn window_items(
window: &CosmicMapped,
is_tiled: bool,
Expand Down Expand Up @@ -126,7 +190,7 @@ pub fn window_items(

vec![
is_stacked.then_some(
Item::new(fl!("window-menu-unstack"), move |handle| {
Item::new(fl!("window-menu-unstack-all"), move |handle| {
let mapped = unstack_clone.clone();
let _ = handle.insert_idle(move |state| {
unstack(state, &mapped);
Expand Down Expand Up @@ -161,7 +225,8 @@ pub fn window_items(
// TODO: Where to save?
Some(Item::new(fl!("window-menu-screenshot"), move |handle| {
let mapped = screenshot_clone.clone();
let _ = handle.insert_idle(move |state| screenshot_window(state, &mapped));
let _ =
handle.insert_idle(move |state| screenshot_window(state, &mapped.active_window()));
})),
Some(Item::Separator),
Some(Item::new(fl!("window-menu-move"), move |handle| {
Expand Down
28 changes: 23 additions & 5 deletions src/shell/layout/tiling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,24 +367,33 @@ impl TilingLayout {
window: CosmicMapped,
focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>,
direction: Option<Direction>,
add_to_stack: bool,
) {
window.output_enter(&self.output, window.bbox());
window.set_bounds(self.output.geometry().size.as_logical());
self.map_internal(window, focus_stack, direction);
self.map_internal(window, focus_stack, direction, add_to_stack);
}

pub fn map_internal<'a>(
&mut self,
window: impl Into<CosmicMapped>,
focus_stack: Option<impl Iterator<Item = &'a CosmicMapped> + 'a>,
direction: Option<Direction>,
add_to_stack: bool,
) {
let gaps = self.gaps();

let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
let last_active = focus_stack
.and_then(|focus_stack| TilingLayout::last_active_window(&mut tree, focus_stack));
TilingLayout::map_to_tree(&mut tree, window, &self.output, last_active, direction);
TilingLayout::map_to_tree(
&mut tree,
window,
&self.output,
last_active,
direction,
add_to_stack,
);
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
}
Expand All @@ -395,6 +404,7 @@ impl TilingLayout {
output: &Output,
node: Option<(NodeId, CosmicMapped)>,
direction: Option<Direction>,
add_to_stack: bool,
) {
let window = window.into();
let new_window = Node::new(Data::Mapped {
Expand Down Expand Up @@ -425,7 +435,7 @@ impl TilingLayout {
}
} else {
if let Some((ref node_id, mut last_active_window)) = node {
if window.is_window() && last_active_window.is_stack() {
if add_to_stack && window.is_window() && last_active_window.is_stack() {
let surface = window.active_window();
last_active_window
.stack_ref_mut()
Expand Down Expand Up @@ -533,7 +543,7 @@ impl TilingLayout {
}

mapped.set_tiled(true);
other.map(mapped.clone(), Some(focus_stack), None);
other.map(mapped.clone(), Some(focus_stack), None, true);
return Some(KeyboardFocusTarget::Element(mapped));
}
None => {
Expand Down Expand Up @@ -1964,6 +1974,7 @@ impl TilingLayout {
&self.output,
Some(current_node),
None,
false,
);

let node = window.tiling_node_id.lock().unwrap().clone().unwrap();
Expand Down Expand Up @@ -2494,7 +2505,14 @@ impl TilingLayout {
}
}
_ => {
TilingLayout::map_to_tree(&mut tree, window.clone(), &self.output, None, None);
TilingLayout::map_to_tree(
&mut tree,
window.clone(),
&self.output,
None,
None,
false,
);
window
}
};
Expand Down
Loading

0 comments on commit 8643645

Please sign in to comment.