This commit is contained in:
Ashley Wulber 2021-12-30 16:54:35 -05:00
parent e6ef9a5357
commit e48f501b0d
18 changed files with 151 additions and 166 deletions

View file

@ -142,7 +142,7 @@ impl ObjectImpl for AppGroup {
.get::<Variant>() .get::<Variant>()
.expect("The icon needs to be a Variant"), .expect("The icon needs to be a Variant"),
) )
.expect("The icon variant needs to be a Vec<String>"); .expect("The icon variant needs to be a Vec<String>");
self.data.borrow_mut().app_names = appnames; self.data.borrow_mut().app_names = appnames;
} }
_ => unimplemented!(), _ => unimplemented!(),

View file

@ -20,7 +20,7 @@ impl AppGroup {
("icon", &data.icon), ("icon", &data.icon),
("category", &data.category), ("category", &data.category),
]) ])
.expect("Failed to create `ApplicationObject`."); .expect("Failed to create `ApplicationObject`.");
if let Err(e) = self_.set_property("appnames", data.app_names.to_variant()) { if let Err(e) = self_.set_property("appnames", data.app_names.to_variant()) {
println!("failed to set category icon property"); println!("failed to set category icon property");
dbg!(e); dbg!(e);

View file

@ -1,18 +1,17 @@
use std::cell::Cell; use std::cell::Cell;
use gtk::glib; use gtk4::CompositeTemplate;
use gtk::prelude::*; use gtk4::glib;
use gtk::subclass::prelude::*; use gtk4::prelude::*;
use gtk::CompositeTemplate; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
#[derive(Debug, Default, CompositeTemplate)] #[derive(Debug, Default, CompositeTemplate)]
#[template(file = "grid_item.ui")] #[template(file = "grid_item.ui")]
pub struct GridItem { pub struct GridItem {
#[template_child] #[template_child]
pub name: TemplateChild<gtk::Label>, pub name: TemplateChild<gtk4::Label>,
#[template_child] #[template_child]
pub image: TemplateChild<gtk::Image>, pub image: TemplateChild<gtk4::Image>,
pub index: Cell<u32>, pub index: Cell<u32>,
} }
@ -20,7 +19,7 @@ pub struct GridItem {
impl ObjectSubclass for GridItem { impl ObjectSubclass for GridItem {
const NAME: &'static str = "GridItem"; const NAME: &'static str = "GridItem";
type Type = super::GridItem; type Type = super::GridItem;
type ParentType = gtk::Box; type ParentType = gtk4::Box;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -2,13 +2,12 @@ use gdk4::ContentProvider;
use gdk4::Display; use gdk4::Display;
use gio::File; use gio::File;
use gio::Icon; use gio::Icon;
use gtk::prelude::*; use gtk4::{gio, glib};
use gtk::subclass::prelude::*;
use gtk::{gio, glib};
use gtk4 as gtk;
use gtk4::traits::WidgetExt;
use gtk4::DragSource; use gtk4::DragSource;
use gtk4::IconTheme; use gtk4::IconTheme;
use gtk4::prelude::*;
use gtk4::subclass::prelude::*;
use gtk4::traits::WidgetExt;
use crate::app_group::AppGroup; use crate::app_group::AppGroup;
@ -16,8 +15,8 @@ mod imp;
glib::wrapper! { glib::wrapper! {
pub struct GridItem(ObjectSubclass<imp::GridItem>) pub struct GridItem(ObjectSubclass<imp::GridItem>)
@extends gtk::Widget, gtk::Box, @extends gtk4::Widget, gtk4::Box,
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget; @implements gtk4::Accessible, gtk4::Actionable, gtk4::Buildable, gtk4::ConstraintTarget;
} }
impl Default for GridItem { impl Default for GridItem {

View file

@ -1,7 +1,6 @@
use gtk::gdk::Display;
use gtk::prelude::*;
use gtk4 as gtk;
use gtk4::CssProvider; use gtk4::CssProvider;
use gtk4::gdk::Display;
use gtk4::prelude::*;
use gtk4::StyleContext; use gtk4::StyleContext;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use x11rb::rust_connection::RustConnection; use x11rb::rust_connection::RustConnection;
@ -16,7 +15,7 @@ mod window;
static X11_CONN: OnceCell<RustConnection> = OnceCell::new(); static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
fn main() { fn main() {
let app = gtk::Application::new(Some("com.cosmic.app_library"), Default::default()); let app = gtk4::Application::new(Some("com.cosmic.app_library"), Default::default());
app.connect_startup(|app| { app.connect_startup(|app| {
load_css(); load_css();
build_ui(&app); build_ui(&app);
@ -38,11 +37,11 @@ fn load_css() {
StyleContext::add_provider_for_display( StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing GTK CSS provider."), &Display::default().expect("Error initializing GTK CSS provider."),
&provider, &provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
); );
} }
fn build_ui(app: &gtk::Application) { fn build_ui(app: &gtk4::Application) {
// Create a new custom window and show it // Create a new custom window and show it
let window = Window::new(app); let window = Window::new(app);
let (conn, _screen_num) = x11rb::connect(None).expect("Failed to connect to X"); let (conn, _screen_num) = x11rb::connect(None).expect("Failed to connect to X");

View file

@ -2,12 +2,11 @@ use std::fs::File;
use glib::signal::Inhibit; use glib::signal::Inhibit;
use glib::subclass::InitializingObject; use glib::subclass::InitializingObject;
use gtk::prelude::*; use gtk4::prelude::*;
use gtk::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk::{gio, glib};
use gtk::{CompositeTemplate, GridView, SearchEntry};
use gtk4 as gtk;
use gtk4::ScrolledWindow; use gtk4::ScrolledWindow;
use gtk4::{gio, glib};
use gtk4::{CompositeTemplate, GridView, SearchEntry};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use crate::app_group::AppGroup; use crate::app_group::AppGroup;
@ -35,7 +34,7 @@ impl ObjectSubclass for Window {
// `NAME` needs to match `class` attribute of template // `NAME` needs to match `class` attribute of template
const NAME: &'static str = "LauncherWindow"; const NAME: &'static str = "LauncherWindow";
type Type = super::Window; type Type = super::Window;
type ParentType = gtk::ApplicationWindow; type ParentType = gtk4::ApplicationWindow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -6,14 +6,13 @@ use gdk4_x11::X11Surface;
use glib::FromVariant; use glib::FromVariant;
use glib::Object; use glib::Object;
use glib::Variant; use glib::Variant;
use gtk::prelude::*; use gtk4::{gio, glib};
use gtk::subclass::prelude::*; use gtk4::{Application, SignalListItemFactory};
use gtk::{gio, glib};
use gtk::{Application, SignalListItemFactory};
use gtk4 as gtk;
use gtk4::Dialog; use gtk4::Dialog;
use gtk4::Entry; use gtk4::Entry;
use gtk4::Label; use gtk4::Label;
use gtk4::prelude::*;
use gtk4::subclass::prelude::*;
use x11rb::connection::Connection; use x11rb::connection::Connection;
use x11rb::protocol::xproto; use x11rb::protocol::xproto;
use x11rb::protocol::xproto::ConnectionExt; use x11rb::protocol::xproto::ConnectionExt;
@ -31,9 +30,9 @@ mod imp;
glib::wrapper! { glib::wrapper! {
pub struct Window(ObjectSubclass<imp::Window>) pub struct Window(ObjectSubclass<imp::Window>)
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget, @extends gtk4::ApplicationWindow, gtk4::Window, gtk4::Widget,
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, @implements gio::ActionGroup, gio::ActionMap, gtk4::Accessible, gtk4::Buildable,
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager; gtk4::ConstraintTarget, gtk4::Native, gtk4::Root, gtk4::ShortcutManager;
} }
impl Window { impl Window {
@ -97,7 +96,7 @@ impl Window {
.set(app_model.clone()) .set(app_model.clone())
.expect("Could not set model"); .expect("Could not set model");
let sorter = gtk::CustomSorter::new(move |obj1, obj2| { let sorter = gtk4::CustomSorter::new(move |obj1, obj2| {
let app_info1 = obj1.downcast_ref::<gio::DesktopAppInfo>().unwrap(); let app_info1 = obj1.downcast_ref::<gio::DesktopAppInfo>().unwrap();
let app_info2 = obj2.downcast_ref::<gio::DesktopAppInfo>().unwrap(); let app_info2 = obj2.downcast_ref::<gio::DesktopAppInfo>().unwrap();
@ -107,14 +106,14 @@ impl Window {
.cmp(&app_info2.name().to_lowercase()) .cmp(&app_info2.name().to_lowercase())
.into() .into()
}); });
let filter = gtk::CustomFilter::new(|_obj| true); let filter = gtk4::CustomFilter::new(|_obj| true);
let search_filter_model = let search_filter_model =
gtk::FilterListModel::new(Some(&app_model), Some(filter).as_ref()); gtk4::FilterListModel::new(Some(&app_model), Some(filter).as_ref());
let filter = gtk::CustomFilter::new(|_obj| true); let filter = gtk4::CustomFilter::new(|_obj| true);
let group_filter_model = let group_filter_model =
gtk::FilterListModel::new(Some(&search_filter_model), Some(filter).as_ref()); gtk4::FilterListModel::new(Some(&search_filter_model), Some(filter).as_ref());
let sorted_model = gtk::SortListModel::new(Some(&group_filter_model), Some(&sorter)); let sorted_model = gtk4::SortListModel::new(Some(&group_filter_model), Some(&sorter));
let selection_model = gtk::SingleSelection::builder() let selection_model = gtk4::SingleSelection::builder()
.model(&sorted_model) .model(&sorted_model)
.autoselect(false) .autoselect(false)
.can_unselect(true) .can_unselect(true)
@ -172,10 +171,10 @@ impl Window {
category: "".to_string(), category: "".to_string(),
}), }),
] ]
.iter() .iter()
.for_each(|group| { .for_each(|group| {
group_model.append(group); group_model.append(group);
}); });
let group_selection = gtk4::SingleSelection::new(Some(&group_model)); let group_selection = gtk4::SingleSelection::new(Some(&group_model));
imp.group_grid_view.set_model(Some(&group_selection)); imp.group_grid_view.set_model(Some(&group_selection));
} }
@ -183,32 +182,32 @@ impl Window {
fn setup_callbacks(&self) { fn setup_callbacks(&self) {
// Get state // Get state
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let window = self.clone().upcast::<gtk::Window>(); let window = self.clone().upcast::<gtk4::Window>();
let app_grid_view = &imp.app_grid_view; let app_grid_view = &imp.app_grid_view;
let group_grid_view = &imp.group_grid_view; let group_grid_view = &imp.group_grid_view;
let app_selection_model = app_grid_view let app_selection_model = app_grid_view
.model() .model()
.expect("List view missing selection model") .expect("List view missing selection model")
.downcast::<gtk::SingleSelection>() .downcast::<gtk4::SingleSelection>()
.expect("could not downcast listview model to single selection model"); .expect("could not downcast listview model to single selection model");
let app_sorted_model = app_selection_model let app_sorted_model = app_selection_model
.model() .model()
.downcast::<gtk::SortListModel>() .downcast::<gtk4::SortListModel>()
.expect("sorted list model could not be downcast"); .expect("sorted list model could not be downcast");
let app_group_filter_model = app_sorted_model let app_group_filter_model = app_sorted_model
.model() .model()
.expect("missing model for sort list model.") .expect("missing model for sort list model.")
.downcast::<gtk::FilterListModel>() .downcast::<gtk4::FilterListModel>()
.expect("could not downcast sort list model to filter list model"); .expect("could not downcast sort list model to filter list model");
let app_filter_model = app_group_filter_model let app_filter_model = app_group_filter_model
.model() .model()
.expect("missing model for sort list model.") .expect("missing model for sort list model.")
.downcast::<gtk::FilterListModel>() .downcast::<gtk4::FilterListModel>()
.expect("could not downcast sort list model to filter list model"); .expect("could not downcast sort list model to filter list model");
let group_selection_model = group_grid_view let group_selection_model = group_grid_view
.model() .model()
.expect("List view missing selection model") .expect("List view missing selection model")
.downcast::<gtk::SingleSelection>() .downcast::<gtk4::SingleSelection>()
.expect("could not downcast listview model to single selection model"); .expect("could not downcast listview model to single selection model");
let entry = &imp.entry; let entry = &imp.entry;
@ -229,10 +228,10 @@ impl Window {
let app_info = item.downcast::<gio::DesktopAppInfo>().unwrap(); let app_info = item.downcast::<gio::DesktopAppInfo>().unwrap();
let context = window.display().app_launch_context(); let context = window.display().app_launch_context();
if let Err(err) = app_info.launch(&[], Some(&context)) { if let Err(err) = app_info.launch(&[], Some(&context)) {
gtk::MessageDialog::builder() gtk4::MessageDialog::builder()
.text(&format!("Failed to start {}", app_info.name())) .text(&format!("Failed to start {}", app_info.name()))
.secondary_text(&err.to_string()) .secondary_text(&err.to_string())
.message_type(gtk::MessageType::Error) .message_type(gtk4::MessageType::Error)
.modal(true) .modal(true)
.transient_for(&window) .transient_for(&window)
.build() .build()
@ -347,7 +346,7 @@ impl Window {
vec![] vec![]
}; };
dbg!(&app_names); dbg!(&app_names);
let new_filter: gtk::CustomFilter = gtk::CustomFilter::new(move |obj| { let new_filter: gtk4::CustomFilter = gtk4::CustomFilter::new(move |obj| {
let app = obj let app = obj
.downcast_ref::<gio::DesktopAppInfo>() .downcast_ref::<gio::DesktopAppInfo>()
.expect("The Object needs to be of type AppInfo"); .expect("The Object needs to be of type AppInfo");
@ -363,15 +362,15 @@ impl Window {
})); }));
entry.connect_changed( entry.connect_changed(
glib::clone!(@weak app_filter_model, @weak app_sorted_model => move |search: &gtk::SearchEntry| { glib::clone!(@weak app_filter_model, @weak app_sorted_model => move |search: &gtk4::SearchEntry| {
let search_text = search.text().to_string().to_lowercase(); let search_text = search.text().to_string().to_lowercase();
let new_filter: gtk::CustomFilter = gtk::CustomFilter::new(move |obj| { let new_filter: gtk4::CustomFilter = gtk4::CustomFilter::new(move |obj| {
let search_res = obj.downcast_ref::<gio::DesktopAppInfo>() let search_res = obj.downcast_ref::<gio::DesktopAppInfo>()
.expect("The Object needs to be of type AppInfo"); .expect("The Object needs to be of type AppInfo");
search_res.name().to_string().to_lowercase().contains(&search_text) search_res.name().to_string().to_lowercase().contains(&search_text)
}); });
let search_text = search.text().to_string().to_lowercase(); let search_text = search.text().to_string().to_lowercase();
let new_sorter: gtk::CustomSorter = gtk::CustomSorter::new(move |obj1, obj2| { let new_sorter: gtk4::CustomSorter = gtk4::CustomSorter::new(move |obj1, obj2| {
let app_info1 = obj1.downcast_ref::<gio::DesktopAppInfo>().unwrap(); let app_info1 = obj1.downcast_ref::<gio::DesktopAppInfo>().unwrap();
let app_info2 = obj2.downcast_ref::<gio::DesktopAppInfo>().unwrap(); let app_info2 = obj2.downcast_ref::<gio::DesktopAppInfo>().unwrap();
if search_text == "" { if search_text == "" {

View file

@ -1,23 +1,22 @@
use gtk::glib; use gtk4::glib;
use gtk::prelude::*; use gtk4::prelude::*;
use gtk::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk::CompositeTemplate; use gtk4::CompositeTemplate;
use gtk4 as gtk;
#[derive(Debug, Default, CompositeTemplate)] #[derive(Debug, Default, CompositeTemplate)]
#[template(file = "dock_item.ui")] #[template(file = "dock_item.ui")]
pub struct DockItem { pub struct DockItem {
#[template_child] #[template_child]
pub image: TemplateChild<gtk::Image>, pub image: TemplateChild<gtk4::Image>,
#[template_child] #[template_child]
pub dots: TemplateChild<gtk::Label>, pub dots: TemplateChild<gtk4::Label>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for DockItem { impl ObjectSubclass for DockItem {
const NAME: &'static str = "DockItem"; const NAME: &'static str = "DockItem";
type Type = super::DockItem; type Type = super::DockItem;
type ParentType = gtk::Box; type ParentType = gtk4::Box;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -1,9 +1,8 @@
use gio::DesktopAppInfo; use gio::DesktopAppInfo;
use gio::Icon; use gio::Icon;
use gtk::glib; use gtk4::glib;
use gtk::prelude::*; use gtk4::prelude::*;
use gtk::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
use crate::dock_object::DockObject; use crate::dock_object::DockObject;
use crate::utils::BoxedWindowList; use crate::utils::BoxedWindowList;
@ -12,7 +11,7 @@ mod imp;
glib::wrapper! { glib::wrapper! {
pub struct DockItem(ObjectSubclass<imp::DockItem>) pub struct DockItem(ObjectSubclass<imp::DockItem>)
@extends gtk::Widget, gtk::Box; @extends gtk4::Widget, gtk4::Box;
} }
impl Default for DockItem { impl Default for DockItem {

View file

@ -4,12 +4,11 @@ use std::time::Duration;
use futures::executor::block_on; use futures::executor::block_on;
use gdk4::Display; use gdk4::Display;
use gio::DesktopAppInfo; use gio::DesktopAppInfo;
use gtk::gio; use gtk4::Application;
use gtk::glib;
use gtk::prelude::*;
use gtk::Application;
use gtk4 as gtk;
use gtk4::CssProvider; use gtk4::CssProvider;
use gtk4::gio;
use gtk4::glib;
use gtk4::prelude::*;
use gtk4::StyleContext; use gtk4::StyleContext;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use postage::mpsc::Sender; use postage::mpsc::Sender;
@ -90,13 +89,13 @@ fn load_css() {
StyleContext::add_provider_for_display( StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing GTK CSS provider."), &Display::default().expect("Error initializing GTK CSS provider."),
&provider, &provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
); );
} }
fn main() { fn main() {
assert!(utils::BoxedWindowList::static_type().is_valid()); assert!(utils::BoxedWindowList::static_type().is_valid());
let app = gtk::Application::builder() let app = gtk4::Application::builder()
.application_id("com.system76.dock") .application_id("com.system76.dock")
.build(); .build();
@ -132,7 +131,7 @@ fn main() {
match event { match event {
Event::Activate(e) => { Event::Activate(e) => {
let _activate_window = zbus_conn let _activate_window = zbus_conn
.call_method(Some(DEST), PATH, Some(DEST), "WindowFocus", &((e,))) .call_method(Some(DEST), PATH, Some(DEST), "WindowFocus", &((e, )))
.await .await
.expect("Failed to focus selected window"); .expect("Failed to focus selected window");
} }
@ -226,16 +225,16 @@ fn main() {
// skip if equal // skip if equal
if cached_results.len() == results.len() if cached_results.len() == results.len()
&& results.iter().zip(cached_results.iter()).fold( && results.iter().zip(cached_results.iter()).fold(
0, 0,
|acc, z: (&Item, &Item)| { |acc, z: (&Item, &Item)| {
let (a, b) = z; let (a, b) = z;
if a.name == b.name { if a.name == b.name {
acc + 1 acc + 1
} else { } else {
acc acc
} }
}, },
) == cached_results.len() ) == cached_results.len()
{ {
continue; // skip this update continue; // skip this update
} }

View file

@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use gtk4::glib; use glib;
use crate::DockObject; use crate::DockObject;
use crate::Item; use crate::Item;

View file

@ -3,16 +3,15 @@ use std::rc::Rc;
use glib::subclass::InitializingObject; use glib::subclass::InitializingObject;
use glib::SignalHandlerId; use glib::SignalHandlerId;
use gtk::prelude::*; use gtk4::prelude::*;
use gtk::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk::{gio, glib};
use gtk::{CompositeTemplate, ListView};
use gtk4 as gtk;
use gtk4::DragSource; use gtk4::DragSource;
use gtk4::DropTarget; use gtk4::DropTarget;
use gtk4::EventControllerMotion; use gtk4::EventControllerMotion;
use gtk4::Revealer; use gtk4::Revealer;
use gtk4::{gio, glib};
use gtk4::{Box, GestureClick}; use gtk4::{Box, GestureClick};
use gtk4::{CompositeTemplate, ListView};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
// Object holding the state // Object holding the state
@ -48,7 +47,7 @@ impl ObjectSubclass for Window {
// `NAME` needs to match `class` attribute of template // `NAME` needs to match `class` attribute of template
const NAME: &'static str = "LauncherWindow"; const NAME: &'static str = "LauncherWindow";
type Type = super::Window; type Type = super::Window;
type ParentType = gtk::ApplicationWindow; type ParentType = gtk4::ApplicationWindow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -1,4 +1,3 @@
use crate::Item;
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;
@ -13,16 +12,15 @@ use gio::Icon;
// use crate::application_row::ApplicationRow; // use crate::application_row::ApplicationRow;
use glib::Object; use glib::Object;
use glib::Type; use glib::Type;
use gtk::prelude::*; use gtk4::{gio, glib};
use gtk::subclass::prelude::*; use gtk4::{Application, SignalListItemFactory};
use gtk::{gio, glib}; use gtk4::{DragSource, GestureClick};
use gtk::{Application, SignalListItemFactory};
use gtk4 as gtk;
use gtk4::prelude::ListModelExt;
use gtk4::DropTarget; use gtk4::DropTarget;
use gtk4::EventControllerMotion; use gtk4::EventControllerMotion;
use gtk4::IconTheme; use gtk4::IconTheme;
use gtk4::{DragSource, GestureClick}; use gtk4::prelude::*;
use gtk4::prelude::ListModelExt;
use gtk4::subclass::prelude::*;
use postage::prelude::Sink; use postage::prelude::Sink;
use x11rb::connection::Connection; use x11rb::connection::Connection;
use x11rb::protocol::xproto; use x11rb::protocol::xproto;
@ -34,18 +32,19 @@ use crate::BoxedWindowList;
// use crate::ApplicationObject; // use crate::ApplicationObject;
use crate::dock_item::DockItem; use crate::dock_item::DockItem;
use crate::dock_object::DockObject; use crate::dock_object::DockObject;
use crate::utils::data_path;
use crate::Event; use crate::Event;
use crate::Item;
use crate::TX; use crate::TX;
use crate::utils::data_path;
use crate::X11_CONN; use crate::X11_CONN;
mod imp; mod imp;
glib::wrapper! { glib::wrapper! {
pub struct Window(ObjectSubclass<imp::Window>) pub struct Window(ObjectSubclass<imp::Window>)
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget, @extends gtk4::ApplicationWindow, gtk4::Window, gtk4::Widget,
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, @implements gio::ActionGroup, gio::ActionMap, gtk4::Accessible, gtk4::Buildable,
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager; gtk4::ConstraintTarget, gtk4::Native, gtk4::Root, gtk4::ShortcutManager;
} }
impl Window { impl Window {
@ -76,7 +75,7 @@ impl Window {
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let saved_app_model = gio::ListStore::new(DockObject::static_type()); let saved_app_model = gio::ListStore::new(DockObject::static_type());
let saved_selection_model = gtk::NoSelection::new(Some(&saved_app_model)); let saved_selection_model = gtk4::NoSelection::new(Some(&saved_app_model));
imp.saved_app_model imp.saved_app_model
.set(saved_app_model) .set(saved_app_model)
@ -86,7 +85,7 @@ impl Window {
.set_model(Some(&saved_selection_model)); .set_model(Some(&saved_selection_model));
let active_app_model = gio::ListStore::new(DockObject::static_type()); let active_app_model = gio::ListStore::new(DockObject::static_type());
let active_selection_model = gtk::NoSelection::new(Some(&active_app_model)); let active_selection_model = gtk4::NoSelection::new(Some(&active_app_model));
imp.active_app_model imp.active_app_model
.set(active_app_model) .set(active_app_model)
@ -99,7 +98,7 @@ impl Window {
fn setup_callbacks(&self) { fn setup_callbacks(&self) {
// Get state // Get state
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let window = self.clone().upcast::<gtk::Window>(); let window = self.clone().upcast::<gtk4::Window>();
let saved_app_list_view = &imp.saved_app_list_view; let saved_app_list_view = &imp.saved_app_list_view;
let saved_app_model = &imp let saved_app_model = &imp
.saved_app_model .saved_app_model
@ -109,16 +108,16 @@ impl Window {
let saved_app_selection_model = saved_app_list_view let saved_app_selection_model = saved_app_list_view
.model() .model()
.expect("List view missing selection model") .expect("List view missing selection model")
.downcast::<gtk::NoSelection>() .downcast::<gtk4::NoSelection>()
.expect("could not downcast listview model to single selection model"); .expect("could not downcast listview model to single selection model");
let active_app_selection_model = imp let active_app_selection_model = imp
.active_app_list_view .active_app_list_view
.model() .model()
.expect("List view missing selection model") .expect("List view missing selection model")
.downcast::<gtk::NoSelection>() .downcast::<gtk4::NoSelection>()
.expect("could not downcast listview model to single selection model"); .expect("could not downcast listview model to single selection model");
// let selected_handler = glib::clone!(@weak window => move |model: &gtk::NoSelection| { // let selected_handler = glib::clone!(@weak window => move |model: &gtk4::NoSelection| {
// let position = model.selected(); // let position = model.selected();
// println!("selected app {}", position); // println!("selected app {}", position);
// // Launch the application when an item of the list is activated // // Launch the application when an item of the list is activated
@ -137,10 +136,10 @@ impl Window {
// else if let Ok(Some(app_info)) = dockobject.property("appinfo").expect("DockObject must have appinfo property").get::<Option<DesktopAppInfo>>() { // else if let Ok(Some(app_info)) = dockobject.property("appinfo").expect("DockObject must have appinfo property").get::<Option<DesktopAppInfo>>() {
// let context = window.display().app_launch_context(); // let context = window.display().app_launch_context();
// if let Err(err) = app_info.launch(&[], Some(&context)) { // if let Err(err) = app_info.launch(&[], Some(&context)) {
// gtk::MessageDialog::builder() // gtk4::MessageDialog::builder()
// .text(&format!("Failed to start {}", app_info.name())) // .text(&format!("Failed to start {}", app_info.name()))
// .secondary_text(&err.to_string()) // .secondary_text(&err.to_string())
// .message_type(gtk::MessageType::Error) // .message_type(gtk4::MessageType::Error)
// .modal(true) // .modal(true)
// .transient_for(&window) // .transient_for(&window)
// .build() // .build()
@ -411,7 +410,7 @@ impl Window {
fn setup_click_callbacks(&self) { fn setup_click_callbacks(&self) {
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let window = self.clone().upcast::<gtk::Window>(); let window = self.clone().upcast::<gtk4::Window>();
let saved_click_controller = imp let saved_click_controller = imp
.saved_click_controller .saved_click_controller
.get() .get()
@ -455,10 +454,10 @@ impl Window {
(click, _, _, Some(app_info)) | (click, _, None, Some(app_info)) if click != 3 => { (click, _, _, Some(app_info)) | (click, _, None, Some(app_info)) if click != 3 => {
let context = window.display().app_launch_context(); let context = window.display().app_launch_context();
if let Err(err) = app_info.launch(&[], Some(&context)) { if let Err(err) = app_info.launch(&[], Some(&context)) {
gtk::MessageDialog::builder() gtk4::MessageDialog::builder()
.text(&format!("Failed to start {}", app_info.name())) .text(&format!("Failed to start {}", app_info.name()))
.secondary_text(&err.to_string()) .secondary_text(&err.to_string())
.message_type(gtk::MessageType::Error) .message_type(gtk4::MessageType::Error)
.modal(true) .modal(true)
.transient_for(&window) .transient_for(&window)
.build() .build()

View file

@ -1,11 +1,10 @@
use gdk4::Display; use gdk4::Display;
use gio::DesktopAppInfo; use gio::DesktopAppInfo;
use gtk::gio; use gtk4::Application;
use gtk::glib;
use gtk::prelude::*;
use gtk::Application;
use gtk4 as gtk;
use gtk4::CssProvider; use gtk4::CssProvider;
use gtk4::gio;
use gtk4::glib;
use gtk4::prelude::*;
use gtk4::StyleContext; use gtk4::StyleContext;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use pop_launcher_service::IpcClient; use pop_launcher_service::IpcClient;
@ -27,7 +26,7 @@ const NUM_LAUNCHER_ITEMS: u8 = 10;
static TX: OnceCell<Sender<Event>> = OnceCell::new(); static TX: OnceCell<Sender<Event>> = OnceCell::new();
static X11_CONN: OnceCell<RustConnection> = OnceCell::new(); static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
fn icon_source(icon: &gtk::Image, source: &Option<pop_launcher::IconSource>) { fn icon_source(icon: &gtk4::Image, source: &Option<pop_launcher::IconSource>) {
match source { match source {
Some(pop_launcher::IconSource::Name(name)) => { Some(pop_launcher::IconSource::Name(name)) => {
icon.set_from_icon_name(Some(name)); icon.set_from_icon_name(Some(name));
@ -80,12 +79,12 @@ fn load_css() {
StyleContext::add_provider_for_display( StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing GTK CSS provider."), &Display::default().expect("Error initializing GTK CSS provider."),
&provider, &provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
); );
} }
fn main() { fn main() {
let app = gtk::Application::builder() let app = gtk4::Application::builder()
.application_id("com.cosmic.Launcher") .application_id("com.cosmic.Launcher")
.build(); .build();

View file

@ -1,29 +1,28 @@
use gtk::glib; use gtk4::CompositeTemplate;
use gtk::prelude::*; use gtk4::glib;
use gtk::subclass::prelude::*; use gtk4::prelude::*;
use gtk::CompositeTemplate; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
#[derive(Debug, Default, CompositeTemplate)] #[derive(Debug, Default, CompositeTemplate)]
#[template(file = "application_row.ui")] #[template(file = "application_row.ui")]
pub struct SearchResultRow { pub struct SearchResultRow {
#[template_child] #[template_child]
pub name: TemplateChild<gtk::Label>, pub name: TemplateChild<gtk4::Label>,
#[template_child] #[template_child]
pub description: TemplateChild<gtk::Label>, pub description: TemplateChild<gtk4::Label>,
#[template_child] #[template_child]
pub shortcut: TemplateChild<gtk::Label>, pub shortcut: TemplateChild<gtk4::Label>,
#[template_child] #[template_child]
pub image: TemplateChild<gtk::Image>, pub image: TemplateChild<gtk4::Image>,
#[template_child] #[template_child]
pub categoryimage: TemplateChild<gtk::Image>, pub categoryimage: TemplateChild<gtk4::Image>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for SearchResultRow { impl ObjectSubclass for SearchResultRow {
const NAME: &'static str = "SearchResultRow"; const NAME: &'static str = "SearchResultRow";
type Type = super::SearchResultRow; type Type = super::SearchResultRow;
type ParentType = gtk::Box; type ParentType = gtk4::Box;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -1,17 +1,16 @@
use gtk::glib; use gtk4::glib;
use gtk::prelude::*; use gtk4::prelude::*;
use gtk::subclass::prelude::*; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
use crate::icon_source;
use crate::BoxedSearchResult; use crate::BoxedSearchResult;
use crate::icon_source;
use crate::SearchResultObject; use crate::SearchResultObject;
mod imp; mod imp;
glib::wrapper! { glib::wrapper! {
pub struct SearchResultRow(ObjectSubclass<imp::SearchResultRow>) pub struct SearchResultRow(ObjectSubclass<imp::SearchResultRow>)
@extends gtk::Widget, gtk::Box; @extends gtk4::Widget, gtk4::Box;
} }
impl Default for SearchResultRow { impl Default for SearchResultRow {

View file

@ -1,9 +1,8 @@
use glib::subclass::InitializingObject; use glib::subclass::InitializingObject;
use gtk::prelude::*; use gtk4::{gio, glib};
use gtk::subclass::prelude::*; use gtk4::{CompositeTemplate, Entry, ListView};
use gtk::{gio, glib}; use gtk4::prelude::*;
use gtk::{CompositeTemplate, Entry, ListView}; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
// Object holding the state // Object holding the state
@ -23,7 +22,7 @@ impl ObjectSubclass for Window {
// `NAME` needs to match `class` attribute of template // `NAME` needs to match `class` attribute of template
const NAME: &'static str = "LauncherWindow"; const NAME: &'static str = "LauncherWindow";
type Type = super::Window; type Type = super::Window;
type ParentType = gtk::ApplicationWindow; type ParentType = gtk4::ApplicationWindow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass); Self::bind_template(klass);

View file

@ -2,11 +2,10 @@ use gdk4::Rectangle;
use gdk4_x11::X11Display; use gdk4_x11::X11Display;
use gdk4_x11::X11Surface; use gdk4_x11::X11Surface;
use glib::Object; use glib::Object;
use gtk::prelude::*; use gtk4::{gio, glib};
use gtk::subclass::prelude::*; use gtk4::{Application, SignalListItemFactory};
use gtk::{gio, glib}; use gtk4::prelude::*;
use gtk::{Application, SignalListItemFactory}; use gtk4::subclass::prelude::*;
use gtk4 as gtk;
use postage::prelude::Sink; use postage::prelude::Sink;
use x11rb::connection::Connection; use x11rb::connection::Connection;
use x11rb::protocol::xproto; use x11rb::protocol::xproto;
@ -23,9 +22,9 @@ mod imp;
glib::wrapper! { glib::wrapper! {
pub struct Window(ObjectSubclass<imp::Window>) pub struct Window(ObjectSubclass<imp::Window>)
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget, @extends gtk4::ApplicationWindow, gtk4::Window, gtk4::Widget,
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, @implements gio::ActionGroup, gio::ActionMap, gtk4::Accessible, gtk4::Buildable,
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager; gtk4::ConstraintTarget, gtk4::Native, gtk4::Root, gtk4::ShortcutManager;
} }
const NUM_LAUNCHER_ITEMS: u8 = 9; const NUM_LAUNCHER_ITEMS: u8 = 9;
@ -47,8 +46,8 @@ impl Window {
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let model = gio::ListStore::new(SearchResultObject::static_type()); let model = gio::ListStore::new(SearchResultObject::static_type());
let slice_model = gtk::SliceListModel::new(Some(&model), 0, NUM_LAUNCHER_ITEMS.into()); let slice_model = gtk4::SliceListModel::new(Some(&model), 0, NUM_LAUNCHER_ITEMS.into());
let selection_model = gtk::SingleSelection::builder() let selection_model = gtk4::SingleSelection::builder()
.model(&slice_model) .model(&slice_model)
.autoselect(false) .autoselect(false)
.can_unselect(true) .can_unselect(true)
@ -63,7 +62,7 @@ impl Window {
fn setup_callbacks(&self) { fn setup_callbacks(&self) {
// Get state // Get state
let imp = imp::Window::from_instance(self); let imp = imp::Window::from_instance(self);
let window = self.clone().upcast::<gtk::Window>(); let window = self.clone().upcast::<gtk4::Window>();
let list_view = &imp.list_view; let list_view = &imp.list_view;
let entry = &imp.entry; let entry = &imp.entry;
let lv = list_view.get(); let lv = list_view.get();
@ -94,7 +93,7 @@ impl Window {
let app_selection_model = list_view let app_selection_model = list_view
.model() .model()
.expect("List view missing selection model") .expect("List view missing selection model")
.downcast::<gtk::SingleSelection>() .downcast::<gtk4::SingleSelection>()
.expect("could not downcast listview model to single selection model"); .expect("could not downcast listview model to single selection model");
app_selection_model.connect_selected_notify(glib::clone!(@weak window => move |model| { app_selection_model.connect_selected_notify(glib::clone!(@weak window => move |model| {
@ -117,7 +116,7 @@ impl Window {
} }
})); }));
entry.connect_changed(glib::clone!(@weak lv => move |search: &gtk::Entry| { entry.connect_changed(glib::clone!(@weak lv => move |search: &gtk4::Entry| {
let search = search.text().to_string(); let search = search.text().to_string();
glib::MainContext::default().spawn_local(async move { glib::MainContext::default().spawn_local(async move {
@ -128,7 +127,7 @@ impl Window {
}); });
})); }));
entry.connect_realize(glib::clone!(@weak lv => move |search: &gtk::Entry| { entry.connect_realize(glib::clone!(@weak lv => move |search: &gtk4::Entry| {
let search = search.text().to_string(); let search = search.text().to_string();
glib::MainContext::default().spawn_local(async move { glib::MainContext::default().spawn_local(async move {