cleanup and re-enable dock autohide
This commit is contained in:
parent
e9c5bf9254
commit
5cda4046a6
10 changed files with 37 additions and 240 deletions
1
examples/app_library/window/.#mod.rs
Symbolic link
1
examples/app_library/window/.#mod.rs
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
ashleywulber@pop-os.146928:1639590163
|
||||
BIN
examples/dock/.main.rs.swp
Normal file
BIN
examples/dock/.main.rs.swp
Normal file
Binary file not shown.
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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: >k::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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue