Skip to content

Commit

Permalink
Add support for set_parent in XDG portals (#209)
Browse files Browse the repository at this point in the history
* Make set_parent require HasWindowHandle + HasDisplayHandle

HasDisplayHandle is required for Wayland to work.

* Add support for set_parent in XDG portals

* Add libwayland-dev as a dependency in CI for Ubuntu XDG
  • Loading branch information
kjarosh authored Aug 12, 2024
1 parent a57dfad commit 42dcc7d
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 20 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: "[Ubuntu] install dependencies"
- name: "[Ubuntu GTK] install dependencies"
if: matrix.name == 'Ubuntu GTK'
run: sudo apt update && sudo apt install libgtk-3-dev
- name: "[Ubuntu XDG] install dependencies"
if: matrix.name == 'Ubuntu XDG'
run: sudo apt update && sudo apt install libwayland-dev
- name: "[WASM] rustup"
if: matrix.name == 'WASM32'
run: rustup target add wasm32-unknown-unknown
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Fix `AsyncFileDialog` blocking the executor on Windows (#191)
- Add `TDF_SIZE_TO_CONTENT` to `TaskDialogIndirect` config so that it can display longer text without truncating/wrapping (80 characters instead of 55) (#202)
- Fix `xdg-portal` backend not accepting special characters in message dialogs
- Make `set_parent` require `HasWindowHandle + HasDisplayHandle`
- Add support for `set_parent` in XDG Portals

## 0.14.0
- i18n for GTK and XDG Portal
Expand Down
104 changes: 104 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ windows-sys = { version = "0.48", features = [

[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))'.dependencies]
# XDG Desktop Portal
ashpd = { version = "0.8", optional = true, default-features = false }
ashpd = { version = "0.8", optional = true, default-features = false, features = ["raw_handle"] }
urlencoding = { version = "2.1.0", optional = true }
pollster = { version = "0.3", optional = true }
# GTK
Expand Down
20 changes: 18 additions & 2 deletions src/backend/xdg_desktop_portal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,22 @@ use crate::message_dialog::MessageDialog;
use crate::{FileDialog, FileHandle, MessageButtons, MessageDialogResult};

use ashpd::desktop::file_chooser::{FileFilter, OpenFileRequest, SaveFileRequest};
// TODO: convert raw_window_handle::RawWindowHandle to ashpd::WindowIdentifier
// https://github.com/bilelmoussaoui/ashpd/issues/40
use ashpd::WindowIdentifier;

use log::error;
use pollster::block_on;
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};

fn to_window_identifier(
window: Option<RawWindowHandle>,
display: Option<RawDisplayHandle>,
) -> Option<WindowIdentifier> {
window.map(|window| {
block_on(Box::pin(async move {
WindowIdentifier::from_raw_handle(&window, display.as_ref()).await
}))
})
}

impl From<&Filter> for FileFilter {
fn from(filter: &Filter) -> Self {
Expand Down Expand Up @@ -44,6 +55,7 @@ impl AsyncFilePickerDialogImpl for FileDialog {
fn pick_file_async(self) -> DialogFutureType<Option<FileHandle>> {
Box::pin(async move {
let res = OpenFileRequest::default()
.identifier(to_window_identifier(self.parent, self.parent_display))
.multiple(false)
.title(self.title.as_deref().or(None))
.filters(self.filters.iter().map(From::from))
Expand Down Expand Up @@ -77,6 +89,7 @@ impl AsyncFilePickerDialogImpl for FileDialog {
fn pick_files_async(self) -> DialogFutureType<Option<Vec<FileHandle>>> {
Box::pin(async move {
let res = OpenFileRequest::default()
.identifier(to_window_identifier(self.parent, self.parent_display))
.multiple(true)
.title(self.title.as_deref().or(None))
.filters(self.filters.iter().map(From::from))
Expand Down Expand Up @@ -130,6 +143,7 @@ impl AsyncFolderPickerDialogImpl for FileDialog {
fn pick_folder_async(self) -> DialogFutureType<Option<FileHandle>> {
Box::pin(async move {
let res = OpenFileRequest::default()
.identifier(to_window_identifier(self.parent, self.parent_display))
.multiple(false)
.directory(true)
.title(self.title.as_deref().or(None))
Expand Down Expand Up @@ -164,6 +178,7 @@ impl AsyncFolderPickerDialogImpl for FileDialog {
fn pick_folders_async(self) -> DialogFutureType<Option<Vec<FileHandle>>> {
Box::pin(async move {
let res = OpenFileRequest::default()
.identifier(to_window_identifier(self.parent, self.parent_display))
.multiple(true)
.directory(true)
.title(self.title.as_deref().or(None))
Expand Down Expand Up @@ -213,6 +228,7 @@ impl AsyncFileSaveDialogImpl for FileDialog {
fn save_file_async(self) -> DialogFutureType<Option<FileHandle>> {
Box::pin(async move {
let res = SaveFileRequest::default()
.identifier(to_window_identifier(self.parent, self.parent_display))
.title(self.title.as_deref().or(None))
.current_name(self.file_name.as_deref())
.filters(self.filters.iter().map(From::from))
Expand Down
23 changes: 15 additions & 8 deletions src/file_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use crate::FileHandle;
use std::path::Path;
use std::path::PathBuf;

use raw_window_handle::HasWindowHandle;
use raw_window_handle::RawWindowHandle;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};

#[derive(Debug, Clone)]
pub(crate) struct Filter {
Expand All @@ -24,6 +23,7 @@ pub struct FileDialog {
pub(crate) file_name: Option<String>,
pub(crate) title: Option<String>,
pub(crate) parent: Option<RawWindowHandle>,
pub(crate) parent_display: Option<RawDisplayHandle>,
pub(crate) can_create_directories: Option<bool>,
}

Expand Down Expand Up @@ -88,10 +88,14 @@ impl FileDialog {
self
}

/// Set parent windows explicitly (optional)
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasWindowHandle>(mut self, parent: &W) -> Self {
/// Set parent windows explicitly (optional).
/// Supported platforms:
/// * Windows
/// * Mac
/// * Linux (XDG only)
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.parent = parent.window_handle().ok().map(|x| x.as_raw());
self.parent_display = parent.display_handle().ok().map(|x| x.as_raw());
self
}

Expand Down Expand Up @@ -206,9 +210,12 @@ impl AsyncFileDialog {
self
}

/// Set parent windows explicitly (optional)
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasWindowHandle>(mut self, parent: &W) -> Self {
/// Set parent windows explicitly (optional).
/// Supported platforms:
/// * Windows
/// * Mac
/// * Linux (XDG only)
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.file_dialog = self.file_dialog.set_parent(parent);
self
}
Expand Down
23 changes: 15 additions & 8 deletions src/message_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use std::fmt::{Display, Formatter};

use std::future::Future;

use raw_window_handle::HasWindowHandle;
use raw_window_handle::RawWindowHandle;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};

/// Synchronous Message Dialog. Supported platforms:
/// * Windows
Expand All @@ -19,6 +18,7 @@ pub struct MessageDialog {
pub(crate) level: MessageLevel,
pub(crate) buttons: MessageButtons,
pub(crate) parent: Option<RawWindowHandle>,
pub(crate) parent_display: Option<RawDisplayHandle>,
}

// Oh god, I don't like sending RawWindowHandle between threads but here we go anyways...
Expand Down Expand Up @@ -64,10 +64,14 @@ impl MessageDialog {
self
}

/// Set parent windows explicitly (optional)
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasWindowHandle>(mut self, parent: &W) -> Self {
/// Set parent windows explicitly (optional).
/// Supported platforms:
/// * Windows
/// * Mac
/// * Linux (XDG only)
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.parent = parent.window_handle().ok().map(|x| x.as_raw());
self.parent_display = parent.display_handle().ok().map(|x| x.as_raw());
self
}

Expand Down Expand Up @@ -124,9 +128,12 @@ impl AsyncMessageDialog {
self
}

/// Set parent windows explicitly (optional)
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasWindowHandle>(mut self, parent: &W) -> Self {
/// Set parent windows explicitly (optional).
/// Supported platforms:
/// * Windows
/// * Mac
/// * Linux (XDG only)
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.0 = self.0.set_parent(parent);
self
}
Expand Down

0 comments on commit 42dcc7d

Please sign in to comment.