cosmic-workspaces/src/main.rs

686 lines
24 KiB
Rust
Raw Normal View History

2023-02-09 14:29:34 -08:00
#![allow(clippy::single_match)]
2022-12-30 14:07:39 -08:00
use cctk::{
2022-12-30 15:21:05 -08:00
cosmic_protocols::{
toplevel_info::v1::client::zcosmic_toplevel_handle_v1,
2023-01-04 15:17:57 -08:00
toplevel_management::v1::client::zcosmic_toplevel_manager_v1,
2023-01-04 14:41:44 -08:00
workspace::v1::client::{zcosmic_workspace_handle_v1, zcosmic_workspace_manager_v1},
2022-12-30 15:21:05 -08:00
},
2023-03-27 10:37:30 -07:00
sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer},
2022-12-30 15:21:05 -08:00
toplevel_info::ToplevelInfo,
2023-01-04 15:41:19 -08:00
wayland_client::{
2023-12-06 10:03:39 -08:00
backend::ObjectId,
2023-07-10 13:55:32 -07:00
protocol::{wl_data_device_manager::DndAction, wl_output, wl_seat},
Connection, Proxy, WEnum,
2023-01-04 15:41:19 -08:00
},
2022-12-30 14:07:39 -08:00
};
2023-11-21 16:15:02 -05:00
use clap::Parser;
2023-01-17 12:36:05 -08:00
use cosmic::{
2023-11-21 16:15:02 -05:00
app::{Application, CosmicFlags, DbusActivationDetails, Message},
cctk,
2023-01-17 12:36:05 -08:00
iced::{
self,
event::wayland::{Event as WaylandEvent, OutputEvent},
keyboard::KeyCode,
2023-07-10 13:55:32 -07:00
wayland::{
actions::data_device::{DataFromMimeType, DndIcon},
data_device::{accept_mime_type, request_dnd_data, set_actions, start_drag},
2023-07-10 13:55:32 -07:00
},
2023-11-21 16:15:02 -05:00
widget, Command, Size, Subscription,
2023-01-17 12:36:05 -08:00
},
iced_runtime::{
2023-01-17 12:36:05 -08:00
command::platform_specific::wayland::layer_surface::{
IcedOutput, SctkLayerSurfaceSettings,
},
window::Id as SurfaceId,
},
2023-11-21 16:15:02 -05:00
iced_sctk::commands::layer_surface::{destroy_layer_surface, get_layer_surface},
2022-12-30 14:07:39 -08:00
};
use cosmic_comp_config::workspace::WorkspaceAmount;
use cosmic_config::{ConfigGet, ConfigSet};
2023-12-06 10:03:39 -08:00
use once_cell::sync::Lazy;
2023-11-03 13:06:43 -07:00
use std::{
collections::{HashMap, HashSet},
mem,
str::{self, FromStr},
2023-11-03 13:06:43 -07:00
};
2022-12-30 14:07:39 -08:00
2023-11-16 19:25:28 -08:00
mod view;
2022-12-30 14:07:39 -08:00
mod wayland;
2023-12-06 10:03:39 -08:00
// Include `pid` in mime. Want to drag between our surfaces, but not another
// process, if we use Wayland object ids.
static WORKSPACE_MIME: Lazy<String> =
Lazy::new(|| format!("text/x.cosmic-workspace-id-{}", std::process::id()));
static TOPLEVEL_MIME: Lazy<String> =
Lazy::new(|| format!("text/x.cosmic-toplevel-id-{}", std::process::id()));
2023-07-10 13:55:32 -07:00
2023-11-21 16:15:02 -05:00
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Args {}
#[derive(Default, Debug, Clone)]
pub struct WorkspaceCommands;
impl ToString for WorkspaceCommands {
fn to_string(&self) -> String {
String::new()
}
}
impl CosmicFlags for Args {
type SubCommand = WorkspaceCommands;
type Args = Vec<String>;
fn action(&self) -> Option<&WorkspaceCommands> {
None
}
}
2023-12-06 10:03:39 -08:00
struct WlDndId {
id: ObjectId,
mime_type: &'static str,
}
impl DataFromMimeType for WlDndId {
fn from_mime_type(&self, mime_type: &str) -> Option<Vec<u8>> {
if mime_type == self.mime_type {
Some(self.id.protocol_id().to_string().into_bytes())
} else {
None
}
}
}
2022-12-30 15:21:05 -08:00
#[derive(Clone, Debug)]
2022-12-30 14:07:39 -08:00
enum Msg {
WaylandEvent(WaylandEvent),
Wayland(wayland::Event),
Close,
2023-04-04 16:20:40 -07:00
Closed(SurfaceId),
2022-12-30 15:21:05 -08:00
ActivateWorkspace(zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1),
2023-01-18 10:58:22 -08:00
CloseWorkspace(zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1),
2023-01-04 15:17:57 -08:00
ActivateToplevel(zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1),
2023-01-18 10:58:22 -08:00
CloseToplevel(zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1),
2023-07-20 15:48:19 -07:00
StartDrag(Size, DragSurface),
DndWorkspaceEnter(
zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
wl_output::WlOutput,
DndAction,
Vec<String>,
(f32, f32),
),
2023-07-20 15:48:19 -07:00
DndWorkspaceLeave,
DndWorkspaceDrop,
DndWorkspaceData(String, Vec<u8>),
SourceFinished,
NewWorkspace,
2022-12-30 14:07:39 -08:00
}
#[derive(Debug)]
struct Workspace {
name: String,
2023-11-16 19:38:42 -08:00
img_for_output: HashMap<wl_output::WlOutput, wayland::CaptureImage>,
2022-12-30 14:07:39 -08:00
handle: zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
outputs: HashSet<wl_output::WlOutput>,
2023-01-05 18:30:50 -08:00
is_active: bool,
2022-12-30 14:07:39 -08:00
}
2022-12-30 15:21:05 -08:00
#[derive(Debug)]
struct Toplevel {
handle: zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1,
info: ToplevelInfo,
2023-11-16 19:38:42 -08:00
img: Option<wayland::CaptureImage>,
2022-12-30 15:21:05 -08:00
}
#[derive(Clone)]
struct Output {
handle: wl_output::WlOutput,
name: String,
width: i32,
height: i32,
}
2022-12-30 14:07:39 -08:00
struct LayerSurface {
output: wl_output::WlOutput,
2022-12-30 15:35:36 -08:00
// for transitions, would need windows in more than one workspace? But don't capture all of
// them all the time every frame.
2022-12-30 14:07:39 -08:00
}
2023-07-10 13:55:32 -07:00
#[derive(Clone, Debug)]
enum DragSurface {
#[allow(dead_code)]
Workspace {
handle: zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
output: wl_output::WlOutput,
},
2023-12-06 10:03:39 -08:00
Toplevel {
handle: zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1,
output: wl_output::WlOutput,
},
}
struct Conf {
cosmic_comp_config: cosmic_config::Config,
workspace_config: cosmic_comp_config::workspace::WorkspaceConfig,
}
impl Default for Conf {
fn default() -> Self {
let cosmic_comp_config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
let workspace_config = cosmic_comp_config.get("workspaces").unwrap_or_else(|err| {
eprintln!("Failed to read config 'worspaces': {}", err);
cosmic_comp_config::workspace::WorkspaceConfig::default()
});
Self {
cosmic_comp_config,
workspace_config,
}
}
}
2022-12-30 14:07:39 -08:00
#[derive(Default)]
struct App {
layer_surfaces: HashMap<SurfaceId, LayerSurface>,
outputs: Vec<Output>,
2022-12-30 14:07:39 -08:00
workspaces: Vec<Workspace>,
2022-12-30 15:21:05 -08:00
toplevels: Vec<Toplevel>,
2023-01-04 15:17:57 -08:00
conn: Option<Connection>,
workspace_manager: Option<zcosmic_workspace_manager_v1::ZcosmicWorkspaceManagerV1>,
toplevel_manager: Option<zcosmic_toplevel_manager_v1::ZcosmicToplevelManagerV1>,
2023-01-04 15:41:19 -08:00
seats: Vec<wl_seat::WlSeat>,
visible: bool,
wayland_cmd_sender: Option<calloop::channel::Sender<wayland::Cmd>>,
2023-07-20 15:48:19 -07:00
drag_surface: Option<(SurfaceId, DragSurface, Size)>,
conf: Conf,
2023-11-21 16:15:02 -05:00
core: cosmic::app::Core,
drop_target: Option<(
zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
wl_output::WlOutput,
)>,
2022-12-30 14:07:39 -08:00
}
impl App {
2023-01-05 18:30:50 -08:00
fn workspace_for_handle(
&self,
handle: &zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
) -> Option<&Workspace> {
self.workspaces.iter().find(|i| &i.handle == handle)
}
fn workspace_for_handle_mut(
&mut self,
handle: &zcosmic_workspace_handle_v1::ZcosmicWorkspaceHandleV1,
) -> Option<&mut Workspace> {
self.workspaces.iter_mut().find(|i| &i.handle == handle)
}
fn toplevel_for_handle_mut(
&mut self,
handle: &zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1,
) -> Option<&mut Toplevel> {
self.toplevels.iter_mut().find(|i| &i.handle == handle)
}
2023-11-21 16:15:02 -05:00
fn create_surface(
&mut self,
output: wl_output::WlOutput,
) -> Command<cosmic::app::Message<Msg>> {
2023-12-08 20:14:31 -08:00
let id = SurfaceId::unique();
self.layer_surfaces.insert(
2023-02-09 14:29:34 -08:00
id,
LayerSurface {
output: output.clone(),
},
);
get_layer_surface(SctkLayerSurfaceSettings {
id,
keyboard_interactivity: KeyboardInteractivity::Exclusive,
namespace: "cosmic-workspace-overview".into(),
layer: Layer::Overlay,
2023-03-27 10:37:30 -07:00
size: Some((None, None)),
output: IcedOutput::Output(output),
2023-03-27 10:37:30 -07:00
anchor: Anchor::all(),
..Default::default()
})
}
2023-11-21 16:15:02 -05:00
fn destroy_surface(
&mut self,
output: &wl_output::WlOutput,
) -> Command<cosmic::app::Message<Msg>> {
if let Some((id, _)) = self
.layer_surfaces
.iter()
.find(|(_id, surface)| &surface.output == output)
{
let id = *id;
self.layer_surfaces.remove(&id).unwrap();
destroy_layer_surface(id)
} else {
Command::none()
}
}
2023-11-21 16:15:02 -05:00
fn toggle(&mut self) -> Command<cosmic::app::Message<Msg>> {
if self.visible {
self.hide()
} else {
self.show()
}
}
2023-11-21 16:15:02 -05:00
fn show(&mut self) -> Command<cosmic::app::Message<Msg>> {
if !self.visible {
self.visible = true;
let outputs = self.outputs.clone();
let cmd = Command::batch(
outputs
.into_iter()
2023-11-16 13:42:19 -08:00
.map(|output| self.create_surface(output.handle))
.collect::<Vec<_>>(),
);
self.update_capture_filter();
cmd
} else {
Command::none()
}
}
// Close all shell surfaces
2023-11-21 16:15:02 -05:00
fn hide(&mut self) -> Command<cosmic::app::Message<Msg>> {
self.visible = false;
self.update_capture_filter();
Command::batch(
mem::take(&mut self.layer_surfaces)
.into_keys()
.map(destroy_layer_surface)
.collect::<Vec<_>>(),
)
}
fn update_capture_filter(&self) {
if let Some(sender) = self.wayland_cmd_sender.as_ref() {
let mut capture_filter = wayland::CaptureFilter::default();
if self.visible {
// XXX handle on wrong connection
capture_filter.workspaces_on_outputs =
self.outputs.iter().map(|x| x.handle.clone()).collect();
capture_filter.toplevels_on_workspaces = self
.workspaces
.iter()
.filter(|x| x.is_active)
.map(|x| x.handle.clone())
.collect();
}
let _ = sender.send(wayland::Cmd::CaptureFilter(capture_filter));
}
}
2022-12-30 14:07:39 -08:00
}
impl Application for App {
type Message = Msg;
type Executor = iced::executor::Default;
2023-11-21 16:15:02 -05:00
type Flags = Args;
const APP_ID: &'static str = "com.system76.CosmicWorkspaces";
fn init(
core: cosmic::app::Core,
_flags: Self::Flags,
) -> (Self, iced::Command<Message<Self::Message>>) {
(
Self {
core,
..Default::default()
},
Command::none(),
)
2022-12-30 14:07:39 -08:00
}
// TODO: show panel and dock? Drag?
2023-11-21 16:15:02 -05:00
fn update(&mut self, message: Msg) -> Command<cosmic::app::Message<Msg>> {
2022-12-30 14:07:39 -08:00
match message {
Msg::SourceFinished => {}
2022-12-30 14:07:39 -08:00
Msg::WaylandEvent(evt) => match evt {
WaylandEvent::Output(evt, output) => {
// TODO: Less hacky way to get connection from iced-sctk
if self.conn.is_none() {
if let Some(backend) = output.backend().upgrade() {
self.conn = Some(Connection::from_backend(backend));
2022-12-30 14:07:39 -08:00
}
}
match evt {
OutputEvent::Created(Some(info)) => {
if let (Some((width, height)), Some(name)) =
(info.logical_size, info.name)
{
self.outputs.push(Output {
handle: output.clone(),
name: name.clone(),
width,
height,
});
if self.visible {
2023-11-16 13:42:19 -08:00
return self.create_surface(output.clone());
}
}
2023-01-20 14:02:52 -08:00
}
OutputEvent::Created(None) => {} // XXX?
OutputEvent::InfoUpdate(info) => {
if let Some(output) =
self.outputs.iter_mut().find(|x| x.handle == output)
{
if let Some((width, height)) = info.logical_size {
output.width = width;
output.height = height;
}
if let Some(name) = info.name {
output.name = name;
}
// XXX re-create surface?
}
}
OutputEvent::Removed => {
if let Some(idx) = self.outputs.iter().position(|x| x.handle == output)
{
self.outputs.remove(idx);
}
if self.visible {
return self.destroy_surface(&output);
}
2022-12-30 14:07:39 -08:00
}
}
}
2022-12-30 14:07:39 -08:00
_ => {}
},
Msg::Wayland(evt) => {
match evt {
wayland::Event::CmdSender(sender) => {
self.wayland_cmd_sender = Some(sender);
}
2023-01-04 15:17:57 -08:00
wayland::Event::ToplevelManager(manager) => {
self.toplevel_manager = Some(manager);
}
wayland::Event::WorkspaceManager(manager) => {
self.workspace_manager = Some(manager);
2023-01-04 14:41:44 -08:00
}
2022-12-30 14:07:39 -08:00
wayland::Event::Workspaces(workspaces) => {
2023-01-04 14:41:44 -08:00
let old_workspaces = mem::take(&mut self.workspaces);
2022-12-30 14:07:39 -08:00
self.workspaces = Vec::new();
for (outputs, workspace) in workspaces {
2023-01-04 14:41:44 -08:00
let is_active = workspace.state.contains(&WEnum::Value(
zcosmic_workspace_handle_v1::State::Active,
));
// XXX efficiency
2023-03-22 10:03:18 -07:00
let img_for_output = old_workspaces
2023-01-04 14:41:44 -08:00
.iter()
2023-02-09 14:29:34 -08:00
.find(|i| i.handle == workspace.handle)
2023-03-22 10:03:18 -07:00
.map(|i| i.img_for_output.clone())
.unwrap_or_default();
2023-01-04 14:41:44 -08:00
2022-12-30 14:07:39 -08:00
self.workspaces.push(Workspace {
name: workspace.name,
handle: workspace.handle,
outputs,
2023-03-22 10:03:18 -07:00
img_for_output,
2023-01-05 18:30:50 -08:00
is_active,
2022-12-30 14:07:39 -08:00
});
}
self.update_capture_filter();
2022-12-30 14:07:39 -08:00
}
wayland::Event::NewToplevel(handle, info) => {
2023-02-09 14:29:34 -08:00
println!("New toplevel: {info:?}");
2022-12-30 15:21:05 -08:00
self.toplevels.push(Toplevel {
handle,
info,
img: None,
});
}
wayland::Event::UpdateToplevel(handle, info) => {
2023-02-10 13:41:08 -08:00
if let Some(toplevel) =
self.toplevels.iter_mut().find(|x| x.handle == handle)
{
toplevel.info = info;
}
}
2023-01-18 11:01:47 -08:00
wayland::Event::CloseToplevel(handle) => {
if let Some(idx) = self.toplevels.iter().position(|x| x.handle == handle) {
self.toplevels.remove(idx);
}
}
2023-03-22 10:03:18 -07:00
wayland::Event::WorkspaceCapture(handle, output_name, image) => {
if let Some(workspace) = self.workspace_for_handle_mut(&handle) {
2023-03-22 10:03:18 -07:00
workspace.img_for_output.insert(output_name, image);
2022-12-30 14:07:39 -08:00
}
}
wayland::Event::ToplevelCapture(handle, image) => {
if let Some(toplevel) = self.toplevel_for_handle_mut(&handle) {
2023-02-10 13:41:08 -08:00
//println!("Got toplevel image!");
2023-02-09 14:29:34 -08:00
toplevel.img = Some(image);
2022-12-30 15:21:05 -08:00
}
}
2023-01-04 15:41:19 -08:00
wayland::Event::Seats(seats) => {
self.seats = seats;
}
2022-12-30 14:07:39 -08:00
}
}
Msg::Close => {
2023-01-26 16:01:43 -08:00
return self.hide();
2022-12-30 14:07:39 -08:00
}
Msg::Closed(_) => {}
2022-12-30 15:35:36 -08:00
Msg::ActivateWorkspace(workspace_handle) => {
2023-01-04 15:17:57 -08:00
let workspace_manager = self.workspace_manager.as_ref().unwrap();
2023-01-04 14:41:44 -08:00
workspace_handle.activate();
workspace_manager.commit();
2023-02-09 14:29:34 -08:00
let _ = self.conn.as_ref().unwrap().flush();
2023-01-04 15:17:57 -08:00
}
Msg::ActivateToplevel(toplevel_handle) => {
if let Some(toplevel_manager) = self.toplevel_manager.as_ref() {
2023-01-04 15:41:19 -08:00
if !self.seats.is_empty() {
for seat in &self.seats {
2023-02-09 14:29:34 -08:00
toplevel_manager.activate(&toplevel_handle, seat);
2023-01-04 15:41:19 -08:00
}
2023-02-09 14:29:34 -08:00
let _ = self.conn.as_ref().unwrap().flush();
2023-01-26 16:01:43 -08:00
return self.hide();
2023-01-04 15:41:19 -08:00
}
2023-01-04 15:17:57 -08:00
}
2022-12-30 15:21:05 -08:00
}
2023-02-09 14:29:34 -08:00
Msg::CloseWorkspace(_workspace_handle) => {}
2023-01-18 10:58:22 -08:00
Msg::CloseToplevel(toplevel_handle) => {
// TODO confirmation?
if let Some(toplevel_manager) = self.toplevel_manager.as_ref() {
toplevel_manager.close(&toplevel_handle);
}
}
2023-07-20 15:48:19 -07:00
Msg::StartDrag(size, drag_surface) => {
let (wl_id, output, mime_type) = match &drag_surface {
DragSurface::Workspace { handle, output } => {
(handle.clone().id(), output, &*WORKSPACE_MIME)
}
DragSurface::Toplevel { handle, output } => {
(handle.clone().id(), output, &*TOPLEVEL_MIME)
}
};
2023-12-08 20:14:31 -08:00
let id = SurfaceId::unique();
2023-12-06 10:03:39 -08:00
if let Some((parent_id, _)) = self
.layer_surfaces
.iter()
.find(|(_, x)| &x.output == output)
{
self.drag_surface = Some((id, drag_surface, size));
return start_drag(
vec![mime_type.to_string()],
DndAction::Move,
*parent_id,
Some(DndIcon::Custom(id)),
Box::new(WlDndId {
id: wl_id,
mime_type,
}),
);
2023-07-10 13:55:32 -07:00
}
}
Msg::DndWorkspaceEnter(handle, output, action, mimes, (_x, _y)) => {
self.drop_target = Some((handle, output));
// XXX
// if mimes.iter().any(|x| x == WORKSPACE_MIME) && action == DndAction::Move {
if mimes.iter().any(|x| x == &*TOPLEVEL_MIME) {
2023-11-16 13:42:19 -08:00
return Command::batch(vec![
set_actions(DndAction::Move, DndAction::Move),
accept_mime_type(Some(TOPLEVEL_MIME.to_string())),
2023-11-16 13:42:19 -08:00
]);
2023-07-20 15:48:19 -07:00
}
}
Msg::DndWorkspaceLeave => {
// XXX Doesn't work since leave for a widget may come after enter for another
// self.drop_target = None;
// return accept_mime_type(None);
2023-07-20 15:48:19 -07:00
}
Msg::DndWorkspaceDrop => {
return request_dnd_data(TOPLEVEL_MIME.to_string());
}
Msg::DndWorkspaceData(mime_type, data) => {
if mime_type == *TOPLEVEL_MIME {
// XXX getting empty data?
let _protocol_id = str::from_utf8(&data)
.ok()
.and_then(|s| u32::from_str(s).ok());
if let Some((_, DragSurface::Toplevel { handle, .. }, _)) = &self.drag_surface {
if let Some(toplevel) = self.toplevels.iter().find(|t| &t.handle == handle)
{
if let Some(drop_target) = &self.drop_target {
if let Some(toplevel_manager) = self.toplevel_manager.as_ref() {
if toplevel_manager.version() >= 2 {
toplevel_manager.move_to_workspace(
handle,
&drop_target.0,
&drop_target.1,
);
}
}
}
}
}
}
}
Msg::NewWorkspace => {
if let WorkspaceAmount::Static(n) = &mut self.conf.workspace_config.workspace_amount
{
*n += 1;
self.conf
.cosmic_comp_config
.set("workspaces", &self.conf.workspace_config);
}
}
2022-12-30 14:07:39 -08:00
}
Command::none()
}
2023-11-21 16:15:02 -05:00
fn dbus_activation(
&mut self,
msg: cosmic::app::DbusActivationMessage,
) -> iced::Command<cosmic::app::Message<Self::Message>> {
if let DbusActivationDetails::Activate = msg.msg {
self.toggle()
} else {
Command::none()
}
}
2022-12-30 14:07:39 -08:00
fn subscription(&self) -> Subscription<Msg> {
2023-12-05 09:48:59 -08:00
let events = iced::event::listen_with(|evt, _| {
2022-12-30 14:07:39 -08:00
if let iced::Event::PlatformSpecific(iced::event::PlatformSpecific::Wayland(evt)) = evt
{
Some(Msg::WaylandEvent(evt))
} else if let iced::Event::Keyboard(iced::keyboard::Event::KeyReleased {
key_code: KeyCode::Escape,
modifiers: _,
}) = evt
{
Some(Msg::Close)
} else {
None
}
});
2023-11-21 16:15:02 -05:00
let mut subscriptions = vec![events];
if let Some(conn) = self.conn.clone() {
subscriptions.push(wayland::subscription(conn).map(Msg::Wayland));
}
iced::Subscription::batch(subscriptions)
2022-12-30 14:07:39 -08:00
}
2023-11-21 16:15:02 -05:00
fn view(&self) -> cosmic::prelude::Element<Self::Message> {
unreachable!()
}
fn view_window(&self, id: iced::window::Id) -> cosmic::prelude::Element<Self::Message> {
2022-12-30 14:07:39 -08:00
use iced::widget::*;
2023-04-04 16:20:40 -07:00
if let Some(surface) = self.layer_surfaces.get(&id) {
2023-11-16 19:25:28 -08:00
return view::layer_surface(self, surface);
2023-04-04 16:20:40 -07:00
}
2023-07-20 15:48:19 -07:00
if let Some((drag_id, drag_surface, size)) = &self.drag_surface {
2023-07-10 13:55:32 -07:00
if drag_id == &id {
match drag_surface {
DragSurface::Workspace { handle, output } => {
if let Some(workspace) =
self.workspaces.iter().find(|x| &x.handle == handle)
{
2023-11-16 19:25:28 -08:00
let item = view::workspace_item(workspace, output);
2023-07-20 15:48:19 -07:00
return widget::container(item)
.height(iced::Length::Fixed(size.height))
2023-12-06 10:03:39 -08:00
.width(iced::Length::Fixed(size.width))
.into();
}
}
DragSurface::Toplevel { handle, .. } => {
if let Some(toplevel) = self.toplevels.iter().find(|x| &x.handle == handle)
{
let item = view::toplevel_preview(toplevel);
return widget::container(item)
.height(iced::Length::Fixed(size.height))
2023-07-20 15:48:19 -07:00
.width(iced::Length::Fixed(size.width))
.into();
2023-07-10 13:55:32 -07:00
}
}
}
}
}
println!("NO VIEW");
2022-12-30 14:07:39 -08:00
text("workspaces").into()
}
2023-11-21 16:15:02 -05:00
fn on_close_requested(&self, id: SurfaceId) -> Option<Msg> {
Some(Msg::Closed(id))
}
fn core(&self) -> &cosmic::app::Core {
&self.core
}
fn core_mut(&mut self) -> &mut cosmic::app::Core {
&mut self.core
2022-12-30 14:07:39 -08:00
}
fn style(
&self,
) -> Option<<cosmic::Theme as cosmic::iced_style::application::StyleSheet>::Style> {
Some(cosmic::theme::style::iced::Application::default())
}
2022-12-30 14:07:39 -08:00
}
pub fn main() -> iced::Result {
2023-04-13 14:30:47 -07:00
env_logger::init();
2023-11-21 16:15:02 -05:00
cosmic::app::run_single_instance::<App>(
cosmic::app::Settings::default()
.antialiasing(true)
.no_main_window(true)
.exit_on_close(false),
Args::parse(),
)
2022-12-30 14:07:39 -08:00
}