fix: gate wayland features and add inline popover fallback
This commit is contained in:
parent
467998433c
commit
8b95675c9b
3 changed files with 85 additions and 23 deletions
92
src/main.rs
92
src/main.rs
|
|
@ -530,6 +530,7 @@ pub struct App {
|
|||
segmented_button::Entity,
|
||||
Option<String>,
|
||||
widget::Id,
|
||||
cosmic::iced::Point,
|
||||
)>,
|
||||
#[cfg(feature = "password_manager")]
|
||||
password_mgr: password_manager::PasswordManager,
|
||||
|
|
@ -2437,14 +2438,14 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
Message::CopyUrlByMenu => {
|
||||
if let Some((_, _, _, ref link, _)) = self.context_menu_popup {
|
||||
if let Some((_, _, _, ref link, _, _)) = self.context_menu_popup {
|
||||
if let Some(url) = link.clone() {
|
||||
return Task::batch([clipboard::write(url), self.update_focus()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::LaunchUrlByMenu => {
|
||||
if let Some((_, _, _, ref link, _)) = self.context_menu_popup {
|
||||
if let Some((_, _, _, ref link, _, _)) = self.context_menu_popup {
|
||||
if let Some(url) = link.as_ref() {
|
||||
if let Err(err) = open::that_detached(url) {
|
||||
log::warn!("failed to open {:?}: {}", url, err);
|
||||
|
|
@ -2799,11 +2800,14 @@ impl Application for App {
|
|||
Message::TabContextAction(entity, action) => {
|
||||
// Close context menu popup
|
||||
let mut tasks = Vec::new();
|
||||
if let Some((popup_id, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
if let Some((_popup_id, _, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::destroy_popup(popup_id),
|
||||
cosmic::surface::action::destroy_popup(_popup_id),
|
||||
)));
|
||||
}
|
||||
}
|
||||
// Also clear terminal context_menu state
|
||||
if let Some(tab_model) = self.pane_model.active() {
|
||||
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
|
|
@ -2815,14 +2819,18 @@ impl Application for App {
|
|||
return cosmic::Task::batch(tasks);
|
||||
}
|
||||
Message::TabContextMenu(pane, menu_state) => {
|
||||
#[allow(unused_mut)]
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
// Close existing context menu popup if any
|
||||
if let Some((popup_id, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
if let Some((_popup_id, _, _, _, _, _)) = self.context_menu_popup.take() {
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::destroy_popup(popup_id),
|
||||
cosmic::surface::action::destroy_popup(_popup_id),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all terminal context_menu state
|
||||
for (_, tab_model) in self.pane_model.panes.iter() {
|
||||
|
|
@ -2835,18 +2843,26 @@ impl Application for App {
|
|||
}
|
||||
|
||||
if let Some(menu_state) = menu_state {
|
||||
if let Some(position) = menu_state.position {
|
||||
if let Some(_position) = menu_state.position {
|
||||
let local_position = menu_state.local_position.unwrap_or(_position);
|
||||
if let Some(tab_model) = self.pane_model.panes.get(pane) {
|
||||
{
|
||||
let entity = tab_model.active();
|
||||
let link = menu_state.link.clone();
|
||||
let popup_id = window::Id::unique();
|
||||
self.context_menu_popup =
|
||||
Some((popup_id, pane, entity, link, widget::Id::unique()));
|
||||
self.context_menu_popup = Some((
|
||||
popup_id,
|
||||
pane,
|
||||
entity,
|
||||
link,
|
||||
widget::Id::unique(),
|
||||
local_position,
|
||||
));
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
if is_wayland() {
|
||||
let main_window = self.core.main_window_id().unwrap();
|
||||
let pos_x = position.x as i32;
|
||||
let pos_y = position.y as i32;
|
||||
let pos_x = _position.x as i32;
|
||||
let pos_y = _position.y as i32;
|
||||
|
||||
tasks.push(cosmic::task::message(Message::Surface(
|
||||
cosmic::surface::action::app_popup(move |_app: &mut Self| {
|
||||
|
|
@ -3159,7 +3175,7 @@ impl Application for App {
|
|||
return self.update_config();
|
||||
}
|
||||
Message::ContextMenuPopupClosed(id) => {
|
||||
if let Some((popup_id, _, _, _, _)) = &self.context_menu_popup {
|
||||
if let Some((popup_id, _, _, _, _, _)) = &self.context_menu_popup {
|
||||
if id == *popup_id {
|
||||
self.context_menu_popup = None;
|
||||
}
|
||||
|
|
@ -3272,7 +3288,7 @@ impl Application for App {
|
|||
}
|
||||
|
||||
fn on_close_requested(&self, id: window::Id) -> Option<Self::Message> {
|
||||
if let Some((popup_id, _, _, _, _)) = &self.context_menu_popup {
|
||||
if let Some((popup_id, _, _, _, _, _)) = &self.context_menu_popup {
|
||||
if id == *popup_id {
|
||||
return Some(Message::ContextMenuPopupClosed(id));
|
||||
}
|
||||
|
|
@ -3281,7 +3297,8 @@ impl Application for App {
|
|||
}
|
||||
|
||||
fn view_window(&self, window_id: window::Id) -> Element<'_, Message> {
|
||||
if let Some((popup_id, _pane, entity, ref link, ref autosize_id)) = self.context_menu_popup
|
||||
if let Some((popup_id, _pane, entity, ref link, ref autosize_id, _)) =
|
||||
self.context_menu_popup
|
||||
{
|
||||
if window_id == popup_id {
|
||||
return widget::autosize::autosize(
|
||||
|
|
@ -3365,7 +3382,42 @@ impl Application for App {
|
|||
terminal_box = terminal_box.context_menu(cosmic::iced::Point::ORIGIN);
|
||||
}
|
||||
|
||||
let tab_element: Element<'_, Message> = terminal_box.into();
|
||||
let use_wayland_popup = {
|
||||
#[cfg(feature = "wayland")]
|
||||
{
|
||||
is_wayland()
|
||||
}
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let tab_element: Element<'_, Message> = if !use_wayland_popup {
|
||||
// Fallback: render context menu as an inline popover
|
||||
if let Some((_, popup_pane, popup_entity, ref link, _, point)) =
|
||||
self.context_menu_popup
|
||||
{
|
||||
if pane == popup_pane {
|
||||
let mut popover = widget::popover(terminal_box.context_menu(point));
|
||||
popover = popover
|
||||
.popup(menu::context_menu(
|
||||
&self.config,
|
||||
&self.key_binds,
|
||||
popup_entity,
|
||||
link.clone(),
|
||||
))
|
||||
.position(widget::popover::Position::Point(point));
|
||||
popover.into()
|
||||
} else {
|
||||
terminal_box.into()
|
||||
}
|
||||
} else {
|
||||
terminal_box.into()
|
||||
}
|
||||
} else {
|
||||
terminal_box.into()
|
||||
};
|
||||
tab_column = tab_column.push(tab_element);
|
||||
}
|
||||
|
||||
|
|
@ -3519,3 +3571,11 @@ impl Application for App {
|
|||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
fn is_wayland() -> bool {
|
||||
matches!(
|
||||
cosmic::app::cosmic::windowing_system(),
|
||||
Some(cosmic::app::cosmic::WindowingSystem::Wayland)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ static MENU_ID: LazyLock<cosmic::widget::Id> =
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct MenuState {
|
||||
pub position: Option<Point>,
|
||||
pub local_position: Option<Point>,
|
||||
pub link: Option<String>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1306,6 +1306,7 @@ where
|
|||
);
|
||||
shell.publish(on_context_menu(Some(MenuState {
|
||||
position: Some(abs),
|
||||
local_position: Some(p),
|
||||
link,
|
||||
})));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue