feat: app list is working fairly well again

This commit is contained in:
Ashley Wulber 2022-07-20 16:17:43 -04:00
parent 2a8497fb2a
commit ab851fceef
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
13 changed files with 80 additions and 66 deletions

3
Cargo.lock generated
View file

@ -299,7 +299,6 @@ dependencies = [
"rust-embed", "rust-embed",
"serde", "serde",
"serde_json", "serde_json",
"tokio",
"wayland-backend", "wayland-backend",
"wayland-client 0.30.0-beta.8", "wayland-client 0.30.0-beta.8",
"xdg", "xdg",
@ -443,7 +442,7 @@ dependencies = [
"i18n-embed", "i18n-embed",
"i18n-embed-fl", "i18n-embed-fl",
"log", "log",
"nix 0.22.3", "nix 0.24.1",
"once_cell", "once_cell",
"pretty_env_logger", "pretty_env_logger",
"rust-embed", "rust-embed",

View file

@ -13,7 +13,6 @@ gio = { git = "https://github.com/gtk-rs/gtk-rs-core" }
libcosmic = { git = "https://github.com/pop-os/libcosmic", branch = "relm4-next" } libcosmic = { git = "https://github.com/pop-os/libcosmic", branch = "relm4-next" }
relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" } relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }
serde_json = "1.0.78" serde_json = "1.0.78"
tokio = { version = "1.16.1", features = ["sync"] }
futures = "0.3.19" futures = "0.3.19"
futures-util = "0.3.19" futures-util = "0.3.19"
once_cell = "1.9.0" once_cell = "1.9.0"

View file

@ -1,10 +1,6 @@
use std::env;
use crate::TX;
// SPDX-License-Identifier: MPL-2.0-only // SPDX-License-Identifier: MPL-2.0-only
use crate::dock_list::DockList; use crate::dock_list::DockList;
use crate::dock_list::DockListType; use crate::dock_list::DockListType;
use crate::utils::AppListEvent;
use cascade::cascade; use cascade::cascade;
use cosmic_panel_config::{CosmicPanelConfig, PanelAnchor}; use cosmic_panel_config::{CosmicPanelConfig, PanelAnchor};
use gtk4::prelude::*; use gtk4::prelude::*;
@ -12,7 +8,6 @@ use gtk4::subclass::prelude::*;
use gtk4::Orientation; use gtk4::Orientation;
use gtk4::Separator; use gtk4::Separator;
use gtk4::{gio, glib}; use gtk4::{gio, glib};
use tokio::sync::mpsc::Sender;
mod imp; mod imp;

View file

@ -43,7 +43,10 @@ impl CosmicAppListWindow {
} }
pub fn apps_container(&self) -> &AppsContainer { pub fn apps_container(&self) -> &AppsContainer {
imp::CosmicAppListWindow::from_instance(&self).inner.get().unwrap() imp::CosmicAppListWindow::from_instance(&self)
.inner
.get()
.unwrap()
} }
fn setup_shortcuts(&self) { fn setup_shortcuts(&self) {

View file

@ -1,17 +1,15 @@
// SPDX-License-Identifier: MPL-2.0-only // SPDX-License-Identifier: MPL-2.0-only
use glib::subclass::Signal; use gtk4::{
use gtk4::glib; glib::{self, subclass::Signal},
use gtk4::prelude::*; prelude::*,
use gtk4::subclass::prelude::*; subclass::prelude::*,
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use once_cell::sync::OnceCell;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use tokio::sync::mpsc::Sender;
use crate::dock_popover::DockPopover; use crate::dock_popover::DockPopover;
use crate::utils::AppListEvent;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct DockItem { pub struct DockItem {
@ -20,7 +18,6 @@ pub struct DockItem {
pub item_box: Rc<RefCell<gtk4::Box>>, pub item_box: Rc<RefCell<gtk4::Box>>,
pub popover: Rc<RefCell<gtk4::Popover>>, pub popover: Rc<RefCell<gtk4::Popover>>,
pub popover_menu: Rc<RefCell<Option<DockPopover>>>, pub popover_menu: Rc<RefCell<Option<DockPopover>>>,
pub tx: OnceCell<Sender<AppListEvent>>,
pub icon_size: Rc<Cell<u32>>, pub icon_size: Rc<Cell<u32>>,
} }

View file

@ -14,7 +14,6 @@ use gtk4::Image;
use gtk4::Orientation; use gtk4::Orientation;
use gtk4::Popover; use gtk4::Popover;
use gtk4::{Align, PositionType}; use gtk4::{Align, PositionType};
use tokio::sync::mpsc::Sender;
mod imp; mod imp;

View file

@ -8,7 +8,6 @@ use gtk4::{Box, DragSource, DropTarget, GestureClick, ListView};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use tokio::sync::mpsc;
use crate::utils::AppListEvent; use crate::utils::AppListEvent;
@ -24,7 +23,6 @@ pub struct DockList {
pub drag_cancel_signal: Rc<RefCell<Option<SignalHandlerId>>>, pub drag_cancel_signal: Rc<RefCell<Option<SignalHandlerId>>>,
pub popover_menu_index: Rc<Cell<Option<u32>>>, pub popover_menu_index: Rc<Cell<Option<u32>>>,
pub position: Rc<Cell<PanelAnchor>>, pub position: Rc<Cell<PanelAnchor>>,
pub tx: OnceCell<mpsc::Sender<AppListEvent>>,
pub config: OnceCell<CosmicPanelConfig>, pub config: OnceCell<CosmicPanelConfig>,
} }

View file

@ -1,34 +1,26 @@
// SPDX-License-Identifier: MPL-2.0-only // SPDX-License-Identifier: MPL-2.0-only
use crate::dock_item::DockItem; use crate::{
use crate::dock_object::DockObject; dock_item::DockItem,
use crate::utils::data_path; utils::{AppListEvent, BoxedWindowList, data_path},
use crate::utils::{AppListEvent, BoxedWindowList}; wayland::{Toplevel, ToplevelEvent},
use crate::wayland::{Toplevel, ToplevelEvent}; {TX, WAYLAND_TX}, dock_object::DockObject,
use crate::{TX, WAYLAND_TX}; };
use cascade::cascade; use cascade::cascade;
use cosmic_panel_config::{CosmicPanelConfig, PanelAnchor}; use cosmic_panel_config::{CosmicPanelConfig, PanelAnchor};
use gio::DesktopAppInfo;
use gio::Icon; use gio::traits::AppLaunchContextExt;
use glib::Object; use gtk4::{
use glib::Type; gdk::{self, ContentProvider, Display, ModifierType},
use gtk4::gdk; gio::{self, DesktopAppInfo, Icon},
use gtk4::gdk::ContentProvider; glib::{self, Object, Type},
use gtk4::gdk::Display; prelude::ListModelExt,
use gtk4::gdk::ModifierType; prelude::*,
use gtk4::glib; subclass::prelude::*,
use gtk4::prelude::ListModelExt; DropTarget, IconTheme, ListView, Orientation, SignalListItemFactory,
use gtk4::prelude::*; {DragSource, GestureClick},
use gtk4::subclass::prelude::*; };
use gtk4::DropTarget; use std::{fs::File, path::Path};
use gtk4::IconTheme;
use gtk4::ListView;
use gtk4::Orientation;
use gtk4::SignalListItemFactory;
use gtk4::{DragSource, GestureClick};
use std::fs::File;
use std::path::Path;
use tokio::sync::mpsc::Sender;
mod imp; mod imp;
@ -239,11 +231,14 @@ impl DockList {
// dbg!(click_modifier); // dbg!(click_modifier);
// Launch the application when an item of the list is activated // Launch the application when an item of the list is activated
// TODO use seat eventually
// let wl_seat = self_.device().map(|d| d.seat().downcast::<WaylandSeat>().unwrap().wl_seat()).unwrap();
let focus_window = move |first_focused_item: &Toplevel| { let focus_window = move |first_focused_item: &Toplevel| {
let toplevel_handle = first_focused_item.toplevel_handle.clone(); let toplevel_handle = first_focused_item.toplevel_handle.clone();
let tx = WAYLAND_TX.get().unwrap().clone(); let tx = WAYLAND_TX.get().unwrap().clone();
let _ = tx.clone().send(ToplevelEvent::Activate(toplevel_handle)); let _ = tx.clone().send(ToplevelEvent::Activate(toplevel_handle));
}; };
let old_index = popover_menu_index.get(); let old_index = popover_menu_index.get();
if let Some(old_index) = old_index { if let Some(old_index) = old_index {
if let Some(old_item) = model.item(old_index) { if let Some(old_item) = model.item(old_index) {

View file

@ -96,12 +96,22 @@ impl DockObject {
if let Some(app_info) = gio::DesktopAppInfo::new(path) { if let Some(app_info) = gio::DesktopAppInfo::new(path) {
if app_info.should_show() if app_info.should_show()
&& Some(&first.app_id) && Some(&first.app_id)
== app_info.filename().and_then(|p| p == app_info
.file_stem() .filename()
.and_then(|s| s.to_str().map(|s| s.to_string()))).as_ref() .and_then(|p| {
p.file_stem().and_then(|s| {
s.to_str().map(|s| s.to_string())
})
})
.as_ref()
{ {
return Some(Object::new(&[("appinfo", &app_info), ("active", &results)]) return Some(
.expect("Failed to create `DockObject`.")); Object::new(&[
("appinfo", &app_info),
("active", &results),
])
.expect("Failed to create `DockObject`."),
);
} }
} }
} }

View file

@ -9,11 +9,8 @@ use gtk4::prelude::*;
use gtk4::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk4::{Box, Button, ListBox, Revealer}; use gtk4::{Box, Button, ListBox, Revealer};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use once_cell::sync::OnceCell;
use tokio::sync::mpsc::Sender;
use crate::dock_object::DockObject; use crate::dock_object::DockObject;
use crate::utils::AppListEvent;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct DockPopover { pub struct DockPopover {
@ -26,7 +23,6 @@ pub struct DockPopover {
pub quit_all_item: Rc<RefCell<Button>>, pub quit_all_item: Rc<RefCell<Button>>,
//TODO figure out how to use lifetimes with glib::wrapper! macro //TODO figure out how to use lifetimes with glib::wrapper! macro
pub dock_object: Rc<RefCell<Option<DockObject>>>, pub dock_object: Rc<RefCell<Option<DockObject>>>,
pub tx: OnceCell<Sender<AppListEvent>>,
} }
#[glib::object_subclass] #[glib::object_subclass]

View file

@ -7,7 +7,6 @@ use gtk4::subclass::prelude::*;
use gtk4::{gdk, gio, glib}; use gtk4::{gdk, gio, glib};
use gtk4::{prelude::*, Label}; use gtk4::{prelude::*, Label};
use gtk4::{Box, Button, Image, ListBox, Orientation}; use gtk4::{Box, Button, Image, ListBox, Orientation};
use tokio::sync::mpsc::Sender;
use crate::dock_object::DockObject; use crate::dock_object::DockObject;
use crate::utils::AppListEvent; use crate::utils::AppListEvent;

View file

@ -9,9 +9,6 @@ use gtk4::gdk::Display;
use gtk4::{glib, prelude::*, CssProvider, StyleContext}; use gtk4::{glib, prelude::*, CssProvider, StyleContext};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use tokio::sync::mpsc;
use utils::{block_on, AppListEvent, BoxedWindowList, DEST, PATH}; use utils::{block_on, AppListEvent, BoxedWindowList, DEST, PATH};
use wayland::{Toplevel, ToplevelEvent}; use wayland::{Toplevel, ToplevelEvent};
@ -87,7 +84,7 @@ fn main() {
let mut index: Option<u32> = None; let mut index: Option<u32> = None;
while let Some(item) = active_app_model.item(cur) { while let Some(item) = active_app_model.item(cur) {
if let Ok(cur_dock_object) = item.downcast::<DockObject>() { if let Ok(cur_dock_object) = item.downcast::<DockObject>() {
if cur_dock_object.get_path() == Some(name.clone()) { if cur_dock_object.get_name() == Some(name.clone()) {
cur_dock_object.set_saved(true); cur_dock_object.set_saved(true);
index = Some(cur); index = Some(cur);
} }
@ -104,7 +101,7 @@ fn main() {
let mut index: Option<u32> = None; let mut index: Option<u32> = None;
while let Some(item) = saved_app_model.item(cur) { while let Some(item) = saved_app_model.item(cur) {
if let Ok(cur_dock_object) = item.downcast::<DockObject>() { if let Ok(cur_dock_object) = item.downcast::<DockObject>() {
if cur_dock_object.get_path() == Some(name.clone()) { if cur_dock_object.get_name() == Some(name.clone()) {
cur_dock_object.set_saved(false); cur_dock_object.set_saved(false);
index = Some(cur); index = Some(cur);
} }

View file

@ -16,6 +16,7 @@ use cosmic_protocols::{
zcosmic_workspace_manager_v1::{self, ZcosmicWorkspaceManagerV1}, zcosmic_workspace_manager_v1::{self, ZcosmicWorkspaceManagerV1},
}, },
}; };
use wayland_client::protocol::wl_seat::{WlSeat, self};
use std::{env, os::unix::net::UnixStream, path::PathBuf, time::Duration}; use std::{env, os::unix::net::UnixStream, path::PathBuf, time::Duration};
use wayland_client::{ use wayland_client::{
event_created_child, event_created_child,
@ -80,15 +81,21 @@ pub fn spawn_toplevels() -> SyncSender<ToplevelEvent> {
expected_output: None, expected_output: None,
running: true, running: true,
toplevels: vec![], toplevels: vec![],
seats: vec![],
}; };
let loop_handle = event_loop.handle(); let loop_handle = event_loop.handle();
loop_handle loop_handle
.insert_source(workspaces_rx, |e, _, state| match e { .insert_source(workspaces_rx, |e, _, state| match e {
Event::Msg(ToplevelEvent::Activate(_t)) => { Event::Msg(ToplevelEvent::Activate(toplevel)) => {
todo!() if let Some(manager) = &state.toplevel_manager {
for seat in &state.seats {
manager.activate(&toplevel,seat)
} }
} }
Event::Msg(ToplevelEvent::Close(_t)) => { Event::Msg(ToplevelEvent::Close(t)) => {
todo!() if let Some(manager) = &state.toplevel_manager {
manager.close(&t);
}
} }
Event::Closed => { Event::Closed => {
if let Some(workspace_manager) = &mut state.workspace_manager { if let Some(workspace_manager) = &mut state.workspace_manager {
@ -134,6 +141,7 @@ pub struct State {
toplevel_info: Option<ZcosmicToplevelInfoV1>, toplevel_info: Option<ZcosmicToplevelInfoV1>,
toplevel_manager: Option<ZcosmicToplevelManagerV1>, toplevel_manager: Option<ZcosmicToplevelManagerV1>,
toplevels: Vec<Toplevel>, toplevels: Vec<Toplevel>,
seats: Vec<WlSeat>,
} }
impl State { impl State {
@ -220,6 +228,9 @@ impl Dispatch<wl_registry::WlRegistry, ()> for State {
.unwrap(); .unwrap();
state.workspace_manager = Some(workspace_manager); state.workspace_manager = Some(workspace_manager);
} }
"wl_seat" => {
registry.bind::<WlSeat, _, _>(name, 1, qh, ()).unwrap();
}
"wl_output" => { "wl_output" => {
registry.bind::<WlOutput, _, _>(name, 1, qh, ()).unwrap(); registry.bind::<WlOutput, _, _>(name, 1, qh, ()).unwrap();
} }
@ -570,3 +581,19 @@ impl Dispatch<WlOutput, ()> for State {
} }
} }
} }
impl Dispatch<WlSeat, ()> for State {
fn event(
state: &mut Self,
seat: &WlSeat,
_: wl_seat::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
if state.seats.iter().find(|s| s == &seat).is_none() {
state.seats.push(seat.clone());
}
}
}