cleanup and re-enable dock autohide

This commit is contained in:
Ashley Wulber 2021-12-17 12:22:45 -05:00
parent e9c5bf9254
commit 5cda4046a6
10 changed files with 37 additions and 240 deletions

View file

@ -0,0 +1 @@
ashleywulber@pop-os.146928:1639590163

BIN
examples/dock/.main.rs.swp Normal file

Binary file not shown.

View file

@ -1,12 +1,10 @@
use gdk4::ContentProvider;
use gdk4::Display;
use gio::File;
use gio::Icon;
use gio::ListStore;
use gtk4 as gtk;
use gtk4::DragSource;
use gtk4::IconTheme;
use gtk4::TreeIter;
mod imp;
use gtk::glib;
@ -89,9 +87,7 @@ impl DockItem {
let icon = app_info
.icon()
.unwrap_or(Icon::for_string("image-missing").expect("Failed to set default icon"));
drag_controller.connect_drag_begin(glib::clone!(@weak icon, => move |_self, drag| {
// drag.set_selected_action(gdk4::DragAction::MOVE);
// override formats
drag_controller.connect_drag_begin(glib::clone!(@weak icon, => move |_self, _drag| {
// set drag source icon if possible...
// gio Icon is not easily converted to a Paintable, but this seems to be the correct method
if let Some(default_display) = &Display::default() {

View file

@ -1,76 +0,0 @@
use pop_launcher::{Request, Response};
use std::process;
use std::io::{self, BufRead, Write};
pub struct LauncherIpc {
child: process::Child,
stdin: process::ChildStdin,
stdout: io::BufReader<process::ChildStdout>,
exited: bool,
}
impl LauncherIpc {
pub fn new() -> io::Result<Self> {
let mut child = process::Command::new("pop-launcher")
.stdin(process::Stdio::piped())
.stdout(process::Stdio::piped())
.spawn()?;
let stdin = child.stdin.take().ok_or(
io::Error::new(io::ErrorKind::Other, "failed to find child stdin")
)?;
let stdout = io::BufReader::new(child.stdout.take().ok_or(
io::Error::new(io::ErrorKind::Other, "failed to find child stdout")
)?);
Ok(Self {
child,
stdin,
stdout,
exited: false,
})
}
fn send_request(&mut self, request: Request) -> io::Result<()> {
let mut request_json = serde_json::to_string(&request).map_err(|err| {
io::Error::new(io::ErrorKind::InvalidInput, err)
})?;
request_json.push('\n');
self.stdin.write_all(request_json.as_bytes())
}
fn recv_response(&mut self) -> io::Result<Response> {
let mut response_json = String::new();
self.stdout.read_line(&mut response_json)?;
serde_json::from_str(&response_json).map_err(|err| {
io::Error::new(io::ErrorKind::InvalidData, err)
})
}
pub fn request(&mut self, request: Request) -> io::Result<Response> {
self.send_request(request)?;
self.recv_response()
}
//TODO: better exit implementation
pub fn exit(&mut self) -> io::Result<Option<process::ExitStatus>> {
if ! self.exited {
self.send_request(Request::Exit)?;
let status = self.child.wait()?;
self.exited = true;
Ok(Some(status))
} else {
Ok(None)
}
}
}
impl Drop for LauncherIpc {
fn drop(&mut self) {
match self.exit() {
Ok(_) => (),
Err(err) => eprintln!("LauncherIpc::drop failed: {}", err),
}
}
}

View file

@ -8,7 +8,6 @@ use gio::DesktopAppInfo;
use gtk::Application;
use gtk4 as gtk;
use gtk4::CssProvider;
use gtk4::Revealer;
use gtk4::StyleContext;
use once_cell::sync::OnceCell;
@ -27,20 +26,6 @@ const NUM_LAUNCHER_ITEMS: u8 = 10;
static TX: OnceCell<Sender<Event>> = OnceCell::new();
static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
fn icon_source(icon: &gtk::Image, source: &Option<pop_launcher::IconSource>) {
match source {
Some(pop_launcher::IconSource::Name(name)) => {
icon.set_from_icon_name(Some(name));
}
Some(pop_launcher::IconSource::Mime(content_type)) => {
icon.set_from_gicon(&gio::content_type_get_icon(content_type));
}
_ => {
icon.set_from_icon_name(None);
}
}
}
pub enum Event {
Response(pop_launcher::Response),
Search(String),

View file

@ -1,42 +1 @@
use gdk4::ContentProvider;
use gdk4::Display;
use gio::File;
use gio::Icon;
use gtk4 as gtk;
use gtk4::DragSource;
use gtk4::IconTheme;
use gtk::glib;
use gtk::prelude::*;
pub fn init_drag_controller(drag_controller: &DragSource, app_info: &gio::DesktopAppInfo) {
if let Some(file) = app_info.filename() {
let file = File::for_path(file);
let provider = ContentProvider::for_value(&file.to_value());
drag_controller.set_content(Some(&provider));
}
drag_controller.connect_drag_end(move |_self, _drag, delete_data| {
dbg!("removing", delete_data);
});
let icon = app_info
.icon()
.unwrap_or(Icon::for_string("image-missing").expect("Failed to set default icon"));
drag_controller.connect_drag_begin(glib::clone!(@weak icon, => move |_self, drag| {
drag.set_selected_action(gdk4::DragAction::MOVE);
// set drag source icon if possible...
// gio Icon is not easily converted to a Paintable, but this seems to be the correct method
if let Some(default_display) = &Display::default() {
if let Some(icon_theme) = IconTheme::for_display(default_display) {
if let Some(paintable_icon) = icon_theme.lookup_by_gicon(
&icon,
64,
1,
gtk4::TextDirection::None,
gtk4::IconLookupFlags::empty(),
) {
_self.set_icon(Some(&paintable_icon), 32, 32);
}
}
}
}));
}

View file

@ -30,6 +30,7 @@ pub struct Window {
pub enter_event_controller: OnceCell<EventControllerMotion>,
pub leave_event_controller: OnceCell<EventControllerMotion>,
pub drop_controller: OnceCell<DropTarget>,
pub window_drop_controller: OnceCell<DropTarget>,
}
// The central trait for subclassing a GObject

View file

@ -2,20 +2,15 @@ mod imp;
// use crate::ApplicationObject;
use crate::dock_item::DockItem;
use crate::X11_CONN;
use gdk4::ContentProvider;
use gdk4::Rectangle;
use gdk4::Surface;
use gdk4_x11::X11Surface;
use gio::Cancellable;
use gio::DesktopAppInfo;
use glib::Type;
use gtk4 as gtk;
use gtk4::prelude::ListModelExt;
use gtk4::DropTarget;
use gtk4::DropTargetAsync;
use gtk4::EventControllerMotion;
use gtk4::ListStore;
use gtk4::TreeIter;
use std::path::Path;
use x11rb::connection::Connection;
use x11rb::protocol::xproto::ConnectionExt;
@ -142,13 +137,13 @@ impl Window {
let enter_event_controller = &imp.enter_event_controller.get().unwrap();
let leave_event_controller = &imp.leave_event_controller.get().unwrap();
let drop_controller = &imp.drop_controller.get().unwrap();
let window_drop_controller = &imp.window_drop_controller.get().unwrap();
let revealer = &imp.revealer.get();
window.connect_show(
glib::clone!(@weak revealer, @weak leave_event_controller => move |_| {
dbg!(!leave_event_controller.contains_pointer());
if !leave_event_controller.contains_pointer() {
// TODO uncomment
// revealer.set_reveal_child(false);
revealer.set_reveal_child(false);
}
}),
);
@ -212,21 +207,25 @@ impl Window {
dbg!("hello, mouse entered me :)");
revealer.set_reveal_child(true);
}));
// TODO uncomment..
// Temporarily disable hiding for dnd testing while the other options are being figured out..
leave_event_controller.connect_leave(glib::clone!(@weak revealer => move |_evc| {
dbg!("hello, mouse left me :)");
// revealer.set_reveal_child(false);
}));
leave_event_controller.connect_leave(
glib::clone!(@weak revealer, @weak drop_controller => move |_evc| {
// only hide if DnD is not happening
if drop_controller.current_drop().is_none() {
dbg!("hello, mouse left me :)");
revealer.set_reveal_child(false);
}
}),
);
// drop_controller.connect_enter(move |_self, drag, x, y| {
// dbg!(x);
// dbg!(y);
// match drag.drag() {
// Some(d) => d.selected_action(),
// None => drag.actions(),
// }
// });
drop_controller.connect_enter(glib::clone!(@weak revealer => @default-return gdk4::DragAction::COPY, move |_self, _x, _y| {
revealer.set_reveal_child(true);
gdk4::DragAction::COPY
}));
// hack for showing hidden dock when drag enters window
window_drop_controller.connect_enter(glib::clone!(@weak revealer => @default-return gdk4::DragAction::COPY, move |_self, _x, _y| {
revealer.set_reveal_child(true);
gdk4::DragAction::empty()
}));
let saved_app_list_view = saved_app_list_view.get();
@ -317,12 +316,8 @@ impl Window {
let drop_actions = gdk4::DragAction::COPY;
// drop_actions.toggle(gdk4::DragAction::MOVE);
let drop_format = gdk4::ContentFormats::for_type(Type::STRING);
let provider =
ContentProvider::for_value(&DesktopAppInfo::new("firefox.desktop").to_value());
let desktop_type = provider.formats().types()[0];
// causes error for some reason...
// let desktop_type = Type::from_name("GDesktopAppInfo").expect("Invalid GType");
drop_format.union(&gdk4::ContentFormats::for_type(desktop_type));
let drop_target_controller = DropTarget::builder()
.preload(true)
.actions(drop_actions)
@ -332,6 +327,18 @@ impl Window {
imp.drop_controller
.set(drop_target_controller)
.expect("Could not set dock dnd drop controller");
// hack for revealing hidden dock when drag enters dock window
let window_drop_target_controller = DropTarget::builder()
.actions(gdk4::DragAction::COPY)
.formats(&gdk4::ContentFormats::for_type(Type::STRING))
.build();
let window = self.clone().upcast::<gtk::Window>();
window.add_controller(&window_drop_target_controller);
imp.window_drop_controller
.set(window_drop_target_controller)
.expect("Could not set dock dnd drop controller");
}
fn setup_factory(&self) {

View file

@ -18,8 +18,8 @@
<child>
<object class="GtkRevealer" id="revealer">
<property name="reveal-child">true</property>
<property name="transition-duration">200</property>
<property name="transition-type">swing-up</property>
<property name="transition-duration">300</property>
<property name="transition-type">slide-up</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>

View file

@ -1,76 +0,0 @@
use pop_launcher::{Request, Response};
use std::process;
use std::io::{self, BufRead, Write};
pub struct LauncherIpc {
child: process::Child,
stdin: process::ChildStdin,
stdout: io::BufReader<process::ChildStdout>,
exited: bool,
}
impl LauncherIpc {
pub fn new() -> io::Result<Self> {
let mut child = process::Command::new("pop-launcher")
.stdin(process::Stdio::piped())
.stdout(process::Stdio::piped())
.spawn()?;
let stdin = child.stdin.take().ok_or(
io::Error::new(io::ErrorKind::Other, "failed to find child stdin")
)?;
let stdout = io::BufReader::new(child.stdout.take().ok_or(
io::Error::new(io::ErrorKind::Other, "failed to find child stdout")
)?);
Ok(Self {
child,
stdin,
stdout,
exited: false,
})
}
fn send_request(&mut self, request: Request) -> io::Result<()> {
let mut request_json = serde_json::to_string(&request).map_err(|err| {
io::Error::new(io::ErrorKind::InvalidInput, err)
})?;
request_json.push('\n');
self.stdin.write_all(request_json.as_bytes())
}
fn recv_response(&mut self) -> io::Result<Response> {
let mut response_json = String::new();
self.stdout.read_line(&mut response_json)?;
serde_json::from_str(&response_json).map_err(|err| {
io::Error::new(io::ErrorKind::InvalidData, err)
})
}
pub fn request(&mut self, request: Request) -> io::Result<Response> {
self.send_request(request)?;
self.recv_response()
}
//TODO: better exit implementation
pub fn exit(&mut self) -> io::Result<Option<process::ExitStatus>> {
if ! self.exited {
self.send_request(Request::Exit)?;
let status = self.child.wait()?;
self.exited = true;
Ok(Some(status))
} else {
Ok(None)
}
}
}
impl Drop for LauncherIpc {
fn drop(&mut self) {
match self.exit() {
Ok(_) => (),
Err(err) => eprintln!("LauncherIpc::drop failed: {}", err),
}
}
}