-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Add activation token support #70
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
use gtk3::prelude::*; | ||
use gtk3::{gdk, glib}; | ||
|
||
#[derive(Debug)] | ||
pub struct Gtk3ActivationToken { | ||
pub(crate) token: String, | ||
} | ||
|
||
impl Gtk3ActivationToken { | ||
pub fn from_window(window: &impl glib::IsA<gdk::Window>) -> Option<Self> { | ||
let display = window.as_ref().display(); | ||
match display.backend() { | ||
gdk::Backend::Wayland => todo!(), | ||
_ => None, | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#[cfg(feature = "wayland")] | ||
use super::wayland::WaylandActivationToken; | ||
use gdk4wayland::prelude::WaylandSurfaceExtManual; | ||
use gtk4::{gdk, glib, prelude::*}; | ||
|
||
#[derive(Debug)] | ||
pub struct Gtk4ActivationToken { | ||
pub(crate) wl_token: WaylandActivationToken, | ||
} | ||
|
||
#[cfg(all(feature = "gtk4_wayland", feature = "wayland"))] | ||
impl Gtk4ActivationToken { | ||
pub async fn from_native<N: glib::IsA<gtk4::Native>>(app_id: &str, native: &N) -> Option<Self> { | ||
let surface = native.surface(); | ||
match surface.display().backend() { | ||
gdk::Backend::Wayland => { | ||
let surface = surface | ||
.downcast_ref::<gdk4wayland::WaylandSurface>() | ||
.unwrap(); | ||
if let Some(wl_surface) = surface.wl_surface() { | ||
let wl_token = WaylandActivationToken::from_surface(app_id, &wl_surface) | ||
.await | ||
.unwrap(); | ||
|
||
Some(Self { wl_token }) | ||
} else { | ||
None | ||
} | ||
} | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "wayland")] | ||
impl From<WaylandActivationToken> for Gtk4ActivationToken { | ||
fn from(wl_token: WaylandActivationToken) -> Self { | ||
Self { wl_token } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
mod gtk3; | ||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
pub use self::gtk3::Gtk3ActivationToken; | ||
|
||
#[cfg(feature = "gtk4_wayland")] | ||
mod gtk4; | ||
#[cfg(feature = "gtk4_wayland")] | ||
pub use self::gtk4::Gtk4ActivationToken; | ||
|
||
#[cfg(any(feature = "wayland"))] | ||
mod wayland; | ||
#[cfg(feature = "wayland")] | ||
pub use wayland::WaylandActivationToken; | ||
|
||
use serde::{ser::Serializer, Serialize}; | ||
use zbus::zvariant::Type; | ||
|
||
// TODO | ||
/// See https://wayland.app/protocols/xdg-activation-v1 | ||
#[derive(Debug, Type)] | ||
#[zvariant(signature = "s")] | ||
pub enum ActivationToken { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add a TODO here to implement a X11 only thing. |
||
#[cfg(feature = "wayland")] | ||
#[doc(hidden)] | ||
Wayland(WaylandActivationToken), | ||
#[cfg(feature = "gtk4_wayland")] | ||
#[doc(hidden)] | ||
Gtk4(Gtk4ActivationToken), | ||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
#[doc(hidden)] | ||
Gtk3(Gtk3ActivationToken), | ||
#[doc(hidden)] | ||
Raw(String), | ||
#[doc(hidden)] | ||
None, | ||
} | ||
|
||
impl Serialize for ActivationToken { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
serializer.serialize_str(self.as_str()) | ||
} | ||
} | ||
|
||
impl Default for ActivationToken { | ||
fn default() -> Self { | ||
Self::None | ||
} | ||
} | ||
|
||
impl ActivationToken { | ||
#[cfg(feature = "wayland")] | ||
/// Create an instance of [`ActivationToken`] from a Wayland surface and the | ||
/// application's id. | ||
pub async fn from_wayland_surface( | ||
app_id: &str, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have plenty of places where we use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its way more convenient for the user to just write their app_id in a &str, ideally it would be preferable to somehow get it from the wayland toplevel or gtkwindow.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, you could make those functions take a |
||
surface: &wayland_client::protocol::wl_surface::WlSurface, | ||
) -> Self { | ||
if let Some(token) = WaylandActivationToken::from_surface(app_id, surface).await { | ||
Self::Wayland(token) | ||
} else { | ||
Self::default() | ||
} | ||
} | ||
|
||
#[cfg(feature = "wayland")] | ||
/// Create an instance of [`ActivationToken`] from a raw Wayland surface and | ||
/// the application's id. | ||
/// | ||
/// # Safety | ||
/// | ||
/// Both pointers have to be valid surface and display pointers. You must | ||
/// ensure the `display_ptr` lives longer than the returned | ||
/// `ActivationToken`. | ||
pub async unsafe fn from_wayland_raw( | ||
app_id: &str, | ||
surface_ptr: *mut std::ffi::c_void, | ||
display_ptr: *mut std::ffi::c_void, | ||
) -> Self { | ||
if let Some(token) = | ||
WaylandActivationToken::from_raw(app_id, surface_ptr, display_ptr).await | ||
{ | ||
Self::Wayland(token) | ||
} else { | ||
Self::default() | ||
} | ||
} | ||
|
||
#[cfg(feature = "gtk4_wayland")] | ||
// TODO Maybe name from_display. | ||
/// Creates a [`ActivationToken`] from a [`gtk4::Native`](https://docs.gtk.org/gtk4/class.Native.html). | ||
pub async fn from_native<N: ::gtk4::glib::IsA<::gtk4::Native>>( | ||
app_id: &str, | ||
native: &N, | ||
) -> Self { | ||
if let Some(token) = Gtk4ActivationToken::from_native(app_id, native).await { | ||
Self::Gtk4(token) | ||
} else { | ||
Self::default() | ||
} | ||
} | ||
|
||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
/// Creates a [`ActivationToken`] from a [`IsA<gdk3::Window>`](https://gtk-rs.org/gtk3-rs/stable/latest/docs/gdk/struct.Window.html). | ||
pub fn from_window(window: &impl ::gtk3::glib::IsA<::gtk3::gdk::Window>) -> Self { | ||
if let Some(token) = Gtk3ActivationToken::from_window(window) { | ||
Self::Gtk3(token) | ||
} else { | ||
Self::default() | ||
} | ||
} | ||
|
||
pub fn is_some(&self) -> bool { | ||
!self.is_none() | ||
} | ||
|
||
pub fn is_none(&self) -> bool { | ||
matches!(self, Self::None) | ||
} | ||
|
||
pub(crate) fn as_str(&self) -> &str { | ||
match self { | ||
#[cfg(feature = "wayland")] | ||
Self::Wayland(activation_token) => activation_token.token.as_str(), | ||
#[cfg(feature = "gtk4_wayland")] | ||
Self::Gtk4(activation_token) => activation_token.wl_token.token.as_str(), | ||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
Self::Gtk3(activation_token) => activation_token.token.as_str(), | ||
Self::Raw(string) => string.as_str(), | ||
Self::None => "", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between None and Raw? You can make the default impl use |
||
} | ||
} | ||
|
||
pub(crate) fn into_string(self) -> String { | ||
match self { | ||
#[cfg(feature = "wayland")] | ||
Self::Wayland(activation_token) => activation_token.token, | ||
#[cfg(feature = "gtk4_wayland")] | ||
Self::Gtk4(activation_token) => activation_token.wl_token.token, | ||
#[cfg(all(feature = "gtk3", feature = "wayland"))] | ||
Self::Gtk3(activation_token) => activation_token.token, | ||
Self::Raw(string) => string, | ||
Self::None => "".into(), | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct, the feature should be enabled only if
gtk4_wayland
is enabled.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what you mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that looks correct to me