├── .github
└── workflows
│ ├── build.yml
│ ├── flatpak.yml
│ └── pages.yml
├── .gitignore
├── COPYING
├── NEWS
├── README.md
├── build-aux
├── build.sh
├── org.gnome.PortalTest.Gtk3.json
├── org.gnome.PortalTest.Gtk4.json
├── org.gnome.PortalTest.Qt5.json
└── org.gnome.PortalTest.Qt6.json
├── doc
├── favicon-128x128.png
├── favicon-180x180.png
├── favicon-192x192.png
├── favicon-32x32.png
├── libportal.md
├── libportal.svg
├── libportal.toml.in
├── meson.build
├── release-checklist.md
└── urlmap.js
├── libportal
├── TODO
├── account.c
├── account.h
├── background.c
├── background.h
├── camera.c
├── camera.h
├── dynamic-launcher.c
├── dynamic-launcher.h
├── email.c
├── email.h
├── filechooser.c
├── filechooser.h
├── glib-backports.h
├── inhibit.c
├── inhibit.h
├── inputcapture-pointerbarrier.c
├── inputcapture-pointerbarrier.h
├── inputcapture-private.h
├── inputcapture-zone.c
├── inputcapture-zone.h
├── inputcapture.c
├── inputcapture.h
├── location.c
├── location.h
├── meson.build
├── notification.c
├── notification.h
├── openuri.c
├── openuri.h
├── parent-private.h
├── parent.c
├── parent.h
├── portal-enums.c.template
├── portal-enums.h.template
├── portal-gtk3.c
├── portal-gtk3.h
├── portal-gtk4.c
├── portal-gtk4.h
├── portal-helpers.h
├── portal-private.h
├── portal-qt5.cpp
├── portal-qt5.h
├── portal-qt6.cpp
├── portal-qt6.h
├── portal.c
├── portal.h
├── print.c
├── print.h
├── remote.c
├── remote.h
├── screenshot.c
├── screenshot.h
├── session-private.h
├── session.c
├── session.h
├── settings-private.h
├── settings.c
├── settings.h
├── spawn.c
├── spawn.h
├── trash.c
├── trash.h
├── types.h
├── updates.c
├── updates.h
├── wallpaper.c
└── wallpaper.h
├── meson.build
├── meson_options.txt
├── portal-test
├── gtk3
│ ├── main.c
│ ├── meson.build
│ ├── org.gnome.PortalTest.Gtk3.desktop
│ ├── org.gnome.PortalTest.Gtk3.service
│ ├── portal-linking-test.c
│ ├── portal-test-app.c
│ ├── portal-test-app.h
│ ├── portal-test-win.c
│ ├── portal-test-win.h
│ ├── portal-test-win.ui
│ ├── portal-test.gresource.xml
│ └── test.txt
├── gtk4
│ ├── application.js
│ ├── main.js
│ ├── meson.build
│ ├── org.gnome.PortalTest.Gtk4.data.gresource.xml
│ ├── org.gnome.PortalTest.Gtk4.desktop
│ ├── org.gnome.PortalTest.Gtk4.in
│ ├── org.gnome.PortalTest.Gtk4.service
│ ├── org.gnome.PortalTest.Gtk4.src.gresource.xml
│ ├── portal-linking-test.c
│ ├── test.txt
│ ├── window.js
│ └── window.ui
├── meson.build
├── qt5
│ ├── main.cpp
│ ├── meson.build
│ ├── portal-test-qt.cpp
│ ├── portal-test-qt.h
│ └── portal-test-qt.ui
└── qt6
│ ├── main.cpp
│ ├── meson.build
│ ├── portal-test-qt.cpp
│ ├── portal-test-qt.h
│ └── portal-test-qt.ui
├── subprojects
└── gi-docgen.wrap
└── tests
├── gir-testenv.sh
├── meson.build
├── pyportaltest
├── __init__.py
├── templates
│ ├── __init__.py
│ ├── inputcapture.py
│ ├── notification.py
│ ├── remotedesktop.py
│ ├── screencast.py
│ └── wallpaper.py
├── test_inputcapture.py
├── test_notification.py
├── test_remotedesktop.py
├── test_screencast.py
└── test_wallpaper.py
├── qt5
├── meson.build
├── test.cpp
└── test.h
└── qt6
├── meson.build
├── test.cpp
└── test.h
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: libportal CI
2 |
3 | env:
4 | DEBIAN_FRONTEND: noninteractive
5 |
6 | on:
7 | push:
8 | branches:
9 | - main
10 | pull_request:
11 | branches:
12 | - main
13 |
14 | jobs:
15 | ubuntu:
16 | name: Ubuntu
17 | runs-on: ubuntu-latest
18 | container: ubuntu:${{ matrix.ubuntu-version }}
19 | strategy:
20 | matrix:
21 | ubuntu-version: ['22.04', '24.04']
22 | compiler: ['gcc', 'clang']
23 |
24 | env:
25 | CC: ${{ matrix.compiler }}
26 |
27 | steps:
28 | - name: Install dependencies
29 | run: |
30 | echo "$HOME/.local/bin" >> $GITHUB_PATH
31 | apt-get update --quiet
32 | apt-get install --quiet -y \
33 | ${{ matrix.compiler }} \
34 | dbus \
35 | gettext \
36 | git \
37 | gi-docgen \
38 | libgirepository1.0-dev \
39 | libglib2.0 \
40 | libgtk-3-dev \
41 | libgtk-4-dev \
42 | libqt5x11extras5-dev \
43 | meson \
44 | python3-dbusmock \
45 | python3-pytest \
46 | qtbase5-dev \
47 | qt6-base-dev \
48 | qt6-base-private-dev \
49 | valac
50 | - name: Check out libportal
51 | uses: actions/checkout@v4
52 | - name: Fix Git ownership
53 | run: |
54 | echo $GITHUB_WORKSPACE
55 | git config --global --add safe.directory $GITHUB_WORKSPACE
56 | git status
57 | - name: Configure libportal
58 | run: meson setup --prefix=/usr _build -Dbackend-gtk3=enabled -Dbackend-gtk4=enabled -Dbackend-qt5=enabled -Dbackend-qt6=enabled
59 | - name: Build libportal
60 | run: ninja -C_build
61 | - name: Run libportal tests
62 | working-directory: _build
63 | run: meson test --verbose --print-errorlogs
64 | - name: Generate dist tarball
65 | working-directory: _build
66 | run: meson dist
67 | - name: Upload test logs
68 | uses: actions/upload-artifact@v4
69 | if: success() || failure()
70 | with:
71 | name: test logs (ubuntu ${{ matrix.ubuntu-version }} ${{ matrix.compiler }})
72 | path: |
73 | tests/*.log
74 | test-*.log
75 | installed-test-logs/
76 | _build/meson-logs/testlog.txt
77 | _build/meson-dist/
78 |
79 | fedora:
80 | name: Fedora
81 | runs-on: ubuntu-latest
82 | container: fedora:${{ matrix.fedora-version }}
83 | strategy:
84 | matrix:
85 | fedora-version: ['39', '40']
86 | compiler: ['gcc', 'clang']
87 |
88 | env:
89 | CC: ${{ matrix.compiler }}
90 |
91 | steps:
92 | - name: Install dependencies
93 | run: |
94 | dnf install --quiet -y \
95 | ${{ matrix.compiler }} \
96 | git \
97 | gi-docgen \
98 | gobject-introspection-devel \
99 | gtk3-devel \
100 | gtk4-devel \
101 | meson \
102 | python3-pytest \
103 | python3-dbusmock \
104 | qt5-qtbase-devel \
105 | qt5-qtx11extras-devel \
106 | qt6-qtbase-devel \
107 | qt6-qtbase-private-devel \
108 | vala
109 | - name: Check out libportal
110 | uses: actions/checkout@v4
111 | - name: Fix Git ownership
112 | run: |
113 | echo $GITHUB_WORKSPACE
114 | git config --global --add safe.directory $GITHUB_WORKSPACE
115 | git status
116 | - name: Configure libportal
117 | run: meson setup --prefix=/usr _build -Dbackend-gtk3=enabled -Dbackend-gtk4=enabled -Dbackend-qt5=enabled -Dbackend-qt6=enabled
118 | - name: Build libportal
119 | run: ninja -C_build
120 | - name: Run libportal tests
121 | working-directory: _build
122 | run: meson test --verbose --print-errorlogs
123 | - name: Generate dist tarball
124 | working-directory: _build
125 | run: meson dist
126 | - name: Upload test logs
127 | uses: actions/upload-artifact@v4
128 | if: success() || failure()
129 | with:
130 | name: test logs (fedora ${{ matrix.fedora-version }} ${{ matrix.compiler }})
131 | path: |
132 | tests/*.log
133 | test-*.log
134 | installed-test-logs/
135 | _build/meson-logs/testlog.txt
136 | _build/meson-dist/
137 |
138 | abi-check:
139 | name: ABI check
140 | runs-on: ubuntu-latest
141 | container: fedora:latest
142 | env:
143 | LAST_ABI_BREAK: "467a397fd7996557f837cdc26ac07c01c62810e5"
144 |
145 | steps:
146 | - name: Install dependencies
147 | run: |
148 | dnf install -y meson gcc gobject-introspection-devel gtk3-devel gtk4-devel qt5-qtbase-devel qt5-qtx11extras-devel qt6-qtbase-devel qt6-qtbase-private-devel git libabigail
149 | - name: Install check-abi
150 | run: |
151 | curl https://gitlab.freedesktop.org/hadess/check-abi/-/raw/main/contrib/check-abi-fedora.sh | bash
152 | rm -rf check-abi/
153 | - name: Check out libportal
154 | uses: actions/checkout@v4
155 | with:
156 | fetch-depth: 0
157 | - name: Work around git safe directory check
158 | run: git config --global --add safe.directory $GITHUB_WORKSPACE
159 | - name: Run ABI check
160 | run: check-abi --old-parameters="-Dvapi=false -Ddocs=false -Dintrospection=false" --new-parameters="-Dvapi=false -Ddocs=false -Dtests=false -Dintrospection=false" ${LAST_ABI_BREAK} $GITHUB_SHA
161 |
--------------------------------------------------------------------------------
/.github/workflows/flatpak.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | name: Flatpak Portal Test App
4 |
5 | on:
6 | push:
7 | paths-ignore: ['**.md']
8 | branches: [main]
9 | pull_request:
10 | paths-ignore: ['**.md']
11 | branches: [main]
12 |
13 | jobs:
14 | build-flatpak-gtk3:
15 | name: GTK3
16 | runs-on: ubuntu-latest
17 | container:
18 | image: bilelmoussaoui/flatpak-github-actions:gnome-46
19 | options: --privileged
20 | steps:
21 | - name: Checkout
22 | uses: actions/checkout@v3
23 |
24 | - name: Build GTK3 portal test
25 | uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v6
26 | with:
27 | bundle: portal-test-gtk3.flatpak
28 | manifest-path: build-aux/org.gnome.PortalTest.Gtk3.json
29 | cache-key: gtk3-${{ github.sha }}
30 |
31 | build-flatpak-gtk4:
32 | name: GTK4
33 | runs-on: ubuntu-latest
34 | container:
35 | image: bilelmoussaoui/flatpak-github-actions:gnome-46
36 | options: --privileged
37 | steps:
38 | - name: Checkout
39 | uses: actions/checkout@v3
40 |
41 | - name: Build GTK4 portal test
42 | uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v6
43 | with:
44 | bundle: portal-test-gtk4.flatpak
45 | manifest-path: build-aux/org.gnome.PortalTest.Gtk4.json
46 | cache-key: gtk4-${{ github.sha }}
47 |
48 | build-flatpak-qt5:
49 | name: Qt5
50 | runs-on: ubuntu-latest
51 | container:
52 | image: bilelmoussaoui/flatpak-github-actions:kde-5.15-23.08
53 | options: --privileged
54 | steps:
55 | - name: Checkout
56 | uses: actions/checkout@v3
57 |
58 | - name: Build Qt5 portal test
59 | uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v6
60 | with:
61 | bundle: portal-test-qt5.flatpak
62 | manifest-path: build-aux/org.gnome.PortalTest.Qt5.json
63 | cache-key: qt5-${{ github.sha }}
64 |
65 | build-flatpak-qt6:
66 | name: Qt6
67 | runs-on: ubuntu-latest
68 | container:
69 | image: bilelmoussaoui/flatpak-github-actions:kde-6.7
70 | options: --privileged
71 | steps:
72 | - name: Checkout
73 | uses: actions/checkout@v3
74 |
75 | - name: Build Qt6 portal test
76 | uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v6
77 | with:
78 | bundle: portal-test-qt6.flatpak
79 | manifest-path: build-aux/org.gnome.PortalTest.Qt6.json
80 | cache-key: qt6-${{ github.sha }}
81 |
--------------------------------------------------------------------------------
/.github/workflows/pages.yml:
--------------------------------------------------------------------------------
1 | name: Documentation
2 |
3 | on: [push, pull_request]
4 |
5 | permissions:
6 | contents: read
7 | pages: write
8 | id-token: write
9 |
10 | concurrency:
11 | group: "pages"
12 | cancel-in-progress: false
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 | container:
18 | image: fedora:latest
19 |
20 | steps:
21 | - name: Install dependencies
22 | run: |
23 | dnf install -y \
24 | gcc \
25 | gi-docgen \
26 | git \
27 | gobject-introspection-devel \
28 | meson \
29 | python3-pytest \
30 | python3-dbusmock
31 |
32 | - name: Check out libportal
33 | uses: actions/checkout@v4
34 |
35 | - name: Configure libportal
36 | run: meson setup --prefix=/usr builddir -Dtests=false -Dvapi=false
37 |
38 | - name: Build libportal
39 | run: ninja -C builddir doc/libportal-1
40 |
41 | - name: Prepare docs
42 | working-directory: builddir/doc
43 | run: |
44 | mv ./libportal-1 ../../_site
45 |
46 | - name: Upload artifact
47 | uses: actions/upload-pages-artifact@v3
48 |
49 | # Deployment job
50 | deploy:
51 | needs: build
52 | runs-on: ubuntu-latest
53 | if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') }}
54 | environment:
55 | name: github-pages
56 | url: ${{ steps.deployment.outputs.page_url }}
57 |
58 | steps:
59 | - name: Deploy to GitHub Pages
60 | id: deployment
61 | uses: actions/deploy-pages@v4
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.flatpak-builder/
2 | /_build/
3 | __pycache__/
4 |
--------------------------------------------------------------------------------
/NEWS:
--------------------------------------------------------------------------------
1 | Changes in 0.9.2, yyyy-mm-dd
2 | ============================
3 |
4 | Not yet released.
5 |
6 | Changes in 0.9.1, 2025-02-12
7 | ============================
8 |
9 | Dependencies:
10 |
11 | - Meson 0.55.0 is required
12 |
13 | Bug fixes:
14 |
15 | - Fix memory management in the Input Capture portal code (#169, #190)
16 | - Correct the type used for GObject signal connections (#184)
17 | - Remove wrong `(closure)` annotations, fixing GObject-Introspection warnings
18 | (#182)
19 | - Don't require a C++ compiler for the build architecture (#181)
20 | - Fix Meson warnings (#181)
21 | - Consistently use `#pragma once` (#192)
22 | - Initialize all g_autoptr variables (#180)
23 |
24 | Changes in 0.9.0, 21-12-2024
25 | ==========================
26 |
27 | Dependencies:
28 |
29 | - GLib 2.72 or higher is now required
30 |
31 | Features:
32 |
33 | - Introduce support for the Notification v2 portal version
34 |
35 | Bug fixes:
36 |
37 | - Fix a file descriptor leak in the Mail portal code
38 | - Fix some minor memory leaks
39 |
40 | Changes in 0.8.1, 04-09-2024
41 | ==========================
42 |
43 | - Fix a regression in the Remote Desktop where it wouldn't work with the
44 | ScreenCast portal correctly.
45 | - Use non-deprecated functions in the GTK4 code
46 | - Run tests in CI so we catch regressions earlier
47 | - Make Qt tests use QTEST_GUILESS_MAIN
48 | - Fix an Input Capture test
49 |
50 | Changes in 0.8.0, 02-09-2024
51 | ==========================
52 |
53 | - Add API to allow for persistence on RemoteDesktop sessions
54 | - Implement support for the Input Capture portal
55 | - Add support for Qt 6
56 | - Support xdg-foreign with Qt 6
57 | - Fix screencasting on wlroots-based compositors
58 |
59 |
60 | Changes in 0.7.1, 09-09-2023
61 | ==========================
62 |
63 | - Restore ability to call g_object_new (XDP_TYPE_PORTAL, ...)
64 |
65 | Changes in 0.7, 06-09-2023
66 | ==========================
67 |
68 | - Add support for the new SetStatus() method of the Background portal
69 | - Add support for the new ConnectToEIS() method of the Remote Desktop portal
70 | - Improve unit and integration tests
71 | - Documentation improvements
72 | - CI improvements
73 |
74 | Changes in 0.6, 21-03-2022
75 | ==========================
76 |
77 | - New portal support: Dynamic launcher
78 | - Add API for checking for flatpak/snap sandbox
79 | - Fix a bug where the callback setup by libportal for a GCancellable was not
80 | properly canceled in case a portal method call was not successful, which can
81 | lead to a double free seg fault
82 | - libportal-qt: Add convenient functions to better deal with GVariants
83 | - libportal-qt: Use a global instance of XdpPortal object
84 | - libportal-qt: make filechooserFilterToGVariant() public
85 | - camera: Use correct variant for is_camera_present()
86 | - portal-test-gtk3: Fix incorrect paths used in tests
87 | - Documentation improvements
88 | - CI improvements
89 |
90 | Changes in 0.5, 21-12-2021
91 | ==========================
92 |
93 | - Relicence to LGPL 3.0
94 | - Fix a refcounting error in xdp_parent_free
95 | - location: Fix location-updated signature
96 | - remote: Add cursor mode
97 | - remote: Support virtual screens
98 | - remote: Support persistent sessions
99 | - Rename qt backend to qt5
100 | - Install separate libraries: libportal-gtk3, libportal-gtk4, libportal-qt5
101 | - Add gobject-introspection support
102 | - Add vala support
103 | - Add a GTK4 portal test app, using gjs
104 | - Build documentation using gi-docgen
105 |
106 | Changes in 0.4
107 | ==============
108 |
109 | - Make GTK4 support work with GTK 4.0
110 | - Qt5 support
111 | - OpenURI: Support write access
112 | - Build fixes
113 | - Add more tests
114 | - Require GLib 2.58
115 |
116 | Changes in 0.3
117 | ==============
118 |
119 | - Clean up includes
120 | - Future-proof the API
121 | - Test and fix update monitor APIs
122 |
123 | Changes in 0.2
124 | ==============
125 |
126 | - Build a portal-test application if you specify -Dbuild-portal-test=true
127 | - The portal-test app comes with a flatpak build script for ease of testing
128 | - The OpenURI call has gained an 'ask' argument
129 | -
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | libportal - Flatpak portal library
2 | ==================================
3 |
4 | libportal provides GIO-style async APIs for most Flatpak portals. You can find
5 | the documentation [here](https://flatpak.github.io/libportal/).
6 |
7 | ## Getting started
8 |
9 | `libportal` uses Meson to build its projects. To install Meson on your system,
10 | follow the [Getting Meson instructions][1]. If your system is missing a
11 | dependency, Meson will tell you which one. How you install your missing
12 | dependencies is up to you.
13 |
14 | ### Build libportal
15 |
16 | The first time you build libportal, give `meson` a directory to build into; we
17 | recommend `_build`:
18 |
19 | ```
20 | meson _build
21 | ```
22 |
23 | Then use `ninja` to build the project, pointing it to your build directory:
24 |
25 | ```
26 | ninja -C _build
27 | ```
28 |
29 | For subsequent builds, you only need to use the `ninja -C _build` command.
30 |
31 | ### Passing options
32 |
33 | libportal includes [Meson build options][2] for components that can optionally
34 | be built. Run `meson configure` to see all available options or,
35 | after first running `meson _build`, view available options and their current
36 | values with:
37 |
38 | ```
39 | meson configure _build
40 | ```
41 |
42 | To change an option, re-configure the project:
43 |
44 | ```
45 | meson configure _build -Dportal-tests=true
46 | ```
47 |
48 | You can also pass in options right from the start, e.g. with:
49 |
50 | ```
51 | meson _build -Dportal-tests=true
52 | ```
53 |
54 | Then build:
55 |
56 | ```
57 | ninja -C _build
58 | ```
59 |
60 | ## Optional components
61 |
62 | ### `portal-tests`
63 |
64 | To generate test binaries, set the `portal-tests` option to `true`,
65 | e.g. `-Dportal-tests=true`, to build the portal tests for the backend
66 | built. Then run the desired test binary, e.g.:
67 |
68 | ```
69 | ./_build/portal-test/gtk3/portal-test-gtk3
70 | ```
71 |
72 | or
73 |
74 | ```
75 | ./_build/portal-test/qt5/portal-test-qt5
76 | ```
77 |
78 | [1]: https://mesonbuild.com/Getting-meson.html
79 | [2]: https://mesonbuild.com/Build-options.html#build-options
80 |
--------------------------------------------------------------------------------
/build-aux/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -eu
4 |
5 | TOP_DIR=`dirname $0`/..
6 | OLD_DIR=`pwd`
7 |
8 | cd "$TOP_DIR"
9 |
10 | for backend in Gtk3 Gtk4 Qt5 Qt6; do
11 | flatpak-builder --force-clean --ccache --repo=_build/repo --install --user "_build/app-$backend" "build-aux/org.gnome.PortalTest.${backend}.json"
12 | done
13 |
14 | cd "$OLD_DIR"
15 |
--------------------------------------------------------------------------------
/build-aux/org.gnome.PortalTest.Gtk3.json:
--------------------------------------------------------------------------------
1 | {
2 | "app-id": "org.gnome.PortalTest.Gtk3",
3 | "runtime": "org.gnome.Platform",
4 | "runtime-version": "47",
5 | "sdk": "org.gnome.Sdk",
6 | "command": "portal-test-gtk3",
7 | "finish-args": [
8 | "--socket=wayland",
9 | "--socket=x11",
10 | "--socket=pulseaudio"
11 | ],
12 | "modules": [
13 | {
14 | "name": "gtk3",
15 | "disabled": true,
16 | "buildsystem": "meson",
17 | "builddir": true,
18 | "config-opts": [
19 | "-Dgtk_doc=false"
20 | ],
21 | "sources": [
22 | {
23 | "type": "git",
24 | "url": "https://gitlab.gnome.org/GNOME/gtk.git",
25 | "branch": "gtk-3-24"
26 | }
27 | ]
28 | },
29 | {
30 | "name": "portal-test-gtk3",
31 | "buildsystem": "meson",
32 | "builddir": true,
33 | "config-opts": [
34 | "-Dbackend-gtk3=enabled",
35 | "-Dbackend-gtk4=disabled",
36 | "-Dbackend-qt5=disabled",
37 | "-Dbackend-qt6=disabled",
38 | "-Dportal-tests=true",
39 | "-Ddocs=false"
40 | ],
41 | "sources": [
42 | {
43 | "type": "dir",
44 | "path": "../"
45 | }
46 | ]
47 | }
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/build-aux/org.gnome.PortalTest.Gtk4.json:
--------------------------------------------------------------------------------
1 | {
2 | "app-id": "org.gnome.PortalTest.Gtk4",
3 | "runtime": "org.gnome.Platform",
4 | "runtime-version": "47",
5 | "sdk": "org.gnome.Sdk",
6 | "command": "org.gnome.PortalTest.Gtk4",
7 | "finish-args": [
8 | "--device=dri",
9 | "--socket=wayland",
10 | "--socket=x11",
11 | "--socket=pulseaudio"
12 | ],
13 | "modules": [
14 | {
15 | "name": "portal-test-gtk4",
16 | "buildsystem": "meson",
17 | "builddir": true,
18 | "config-opts": [
19 | "-Dbackend-gtk3=disabled",
20 | "-Dbackend-gtk4=enabled",
21 | "-Dbackend-qt5=disabled",
22 | "-Dbackend-qt6=disabled",
23 | "-Dportal-tests=true",
24 | "-Ddocs=false"
25 | ],
26 | "sources": [
27 | {
28 | "type": "dir",
29 | "path": "../"
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/build-aux/org.gnome.PortalTest.Qt5.json:
--------------------------------------------------------------------------------
1 | {
2 | "app-id": "org.gnome.PortalTest.Qt5",
3 | "runtime": "org.kde.Platform",
4 | "runtime-version": "5.15-23.08",
5 | "sdk": "org.kde.Sdk",
6 | "command": "portal-test-qt5",
7 | "finish-args": [
8 | "--socket=wayland",
9 | "--socket=x11",
10 | "--socket=pulseaudio"
11 | ],
12 | "modules": [
13 | {
14 | "name": "portal-test-qt5",
15 | "buildsystem": "meson",
16 | "builddir": true,
17 | "config-opts": [
18 | "-Dbackend-gtk3=disabled",
19 | "-Dbackend-gtk4=disabled",
20 | "-Dbackend-qt5=enabled",
21 | "-Dbackend-qt6=disabled",
22 | "-Dportal-tests=true",
23 | "-Dintrospection=false",
24 | "-Dvapi=false",
25 | "-Ddocs=false"
26 | ],
27 | "sources": [
28 | {
29 | "type": "dir",
30 | "path": "../"
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/build-aux/org.gnome.PortalTest.Qt6.json:
--------------------------------------------------------------------------------
1 | {
2 | "app-id": "org.gnome.PortalTest.Qt6",
3 | "runtime": "org.kde.Platform",
4 | "runtime-version": "6.7",
5 | "sdk": "org.kde.Sdk",
6 | "command": "portal-test-qt6",
7 | "finish-args": [
8 | "--socket=wayland",
9 | "--socket=x11",
10 | "--socket=pulseaudio"
11 | ],
12 | "modules": [
13 | {
14 | "name": "portal-test-qt6",
15 | "buildsystem": "meson",
16 | "builddir": true,
17 | "config-opts": [
18 | "-Dbackend-gtk3=disabled",
19 | "-Dbackend-gtk4=disabled",
20 | "-Dbackend-qt5=disabled",
21 | "-Dbackend-qt6=enabled",
22 | "-Dportal-tests=true",
23 | "-Dintrospection=false",
24 | "-Dvapi=false",
25 | "-Ddocs=false"
26 | ],
27 | "sources": [
28 | {
29 | "type": "dir",
30 | "path": "../"
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/doc/favicon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatpak/libportal/796053d2eebe4532aad6bd3fd80cdf3b197806ec/doc/favicon-128x128.png
--------------------------------------------------------------------------------
/doc/favicon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatpak/libportal/796053d2eebe4532aad6bd3fd80cdf3b197806ec/doc/favicon-180x180.png
--------------------------------------------------------------------------------
/doc/favicon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatpak/libportal/796053d2eebe4532aad6bd3fd80cdf3b197806ec/doc/favicon-192x192.png
--------------------------------------------------------------------------------
/doc/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flatpak/libportal/796053d2eebe4532aad6bd3fd80cdf3b197806ec/doc/favicon-32x32.png
--------------------------------------------------------------------------------
/doc/libportal.md:
--------------------------------------------------------------------------------
1 | Title: libportal Reference Manual
2 | Slug: reference-manual
3 |
4 | # Portals
5 |
6 | libportal is a library that provides GIO-style async API wrappers
7 | for the D-Bus portal APIs in xdg-desktop-portal.
8 |
9 | Where possible, applications should prefer to use existing library
10 | APIs that have portal support. For example, a GTK application should
11 | use [class@Gtk.FileChooserNative] instead of [method@Portal.open_file].
12 |
13 | Some portal interfaces are not covered in libportal, since
14 | they already have perfectly adequate APIs in GLib (which libportal depends on anyway).
15 |
16 | - NetworkMonitor: Use [iface@Gio.NetworkMonitor]
17 | - ProxyResolver: Use [iface@Gio.ProxyResolver]
18 | - Settings: Use a plain [class@Gio.DBusProxy]
19 | - GameMode: Not currently covered
20 | - Secrets: Not currently covered
21 |
22 | ## Accounts
23 |
24 | The Accounts portal lets applications query basic information about
25 | the user, such as user ID, name and avatar picture.
26 |
27 | See [method@Portal.get_user_information].
28 |
29 | The underlying D-Bus interface is [org.freedesktop.portal.Account](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Account).
30 |
31 | ## Background
32 |
33 | The Background portal lets applications request background permissions
34 | such as enabling autostart.
35 |
36 | See [method@Portal.request_background].
37 |
38 | The underlying D-Bus interface is [org.freedesktop.portal.Background](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Background).
39 |
40 | ## Camera
41 |
42 | The Camera portal lets applications access camera devices and open [PipeWire][pipewire] remotes for them.
43 |
44 | To test if the Camera portal is available, you can use [method@Portal.is_camera_present].
45 |
46 | See [method@Portal.access_camera].
47 |
48 | The underlying D-Bus interface is [org.freedesktop.portal.Camera](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Camera).
49 |
50 | ## Email
51 |
52 | The Email portal lets applications send email, by prompting
53 | the user to compose a message. The email may already have
54 | an address, subject, body or attachments.
55 |
56 | See [method@Portal.compose_email].
57 |
58 | The underlying D-Bus interface is [org.freedesktop.portal.Email](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Email).
59 |
60 | ## File
61 |
62 | The File portal lets applications ask the user for access to
63 | files outside the sandbox, by presenting a file chooser dialog.
64 |
65 | The selected files will be made accessible to the application
66 | via the document portal, and the returned URI will point
67 | into the document portal fuse filesystem in `/run/user/$UID/doc/`.
68 |
69 | See [method@Portal.open_file], [method@Portal.save_file], and [method@Portal.save_files].
70 |
71 | The underlying D-Bus interface is [org.freedesktop.portal.FileChooser](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.FileChooser).
72 |
73 | ## Session
74 |
75 | The Session portal lets applications inhibit certain login session
76 | state changes, and be informed about the impending end of the
77 | session.
78 |
79 | A typical use for this functionality is to prevent the session
80 | from locking while a video is playing.
81 |
82 | See [method@Portal.session_inhibit], and [method@Portal.session_monitor_start].
83 |
84 | The underlying D-Bus interface is [org.freedesktop.portal.Inhibit](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Inhibit).
85 |
86 | ## Location
87 |
88 | The Access portal lets app access to location information.
89 |
90 | Location monitoring makes location information available
91 | via the [signal@Portal::location-updated] signal.
92 |
93 | See [method@Portal.location_monitor_start].
94 |
95 | The underlying D-Bus interface is [org.freedesktop.portal.Location](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Location).
96 |
97 | ## Notification
98 |
99 | The Notification portal lets applications send desktop notifications.
100 |
101 | See [method@Portal.add_notification].
102 |
103 | The underlying D-Bus interface is [org.freedesktop.portal.Notification](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Notification).
104 |
105 | ## Open URI
106 |
107 | The Open URI portal lets applications open URIs in external handlers.
108 | A typical example is to open a pdf file in a document viewer.
109 |
110 | See [method@Portal.open_uri], and [method@Portal.open_directory].
111 |
112 | The underlying D-Bus interface is [org.freedesktop.portal.OpenURI](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.OpenURI).
113 |
114 | ## Print
115 |
116 | The Print portal lets applications send documents to a printer.
117 |
118 | See [method@Portal.prepare_print], and [method@Portal.print_file].
119 |
120 | The underlying D-Bus interface is [org.freedesktop.portal.Print](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Print).
121 |
122 | ## Screencast
123 |
124 | The Screencast portal lets applications create screencast sessions.
125 |
126 | A screencast session makes the content of a monitor or window
127 | available as a [PipeWire][pipewire] stream.
128 |
129 | See [method@Portal.create_screencast_session].
130 |
131 | The underlying D-Bus interface is [org.freedesktop.portal.ScreenCast](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.ScreenCast).
132 |
133 | ## Remote Desktop
134 |
135 | The Remote Desktop portal allows remote control of a session.
136 |
137 | A remote desktop session allows to inject events into the input stream.
138 |
139 | See [method@Portal.create_remote_desktop_session].
140 |
141 | The underlying D-Bus interface is [org.freedesktop.portal.RemoteDesktop](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.RemoteDesktop).
142 |
143 | ## Screenshot
144 |
145 | The Screenshot portal allows applications to take screenshots or pick colors.
146 |
147 | See [method@Portal.take_screenshot], and [method@Portal.pick_color].
148 |
149 | The underlying D-Bus interface is [org.freedesktop.portal.Screenshot](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Screenshot).
150 |
151 | ## Spawn
152 |
153 | The Spawn portal lets applications spawn a process in another
154 | copy of their sandbox.
155 |
156 | To monitor spawned processes, use the [signal@Portal::spawn-exited]
157 | signal.
158 |
159 | See [method@Portal.spawn].
160 |
161 | The underlying D-Bus interface is [org.freedesktop.portal.Flatpak](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Flatpak).
162 |
163 | ## Trash
164 |
165 | The Trash portal lets applications send a file to the trash can.
166 |
167 | See [method@Portal.trash_file].
168 |
169 | The underlying D-Bus interface is [org.freedesktop.portal.Trash](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Trash).
170 |
171 | ## Updates
172 |
173 | The Updates portal lets applications be informed about available
174 | software updates (for themselves) and install those updates.
175 |
176 | See [method@Portal.update_install].
177 |
178 | The underlying D-Bus interface is [org.freedesktop.portal.Flatpak](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Flatpak).
179 |
180 | ## Wallpaper
181 |
182 | The Wallpaper portal lets applications set desktop backgrounds.
183 |
184 | See [method@Portal.set_wallpaper].
185 |
186 | The underlying D-Bus interface is [org.freedesktop.portal.Wallpaper](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Wallpaper).
187 |
188 | [pipewire]: https://pipewire.org
189 |
--------------------------------------------------------------------------------
/doc/libportal.svg:
--------------------------------------------------------------------------------
1 |
2 |
33 |
--------------------------------------------------------------------------------
/doc/libportal.toml.in:
--------------------------------------------------------------------------------
1 | [library]
2 | version = "@VERSION@"
3 | description = "Flatpak portal library"
4 | authors = "Flatpak"
5 | license = "LGPL-3.0-only"
6 | browse_url = "https://github.com/flatpak/libportal"
7 | repository_url = "https://github.com/flatpak/libportal.git"
8 | website_url = "https://libportal.org/"
9 | docs_url = "https://libportal.org/"
10 | logo_url = "libportal.svg"
11 | dependencies = [
12 | "GObject-2.0",
13 | "Gtk-4.0",
14 | ]
15 | devhelp = true
16 | search_index = true
17 |
18 | [dependencies."GObject-2.0"]
19 | name = "GObject"
20 | description = "The base type system library"
21 | docs_url = "https://developer.gnome.org/gobject/stable"
22 |
23 | [dependencies."Gtk-4.0"]
24 | name = "GTK"
25 | description = "The GTK toolkit"
26 | docs_url = "https://docs.gtk.org/gtk4/"
27 |
28 | [theme]
29 | name = "basic"
30 | show_index_summary = true
31 | show_class_hierarchy = true
32 |
33 | [source-location]
34 | # The base URL for the web UI
35 | base_url = "https://github.com/flatpak/libportal/blob/main/"
36 |
37 | [extra]
38 | urlmap_file = "urlmap.js"
39 | content_files = [
40 | "libportal.md",
41 | ]
42 | content_images = [
43 | "libportal.svg",
44 | "favicon-32x32.png",
45 | "favicon-128x128.png",
46 | "favicon-180x180.png",
47 | "favicon-192x192.png",
48 | ]
49 |
--------------------------------------------------------------------------------
/doc/meson.build:
--------------------------------------------------------------------------------
1 | toml_data = configuration_data()
2 | toml_data.set('VERSION', meson.project_version())
3 |
4 | libportal_toml = configure_file(
5 | input: 'libportal.toml.in',
6 | output: 'libportal.toml',
7 | configuration: toml_data
8 | )
9 |
10 | dependency('gi-docgen', version: '>= 2021.1',
11 | fallback: ['gi-docgen', 'dummy_dep'],
12 | native: true,
13 | required: get_option('docs'))
14 |
15 | gidocgen = find_program('gi-docgen')
16 |
17 | docs_dir = get_option('datadir') / 'doc'
18 |
19 | gidocgen_opts = [
20 | '--quiet',
21 | '--add-include-path=@0@'.format(meson.current_build_dir() / '../../libportal'),
22 | '--no-namespace-dir',
23 | '--content-dir=@0@'.format(meson.current_source_dir()),
24 | ]
25 | if get_option('werror')
26 | gidocgen_opts += ['--fatal-warnings']
27 | endif
28 |
29 | custom_target('libportal-doc',
30 | input: [ libportal_toml, libportal_gir[0] ],
31 | output: 'libportal-1',
32 | command: [
33 | gidocgen,
34 | 'generate',
35 | gidocgen_opts,
36 | '--config=@INPUT0@',
37 | '--output-dir=@OUTPUT@',
38 | '@INPUT1@',
39 | ],
40 | build_by_default: true,
41 | install: true,
42 | install_dir: docs_dir,
43 | )
44 |
--------------------------------------------------------------------------------
/doc/release-checklist.md:
--------------------------------------------------------------------------------
1 | libportal release checklist
2 | ===========================
3 |
4 | * Update NEWS
5 | * Check that version number in `meson.build` is correct
6 | * Update release date in `NEWS`
7 | * Commit the changes
8 | * `meson dist -C ${builddir}`
9 | * Do any final smoke-testing, e.g. update a package, install and test it
10 | * `git evtag sign $VERSION`
11 | * `git push --atomic origin main $VERSION`
12 | * https://github.com/flatpak/libportal/releases/new
13 | * Fill in the new version's tag in the "Tag version" box
14 | * Title: `$VERSION`
15 | * Copy the `NEWS` text into the description
16 | * Upload the tarball that you built with `meson dist`
17 | * Get the `sha256sum` of the tarball and append it to the description
18 | * `Publish release`
19 |
20 | After the release:
21 |
22 | * Update version number in `meson.build` to the next release version
23 | * Start a new section in `NEWS`
24 |
--------------------------------------------------------------------------------
/doc/urlmap.js:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2021 GNOME Foundation
2 | // SPDX-License-Identifier: LGPL-2.1-or-later
3 |
4 | // Copied from GTK
5 |
6 | // A map between namespaces and base URLs for their online documentation
7 | baseURLs = [
8 | ["GLib", "https://docs.gtk.org/glib/"],
9 | ["Gio", "https://docs.gtk.org/gio/"],
10 | ["GObject", "https://docs.gtk.org/gobject/"],
11 | ["Gdk", "https://docs.gtk.org/gdk4/"],
12 | ["Gsk", "https://docs.gtk.org/gsk4/"],
13 | ["Gtk", "https://docs.gtk.org/gtk4/"],
14 | ["Pango", "https://docs.gtk.org/Pango/"]
15 | ];
16 |
--------------------------------------------------------------------------------
/libportal/TODO:
--------------------------------------------------------------------------------
1 | portal version checks ?
2 | thread-safety ?
3 |
--------------------------------------------------------------------------------
/libportal/account.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef enum {
27 | XDP_USER_INFORMATION_FLAG_NONE = 0
28 | } XdpUserInformationFlags;
29 |
30 | XDP_PUBLIC
31 | void xdp_portal_get_user_information (XdpPortal *portal,
32 | XdpParent *parent,
33 | const char *reason,
34 | XdpUserInformationFlags flags,
35 | GCancellable *cancellable,
36 | GAsyncReadyCallback callback,
37 | gpointer data);
38 |
39 | XDP_PUBLIC
40 | GVariant * xdp_portal_get_user_information_finish (XdpPortal *portal,
41 | GAsyncResult *result,
42 | GError **error);
43 |
44 | G_END_DECLS
45 |
--------------------------------------------------------------------------------
/libportal/background.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpBackgroundFlags:
28 | * @XDP_BACKGROUND_FLAG_NONE: No options
29 | * @XDP_BACKGROUND_FLAG_AUTOSTART: Request autostart as well
30 | * @XDP_BACKGROUND_FLAG_ACTIVATABLE: Whether the application is D-Bus-activatable
31 | *
32 | * Options to use when requesting background.
33 | */
34 | typedef enum {
35 | XDP_BACKGROUND_FLAG_NONE = 0,
36 | XDP_BACKGROUND_FLAG_AUTOSTART = 1 << 0,
37 | XDP_BACKGROUND_FLAG_ACTIVATABLE = 1 << 1
38 | } XdpBackgroundFlags;
39 |
40 | XDP_PUBLIC
41 | void xdp_portal_request_background (XdpPortal *portal,
42 | XdpParent *parent,
43 | char *reason,
44 | GPtrArray *commandline,
45 | XdpBackgroundFlags flags,
46 | GCancellable *cancellable,
47 | GAsyncReadyCallback callback,
48 | gpointer user_data);
49 |
50 | XDP_PUBLIC
51 | gboolean xdp_portal_request_background_finish (XdpPortal *portal,
52 | GAsyncResult *result,
53 | GError **error);
54 |
55 | XDP_PUBLIC
56 | void xdp_portal_set_background_status (XdpPortal *portal,
57 | const char *status_message,
58 | GCancellable *cancellable,
59 | GAsyncReadyCallback callback,
60 | gpointer data);
61 |
62 | XDP_PUBLIC
63 | gboolean xdp_portal_set_background_status_finish (XdpPortal *portal,
64 | GAsyncResult *result,
65 | GError **error);
66 |
67 | G_END_DECLS
68 |
--------------------------------------------------------------------------------
/libportal/camera.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | XDP_PUBLIC
27 | gboolean xdp_portal_is_camera_present (XdpPortal *portal);
28 |
29 | typedef enum {
30 | XDP_CAMERA_FLAG_NONE = 0
31 | } XdpCameraFlags;
32 |
33 | XDP_PUBLIC
34 | void xdp_portal_access_camera (XdpPortal *portal,
35 | XdpParent *parent,
36 | XdpCameraFlags flags,
37 | GCancellable *cancellable,
38 | GAsyncReadyCallback callback,
39 | gpointer data);
40 |
41 | XDP_PUBLIC
42 | gboolean xdp_portal_access_camera_finish (XdpPortal *portal,
43 | GAsyncResult *result,
44 | GError **error);
45 |
46 | XDP_PUBLIC
47 | int xdp_portal_open_pipewire_remote_for_camera (XdpPortal *portal);
48 |
49 | G_END_DECLS
50 |
--------------------------------------------------------------------------------
/libportal/dynamic-launcher.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Matthew Leeds
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpLauncherType:
28 | * @XDP_LAUNCHER_APPLICATION: a launcher for a regular application
29 | * @XDP_LAUNCHER_WEBAPP: a launcher for a web app
30 | *
31 | * The type of a launcher.
32 | */
33 | typedef enum {
34 | XDP_LAUNCHER_APPLICATION = 1 << 0,
35 | XDP_LAUNCHER_WEBAPP = 1 << 1
36 | } XdpLauncherType;
37 |
38 | XDP_PUBLIC
39 | void xdp_portal_dynamic_launcher_prepare_install (XdpPortal *portal,
40 | XdpParent *parent,
41 | const char *name,
42 | GVariant *icon_v,
43 | XdpLauncherType launcher_type,
44 | const char *target,
45 | gboolean editable_name,
46 | gboolean editable_icon,
47 | GCancellable *cancellable,
48 | GAsyncReadyCallback callback,
49 | gpointer data);
50 |
51 | XDP_PUBLIC
52 | GVariant *xdp_portal_dynamic_launcher_prepare_install_finish (XdpPortal *portal,
53 | GAsyncResult *result,
54 | GError **error);
55 |
56 | XDP_PUBLIC
57 | char *xdp_portal_dynamic_launcher_request_install_token (XdpPortal *portal,
58 | const char *name,
59 | GVariant *icon_v,
60 | GError **error);
61 |
62 | XDP_PUBLIC
63 | gboolean xdp_portal_dynamic_launcher_install (XdpPortal *portal,
64 | const char *token,
65 | const char *desktop_file_id,
66 | const char *desktop_entry,
67 | GError **error);
68 |
69 | XDP_PUBLIC
70 | gboolean xdp_portal_dynamic_launcher_uninstall (XdpPortal *portal,
71 | const char *desktop_file_id,
72 | GError **error);
73 |
74 | XDP_PUBLIC
75 | char *xdp_portal_dynamic_launcher_get_desktop_entry (XdpPortal *portal,
76 | const char *desktop_file_id,
77 | GError **error);
78 |
79 | XDP_PUBLIC
80 | GVariant *xdp_portal_dynamic_launcher_get_icon (XdpPortal *portal,
81 | const char *desktop_file_id,
82 | char **out_icon_format,
83 | guint *out_icon_size,
84 | GError **error);
85 |
86 | XDP_PUBLIC
87 | gboolean xdp_portal_dynamic_launcher_launch (XdpPortal *portal,
88 | const char *desktop_file_id,
89 | const char *activation_token,
90 | GError **error);
91 |
92 | G_END_DECLS
93 |
--------------------------------------------------------------------------------
/libportal/email.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef enum {
27 | XDP_EMAIL_FLAG_NONE = 0
28 | } XdpEmailFlags;
29 |
30 | XDP_PUBLIC
31 | void xdp_portal_compose_email (XdpPortal *portal,
32 | XdpParent *parent,
33 | const char *const *addresses,
34 | const char *const *cc,
35 | const char *const *bcc,
36 | const char *subject,
37 | const char *body,
38 | const char *const *attachments,
39 | XdpEmailFlags flags,
40 | GCancellable *cancellable,
41 | GAsyncReadyCallback callback,
42 | gpointer data);
43 |
44 | XDP_PUBLIC
45 | gboolean xdp_portal_compose_email_finish (XdpPortal *portal,
46 | GAsyncResult *result,
47 | GError **error);
48 |
49 | G_END_DECLS
50 |
--------------------------------------------------------------------------------
/libportal/filechooser.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpOpenFileFlags:
28 | * @XDP_OPEN_FILE_FLAG_NONE: No options
29 | * @XDP_OPEN_FILE_FLAG_MULTIPLE: Allow selecting multiple files
30 | *
31 | * Options for opening files.
32 | */
33 | typedef enum {
34 | XDP_OPEN_FILE_FLAG_NONE = 0,
35 | XDP_OPEN_FILE_FLAG_MULTIPLE = 1 << 0,
36 | } XdpOpenFileFlags;
37 |
38 | XDP_PUBLIC
39 | void xdp_portal_open_file (XdpPortal *portal,
40 | XdpParent *parent,
41 | const char *title,
42 | GVariant *filters,
43 | GVariant *current_filter,
44 | GVariant *choices,
45 | XdpOpenFileFlags flags,
46 | GCancellable *cancellable,
47 | GAsyncReadyCallback callback,
48 | gpointer data);
49 |
50 | XDP_PUBLIC
51 | GVariant *xdp_portal_open_file_finish (XdpPortal *portal,
52 | GAsyncResult *result,
53 | GError **error);
54 |
55 | typedef enum {
56 | XDP_SAVE_FILE_FLAG_NONE = 0
57 | } XdpSaveFileFlags;
58 |
59 | XDP_PUBLIC
60 | void xdp_portal_save_file (XdpPortal *portal,
61 | XdpParent *parent,
62 | const char *title,
63 | const char *current_name,
64 | const char *current_folder,
65 | const char *current_file,
66 | GVariant *filters,
67 | GVariant *current_filter,
68 | GVariant *choices,
69 | XdpSaveFileFlags flags,
70 | GCancellable *cancellable,
71 | GAsyncReadyCallback callback,
72 | gpointer data);
73 |
74 | XDP_PUBLIC
75 | GVariant *xdp_portal_save_file_finish (XdpPortal *portal,
76 | GAsyncResult *result,
77 | GError **error);
78 |
79 | XDP_PUBLIC
80 | void xdp_portal_save_files (XdpPortal *portal,
81 | XdpParent *parent,
82 | const char *title,
83 | const char *current_name,
84 | const char *current_folder,
85 | GVariant *files,
86 | GVariant *choices,
87 | XdpSaveFileFlags flags,
88 | GCancellable *cancellable,
89 | GAsyncReadyCallback callback,
90 | gpointer data);
91 |
92 | XDP_PUBLIC
93 | GVariant *xdp_portal_save_files_finish (XdpPortal *portal,
94 | GAsyncResult *result,
95 | GError **error);
96 |
97 | G_END_DECLS
98 |
--------------------------------------------------------------------------------
/libportal/glib-backports.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2024 GNOME Foundation Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | #include
25 |
26 | #if !GLIB_CHECK_VERSION(2, 76, 0)
27 |
28 | static inline gboolean
29 | g_clear_fd (int *fd_ptr,
30 | GError **error)
31 | {
32 | int fd = *fd_ptr;
33 |
34 | *fd_ptr = -1;
35 |
36 | if (fd < 0)
37 | return TRUE;
38 |
39 | /* Suppress "Not available before" warning */
40 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS
41 | return g_close (fd, error);
42 | G_GNUC_END_IGNORE_DEPRECATIONS
43 | }
44 |
45 | static inline void
46 | _g_clear_fd_ignore_error (int *fd_ptr)
47 | {
48 | /* Don't overwrite thread-local errno if closing the fd fails */
49 | int errsv = errno;
50 |
51 | /* Suppress "Not available before" warning */
52 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS
53 |
54 | if (!g_clear_fd (fd_ptr, NULL))
55 | {
56 | /* Do nothing: we ignore all errors, except for EBADF which
57 | * is a programming error, checked for by g_close(). */
58 | }
59 |
60 | G_GNUC_END_IGNORE_DEPRECATIONS
61 |
62 | errno = errsv;
63 | }
64 |
65 | #define g_autofd __attribute__((cleanup(_g_clear_fd_ignore_error)))
66 |
67 | #endif
68 |
69 | #if !GLIB_CHECK_VERSION(2, 84, 0)
70 | static inline unsigned int
71 | backport_steal_handle_id (unsigned int *handle_pointer)
72 | {
73 | unsigned int handle;
74 |
75 | handle = *handle_pointer;
76 | *handle_pointer = 0;
77 |
78 | return handle;
79 | }
80 | #define g_steal_handle_id(hp) backport_steal_handle_id (hp)
81 | #endif
82 |
--------------------------------------------------------------------------------
/libportal/inhibit.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpInhibitFlags:
28 | * @XDP_INHIBIT_FLAG_LOGOUT: Inhibit logout
29 | * @XDP_INHIBIT_FLAG_USER_SWITCH: Inhibit user switching
30 | * @XDP_INHIBIT_FLAG_SUSPEND: Inhibit suspend
31 | * @XDP_INHIBIT_FLAG_IDLE: Inhibit the session going idle
32 | *
33 | * Flags that determine what session status changes are inhibited.
34 | */
35 | typedef enum {
36 | XDP_INHIBIT_FLAG_LOGOUT = 1 << 0,
37 | XDP_INHIBIT_FLAG_USER_SWITCH = 1 << 1,
38 | XDP_INHIBIT_FLAG_SUSPEND = 1 << 2,
39 | XDP_INHIBIT_FLAG_IDLE = 1 << 3
40 | } XdpInhibitFlags;
41 |
42 | XDP_PUBLIC
43 | void xdp_portal_session_inhibit (XdpPortal *portal,
44 | XdpParent *parent,
45 | const char *reason,
46 | XdpInhibitFlags flags,
47 | GCancellable *cancellable,
48 | GAsyncReadyCallback callback,
49 | gpointer data);
50 |
51 | XDP_PUBLIC
52 | int xdp_portal_session_inhibit_finish (XdpPortal *portal,
53 | GAsyncResult *result,
54 | GError **error);
55 |
56 | XDP_PUBLIC
57 | void xdp_portal_session_uninhibit (XdpPortal *portal,
58 | int id);
59 |
60 | /**
61 | * XdpLoginSessionState:
62 | * @XDP_LOGIN_SESSION_RUNNING: the session is running
63 | * @XDP_LOGIN_SESSION_QUERY_END: the session is in the query end phase,
64 | * during which applications can save their state or inhibit the
65 | * session from ending
66 | * @XDP_LOGIN_SESSION_ENDING: the session is about to end
67 | *
68 | * The values of this enum are returned in the [signal@Portal::session-state-changed] signal
69 | * to indicate the current state of the user session.
70 | */
71 | typedef enum {
72 | XDP_LOGIN_SESSION_RUNNING = 1,
73 | XDP_LOGIN_SESSION_QUERY_END = 2,
74 | XDP_LOGIN_SESSION_ENDING = 3,
75 | } XdpLoginSessionState;
76 |
77 | typedef enum {
78 | XDP_SESSION_MONITOR_FLAG_NONE = 0
79 | } XdpSessionMonitorFlags;
80 |
81 | XDP_PUBLIC
82 | void xdp_portal_session_monitor_start (XdpPortal *portal,
83 | XdpParent *parent,
84 | XdpSessionMonitorFlags flags,
85 | GCancellable *cancellable,
86 | GAsyncReadyCallback callback,
87 | gpointer data);
88 |
89 | XDP_PUBLIC
90 | gboolean xdp_portal_session_monitor_start_finish (XdpPortal *portal,
91 | GAsyncResult *result,
92 | GError **error);
93 |
94 | XDP_PUBLIC
95 | void xdp_portal_session_monitor_stop (XdpPortal *portal);
96 |
97 | XDP_PUBLIC
98 | void xdp_portal_session_monitor_query_end_response (XdpPortal *portal);
99 |
100 | G_END_DECLS
101 |
--------------------------------------------------------------------------------
/libportal/inputcapture-pointerbarrier.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Red Hat, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | #define XDP_TYPE_INPUT_CAPTURE_POINTER_BARRIER (xdp_input_capture_pointer_barrier_get_type ())
27 |
28 | XDP_PUBLIC
29 | G_DECLARE_FINAL_TYPE (XdpInputCapturePointerBarrier, xdp_input_capture_pointer_barrier, XDP, INPUT_CAPTURE_POINTER_BARRIER, GObject)
30 |
31 | G_END_DECLS
32 |
--------------------------------------------------------------------------------
/libportal/inputcapture-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Red Hat, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include "inputcapture-pointerbarrier.h"
23 | #include "inputcapture-zone.h"
24 |
25 | guint
26 | _xdp_input_capture_pointer_barrier_get_id (XdpInputCapturePointerBarrier *barrier);
27 |
28 | void
29 | _xdp_input_capture_pointer_barrier_set_is_active (XdpInputCapturePointerBarrier *barrier, gboolean active);
30 |
31 | void
32 | _xdp_input_capture_zone_invalidate_and_free (XdpInputCaptureZone *zone);
33 |
--------------------------------------------------------------------------------
/libportal/inputcapture-zone.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Red Hat, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 |
22 | #include "inputcapture-zone.h"
23 |
24 | /**
25 | * XdpInputCaptureZone
26 | *
27 | * A representation of a zone that supports input capture.
28 | *
29 | * The [class@XdpInputCaptureZone] object is used to represent a zone on the
30 | * user-visible desktop that may be used to set up
31 | * [class@XdpInputCapturePointerBarrier] objects. In most cases, the set of
32 | * [class@XdpInputCaptureZone] objects represent the available monitors but the
33 | * exact implementation is up to the implementation.
34 | */
35 |
36 | enum
37 | {
38 | PROP_0,
39 |
40 | PROP_WIDTH,
41 | PROP_HEIGHT,
42 | PROP_X,
43 | PROP_Y,
44 | PROP_ZONE_SET,
45 | PROP_IS_VALID,
46 |
47 | N_PROPERTIES
48 | };
49 |
50 | static GParamSpec *zone_properties[N_PROPERTIES] = { NULL, };
51 |
52 | struct _XdpInputCaptureZone {
53 | GObject parent_instance;
54 |
55 | unsigned int width;
56 | unsigned int height;
57 | int x;
58 | int y;
59 |
60 | unsigned int zone_set;
61 |
62 | gboolean is_valid;
63 | };
64 |
65 | G_DEFINE_TYPE (XdpInputCaptureZone, xdp_input_capture_zone, G_TYPE_OBJECT)
66 |
67 | static void
68 | xdp_input_capture_zone_get_property (GObject *object,
69 | unsigned int property_id,
70 | GValue *value,
71 | GParamSpec *pspec)
72 | {
73 |
74 | XdpInputCaptureZone *zone = XDP_INPUT_CAPTURE_ZONE (object);
75 |
76 | switch (property_id)
77 | {
78 | case PROP_WIDTH:
79 | g_value_set_uint (value, zone->width);
80 | break;
81 | case PROP_HEIGHT:
82 | g_value_set_uint (value, zone->height);
83 | break;
84 | case PROP_X:
85 | g_value_set_int (value, zone->x);
86 | break;
87 | case PROP_Y:
88 | g_value_set_int (value, zone->y);
89 | break;
90 | case PROP_ZONE_SET:
91 | g_value_set_uint (value, zone->zone_set);
92 | break;
93 | case PROP_IS_VALID:
94 | g_value_set_boolean (value, zone->is_valid);
95 | break;
96 | default:
97 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
98 | break;
99 | }
100 | }
101 |
102 | static void
103 | xdp_input_capture_zone_set_property (GObject *object,
104 | unsigned int property_id,
105 | const GValue *value,
106 | GParamSpec *pspec)
107 | {
108 | XdpInputCaptureZone *zone = XDP_INPUT_CAPTURE_ZONE (object);
109 |
110 | switch (property_id)
111 | {
112 | case PROP_WIDTH:
113 | zone->width = g_value_get_uint (value);
114 | break;
115 | case PROP_HEIGHT:
116 | zone->height = g_value_get_uint (value);
117 | break;
118 | case PROP_X:
119 | zone->x = g_value_get_int (value);
120 | break;
121 | case PROP_Y:
122 | zone->y = g_value_get_int (value);
123 | break;
124 | case PROP_ZONE_SET:
125 | zone->zone_set = g_value_get_uint (value);
126 | break;
127 | case PROP_IS_VALID:
128 | zone->is_valid = g_value_get_boolean (value);
129 | break;
130 | default:
131 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
132 | break;
133 | }
134 | }
135 |
136 | static void
137 | xdp_input_capture_zone_class_init (XdpInputCaptureZoneClass *klass)
138 | {
139 | GObjectClass *object_class = G_OBJECT_CLASS (klass);
140 |
141 | object_class->get_property = xdp_input_capture_zone_get_property;
142 | object_class->set_property = xdp_input_capture_zone_set_property;
143 |
144 | /**
145 | * XdpInputCaptureZone:width:
146 | *
147 | * The width of this zone in logical pixels
148 | */
149 | zone_properties[PROP_WIDTH] =
150 | g_param_spec_uint ("width",
151 | "zone width",
152 | "The zone width in logical pixels",
153 | 0, UINT_MAX, 0,
154 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
155 |
156 | /**
157 | * XdpInputCaptureZone:height:
158 | *
159 | * The height of this zone in logical pixels
160 | */
161 | zone_properties[PROP_HEIGHT] =
162 | g_param_spec_uint ("height",
163 | "zone height",
164 | "The zone height in logical pixels",
165 | 0, UINT_MAX, 0,
166 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
167 |
168 | /**
169 | * XdpInputCaptureZone:x:
170 | *
171 | * The x offset of this zone in logical pixels
172 | */
173 | zone_properties[PROP_X] =
174 | g_param_spec_int ("x",
175 | "zone x offset",
176 | "The zone x offset in logical pixels",
177 | INT_MIN, INT_MAX, 0,
178 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
179 | /**
180 | * XdpInputCaptureZone:y:
181 | *
182 | * The x offset of this zone in logical pixels
183 | */
184 | zone_properties[PROP_Y] =
185 | g_param_spec_int ("y",
186 | "zone y offset",
187 | "The zone y offset in logical pixels",
188 | INT_MIN, INT_MAX, 0,
189 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
190 |
191 | /**
192 | * XdpInputCaptureZone:zone_set:
193 | *
194 | * The unique zone_set number assigned to this set of zones. A set of zones as
195 | * returned by [method@InputCaptureSession.get_zones] have the same zone_set
196 | * number and only one set of zones may be valid at any time (the most
197 | * recently returned set).
198 | */
199 | zone_properties[PROP_ZONE_SET] =
200 | g_param_spec_uint ("zone_set",
201 | "zone set number",
202 | "The zone_set number when this zone was retrieved",
203 | 0, UINT_MAX, 0,
204 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
205 |
206 | /**
207 | * XdpInputCaptureZone:is-valid:
208 | *
209 | * A boolean indicating whether this zone is currently valid. Zones are
210 | * invalidated by the Portal's ZonesChanged signal, see
211 | * [signal@InputCaptureSession::zones-changed].
212 | *
213 | * Once invalidated, a Zone can be discarded by the caller, it cannot become
214 | * valid again.
215 | */
216 | zone_properties[PROP_IS_VALID] =
217 | g_param_spec_boolean ("is-valid",
218 | "validity check",
219 | "True if this zone is currently valid",
220 | TRUE,
221 | G_PARAM_READWRITE);
222 |
223 | g_object_class_install_properties (object_class,
224 | N_PROPERTIES,
225 | zone_properties);
226 | }
227 |
228 | static void
229 | xdp_input_capture_zone_init (XdpInputCaptureZone *zone)
230 | {
231 | }
232 |
233 | void
234 | _xdp_input_capture_zone_invalidate_and_free (XdpInputCaptureZone *zone)
235 | {
236 | g_object_set (zone, "is-valid", FALSE, NULL);
237 | g_object_unref (zone);
238 | }
239 |
--------------------------------------------------------------------------------
/libportal/inputcapture-zone.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Red Hat, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | #define XDP_TYPE_INPUT_CAPTURE_ZONE (xdp_input_capture_zone_get_type ())
27 |
28 | XDP_PUBLIC
29 | G_DECLARE_FINAL_TYPE (XdpInputCaptureZone, xdp_input_capture_zone, XDP, INPUT_CAPTURE_ZONE, GObject)
30 |
31 | G_END_DECLS
32 |
--------------------------------------------------------------------------------
/libportal/inputcapture.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | G_BEGIN_DECLS
29 |
30 | #define XDP_TYPE_INPUT_CAPTURE_SESSION (xdp_input_capture_session_get_type ())
31 |
32 | XDP_PUBLIC
33 | G_DECLARE_FINAL_TYPE (XdpInputCaptureSession, xdp_input_capture_session, XDP, INPUT_CAPTURE_SESSION, GObject)
34 |
35 | /**
36 | * XdpInputCapability:
37 | * @XDP_INPUT_CAPABILITY_NONE: no device
38 | * @XDP_INPUT_CAPABILITY_KEYBOARD: capture the keyboard
39 | * @XDP_INPUT_CAPABILITY_POINTER: capture pointer events
40 | * @XDP_INPUT_CAPABILITY_TOUCHSCREEN: capture touchscreen events
41 | *
42 | * Flags to specify what input device capabilities should be captured
43 | */
44 | typedef enum {
45 | XDP_INPUT_CAPABILITY_NONE = 0,
46 | XDP_INPUT_CAPABILITY_KEYBOARD = 1 << 0,
47 | XDP_INPUT_CAPABILITY_POINTER = 1 << 1,
48 | XDP_INPUT_CAPABILITY_TOUCHSCREEN = 1 << 2
49 | } XdpInputCapability;
50 |
51 |
52 | XDP_PUBLIC
53 | void xdp_portal_create_input_capture_session (XdpPortal *portal,
54 | XdpParent *parent,
55 | XdpInputCapability capabilities,
56 | GCancellable *cancellable,
57 | GAsyncReadyCallback callback,
58 | gpointer data);
59 |
60 | XDP_PUBLIC
61 | XdpInputCaptureSession * xdp_portal_create_input_capture_session_finish (XdpPortal *portal,
62 | GAsyncResult *result,
63 | GError **error);
64 |
65 | XDP_PUBLIC
66 | XdpSession *xdp_input_capture_session_get_session (XdpInputCaptureSession *session);
67 |
68 | XDP_PUBLIC
69 | GList * xdp_input_capture_session_get_zones (XdpInputCaptureSession *session);
70 |
71 | XDP_PUBLIC
72 | void xdp_input_capture_session_set_pointer_barriers (XdpInputCaptureSession *session,
73 | GList *barriers,
74 | GCancellable *cancellable,
75 | GAsyncReadyCallback callback,
76 | gpointer data);
77 |
78 | XDP_PUBLIC
79 | GList * xdp_input_capture_session_set_pointer_barriers_finish (XdpInputCaptureSession *session,
80 | GAsyncResult *result,
81 | GError **error);
82 |
83 | XDP_PUBLIC
84 | void xdp_input_capture_session_enable (XdpInputCaptureSession *session);
85 |
86 | XDP_PUBLIC
87 | void xdp_input_capture_session_disable (XdpInputCaptureSession *session);
88 |
89 | XDP_PUBLIC
90 | void xdp_input_capture_session_release_at (XdpInputCaptureSession *session,
91 | guint activation_id,
92 | gdouble cursor_x_position,
93 | gdouble cursor_y_position);
94 |
95 | XDP_PUBLIC
96 | void xdp_input_capture_session_release (XdpInputCaptureSession *session,
97 | guint activation_id);
98 |
99 | XDP_PUBLIC
100 | int xdp_input_capture_session_connect_to_eis (XdpInputCaptureSession *session,
101 | GError **error);
102 |
103 | G_END_DECLS
104 |
--------------------------------------------------------------------------------
/libportal/location.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpLocationAccuracy:
28 | * @XDP_LOCATION_ACCURACY_NONE: No particular accuracy
29 | * @XDP_LOCATION_ACCURACY_COUNTRY: Country-level accuracy
30 | * @XDP_LOCATION_ACCURACY_CITY: City-level accuracy
31 | * @XDP_LOCATION_ACCURACY_NEIGHBORHOOD: Neighborhood-level accuracy
32 | * @XDP_LOCATION_ACCURACY_STREET: Street-level accuracy
33 | * @XDP_LOCATION_ACCURACY_EXACT: Maximum accuracy
34 | *
35 | * The values of this enum indicate the desired level
36 | * of accuracy for location information.
37 | */
38 | typedef enum {
39 | XDP_LOCATION_ACCURACY_NONE,
40 | XDP_LOCATION_ACCURACY_COUNTRY,
41 | XDP_LOCATION_ACCURACY_CITY,
42 | XDP_LOCATION_ACCURACY_NEIGHBORHOOD,
43 | XDP_LOCATION_ACCURACY_STREET,
44 | XDP_LOCATION_ACCURACY_EXACT
45 | } XdpLocationAccuracy;
46 |
47 | typedef enum {
48 | XDP_LOCATION_MONITOR_FLAG_NONE = 0
49 | } XdpLocationMonitorFlags;
50 |
51 | XDP_PUBLIC
52 | void xdp_portal_location_monitor_start (XdpPortal *portal,
53 | XdpParent *parent,
54 | guint distance_threshold,
55 | guint time_threshold,
56 | XdpLocationAccuracy accuracy,
57 | XdpLocationMonitorFlags flags,
58 | GCancellable *cancellable,
59 | GAsyncReadyCallback callback,
60 | gpointer data);
61 |
62 | XDP_PUBLIC
63 | gboolean xdp_portal_location_monitor_start_finish (XdpPortal *portal,
64 | GAsyncResult *result,
65 | GError **error);
66 |
67 | XDP_PUBLIC
68 | void xdp_portal_location_monitor_stop (XdpPortal *portal);
69 |
70 | G_END_DECLS
71 |
--------------------------------------------------------------------------------
/libportal/notification.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef enum {
27 | XDP_NOTIFICATION_FLAG_NONE = 0
28 | } XdpNotificationFlags;
29 |
30 | XDP_PUBLIC
31 | void xdp_portal_add_notification (XdpPortal *portal,
32 | const char *id,
33 | GVariant *notification,
34 | XdpNotificationFlags flags,
35 | GCancellable *cancellable,
36 | GAsyncReadyCallback callback,
37 | gpointer data);
38 |
39 | XDP_PUBLIC
40 | gboolean xdp_portal_add_notification_finish (XdpPortal *portal,
41 | GAsyncResult *result,
42 | GError **error);
43 |
44 | XDP_PUBLIC
45 | void xdp_portal_remove_notification (XdpPortal *portal,
46 | const char *id);
47 |
48 | XDP_PUBLIC
49 | GVariant *xdp_portal_get_supported_notification_options (XdpPortal *portal,
50 | GError **error);
51 |
52 | G_END_DECLS
53 |
--------------------------------------------------------------------------------
/libportal/openuri.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpOpenUriFlags:
28 | * @XDP_OPEN_URI_FLAG_NONE: No options
29 | * @XDP_OPEN_URI_FLAG_ASK: Use an application chooser for the given uri
30 | * @XDP_OPEN_URI_FLAG_WRITABLE: Allow writing to file (if uri points to a local file that is exported in the document portal and app is sandboxed itself)
31 | *
32 | * Options for opening uris.
33 | */
34 | typedef enum {
35 | XDP_OPEN_URI_FLAG_NONE = 0,
36 | XDP_OPEN_URI_FLAG_ASK = 1 << 0,
37 | XDP_OPEN_URI_FLAG_WRITABLE = 1 << 1
38 | } XdpOpenUriFlags;
39 |
40 | XDP_PUBLIC
41 | void xdp_portal_open_uri (XdpPortal *portal,
42 | XdpParent *parent,
43 | const char *uri,
44 | XdpOpenUriFlags flags,
45 | GCancellable *cancellable,
46 | GAsyncReadyCallback callback,
47 | gpointer data);
48 |
49 | XDP_PUBLIC
50 | gboolean xdp_portal_open_uri_finish (XdpPortal *portal,
51 | GAsyncResult *result,
52 | GError **error);
53 |
54 | XDP_PUBLIC
55 | void xdp_portal_open_directory (XdpPortal *portal,
56 | XdpParent *parent,
57 | const char *uri,
58 | XdpOpenUriFlags flags,
59 | GCancellable *cancellable,
60 | GAsyncReadyCallback callback,
61 | gpointer data);
62 |
63 | XDP_PUBLIC
64 | gboolean xdp_portal_open_directory_finish (XdpPortal *portal,
65 | GAsyncResult *result,
66 | GError **error);
67 |
68 | G_END_DECLS
69 |
--------------------------------------------------------------------------------
/libportal/parent-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include "parent.h"
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef void (* XdpParentExported) (XdpParent *parent,
27 | const char *handle,
28 | gpointer data);
29 | typedef gboolean (* XdpParentExport) (XdpParent *parent,
30 | XdpParentExported callback,
31 | gpointer data);
32 | typedef void (* XdpParentUnexport) (XdpParent *parent);
33 |
34 | struct _XdpParent {
35 | /*< private >*/
36 | XdpParentExport parent_export;
37 | XdpParentUnexport parent_unexport;
38 | GObject *object;
39 | XdpParentExported callback;
40 | char *exported_handle;
41 | gpointer data;
42 | };
43 |
44 | G_END_DECLS
45 |
--------------------------------------------------------------------------------
/libportal/parent.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 | #include "parent-private.h"
22 |
23 |
24 | /**
25 | * XdpParent
26 | *
27 | * Parent window abstraction.
28 | *
29 | * The [struct@Parent] struct provides an abstract way to represent a window,
30 | * without introducing a dependency on a toolkit library.
31 | *
32 | * XdpParent implementations for GTK 3, GTK 4, Qt 5, and Qt 6 are available as
33 | * separate libraries.
34 | */
35 | G_DEFINE_BOXED_TYPE (XdpParent, xdp_parent, xdp_parent_copy, xdp_parent_free)
36 |
37 | /**
38 | * xdp_parent_copy:
39 | * @source: a [struct@Parent]
40 | *
41 | * Copies @source into a new [struct@Parent].
42 | *
43 | * Returns: (transfer full): an [struct@Parent] that is a copy of @source
44 | */
45 | XdpParent *
46 | xdp_parent_copy (XdpParent *source)
47 | {
48 | XdpParent *parent;
49 |
50 | parent = g_new0 (XdpParent, 1);
51 |
52 | parent->parent_export = source->parent_export;
53 | parent->parent_unexport = source->parent_unexport;
54 | g_set_object (&parent->object, source->object);
55 | parent->data = source->data;
56 | parent->exported_handle = g_strdup (source->exported_handle);
57 |
58 | return parent;
59 | }
60 |
61 | /**
62 | * xdp_parent_free:
63 | * @parent: an [struct@Parent]
64 | *
65 | * Frees @parent.
66 | */
67 | void
68 | xdp_parent_free (XdpParent *parent)
69 | {
70 | g_clear_pointer (&parent->exported_handle, g_free);
71 | g_clear_object (&parent->object);
72 | g_free (parent);
73 | }
74 |
--------------------------------------------------------------------------------
/libportal/parent.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | #define XDP_TYPE_PARENT (xdp_parent_get_type ())
27 |
28 | XDP_PUBLIC
29 | GType xdp_parent_get_type (void) G_GNUC_CONST;
30 |
31 | XDP_PUBLIC
32 | XdpParent *xdp_parent_copy (XdpParent *source);
33 |
34 | XDP_PUBLIC
35 | void xdp_parent_free (XdpParent *parent);
36 |
37 | G_DEFINE_AUTOPTR_CLEANUP_FUNC (XdpParent, xdp_parent_free)
38 |
39 | G_END_DECLS
40 |
--------------------------------------------------------------------------------
/libportal/portal-enums.c.template:
--------------------------------------------------------------------------------
1 | /*** BEGIN file-header ***/
2 |
3 | #include "config.h"
4 |
5 | #include
6 |
7 | /*** END file-header ***/
8 |
9 | /*** BEGIN file-production ***/
10 | /* enumerations from "@basename@" */
11 | /*** END file-production ***/
12 |
13 | /*** BEGIN value-header ***/
14 | GType
15 | @enum_name@_get_type (void)
16 | {
17 | static gsize g_define_type_id__volatile = 0;
18 |
19 | if (g_once_init_enter (&g_define_type_id__volatile))
20 | {
21 | static const G@Type@Value values[] = {
22 | /*** END value-header ***/
23 |
24 | /*** BEGIN value-production ***/
25 | { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
26 | /*** END value-production ***/
27 |
28 | /*** BEGIN value-tail ***/
29 | { 0, NULL, NULL }
30 | };
31 | GType g_define_type_id =
32 | g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
33 | g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
34 | }
35 |
36 | return g_define_type_id__volatile;
37 | }
38 |
39 | /*** END value-tail ***/
40 |
41 | /*** BEGIN file-tail ***/
42 |
43 | /*** END file-tail ***/
44 |
--------------------------------------------------------------------------------
/libportal/portal-enums.h.template:
--------------------------------------------------------------------------------
1 | /*** BEGIN file-header ***/
2 | #pragma once
3 |
4 | #include
5 | #include
6 |
7 | G_BEGIN_DECLS
8 | /*** END file-header ***/
9 |
10 | /*** BEGIN file-production ***/
11 |
12 | /* enumerations from "@basename@" */
13 | /*** END file-production ***/
14 |
15 | /*** BEGIN value-header ***/
16 | XDP_PUBLIC
17 | GType @enum_name@_get_type (void) G_GNUC_CONST;
18 | #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
19 | /*** END value-header ***/
20 |
21 | /*** BEGIN file-tail ***/
22 | G_END_DECLS
23 |
24 | /*** END file-tail ***/
25 |
--------------------------------------------------------------------------------
/libportal/portal-gtk3.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 | #include "portal-gtk3.h"
22 |
23 | #include "parent-private.h"
24 |
25 | #ifdef GDK_WINDOWING_X11
26 | #include
27 | #endif
28 | #ifdef GDK_WINDOWING_WAYLAND
29 | #include
30 | #endif
31 |
32 | static void
33 | _xdp_parent_exported_wayland (GdkWindow *window,
34 | const char *handle,
35 | gpointer data)
36 |
37 | {
38 | XdpParent *parent = data;
39 | g_autofree char *handle_str = g_strdup_printf ("wayland:%s", handle);
40 |
41 | g_assert (parent->exported_handle == NULL);
42 |
43 | parent->exported_handle = g_strdup (handle);
44 | parent->callback (parent, handle_str, parent->data);
45 | }
46 |
47 | static gboolean
48 | _xdp_parent_export_gtk (XdpParent *parent,
49 | XdpParentExported callback,
50 | gpointer data)
51 | {
52 | #ifdef GDK_WINDOWING_X11
53 | if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
54 | {
55 | GdkWindow *w = gtk_widget_get_window (GTK_WIDGET (parent->object));
56 | guint32 xid = (guint32) gdk_x11_window_get_xid (w);
57 | g_autofree char *handle = g_strdup_printf ("x11:%x", xid);
58 |
59 | g_assert (parent->exported_handle == NULL);
60 |
61 | parent->exported_handle = g_strdup (handle);
62 | callback (parent, handle, data);
63 | return TRUE;
64 | }
65 | #endif
66 | #ifdef GDK_WINDOWING_WAYLAND
67 | if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
68 | {
69 | GdkWindow *w = gtk_widget_get_window (GTK_WIDGET (parent->object));
70 | parent->callback = callback;
71 | parent->data = data;
72 | return gdk_wayland_window_export_handle (w, _xdp_parent_exported_wayland, parent, NULL);
73 | }
74 | #endif
75 | g_warning ("Couldn't export handle, unsupported windowing system");
76 | return FALSE;
77 | }
78 |
79 | static void
80 | _xdp_parent_unexport_gtk (XdpParent *parent)
81 | {
82 | #ifdef GDK_WINDOWING_WAYLAND
83 | if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
84 | {
85 | GdkWindow *w = gtk_widget_get_window (GTK_WIDGET (parent->object));
86 | gdk_wayland_window_unexport_handle (w);
87 | }
88 | #endif
89 | }
90 |
91 | /**
92 | * xdp_parent_new_gtk:
93 | * @window: a [class@Gtk.Window]
94 | *
95 | * Creates a new [struct@Parent] from @window.
96 | *
97 | * Returns: (transfer full): a [struct@Parent]
98 | */
99 | XdpParent *
100 | xdp_parent_new_gtk (GtkWindow *window)
101 | {
102 | XdpParent *parent = g_new0 (XdpParent, 1);
103 | parent->parent_export = _xdp_parent_export_gtk;
104 | parent->parent_unexport = _xdp_parent_unexport_gtk;
105 | parent->object = (GObject *) g_object_ref (window);
106 | return parent;
107 | }
108 |
--------------------------------------------------------------------------------
/libportal/portal-gtk3.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 |
25 | #if GTK_CHECK_VERSION(3,96,0) || GTK_CHECK_VERSION(4,0,0)
26 | #error "To use libportal with GTK4, include portal-gtk4.h"
27 | #endif
28 |
29 | G_BEGIN_DECLS
30 |
31 | XDP_PUBLIC
32 | XdpParent *xdp_parent_new_gtk (GtkWindow *window);
33 |
34 | G_END_DECLS
35 |
--------------------------------------------------------------------------------
/libportal/portal-gtk4.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 | #include "portal-gtk4.h"
22 |
23 | #include "parent-private.h"
24 |
25 | #ifdef GDK_WINDOWING_X11
26 | #include
27 | #endif
28 | #ifdef GDK_WINDOWING_WAYLAND
29 | #include
30 | #endif
31 |
32 | static void
33 | _xdp_parent_exported_wayland (GdkToplevel *toplevel,
34 | const char *handle,
35 | gpointer data)
36 |
37 | {
38 | XdpParent *parent = data;
39 | g_autofree char *handle_str = g_strdup_printf ("wayland:%s", handle);
40 |
41 | g_assert (parent->exported_handle == NULL);
42 |
43 | parent->exported_handle = g_strdup (handle);
44 | parent->callback (parent, handle_str, parent->data);
45 | }
46 |
47 | static gboolean
48 | _xdp_parent_export_gtk (XdpParent *parent,
49 | XdpParentExported callback,
50 | gpointer data)
51 | {
52 | #ifdef GDK_WINDOWING_X11
53 | if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
54 | {
55 | GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (parent->object));
56 | guint32 xid = (guint32) gdk_x11_surface_get_xid (surface);
57 | g_autofree char *handle = g_strdup_printf ("x11:%x", xid);
58 |
59 | g_assert (parent->exported_handle == NULL);
60 |
61 | parent->exported_handle = g_strdup (handle);
62 | callback (parent, handle, data);
63 | return TRUE;
64 | }
65 | #endif
66 | #ifdef GDK_WINDOWING_WAYLAND
67 | if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
68 | {
69 | GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (parent->object));
70 | parent->callback = callback;
71 | parent->data = data;
72 | return gdk_wayland_toplevel_export_handle (GDK_TOPLEVEL (surface),
73 | _xdp_parent_exported_wayland,
74 | parent,
75 | NULL);
76 | }
77 | #endif
78 | g_warning ("Couldn't export handle, unsupported windowing system");
79 | return FALSE;
80 | }
81 |
82 | static void
83 | _xdp_parent_unexport_gtk (XdpParent *parent)
84 | {
85 | #ifdef GDK_WINDOWING_WAYLAND
86 | if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (parent->object))))
87 | {
88 | GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (parent->object));
89 |
90 | #if GTK_CHECK_VERSION(4, 12, 0)
91 | gdk_wayland_toplevel_drop_exported_handle (GDK_TOPLEVEL (surface), parent->exported_handle);
92 | #else
93 | gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (surface));
94 | #endif
95 | }
96 | #endif
97 | }
98 |
99 | /**
100 | * xdp_parent_new_gtk:
101 | * @window: a [class@Gtk.Window]
102 | *
103 | * Creates a new [struct@Parent] from @window.
104 | *
105 | * Returns: (transfer full): a [struct@Parent]
106 | */
107 | XdpParent *
108 | xdp_parent_new_gtk (GtkWindow *window)
109 | {
110 | XdpParent *parent = g_new0 (XdpParent, 1);
111 | parent->parent_export = _xdp_parent_export_gtk;
112 | parent->parent_unexport = _xdp_parent_unexport_gtk;
113 | parent->object = (GObject *) g_object_ref (window);
114 | return parent;
115 | }
116 |
--------------------------------------------------------------------------------
/libportal/portal-gtk4.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 |
25 | #if !(GTK_CHECK_VERSION(3,96,0) || GTK_CHECK_VERSION(4,0,0))
26 | #error "To use libportal with GTK3, include portal-gtk3.h"
27 | #endif
28 |
29 | G_BEGIN_DECLS
30 |
31 | XDP_PUBLIC
32 | XdpParent *xdp_parent_new_gtk (GtkWindow *window);
33 |
34 | G_END_DECLS
35 |
--------------------------------------------------------------------------------
/libportal/portal-helpers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | * Copyright (C) 2024 GNOME Foundation, Inc.
4 | *
5 | * This file is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as
7 | * published by the Free Software Foundation, version 3.0 of the
8 | * License.
9 | *
10 | * This file is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this program. If not, see .
17 | *
18 | * SPDX-License-Identifier: LGPL-3.0-only
19 | *
20 | * Authors:
21 | * Matthias Clasen
22 | * Hubert Figuière
23 | */
24 |
25 | #pragma once
26 |
27 | #include
28 |
29 | #include
30 |
31 | G_BEGIN_DECLS
32 |
33 | #ifndef XDP_PUBLIC
34 | #define XDP_PUBLIC extern
35 | #endif
36 |
37 | #define XDP_TYPE_PORTAL (xdp_portal_get_type ())
38 |
39 | XDP_PUBLIC
40 | G_DECLARE_FINAL_TYPE (XdpPortal, xdp_portal, XDP, PORTAL, GObject)
41 |
42 | XDP_PUBLIC
43 | XdpPortal *xdp_portal_new (void);
44 |
45 | XDP_PUBLIC
46 | XdpPortal *xdp_portal_initable_new (GError **error);
47 |
48 | XDP_PUBLIC
49 | gboolean xdp_portal_running_under_flatpak (void);
50 |
51 | XDP_PUBLIC
52 | gboolean xdp_portal_running_under_snap (GError **error);
53 |
54 | XDP_PUBLIC
55 | gboolean xdp_portal_running_under_sandbox (void);
56 |
57 | XDP_PUBLIC
58 | XdpSettings *xdp_portal_get_settings (XdpPortal *portal);
59 |
60 | G_END_DECLS
61 |
--------------------------------------------------------------------------------
/libportal/portal-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include "glib-backports.h"
23 | #include "parent-private.h"
24 | #include "portal-helpers.h"
25 |
26 | struct _XdpPortal {
27 | GObject parent_instance;
28 |
29 | GError *init_error;
30 | GDBusConnection *bus;
31 | char *sender;
32 |
33 | /* inhibit */
34 | int next_inhibit_id;
35 | GHashTable *inhibit_handles;
36 | char *session_monitor_handle;
37 | guint state_changed_signal;
38 |
39 | /* spawn */
40 | guint spawn_exited_signal;
41 |
42 | /* updates */
43 | char *update_monitor_handle;
44 | guint update_available_signal;
45 | guint update_progress_signal;
46 |
47 | /* location */
48 | char *location_monitor_handle;
49 | guint location_updated_signal;
50 |
51 | /* notification */
52 | guint action_invoked_signal;
53 | guint notification_interface_version;
54 | GVariant *supported_notification_options;
55 |
56 | /* screencast */
57 | guint screencast_interface_version;
58 | guint remote_desktop_interface_version;
59 |
60 | /* background */
61 | guint background_interface_version;
62 | };
63 |
64 | const char * portal_get_bus_name (void);
65 |
66 | #define PORTAL_BUS_NAME (portal_get_bus_name ())
67 | #define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
68 | #define REQUEST_PATH_PREFIX "/org/freedesktop/portal/desktop/request/"
69 | #define SESSION_PATH_PREFIX "/org/freedesktop/portal/desktop/session/"
70 | #define REQUEST_INTERFACE "org.freedesktop.portal.Request"
71 | #define SESSION_INTERFACE "org.freedesktop.portal.Session"
72 | #define SETTINGS_INTERFACE "org.freedesktop.portal.Settings"
73 |
74 | #define FLATPAK_PORTAL_BUS_NAME "org.freedesktop.portal.Flatpak"
75 | #define FLATPAK_PORTAL_OBJECT_PATH "/org/freedesktop/portal/Flatpak"
76 | #define FLATPAK_PORTAL_INTERFACE "org.freedesktop.portal.Flatpak"
77 |
--------------------------------------------------------------------------------
/libportal/portal-qt5.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2022, Jan Grulich
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | XDP_PUBLIC
31 | XdpParent *xdp_parent_new_qt (QWindow *window);
32 |
33 | namespace XdpQt {
34 |
35 | // Returns a global instance of XdpPortal object and takes care
36 | // of its deletion
37 | XDP_PUBLIC
38 | XdpPortal *globalPortalObject();
39 |
40 | // Account portal helpers
41 | struct GetUserInformationResult {
42 | QString id;
43 | QString name;
44 | QString image;
45 | };
46 |
47 | XDP_PUBLIC
48 | GetUserInformationResult getUserInformationResultFromGVariant(GVariant *variant);
49 |
50 | // FileChooser portal helpers
51 | enum FileChooserFilterRuleType{
52 | Pattern = 0,
53 | Mimetype = 1
54 | };
55 |
56 | struct FileChooserFilterRule {
57 | FileChooserFilterRuleType type;
58 | QString rule;
59 | };
60 |
61 | struct FileChooserFilter {
62 | QString label;
63 | QList rules;
64 | };
65 |
66 | struct FileChooserChoice {
67 | QString id;
68 | QString label;
69 | QMap options;
70 | QString selected;
71 | };
72 |
73 | XDP_PUBLIC
74 | GVariant *filechooserFilesToGVariant(const QStringList &files);
75 |
76 | XDP_PUBLIC
77 | GVariant *filechooserFilterToGVariant(const FileChooserFilter &filter);
78 |
79 | XDP_PUBLIC
80 | GVariant *filechooserFiltersToGVariant(const QList &filters);
81 |
82 | XDP_PUBLIC
83 | GVariant *filechooserChoicesToGVariant(const QList &choices);
84 |
85 | struct FileChooserResult {
86 | QMap choices;
87 | QStringList uris;
88 | };
89 |
90 | XDP_PUBLIC
91 | FileChooserResult filechooserResultFromGVariant(GVariant *variant);
92 |
93 | // Notification portal helpers
94 | struct NotificationButton {
95 | QString label;
96 | QString action;
97 | QVariant target;
98 | };
99 |
100 | struct Notification {
101 | QString title;
102 | QString body;
103 | QString icon;
104 | QPixmap pixmap;
105 | QString priority;
106 | QString defaultAction;
107 | QVariant defaultTarget;
108 | QList buttons;
109 | };
110 |
111 | XDP_PUBLIC
112 | GVariant *notificationToGVariant(const Notification ¬ification);
113 |
114 | XDP_PUBLIC
115 | QVariant GVariantToQVariant(GVariant *variant);
116 |
117 | } // namespace XdpQt
118 |
--------------------------------------------------------------------------------
/libportal/portal-qt6.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2022, Jan Grulich
3 | * Copyright (C) 2023, Neal Gompa
4 | *
5 | * This file is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as
7 | * published by the Free Software Foundation, version 3.0 of the
8 | * License.
9 | *
10 | * This file is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this program. If not, see .
17 | *
18 | * SPDX-License-Identifier: LGPL-3.0-only
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | XDP_PUBLIC
32 | XdpParent *xdp_parent_new_qt (QWindow *window);
33 |
34 | namespace XdpQt {
35 |
36 | // Returns a global instance of XdpPortal object and takes care
37 | // of its deletion
38 | XDP_PUBLIC
39 | XdpPortal *globalPortalObject();
40 |
41 | // Account portal helpers
42 | struct GetUserInformationResult {
43 | QString id;
44 | QString name;
45 | QString image;
46 | };
47 |
48 | XDP_PUBLIC
49 | GetUserInformationResult getUserInformationResultFromGVariant(GVariant *variant);
50 |
51 | // FileChooser portal helpers
52 | enum FileChooserFilterRuleType{
53 | Pattern = 0,
54 | Mimetype = 1
55 | };
56 |
57 | struct FileChooserFilterRule {
58 | FileChooserFilterRuleType type;
59 | QString rule;
60 | };
61 |
62 | struct FileChooserFilter {
63 | QString label;
64 | QList rules;
65 | };
66 |
67 | struct FileChooserChoice {
68 | QString id;
69 | QString label;
70 | QMap options;
71 | QString selected;
72 | };
73 |
74 | XDP_PUBLIC
75 | GVariant *filechooserFilesToGVariant(const QStringList &files);
76 |
77 | XDP_PUBLIC
78 | GVariant *filechooserFilterToGVariant(const FileChooserFilter &filter);
79 |
80 | XDP_PUBLIC
81 | GVariant *filechooserFiltersToGVariant(const QList &filters);
82 |
83 | XDP_PUBLIC
84 | GVariant *filechooserChoicesToGVariant(const QList &choices);
85 |
86 | struct FileChooserResult {
87 | QMap choices;
88 | QStringList uris;
89 | };
90 |
91 | XDP_PUBLIC
92 | FileChooserResult filechooserResultFromGVariant(GVariant *variant);
93 |
94 | // Notification portal helpers
95 | struct NotificationButton {
96 | QString label;
97 | QString action;
98 | QVariant target;
99 | };
100 |
101 | struct Notification {
102 | QString title;
103 | QString body;
104 | QString icon;
105 | QPixmap pixmap;
106 | QString priority;
107 | QString defaultAction;
108 | QVariant defaultTarget;
109 | QList buttons;
110 | };
111 |
112 | XDP_PUBLIC
113 | GVariant *notificationToGVariant(const Notification ¬ification);
114 |
115 | XDP_PUBLIC
116 | QVariant GVariantToQVariant(GVariant *variant);
117 |
118 | } // namespace XdpQt
119 |
--------------------------------------------------------------------------------
/libportal/portal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 |
--------------------------------------------------------------------------------
/libportal/print.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef enum {
27 | XDP_PRINT_FLAG_NONE = 0
28 | } XdpPrintFlags;
29 |
30 | XDP_PUBLIC
31 | void xdp_portal_prepare_print (XdpPortal *portal,
32 | XdpParent *parent,
33 | const char *title,
34 | GVariant *settings,
35 | GVariant *page_setup,
36 | XdpPrintFlags flags,
37 | GCancellable *cancellable,
38 | GAsyncReadyCallback callback,
39 | gpointer data);
40 |
41 | XDP_PUBLIC
42 | GVariant *xdp_portal_prepare_print_finish (XdpPortal *portal,
43 | GAsyncResult *result,
44 | GError **error);
45 |
46 | XDP_PUBLIC
47 | void xdp_portal_print_file (XdpPortal *portal,
48 | XdpParent *parent,
49 | const char *title,
50 | guint token,
51 | const char *file,
52 | XdpPrintFlags flags,
53 | GCancellable *cancellable,
54 | GAsyncReadyCallback callback,
55 | gpointer data);
56 |
57 | XDP_PUBLIC
58 | gboolean xdp_portal_print_file_finish (XdpPortal *portal,
59 | GAsyncResult *result,
60 | GError **error);
61 |
62 | G_END_DECLS
63 |
--------------------------------------------------------------------------------
/libportal/screenshot.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | typedef enum {
27 | XDP_SCREENSHOT_FLAG_NONE = 0,
28 | XDP_SCREENSHOT_FLAG_INTERACTIVE = 1 << 0
29 | } XdpScreenshotFlags;
30 |
31 | XDP_PUBLIC
32 | void xdp_portal_take_screenshot (XdpPortal *portal,
33 | XdpParent *parent,
34 | XdpScreenshotFlags flags,
35 | GCancellable *cancellable,
36 | GAsyncReadyCallback callback,
37 | gpointer data);
38 |
39 | XDP_PUBLIC
40 | char * xdp_portal_take_screenshot_finish (XdpPortal *portal,
41 | GAsyncResult *result,
42 | GError **error);
43 |
44 | XDP_PUBLIC
45 | void xdp_portal_pick_color (XdpPortal *portal,
46 | XdpParent *parent,
47 | GCancellable *cancellable,
48 | GAsyncReadyCallback callback,
49 | gpointer data);
50 |
51 | XDP_PUBLIC
52 | GVariant * xdp_portal_pick_color_finish (XdpPortal *portal,
53 | GAsyncResult *result,
54 | GError **error);
55 |
56 | G_END_DECLS
57 |
--------------------------------------------------------------------------------
/libportal/session-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 |
25 | struct _XdpSession {
26 | GObject parent_instance;
27 |
28 | /* Generic Session implementation */
29 | XdpPortal *portal;
30 | char *id;
31 | gboolean is_closed;
32 | XdpSessionType type;
33 | guint signal_id;
34 |
35 | /* RemoteDesktop/ScreenCast */
36 | XdpSessionState state;
37 | XdpDeviceType devices;
38 | GVariant *streams;
39 |
40 | XdpPersistMode persist_mode;
41 | char *restore_token;
42 |
43 | gboolean uses_eis;
44 |
45 | /* InputCapture */
46 | XdpInputCaptureSession *input_capture_session; /* weak ref */
47 | };
48 |
49 | XdpSession * _xdp_session_new (XdpPortal *portal,
50 | const char *id,
51 | XdpSessionType type);
52 |
53 | void _xdp_session_set_session_state (XdpSession *session,
54 | XdpSessionState state);
55 |
56 | void _xdp_session_set_devices (XdpSession *session,
57 | XdpDeviceType devices);
58 |
59 | void _xdp_session_set_streams (XdpSession *session,
60 | GVariant *streams);
61 |
62 | void _xdp_session_close (XdpSession *session);
63 |
--------------------------------------------------------------------------------
/libportal/session.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 |
22 | #include "session-private.h"
23 | #include "portal-private.h"
24 |
25 | /**
26 | * XdpSession
27 | *
28 | * A representation of long-lived screencast portal interactions.
29 | *
30 | * The XdpSession object is used to represent portal interactions with the
31 | * screencast or remote desktop portals that extend over multiple portal calls.
32 | *
33 | * To find out what kind of session an XdpSession object represents and whether
34 | * it is still active, you can use [method@Session.get_session_type] and
35 | * [method@Session.get_session_state].
36 | *
37 | * All sessions start in an initial state. They can be made active by calling
38 | * [method@Session.start], and ended by calling [method@Session.close].
39 | */
40 | enum {
41 | CLOSED,
42 | LAST_SIGNAL
43 | };
44 |
45 | static guint signals[LAST_SIGNAL];
46 |
47 | G_DEFINE_TYPE (XdpSession, xdp_session, G_TYPE_OBJECT)
48 |
49 | static void
50 | xdp_session_finalize (GObject *object)
51 | {
52 | XdpSession *session = XDP_SESSION (object);
53 |
54 | if (session->signal_id)
55 | g_dbus_connection_signal_unsubscribe (session->portal->bus, session->signal_id);
56 |
57 | g_clear_object (&session->portal);
58 | g_clear_pointer (&session->restore_token, g_free);
59 | g_clear_pointer (&session->id, g_free);
60 | g_clear_pointer (&session->streams, g_variant_unref);
61 | if (session->input_capture_session != NULL)
62 | g_critical ("XdpSession destroyed before XdpInputCaptureSesssion, you lost count of your session refs");
63 | session->input_capture_session = NULL;
64 |
65 | G_OBJECT_CLASS (xdp_session_parent_class)->finalize (object);
66 | }
67 |
68 | static void
69 | xdp_session_class_init (XdpSessionClass *klass)
70 | {
71 | GObjectClass *object_class = G_OBJECT_CLASS (klass);
72 |
73 | object_class->finalize = xdp_session_finalize;
74 |
75 | /**
76 | * XdpSession::closed:
77 | *
78 | * Emitted when a session is closed externally.
79 | */
80 | signals[CLOSED] =
81 | g_signal_new ("closed",
82 | G_TYPE_FROM_CLASS (object_class),
83 | G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
84 | 0,
85 | NULL, NULL,
86 | NULL,
87 | G_TYPE_NONE, 0);
88 | }
89 |
90 | static void
91 | xdp_session_init (XdpSession *session)
92 | {
93 | }
94 |
95 | static void
96 | session_closed (GDBusConnection *bus,
97 | const char *sender_name,
98 | const char *object_path,
99 | const char *interface_name,
100 | const char *signal_name,
101 | GVariant *parameters,
102 | gpointer data)
103 | {
104 | XdpSession *session = data;
105 |
106 | _xdp_session_set_session_state (session, XDP_SESSION_CLOSED);
107 | }
108 |
109 | XdpSession *
110 | _xdp_session_new (XdpPortal *portal,
111 | const char *id,
112 | XdpSessionType type)
113 | {
114 | XdpSession *session;
115 |
116 | session = g_object_new (XDP_TYPE_SESSION, NULL);
117 | session->portal = g_object_ref (portal);
118 | session->id = g_strdup (id);
119 | session->type = type;
120 | session->state = XDP_SESSION_INITIAL;
121 | session->input_capture_session = NULL;
122 |
123 | session->signal_id = g_dbus_connection_signal_subscribe (portal->bus,
124 | PORTAL_BUS_NAME,
125 | SESSION_INTERFACE,
126 | "Closed",
127 | id,
128 | NULL,
129 | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
130 | session_closed,
131 | session,
132 | NULL);
133 | return session;
134 | }
135 |
136 | void
137 | _xdp_session_close (XdpSession *session)
138 | {
139 | if (session->is_closed)
140 | return;
141 |
142 | session->is_closed = TRUE;
143 | g_signal_emit_by_name (session, "closed");
144 | }
145 |
146 | /**
147 | * xdp_session_get_session_type:
148 | * @session: an [class@Session]
149 | *
150 | * Obtains information about the type of session that is represented
151 | * by @session.
152 | *
153 | * Returns: the type of @session
154 | */
155 | XdpSessionType
156 | xdp_session_get_session_type (XdpSession *session)
157 | {
158 | g_return_val_if_fail (XDP_IS_SESSION (session), XDP_SESSION_SCREENCAST);
159 |
160 | return session->type;
161 | }
162 |
163 | /**
164 | * xdp_session_close:
165 | * @session: an active [class@Session]
166 | *
167 | * Closes the session.
168 | */
169 | void
170 | xdp_session_close (XdpSession *session)
171 | {
172 | g_return_if_fail (XDP_IS_SESSION (session));
173 |
174 | g_dbus_connection_call (session->portal->bus,
175 | PORTAL_BUS_NAME,
176 | session->id,
177 | SESSION_INTERFACE,
178 | "Close",
179 | NULL,
180 | NULL, 0, -1, NULL, NULL, NULL);
181 |
182 | _xdp_session_set_session_state (session, XDP_SESSION_CLOSED);
183 | _xdp_session_close (session);
184 | }
185 |
--------------------------------------------------------------------------------
/libportal/session.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | #define XDP_TYPE_SESSION (xdp_session_get_type ())
27 |
28 | XDP_PUBLIC
29 | G_DECLARE_FINAL_TYPE (XdpSession, xdp_session, XDP, SESSION, GObject)
30 |
31 | /**
32 | * XdpSessionType:
33 | * @XDP_SESSION_SCREENCAST: a screencast session.
34 | * @XDP_SESSION_REMOTE_DESKTOP: a remote desktop session.
35 | * @XDP_SESSION_INPUT_CAPTURE: an input capture session.
36 | *
37 | * The type of a session.
38 | */
39 | typedef enum {
40 | XDP_SESSION_SCREENCAST,
41 | XDP_SESSION_REMOTE_DESKTOP,
42 | XDP_SESSION_INPUT_CAPTURE,
43 | } XdpSessionType;
44 |
45 | XDP_PUBLIC
46 | void xdp_session_close (XdpSession *session);
47 |
48 | XDP_PUBLIC
49 | XdpSessionType xdp_session_get_session_type (XdpSession *session);
50 |
51 | G_END_DECLS
52 |
--------------------------------------------------------------------------------
/libportal/settings-private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 GNOME Foundation, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | *
19 | * Authors:
20 | * Hubert Figuière
21 | */
22 |
23 | #pragma once
24 |
25 | #include
26 |
27 | #include "settings.h"
28 |
29 | G_BEGIN_DECLS
30 |
31 | XdpSettings * _xdp_settings_new (XdpPortal *portal);
32 |
33 | G_END_DECLS
34 |
--------------------------------------------------------------------------------
/libportal/settings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 GNOME Foundation, Inc.
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | *
19 | * Authors:
20 | * Hubert Figuière
21 | */
22 |
23 | #pragma once
24 |
25 | #include
26 |
27 | G_BEGIN_DECLS
28 |
29 | #define XDP_TYPE_SETTINGS (xdp_settings_get_type ())
30 |
31 | XDP_PUBLIC
32 | G_DECLARE_FINAL_TYPE (XdpSettings, xdp_settings, XDP, SETTINGS, GObject)
33 |
34 | XDP_PUBLIC
35 | GVariant *xdp_settings_read_value (XdpSettings *settings, const char *namespace, const char *key, GCancellable *cancellable, GError **error);
36 |
37 | XDP_PUBLIC
38 | void
39 | xdp_settings_read (XdpSettings *settings, const char *namespace,
40 | const gchar *key,
41 | GCancellable *cancellable, GError **error,
42 | const gchar *format, ...);
43 |
44 | XDP_PUBLIC
45 | guint xdp_settings_read_uint (XdpSettings *settings, const char *namespace, const char *key, GCancellable *cancellable, GError **error);
46 |
47 | XDP_PUBLIC
48 | char *xdp_settings_read_string (XdpSettings *settings, const char *namespace, const char *key, GCancellable *cancellable, GError **error);
49 |
50 | XDP_PUBLIC
51 | GVariant *xdp_settings_read_all_values (XdpSettings *settings, const char *const *namespaces, GCancellable *cancellable, GError **error);
52 |
53 | G_END_DECLS
54 |
--------------------------------------------------------------------------------
/libportal/spawn.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpSpawnFlags:
28 | * @XDP_SPAWN_FLAG_NONE: No flags
29 | * @XDP_SPAWN_FLAG_CLEARENV: Clear the environment
30 | * @XDP_SPAWN_FLAG_LATEST: Spawn the latest version of the app
31 | * @XDP_SPAWN_FLAG_SANDBOX: Spawn in a sandbox (equivalent to the --sandbox option of flatpak run)
32 | * @XDP_SPAWN_FLAG_NO_NETWORK: Spawn without network (equivalent to the --unshare=network option of flatpak run)
33 | * @XDP_SPAWN_FLAG_WATCH: Kill the sandbox when the caller disappears from the session bus
34 | *
35 | * Flags influencing the spawn operation and how the
36 | * new sandbox is created.
37 | */
38 | typedef enum {
39 | XDP_SPAWN_FLAG_NONE = 0,
40 | XDP_SPAWN_FLAG_CLEARENV = 1 << 0,
41 | XDP_SPAWN_FLAG_LATEST = 1 << 1,
42 | XDP_SPAWN_FLAG_SANDBOX = 1 << 2,
43 | XDP_SPAWN_FLAG_NO_NETWORK = 1 << 3,
44 | XDP_SPAWN_FLAG_WATCH = 1 << 4,
45 | } XdpSpawnFlags;
46 |
47 | XDP_PUBLIC
48 | void xdp_portal_spawn (XdpPortal *portal,
49 | const char *cwd,
50 | const char * const *argv,
51 | int *fds,
52 | int *map_to,
53 | int n_fds,
54 | const char * const *env,
55 | XdpSpawnFlags flags,
56 | const char * const *sandbox_expose,
57 | const char * const *sandbox_expose_ro,
58 | GCancellable *cancellable,
59 | GAsyncReadyCallback callback,
60 | gpointer data);
61 |
62 | XDP_PUBLIC
63 | pid_t xdp_portal_spawn_finish (XdpPortal *portal,
64 | GAsyncResult *result,
65 | GError **error);
66 |
67 | XDP_PUBLIC
68 | void xdp_portal_spawn_signal (XdpPortal *portal,
69 | pid_t pid,
70 | int signal,
71 | gboolean to_process_group);
72 |
73 | G_END_DECLS
74 |
--------------------------------------------------------------------------------
/libportal/trash.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #include "config.h"
21 |
22 | #include "trash.h"
23 |
24 | #define GNU_SOURCE 1
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 |
33 | #include "portal-private.h"
34 |
35 | typedef struct {
36 | XdpPortal *portal;
37 | char *path;
38 | GTask *task;
39 | } TrashCall;
40 |
41 | static void
42 | trash_call_free (TrashCall *call)
43 | {
44 | g_object_unref (call->portal);
45 | g_object_unref (call->task);
46 | g_free (call->path);
47 |
48 | g_free (call);
49 | }
50 |
51 | #ifndef O_PATH
52 | #define O_PATH 0
53 | #endif
54 |
55 | static void
56 | file_trashed (GObject *bus,
57 | GAsyncResult *result,
58 | gpointer data)
59 | {
60 | GError *error = NULL;
61 | g_autoptr(GVariant) ret = NULL;
62 | TrashCall *call = data;
63 |
64 | ret = g_dbus_connection_call_with_unix_fd_list_finish (G_DBUS_CONNECTION (bus),
65 | NULL,
66 | result,
67 | &error);
68 | if (error)
69 | g_task_return_error (call->task, error);
70 | else
71 | {
72 | guint retval;
73 |
74 | g_variant_get (ret, "(u)", &retval);
75 |
76 | if (retval == 1)
77 | g_task_return_boolean (call->task, TRUE);
78 | else
79 | g_task_return_new_error (call->task, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to trash");
80 | }
81 |
82 | trash_call_free (call);
83 | }
84 |
85 | static void
86 | trash_file (TrashCall *call)
87 | {
88 | g_autoptr(GUnixFDList) fd_list = NULL;
89 | int fd, fd_in;
90 | GCancellable *cancellable;
91 |
92 | fd = g_open (call->path, O_PATH | O_CLOEXEC);
93 | if (fd == -1)
94 | {
95 | g_task_return_new_error (call->task, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to open '%s'", call->path);
96 | trash_call_free (call);
97 | return;
98 | }
99 |
100 | fd_list = g_unix_fd_list_new_from_array (&fd, 1);
101 | fd = -1;
102 | fd_in = 0;
103 |
104 | cancellable = g_task_get_cancellable (call->task);
105 |
106 | g_dbus_connection_call_with_unix_fd_list (call->portal->bus,
107 | PORTAL_BUS_NAME,
108 | PORTAL_OBJECT_PATH,
109 | "org.freedesktop.portal.Trash",
110 | "TrashFile",
111 | g_variant_new ("(h)", fd_in),
112 | NULL,
113 | G_DBUS_CALL_FLAGS_NONE,
114 | -1,
115 | fd_list,
116 | cancellable,
117 | file_trashed,
118 | call);
119 |
120 | }
121 |
122 | /**
123 | * xdp_portal_trash_file:
124 | * @portal: a [class@Portal]
125 | * @path: the path for a local file
126 | * @cancellable: (nullable): optional [class@Gio.Cancellable]
127 | * @callback: (scope async): a callback to call when the request is done
128 | * @data: data to pass to @callback
129 | *
130 | * Sends the file at @path to the trash can.
131 | */
132 | void
133 | xdp_portal_trash_file (XdpPortal *portal,
134 | const char *path,
135 | GCancellable *cancellable,
136 | GAsyncReadyCallback callback,
137 | gpointer data)
138 |
139 | {
140 | TrashCall *call;
141 |
142 | g_return_if_fail (XDP_IS_PORTAL (portal));
143 | g_return_if_fail (path != NULL);
144 |
145 | call = g_new0 (TrashCall, 1);
146 | call->portal = g_object_ref (portal);
147 | call->path = g_strdup (path);
148 | call->task = g_task_new (portal, cancellable, callback, data);
149 | g_task_set_source_tag (call->task, xdp_portal_trash_file);
150 |
151 | trash_file (call);
152 | }
153 |
154 | /**
155 | * xdp_portal_trash_file_finish:
156 | * @portal: a [class@Portal]
157 | * @result: a [iface@Gio.AsyncResult]
158 | * @error: return location for an error
159 | *
160 | * Finishes the trash-file request.
161 | *
162 | * Returns the result in the form of a boolean.
163 | *
164 | * Returns: `TRUE` if the call succeeded
165 | */
166 | gboolean
167 | xdp_portal_trash_file_finish (XdpPortal *portal,
168 | GAsyncResult *result,
169 | GError **error)
170 | {
171 | g_return_val_if_fail (XDP_IS_PORTAL (portal), FALSE);
172 | g_return_val_if_fail (g_task_is_valid (result, portal), FALSE);
173 | g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == xdp_portal_trash_file, FALSE);
174 |
175 | return g_task_propagate_boolean (G_TASK (result), error);
176 | }
177 |
--------------------------------------------------------------------------------
/libportal/trash.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | XDP_PUBLIC
27 | void xdp_portal_trash_file (XdpPortal *portal,
28 | const char *path,
29 | GCancellable *cancellable,
30 | GAsyncReadyCallback callback,
31 | gpointer data);
32 |
33 | XDP_PUBLIC
34 | gboolean xdp_portal_trash_file_finish (XdpPortal *portal,
35 | GAsyncResult *result,
36 | GError **error);
37 |
38 | G_END_DECLS
39 |
--------------------------------------------------------------------------------
/libportal/types.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021, Georges Basile Stavracas Neto
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | typedef struct _XdpParent XdpParent;
27 | typedef struct _XdpPortal XdpPortal;
28 | typedef struct _XdpSettings XdpSettings;
29 |
--------------------------------------------------------------------------------
/libportal/updates.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpUpdateStatus:
28 | * @XDP_UPDATE_STATUS_RUNNING: Installation in progress
29 | * @XDP_UPDATE_STATUS_EMPTY: Nothing to install
30 | * @XDP_UPDATE_STATUS_DONE: Installation finished successfully
31 | * @XDP_UPDATE_STATUS_FAILED: Installation failed
32 | *
33 | * The values of this enum are returned in the
34 | * [signal@Portal::update-progress] signal to indicate
35 | * the current progress of an installation.
36 | */
37 | typedef enum {
38 | XDP_UPDATE_STATUS_RUNNING,
39 | XDP_UPDATE_STATUS_EMPTY,
40 | XDP_UPDATE_STATUS_DONE,
41 | XDP_UPDATE_STATUS_FAILED
42 | } XdpUpdateStatus;
43 |
44 | typedef enum
45 | {
46 | XDP_UPDATE_MONITOR_FLAG_NONE = 0,
47 | } XdpUpdateMonitorFlags;
48 |
49 | XDP_PUBLIC
50 | void xdp_portal_update_monitor_start (XdpPortal *portal,
51 | XdpUpdateMonitorFlags flags,
52 | GCancellable *cancellable,
53 | GAsyncReadyCallback callback,
54 | gpointer data);
55 |
56 | XDP_PUBLIC
57 | gboolean xdp_portal_update_monitor_start_finish (XdpPortal *portal,
58 | GAsyncResult *result,
59 | GError **error);
60 |
61 | XDP_PUBLIC
62 | void xdp_portal_update_monitor_stop (XdpPortal *portal);
63 |
64 | typedef enum
65 | {
66 | XDP_UPDATE_INSTALL_FLAG_NONE = 0,
67 | } XdpUpdateInstallFlags;
68 |
69 | XDP_PUBLIC
70 | void xdp_portal_update_install (XdpPortal *portal,
71 | XdpParent *parent,
72 | XdpUpdateInstallFlags flags,
73 | GCancellable *cancellable,
74 | GAsyncReadyCallback callback,
75 | gpointer data);
76 |
77 | XDP_PUBLIC
78 | gboolean xdp_portal_update_install_finish (XdpPortal *portal,
79 | GAsyncResult *result,
80 | GError **error);
81 |
82 | G_END_DECLS
83 |
--------------------------------------------------------------------------------
/libportal/wallpaper.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019, Matthias Clasen
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | G_BEGIN_DECLS
25 |
26 | /**
27 | * XdpWallpaperFlags:
28 | * @XDP_WALLPAPER_FLAG_NONE: No flags
29 | * @XDP_WALLPAPER_FLAG_BACKGROUND: Set wallpaper on the desktop background
30 | * @XDP_WALLPAPER_FLAG_LOCKSCREEN: Set wallpaper on the lockscreen
31 | * @XDP_WALLPAPER_FLAG_PREVIEW: Request the preview to be shown
32 | *
33 | * The values of this enumeration determine where the wallpaper is being set.
34 | */
35 | typedef enum {
36 | XDP_WALLPAPER_FLAG_NONE = 0,
37 | XDP_WALLPAPER_FLAG_BACKGROUND = 1 << 0,
38 | XDP_WALLPAPER_FLAG_LOCKSCREEN = 1 << 1,
39 | XDP_WALLPAPER_FLAG_PREVIEW = 1 << 2
40 | } XdpWallpaperFlags;
41 |
42 | #define XDP_WALLPAPER_TARGET_BOTH (XDP_WALLPAPER_TARGET_BACKGROUND|XDP_WALLPAPER_TARGET_LOCKSCREEN)
43 |
44 | XDP_PUBLIC
45 | void xdp_portal_set_wallpaper (XdpPortal *portal,
46 | XdpParent *parent,
47 | const char *uri,
48 | XdpWallpaperFlags flags,
49 | GCancellable *cancellable,
50 | GAsyncReadyCallback callback,
51 | gpointer data);
52 |
53 | XDP_PUBLIC
54 | gboolean xdp_portal_set_wallpaper_finish (XdpPortal *portal,
55 | GAsyncResult *result,
56 | GError **error);
57 |
58 | G_END_DECLS
59 |
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | project('libportal','c',
2 | version: '0.9.2',
3 | default_options: ['warning_level=2'],
4 | meson_version: '>= 0.55.0')
5 |
6 | cc = meson.get_compiler('c')
7 | cflags = [
8 | '-Wno-unused-parameter',
9 | '-Wno-missing-field-initializers',
10 | ]
11 | add_project_arguments(cc.get_supported_arguments(cflags), language: 'c')
12 |
13 | gnome = import('gnome')
14 | pkgconfig = import('pkgconfig')
15 |
16 | qt5 = import('qt5')
17 |
18 | if get_option('backend-qt6').enabled() and meson.version().version_compare('< 0.59.0')
19 | error('qt6 backend requires meson 0.59.0 or newer')
20 | endif
21 |
22 | if meson.version().version_compare('>= 0.59.0')
23 | qt6 = import('qt6')
24 | endif
25 |
26 | conf = configuration_data()
27 | conf.set_quoted('G_LOG_DOMAIN', 'libportal')
28 | conf.set_quoted('PACKAGE_NAME', 'libportal')
29 | conf.set_quoted('PKGDATADIR', join_paths(get_option('prefix'), get_option('datadir'), 'libportal'))
30 | conf.set_quoted('APPDATADIR', join_paths(get_option('prefix'), get_option('datadir'), 'org.gnome.PortalTest'))
31 |
32 | if cc.has_argument('-fvisibility=hidden')
33 | conf.set('XDP_PUBLIC', '__attribute__((visibility("default"))) extern')
34 | endif
35 |
36 | check_headers = ['sys/vfs.h']
37 |
38 | foreach header : check_headers
39 | macro = 'HAVE_' + header.underscorify().to_upper()
40 | conf.set(macro, cc.has_header(header) ? 1 : false)
41 | endforeach
42 |
43 | configure_file(output : 'config.h', configuration : conf)
44 |
45 | introspection = get_option('introspection')
46 | vapi = get_option('vapi')
47 |
48 | top_inc = include_directories('.')
49 | libportal_inc = include_directories('libportal')
50 |
51 | subdir('libportal')
52 |
53 | if get_option('portal-tests')
54 | subdir('portal-test')
55 | endif
56 |
57 | if get_option('tests')
58 | subdir('tests')
59 | endif
60 |
61 | if get_option('docs')
62 | subdir('doc')
63 | endif
64 |
--------------------------------------------------------------------------------
/meson_options.txt:
--------------------------------------------------------------------------------
1 | option('backend-gtk3', type: 'feature', value: 'auto',
2 | description: 'Build the GTK3 portal backend')
3 | option('backend-gtk4', type: 'feature', value: 'auto',
4 | description: 'Build the GTK4 portal backend')
5 | option('backend-qt5', type: 'feature', value: 'auto',
6 | description: 'Build the Qt5 portal backend')
7 | option('backend-qt6', type: 'feature', value: 'auto',
8 | description: 'Build the Qt6 portal backend')
9 | option('portal-tests', type: 'boolean', value: false,
10 | description : 'Build portal tests of each backend')
11 | option('introspection', type: 'boolean', value: true,
12 | description: 'Generate GObject introspection files')
13 | option('vapi', type: 'boolean', value: true,
14 | description : 'Generate Vala bindings')
15 | option('docs', type: 'boolean', value: true,
16 | description : 'Build API reference with gi-docgen')
17 | option('tests', type: 'boolean', value: true,
18 | description : 'Build unit tests')
19 |
--------------------------------------------------------------------------------
/portal-test/gtk3/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "portal-test-app.h"
5 |
6 | int
7 | main (int argc, char *argv[])
8 | {
9 | gst_init (&argc, &argv);
10 |
11 | g_message ("Starting org.gnome.PortalTest.Gtk3");
12 |
13 | if (g_strv_contains ((const char * const *)argv, "--replace"))
14 | portal_test_app_stop_running_instance ();
15 |
16 | return g_application_run (portal_test_app_new (), argc, argv);
17 | }
18 |
--------------------------------------------------------------------------------
/portal-test/gtk3/meson.build:
--------------------------------------------------------------------------------
1 |
2 | gst_dep = dependency('gstreamer-audio-1.0')
3 |
4 | resources = gnome.compile_resources('resources',
5 | 'portal-test.gresource.xml',
6 | c_name: '_portal_test',
7 | )
8 |
9 | src = [
10 | 'main.c',
11 | 'portal-test-app.h',
12 | 'portal-test-app.c',
13 | 'portal-test-win.h',
14 | 'portal-test-win.c',
15 | resources,
16 | ]
17 |
18 | portal_test_gtk3 = executable('portal-test-gtk3',
19 | src,
20 | include_directories: [top_inc, libportal_inc],
21 | dependencies: [gst_dep, libportal_gtk3_dep],
22 | install : true,
23 | )
24 |
25 | install_data('test.txt', install_dir: 'share/org.gnome.PortalTest.Gtk3')
26 | install_data('org.gnome.PortalTest.Gtk3.desktop', install_dir: 'share/applications')
27 | install_data('org.gnome.PortalTest.Gtk3.service', install_dir: 'share/dbus-1/services')
28 |
29 | executable('portal-linking-test-gtk3',
30 | [ 'portal-linking-test.c' ],
31 | include_directories: [libportal_inc],
32 | dependencies: [libportal_gtk3_dep],
33 | )
34 |
35 | if meson.can_run_host_binaries()
36 | run_target('portal-test-gtk3',
37 | command: portal_test_gtk3,
38 | )
39 | endif
40 |
--------------------------------------------------------------------------------
/portal-test/gtk3/org.gnome.PortalTest.Gtk3.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Portal test (GTK3)
3 | Exec=portal-test-gtk3
4 | Type=Application
5 | DBusActivatable=true
6 |
--------------------------------------------------------------------------------
/portal-test/gtk3/org.gnome.PortalTest.Gtk3.service:
--------------------------------------------------------------------------------
1 | [D-BUS Service]
2 | Name=org.gnome.PortalTest.Gtk3
3 | Exec=portal-test-gtk3
4 |
--------------------------------------------------------------------------------
/portal-test/gtk3/portal-linking-test.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int
4 | main (int argc, char **argv)
5 | {
6 | XdpPortal *portal;
7 |
8 | portal = xdp_portal_new ();
9 | (void) xdp_portal_is_camera_present (portal);
10 |
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/portal-test/gtk3/portal-test-app.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "portal-test-app.h"
5 | #include "portal-test-win.h"
6 |
7 | struct _PortalTestApp
8 | {
9 | GtkApplication parent;
10 | };
11 |
12 | struct _PortalTestAppClass
13 | {
14 | GtkApplicationClass parent_class;
15 | };
16 |
17 | G_DEFINE_TYPE(PortalTestApp, portal_test_app, GTK_TYPE_APPLICATION)
18 |
19 | static void
20 | portal_test_app_init (PortalTestApp *app)
21 | {
22 | /* this option is handled explicitly in main(),
23 | * just add it here so GApplication is not surprised.
24 | */
25 | g_application_add_main_option (G_APPLICATION (app),
26 | "replace",
27 | 0,
28 | G_OPTION_FLAG_NONE,
29 | G_OPTION_ARG_NONE,
30 | "Replace the running instance", NULL);
31 | }
32 |
33 | static void
34 | name_appeared (GDBusConnection *bus,
35 | const char *name,
36 | const char *name_owner,
37 | gpointer data)
38 | {
39 | gboolean *name_free = data;
40 |
41 | g_message ("Name %s owned by %s", name, name_owner);
42 |
43 | *name_free = FALSE;
44 | }
45 |
46 | static void
47 | name_vanished (GDBusConnection *bus,
48 | const char *name,
49 | gpointer data)
50 | {
51 | gboolean *name_free = data;
52 |
53 | g_message ("Name %s unowned", name);
54 |
55 | *name_free = TRUE;
56 | }
57 |
58 | void
59 | portal_test_app_stop_running_instance (void)
60 | {
61 | g_autoptr(GDBusConnection) bus = NULL;
62 | g_autoptr(GError) error = NULL;
63 | g_autoptr(GVariant) ret = NULL;
64 | GVariantBuilder options;
65 | GVariantBuilder pdata;
66 | guint watcher_id;
67 | gboolean name_free = FALSE;
68 |
69 | g_message ("Replacing the running instance");
70 |
71 | /* Can't use g_application_activate_action here,
72 | * since we're not set up as a remote instance yet.
73 | */
74 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
75 | if (bus == NULL)
76 | {
77 | g_warning ("Failed to get session bus");
78 | exit (1);
79 | }
80 |
81 | watcher_id = g_bus_watch_name_on_connection (bus,
82 | "org.gnome.PortalTest",
83 | 0,
84 | name_appeared,
85 | name_vanished,
86 | &name_free,
87 | NULL);
88 |
89 | g_variant_builder_init (&options, G_VARIANT_TYPE ("av"));
90 | g_variant_builder_init (&pdata, G_VARIANT_TYPE ("a{sv}"));
91 | ret = g_dbus_connection_call_sync (bus,
92 | "org.gnome.PortalTest",
93 | "/org/gnome/PortalTest",
94 | "org.gtk.Actions",
95 | "Activate",
96 | g_variant_new ("(sava{sv})",
97 | "quit", &options, &pdata),
98 | NULL,
99 | G_DBUS_CALL_FLAGS_NONE,
100 | -1,
101 | NULL,
102 | &error);
103 | if (error != NULL)
104 | {
105 | g_warning ("Failed to quit the running instance: %s", error->message);
106 | exit (1);
107 | }
108 |
109 | if (!name_free)
110 | g_message ("Waiting for running instance to give up name ownership");
111 |
112 | while (!name_free)
113 | g_main_context_iteration (NULL, TRUE);
114 |
115 | g_bus_unwatch_name (watcher_id);
116 | }
117 |
118 | static void
119 | portal_test_app_startup (GApplication *app)
120 | {
121 | g_autoptr(GMenu) menu = NULL;
122 |
123 | G_APPLICATION_CLASS (portal_test_app_parent_class)->startup (app);
124 |
125 | menu = g_menu_new ();
126 | g_menu_append (menu, "Restart", "app.restart");
127 | g_menu_append (menu, "Quit", "app.quit");
128 |
129 | gtk_application_set_app_menu (GTK_APPLICATION (app), G_MENU_MODEL (menu));
130 | }
131 |
132 | static void
133 | portal_test_app_activate (GApplication *app)
134 | {
135 | GtkWindow *win;
136 |
137 | win = gtk_application_get_active_window (GTK_APPLICATION (app));
138 | if (!win)
139 | win = GTK_WINDOW (portal_test_win_new (PORTAL_TEST_APP (app)));
140 | gtk_window_present (win);
141 | }
142 |
143 | static void
144 | portal_test_app_class_init (PortalTestAppClass *class)
145 | {
146 | G_APPLICATION_CLASS (class)->startup = portal_test_app_startup;
147 | G_APPLICATION_CLASS (class)->activate = portal_test_app_activate;
148 | }
149 |
150 | static void
151 | acktivate (GSimpleAction *action,
152 | GVariant *parameter,
153 | gpointer user_data)
154 | {
155 | GtkApplication *app = user_data;
156 | GtkWindow *win;
157 |
158 | win = gtk_application_get_active_window (app);
159 | portal_test_win_ack (PORTAL_TEST_WIN (win));
160 | }
161 |
162 | static void
163 | spawned_cb (GObject *source,
164 | GAsyncResult *res,
165 | gpointer data)
166 | {
167 | GDBusConnection *bus = G_DBUS_CONNECTION (source);
168 | g_autoptr(GError) error = NULL;
169 | g_autoptr(GVariant) ret = NULL;
170 | guint32 pid;
171 |
172 | ret = g_dbus_connection_call_finish (bus, res, &error);
173 |
174 | if (!ret)
175 | {
176 | g_warning ("Restart failed: %s\n", error->message);
177 | return;
178 | }
179 |
180 | g_variant_get (ret, "(u)", &pid);
181 | g_message ("Restarted with pid %d", pid);
182 | }
183 |
184 | void
185 | portal_test_app_restart (PortalTestApp *app)
186 | {
187 | GDBusConnection *bus;
188 | const char *strv[3] = { "portal-test", "--replace", NULL };
189 | GVariant *args;
190 |
191 | bus = g_application_get_dbus_connection (G_APPLICATION (app));
192 |
193 | g_message ("Calling org.freedesktop.portal.Flatpak.Spawn");
194 | args = g_variant_new ("(@ay@aay@a{uh}@a{ss}u@a{sv})",
195 | g_variant_new_bytestring ("/"),
196 | g_variant_new_bytestring_array (strv, -1),
197 | g_variant_new_array (G_VARIANT_TYPE ("{uh}"), NULL, 0),
198 | g_variant_new_array (G_VARIANT_TYPE ("{ss}"), NULL, 0),
199 | 2,
200 | g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)),
201 |
202 | g_dbus_connection_call (bus,
203 | "org.freedesktop.portal.Flatpak",
204 | "/org/freedesktop/portal/Flatpak",
205 | "org.freedesktop.portal.Flatpak",
206 | "Spawn",
207 | args,
208 | G_VARIANT_TYPE ("(u)"),
209 | 0,
210 | -1,
211 | NULL,
212 | spawned_cb,
213 | app);
214 | }
215 |
216 | static void
217 | restart (GSimpleAction *action,
218 | GVariant *parameter,
219 | gpointer user_data)
220 | {
221 | portal_test_app_restart (PORTAL_TEST_APP (user_data));
222 | }
223 |
224 | static void
225 | quit (GSimpleAction *action,
226 | GVariant *parameter,
227 | gpointer user_data)
228 | {
229 | g_message ("Received a request to quit");
230 | g_application_quit (G_APPLICATION (user_data));
231 | }
232 |
233 | static GActionEntry entries[] = {
234 | { "ack", acktivate, NULL, NULL, NULL },
235 | { "restart", restart, NULL, NULL, NULL },
236 | { "quit", quit, NULL, NULL, NULL }
237 | };
238 |
239 | GApplication *
240 | portal_test_app_new (void)
241 | {
242 | GApplication *app;
243 |
244 | app = g_object_new (portal_test_app_get_type (),
245 | "application-id", "org.gnome.PortalTest.Gtk3",
246 | NULL);
247 |
248 | g_action_map_add_action_entries (G_ACTION_MAP (app), entries, G_N_ELEMENTS (entries), app);
249 |
250 | return app;
251 | }
252 |
--------------------------------------------------------------------------------
/portal-test/gtk3/portal-test-app.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | G_DECLARE_FINAL_TYPE(PortalTestApp, portal_test_app, PORTAL, TEST_APP, GtkApplication)
6 |
7 | GType portal_test_app_get_type (void);
8 | GApplication *portal_test_app_new (void);
9 | void portal_test_app_restart (PortalTestApp *app);
10 | void portal_test_app_stop_running_instance (void);
11 |
--------------------------------------------------------------------------------
/portal-test/gtk3/portal-test-win.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "portal-test-app.h"
5 |
6 | G_DECLARE_FINAL_TYPE(PortalTestWin, portal_test_win, PORTAL, TEST_WIN, GtkApplicationWindow)
7 |
8 | GType portal_test_win_get_type (void);
9 | GtkApplicationWindow *portal_test_win_new (PortalTestApp *app);
10 | void portal_test_win_ack (PortalTestWin *win);
11 |
--------------------------------------------------------------------------------
/portal-test/gtk3/portal-test.gresource.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | portal-test-win.ui
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/portal-test/gtk3/test.txt:
--------------------------------------------------------------------------------
1 | Like a trash can fire in a prison cell \\
2 | like a search light in the parking lot of hell
3 |
--------------------------------------------------------------------------------
/portal-test/gtk4/application.js:
--------------------------------------------------------------------------------
1 | const { Gio, GLib, GObject, Gtk } = imports.gi;
2 |
3 | const { PortalTestWindow } = imports.window;
4 | const ByteArray = imports.byteArray;
5 |
6 | var Application = GObject.registerClass({
7 | GTypeName: 'Gtk4PortalTestApplication',
8 | }, class Application extends Gtk.Application {
9 | _init(params) {
10 | super._init(params);
11 |
12 | this.add_main_option('replace', 0, 0, 0, 'Replace the running instance', null);
13 |
14 | let action = new Gio.SimpleAction({ name: 'ack' });
15 | action.connect('activate', () => this._window.ack());
16 | this.add_action(action);
17 |
18 | action = new Gio.SimpleAction({ name: 'restart' });
19 | action.connect('activate', () => this.restart());
20 | this.add_action(action);
21 |
22 | action = new Gio.SimpleAction({ name: 'quit' });
23 | action.connect('activate', () => this.quit());
24 | this.add_action(action);
25 | }
26 |
27 | vfunc_activate() {
28 | super.vfunc_activate();
29 |
30 | this._window.present();
31 | }
32 |
33 | vfunc_startup() {
34 | super.vfunc_startup();
35 |
36 | if (!this._window)
37 | this._window = new PortalTestWindow(this);
38 | }
39 |
40 | restart() {
41 | const bus = this.get_dbus_connection();
42 |
43 | const s2ay = value => {
44 | let bytes;
45 | if (typeof value === 'string') {
46 | let byteArray = ByteArray.fromString(value);
47 | if (byteArray[byteArray.length - 1] !== 0)
48 | byteArray = Uint8Array.of(...byteArray, 0);
49 | bytes = ByteArray.toGBytes(byteArray);
50 | } else {
51 | bytes = new GLib.Bytes(value);
52 | }
53 | return GLib.Variant.new_from_bytes(new GLib.VariantType('ay'),
54 | bytes, true);
55 | };
56 |
57 | bus.call(
58 | 'org.freedesktop.portal.Flatpak',
59 | '/org/freedesktop/portal/Flatpak',
60 | 'org.freedesktop.portal.Flatpak',
61 | 'Spawn', GLib.Variant.new_tuple([
62 | s2ay('/'),
63 | GLib.Variant.new_array(new GLib.VariantType('ay'), [
64 | s2ay('org.gnome.PortalTest.Gtk4'),
65 | s2ay('--replace'),
66 | ]),
67 | GLib.Variant.new_array(new GLib.VariantType('{uh}'), []),
68 | GLib.Variant.new_array(new GLib.VariantType('{ss}'), []),
69 | GLib.Variant.new_uint32(2),
70 | GLib.Variant.new_array(new GLib.VariantType('{sv}'), []),
71 | ]),
72 | new GLib.VariantType('(u)'),
73 | 0, -1, null,
74 | (connection, result) => {
75 | try {
76 | const res = bus.call_finish(result);
77 | log(`Restarted with pid ${res.deepUnpack()}`);
78 | } catch(e) {
79 | logError(e);
80 | return;
81 | }
82 | });
83 | }
84 | });
85 |
--------------------------------------------------------------------------------
/portal-test/gtk4/main.js:
--------------------------------------------------------------------------------
1 |
2 | pkg.initGettext();
3 | pkg.initFormat();
4 | pkg.require({
5 | 'GdkPixbuf': '2.0',
6 | 'Gio': '2.0',
7 | 'Gst': '1.0',
8 | 'Gtk': '4.0',
9 | 'Xdp': '1.0',
10 | 'XdpGtk4': '1.0',
11 | });
12 |
13 | const { Gdk, Gio, GLib, Gst, Gtk } = imports.gi;
14 |
15 | const { Application } = imports.application;
16 |
17 | function stopRunningInstance() {
18 | const bus = Gio.DBus.session;
19 |
20 | const mainloop = GLib.MainLoop.new(null, false);
21 |
22 | const watchId = bus.watch_name(
23 | 'org.gnome.PortalTest.Gtk4',
24 | 0,
25 | (bus, name, owner) => {
26 | log(`Name ${name} owned by ${owner}`);
27 | },
28 | (bus, name) => {
29 | log(`Name ${name} unowned`);
30 | mainloop.quit();
31 | });
32 |
33 | try {
34 | bus.call_sync(
35 | 'org.gnome.PortalTest.Gtk4',
36 | '/org/gnome/PortalTest/Gtk4',
37 | 'org.gtk.Actions',
38 | 'Activate', GLib.Variant.new_tuple([
39 | GLib.Variant.new_string('quit'),
40 | new GLib.Variant('av', []),
41 | new GLib.Variant('a{sv}', {}),
42 | ]),
43 | null,
44 | Gio.DBusCallFlags.NONE,
45 | -1, null);
46 | } catch(e) {
47 | logError(e);
48 | }
49 |
50 | mainloop.run();
51 |
52 | bus.unwatch_name(watchId);
53 | }
54 |
55 | function main(argv) {
56 | Gst.init(null);
57 |
58 | if (argv.indexOf('--replace') !== -1)
59 | stopRunningInstance();
60 |
61 | const application = new Application({
62 | application_id: 'org.gnome.PortalTest.Gtk4',
63 | flags: Gio.ApplicationFlags.FLAGS_NONE,
64 | });
65 |
66 | return application.run(argv);
67 | }
68 |
--------------------------------------------------------------------------------
/portal-test/gtk4/meson.build:
--------------------------------------------------------------------------------
1 |
2 | if not introspection
3 | error('The GTK4 test portal requires introspection')
4 | endif
5 |
6 | gst_dep = dependency('gstreamer-audio-1.0')
7 |
8 | package_name = 'portal-test-gtk4'
9 | pkgdatadir = get_option('datadir') / package_name
10 |
11 | data_resouces = gnome.compile_resources(
12 | 'org.gnome.PortalTest.Gtk4.data',
13 | 'org.gnome.PortalTest.Gtk4.data.gresource.xml',
14 | gresource_bundle: true,
15 | install: true,
16 | install_dir: pkgdatadir,
17 | )
18 |
19 | js_resouces = gnome.compile_resources(
20 | 'org.gnome.PortalTest.Gtk4.src',
21 | 'org.gnome.PortalTest.Gtk4.src.gresource.xml',
22 | gresource_bundle: true,
23 | install: true,
24 | install_dir: pkgdatadir,
25 | )
26 |
27 | bin_conf = configuration_data()
28 | bin_conf.set('GJS', find_program('gjs').full_path())
29 | bin_conf.set('PACKAGE_NAME', package_name)
30 | bin_conf.set('PACKAGE_VERSION', '1.0.0')
31 | bin_conf.set('prefix', get_option('prefix'))
32 | bin_conf.set('libdir', get_option('prefix') / get_option('libdir'))
33 | bin_conf.set('datadir', get_option('prefix') / get_option('datadir'))
34 |
35 | portal_test_gtk4 = configure_file(
36 | input: 'org.gnome.PortalTest.Gtk4.in',
37 | output: 'org.gnome.PortalTest.Gtk4',
38 | configuration: bin_conf,
39 | )
40 | install_data(portal_test_gtk4, install_mode: 'rwxr-xr-x', install_dir: get_option('bindir'))
41 | install_data('test.txt', install_dir: 'share/org.gnome.PortalTest.Gtk4')
42 | install_data('org.gnome.PortalTest.Gtk4.desktop', install_dir: 'share/applications')
43 | install_data('org.gnome.PortalTest.Gtk4.service', install_dir: 'share/dbus-1/services')
44 |
45 | executable('portal-linking-test-gtk4',
46 | [ 'portal-linking-test.c' ],
47 | include_directories: [libportal_inc],
48 | dependencies: [libportal_gtk4_dep],
49 | )
50 |
--------------------------------------------------------------------------------
/portal-test/gtk4/org.gnome.PortalTest.Gtk4.data.gresource.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | window.ui
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/portal-test/gtk4/org.gnome.PortalTest.Gtk4.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Portal test (GTK4)
3 | Exec=org.gnome.PortalTest.Gtk4
4 | Type=Application
5 | DBusActivatable=true
6 |
--------------------------------------------------------------------------------
/portal-test/gtk4/org.gnome.PortalTest.Gtk4.in:
--------------------------------------------------------------------------------
1 | #!@GJS@
2 | imports.package.init({
3 | name: "@PACKAGE_NAME@",
4 | version: "@PACKAGE_VERSION@",
5 | prefix: "@prefix@",
6 | libdir: "@libdir@",
7 | datadir: "@datadir@",
8 | });
9 | imports.package.run(imports.main);
10 |
--------------------------------------------------------------------------------
/portal-test/gtk4/org.gnome.PortalTest.Gtk4.service:
--------------------------------------------------------------------------------
1 | [D-BUS Service]
2 | Name=org.gnome.PortalTest.Gtk4
3 | Exec=org.gnome.PortalTest.Gtk4
4 |
--------------------------------------------------------------------------------
/portal-test/gtk4/org.gnome.PortalTest.Gtk4.src.gresource.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | application.js
5 | main.js
6 | window.js
7 |
8 |
9 |
--------------------------------------------------------------------------------
/portal-test/gtk4/portal-linking-test.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int
4 | main (int argc, char **argv)
5 | {
6 | XdpPortal *portal;
7 |
8 | portal = xdp_portal_new ();
9 | (void) xdp_portal_is_camera_present (portal);
10 |
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/portal-test/gtk4/test.txt:
--------------------------------------------------------------------------------
1 | Like a trash can fire in a prison cell \\
2 | like a search light in the parking lot of hell
3 |
--------------------------------------------------------------------------------
/portal-test/meson.build:
--------------------------------------------------------------------------------
1 | foreach backend : enabled_backends
2 | subdir(backend)
3 | endforeach
4 |
--------------------------------------------------------------------------------
/portal-test/qt5/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #include "portal-test-qt.h"
5 |
6 | int main(int argc, char *argv[])
7 | {
8 | QApplication a(argc, argv);
9 |
10 | PortalTestQt *portalTest = new PortalTestQt(nullptr);
11 | portalTest->show();
12 |
13 | return a.exec();
14 | }
15 |
--------------------------------------------------------------------------------
/portal-test/qt5/meson.build:
--------------------------------------------------------------------------------
1 |
2 | add_languages('cpp', required : true, native : false)
3 |
4 | src = [
5 | 'main.cpp',
6 | 'portal-test-qt.h',
7 | 'portal-test-qt.cpp',
8 | ]
9 |
10 | prep = qt5.preprocess(
11 | moc_headers : 'portal-test-qt.h',
12 | moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
13 | ui_files : 'portal-test-qt.ui',
14 | dependencies: libportal_qt5_dep,
15 | )
16 |
17 | executable('portal-test-qt5',
18 | [src, prep],
19 | include_directories: [top_inc, libportal_inc],
20 | dependencies: [libportal_qt5_dep],
21 | cpp_args : '-std=c++11',
22 | install : true,
23 | )
24 |
--------------------------------------------------------------------------------
/portal-test/qt5/portal-test-qt.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "portal-test-qt.h"
3 | #include "ui_portal-test-qt.h"
4 |
5 | #include
6 |
7 | PortalTestQt::PortalTestQt(QWidget *parent, Qt::WindowFlags f)
8 | : QMainWindow(parent, f)
9 | , m_mainWindow(new Ui_PortalTestQt)
10 | , m_portal(xdp_portal_new())
11 | {
12 | m_mainWindow->setupUi(this);
13 |
14 | connect(m_mainWindow->openFileButton, &QPushButton::clicked, [=] (G_GNUC_UNUSED bool clicked) {
15 | XdpParent *parent;
16 | XdpOpenFileFlags flags = XDP_OPEN_FILE_FLAG_NONE;
17 |
18 | parent = xdp_parent_new_qt(windowHandle());
19 | xdp_portal_open_file (m_portal, parent, "Portal Test Qt", nullptr /*filters*/, nullptr /*current_filters*/,
20 | nullptr /*choices*/, flags, nullptr /*cancellable*/, openedFile, this);
21 | xdp_parent_free (parent);
22 | });
23 | }
24 |
25 | PortalTestQt::~PortalTestQt()
26 | {
27 | delete m_mainWindow;
28 | g_object_unref( m_portal);
29 | }
30 |
31 | void PortalTestQt::updateLastOpenedFile(const QString &file)
32 | {
33 | if (!file.isEmpty()) {
34 | m_mainWindow->openedFileLabel->setText(QStringLiteral("Opened file: %1").arg(file));
35 | } else {
36 | m_mainWindow->openedFileLabel->setText(QStringLiteral("Failed to open a file!!!"));
37 | }
38 | }
39 |
40 | void PortalTestQt::openedFile(GObject *object, GAsyncResult *result, gpointer data)
41 | {
42 | Q_UNUSED(data);
43 | XdpPortal *portal = XDP_PORTAL (object);
44 | PortalTestQt *win = static_cast(data);
45 | g_autoptr(GError) error = nullptr;
46 | g_autoptr(GVariant) ret = nullptr;
47 |
48 | ret = xdp_portal_open_file_finish(portal, result, &error);
49 |
50 | if (ret) {
51 | const char **uris;
52 | if (g_variant_lookup(ret, "uris", "^a&s", &uris)) {
53 | win->updateLastOpenedFile(uris[0]);
54 | }
55 | } else {
56 | win->updateLastOpenedFile(QString());
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/portal-test/qt5/portal-test-qt.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #undef signals
6 | #include "libportal/portal-qt5.h"
7 | #define signals Q_SIGNALS
8 |
9 | class Ui_PortalTestQt;
10 |
11 | class PortalTestQt : public QMainWindow
12 | {
13 | Q_OBJECT
14 | public:
15 | PortalTestQt(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
16 | ~PortalTestQt();
17 |
18 | void updateLastOpenedFile(const QString &file);
19 | private:
20 | static void openedFile(GObject *object, GAsyncResult *result, gpointer data);
21 |
22 | Ui_PortalTestQt *m_mainWindow;
23 | XdpPortal *m_portal;
24 | };
25 |
--------------------------------------------------------------------------------
/portal-test/qt5/portal-test-qt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | PortalTestQt
4 |
5 |
6 |
7 | 0
8 | 0
9 | 355
10 | 100
11 |
12 |
13 |
14 | Portal Test Qt
15 |
16 |
17 |
18 | -
19 |
20 |
21 | Open File...
22 |
23 |
24 |
25 | -
26 |
27 |
28 | No file opened!!
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/portal-test/qt6/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #include "portal-test-qt.h"
5 |
6 | int main(int argc, char *argv[])
7 | {
8 | QApplication a(argc, argv);
9 |
10 | PortalTestQt *portalTest = new PortalTestQt(nullptr);
11 | portalTest->show();
12 |
13 | return a.exec();
14 | }
15 |
--------------------------------------------------------------------------------
/portal-test/qt6/meson.build:
--------------------------------------------------------------------------------
1 |
2 | add_languages('cpp', required : true, native : false)
3 |
4 | src = [
5 | 'main.cpp',
6 | 'portal-test-qt.h',
7 | 'portal-test-qt.cpp',
8 | ]
9 |
10 | prep = qt6.preprocess(
11 | moc_headers : 'portal-test-qt.h',
12 | moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
13 | ui_files : 'portal-test-qt.ui',
14 | dependencies: libportal_qt6_dep,
15 | )
16 |
17 | executable('portal-test-qt6',
18 | [src, prep],
19 | include_directories: [top_inc, libportal_inc],
20 | dependencies: [libportal_qt6_dep],
21 | cpp_args : '-std=c++17',
22 | install : true,
23 | )
24 |
--------------------------------------------------------------------------------
/portal-test/qt6/portal-test-qt.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "portal-test-qt.h"
3 | #include "ui_portal-test-qt.h"
4 |
5 | #include
6 |
7 | PortalTestQt::PortalTestQt(QWidget *parent, Qt::WindowFlags f)
8 | : QMainWindow(parent, f)
9 | , m_mainWindow(new Ui_PortalTestQt)
10 | , m_portal(xdp_portal_new())
11 | {
12 | m_mainWindow->setupUi(this);
13 |
14 | connect(m_mainWindow->openFileButton, &QPushButton::clicked, [=] (G_GNUC_UNUSED bool clicked) {
15 | XdpParent *parent;
16 | XdpOpenFileFlags flags = XDP_OPEN_FILE_FLAG_NONE;
17 |
18 | parent = xdp_parent_new_qt(windowHandle());
19 | xdp_portal_open_file (m_portal, parent, "Portal Test Qt", nullptr /*filters*/, nullptr /*current_filters*/,
20 | nullptr /*choices*/, flags, nullptr /*cancellable*/, openedFile, this);
21 | xdp_parent_free (parent);
22 | });
23 | }
24 |
25 | PortalTestQt::~PortalTestQt()
26 | {
27 | delete m_mainWindow;
28 | g_object_unref( m_portal);
29 | }
30 |
31 | void PortalTestQt::updateLastOpenedFile(const QString &file)
32 | {
33 | if (!file.isEmpty()) {
34 | m_mainWindow->openedFileLabel->setText(QStringLiteral("Opened file: %1").arg(file));
35 | } else {
36 | m_mainWindow->openedFileLabel->setText(QStringLiteral("Failed to open a file!!!"));
37 | }
38 | }
39 |
40 | void PortalTestQt::openedFile(GObject *object, GAsyncResult *result, gpointer data)
41 | {
42 | Q_UNUSED(data);
43 | XdpPortal *portal = XDP_PORTAL (object);
44 | PortalTestQt *win = static_cast(data);
45 | g_autoptr(GError) error = nullptr;
46 | g_autoptr(GVariant) ret = nullptr;
47 |
48 | ret = xdp_portal_open_file_finish(portal, result, &error);
49 |
50 | if (ret) {
51 | const char **uris;
52 | if (g_variant_lookup(ret, "uris", "^a&s", &uris)) {
53 | win->updateLastOpenedFile(uris[0]);
54 | }
55 | } else {
56 | win->updateLastOpenedFile(QString());
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/portal-test/qt6/portal-test-qt.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #undef signals
6 | #include "libportal/portal-qt6.h"
7 | #define signals Q_SIGNALS
8 |
9 | class Ui_PortalTestQt;
10 |
11 | class PortalTestQt : public QMainWindow
12 | {
13 | Q_OBJECT
14 | public:
15 | PortalTestQt(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
16 | ~PortalTestQt();
17 |
18 | void updateLastOpenedFile(const QString &file);
19 | private:
20 | static void openedFile(GObject *object, GAsyncResult *result, gpointer data);
21 |
22 | Ui_PortalTestQt *m_mainWindow;
23 | XdpPortal *m_portal;
24 | };
25 |
--------------------------------------------------------------------------------
/portal-test/qt6/portal-test-qt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | PortalTestQt
4 |
5 |
6 |
7 | 0
8 | 0
9 | 355
10 | 100
11 |
12 |
13 |
14 | Portal Test Qt
15 |
16 |
17 |
18 | -
19 |
20 |
21 | Open File...
22 |
23 |
24 |
25 | -
26 |
27 |
28 | No file opened!!
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/subprojects/gi-docgen.wrap:
--------------------------------------------------------------------------------
1 | [wrap-git]
2 | directory=gi-docgen
3 | url=https://gitlab.gnome.org/GNOME/gi-docgen.git
4 | push-url=ssh://git@gitlab.gnome.org:GNOME/gi-docgen.git
5 | revision=main
6 | depth=1
7 |
--------------------------------------------------------------------------------
/tests/gir-testenv.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Wrapper to set up the right environment variables and start a nested
4 | # shell. Usage:
5 | #
6 | # $ ./tests/gir-testenv.sh
7 | # (nested shell) $ pytest
8 | # (nested shell) $ exit
9 | #
10 | # If you have meson 0.58 or later, you can instead do:
11 | # $ meson devenv -C builddir
12 | # (nested shell) $ cd ../tests
13 | # (nested shell) $ pytest
14 | # (nested shell) $ exit
15 | #
16 |
17 | builddir=$(find $PWD -name meson-logs -printf "%h" -quit)
18 |
19 | if [ -z "$builddir" ]; then
20 | echo "Unable to find meson builddir"
21 | exit 1
22 | fi
23 |
24 | echo "Using meson builddir: $builddir"
25 |
26 | export LD_LIBRARY_PATH="$builddir/libportal:$LD_LIBRARY_PATH"
27 | export GI_TYPELIB_PATH="$builddir/libportal:$GI_TYPELIB_PATH"
28 |
29 | echo "pytest must be run from within the tests/ directory"
30 | # Don't think this is portable, but oh well
31 | ${SHELL}
32 |
--------------------------------------------------------------------------------
/tests/meson.build:
--------------------------------------------------------------------------------
1 | if 'qt5' in enabled_backends
2 | subdir('qt5')
3 | endif
4 | if 'qt6' in enabled_backends
5 | subdir('qt6')
6 | endif
7 |
8 | if meson.version().version_compare('>= 0.56.0')
9 | pytest = find_program('pytest-3', 'pytest', required: false)
10 | pymod = import('python')
11 | python = pymod.find_installation('python3', modules: ['dbus', 'dbusmock'], required: false)
12 |
13 | if pytest.found() and python.found()
14 | test_env = environment()
15 | test_env.set('LD_LIBRARY_PATH', meson.project_build_root() / 'libportal')
16 | test_env.set('GI_TYPELIB_PATH', meson.project_build_root() / 'libportal')
17 |
18 | test('pytest',
19 | pytest,
20 | args: ['--verbose', '--verbose', '--log-level=DEBUG'],
21 | env: test_env,
22 | workdir: meson.current_source_dir(),
23 | timeout: 180,
24 | )
25 | endif
26 | endif
27 |
--------------------------------------------------------------------------------
/tests/pyportaltest/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from typing import Any, Dict, List, Tuple
6 |
7 | import gi
8 | from gi.repository import GLib
9 | from dbus.mainloop.glib import DBusGMainLoop
10 |
11 | import dbus
12 | import dbusmock
13 | import fcntl
14 | import logging
15 | import os
16 | import pytest
17 | import subprocess
18 |
19 | logging.basicConfig(format="%(levelname)s | %(name)s: %(message)s", level=logging.DEBUG)
20 | logger = logging.getLogger("pyportaltest")
21 |
22 | DBusGMainLoop(set_as_default=True)
23 |
24 | # Uncomment this to have dbus-monitor listen on the normal session address
25 | # rather than the test DBus. This can be useful for cases where *something*
26 | # messes up and tests run against the wrong bus.
27 | #
28 | # session_dbus_address = os.environ["DBUS_SESSION_BUS_ADDRESS"]
29 |
30 |
31 | def start_dbus_monitor() -> "subprocess.Process":
32 | import subprocess
33 |
34 | env = os.environ.copy()
35 | try:
36 | env["DBUS_SESSION_BUS_ADDRESS"] = session_dbus_address
37 | except NameError:
38 | # See comment above
39 | pass
40 |
41 | argv = ["dbus-monitor", "--session"]
42 | mon = subprocess.Popen(argv, env=env)
43 |
44 | def stop_dbus_monitor():
45 | mon.terminate()
46 | mon.wait()
47 |
48 | GLib.timeout_add(2000, stop_dbus_monitor)
49 | return mon
50 |
51 |
52 | class PortalTest(dbusmock.DBusTestCase):
53 | """
54 | Parent class for portal tests. Subclass from this and name it after the
55 | portal, e.g. ``TestWallpaper``.
56 |
57 | .. attribute:: portal_interface
58 |
59 | The :class:`dbus.Interface` referring to our portal
60 |
61 | .. attribute:: properties_interface
62 |
63 | A convenience :class:`dbus.Interface` referring to the DBus Properties
64 | interface, call ``Get``, ``Set`` or ``GetAll`` on this interface to
65 | retrieve the matching property/properties.
66 |
67 | .. attribute:: mock_interface
68 |
69 | The DBusMock :class:`dbus.Interface` that controls our DBus
70 | appearance.
71 |
72 | """
73 |
74 | @classmethod
75 | def setUpClass(cls):
76 | if cls.__name__ != "PortalTest":
77 | cls.PORTAL_NAME = cls.__name__.removeprefix("Test")
78 | cls.INTERFACE_NAME = f"org.freedesktop.portal.{cls.PORTAL_NAME}"
79 | os.environ["LIBPORTAL_TEST_SUITE"] = "1"
80 |
81 | try:
82 | dbusmock.mockobject.DBusMockObject.EmitSignalDetailed
83 | except AttributeError:
84 | pytest.skip("Updated version of dbusmock required")
85 |
86 | cls.__have_session_bus = False
87 |
88 | @classmethod
89 | def ensure_session_bus(cls):
90 | if not cls.__have_session_bus:
91 | cls.__have_session_bus = True
92 | cls.start_session_bus()
93 |
94 | def setUp(self):
95 | self.p_mock = None
96 | self._mainloop = None
97 | self.dbus_monitor = None
98 |
99 | def setup_daemon(self, params=None, extra_templates: List[Tuple[str, Dict]] = []):
100 | """
101 | Start a DBusMock daemon in a separate process.
102 |
103 | If extra_templates is specified, it is a list of tuples with the
104 | portal name as first value and the param dict to be passed to that
105 | template as second value, e.g. ("ScreenCast", {...}).
106 | """
107 | self.ensure_session_bus()
108 | self.p_mock, self.obj_portal = self.spawn_server_template(
109 | template=f"pyportaltest/templates/{self.PORTAL_NAME.lower()}.py",
110 | parameters=params,
111 | stdout=subprocess.PIPE,
112 | )
113 |
114 | flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL)
115 | fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
116 | self.mock_interface = dbus.Interface(self.obj_portal, dbusmock.MOCK_IFACE)
117 | self.properties_interface = dbus.Interface(
118 | self.obj_portal, dbus.PROPERTIES_IFACE
119 | )
120 | self.portal_interface = dbus.Interface(self.obj_portal, self.INTERFACE_NAME)
121 |
122 | for t, tparams in extra_templates:
123 | template = f"pyportaltest/templates/{t.lower()}.py"
124 | self.obj_portal.AddTemplate(
125 | template,
126 | dbus.Dictionary(tparams, signature="sv"),
127 | dbus_interface=dbusmock.MOCK_IFACE,
128 | )
129 |
130 | self.dbus_monitor = start_dbus_monitor()
131 |
132 | def tearDown(self):
133 | if self.p_mock:
134 | if self.p_mock.stdout:
135 | out = (self.p_mock.stdout.read() or b"").decode("utf-8")
136 | if out:
137 | print(out)
138 | self.p_mock.stdout.close()
139 | self.p_mock.terminate()
140 | self.p_mock.wait()
141 |
142 | if self.dbus_monitor:
143 | self.dbus_monitor.terminate()
144 | self.dbus_monitor.wait()
145 |
146 | @property
147 | def mainloop(self):
148 | """
149 | The mainloop for this test. This mainloop automatically quits after a
150 | fixed timeout, but only on the first run. That's usually enough for
151 | tests, if you need to call mainloop.run() repeatedly ensure that a
152 | timeout handler is set to ensure quick test case failure in case of
153 | error.
154 | """
155 | if self._mainloop is None:
156 |
157 | def quit():
158 | self._mainloop.quit()
159 | self._mainloop = None
160 |
161 | self._mainloop = GLib.MainLoop()
162 | GLib.timeout_add(2000, quit)
163 |
164 | return self._mainloop
165 |
166 | def assert_version_eq(self, version: int):
167 | """Assert the given version number is the one our portal exports"""
168 | interface_name = self.INTERFACE_NAME
169 | params = {}
170 | self.setup_daemon(params)
171 | assert self.properties_interface.Get(interface_name, "version") == version
172 |
--------------------------------------------------------------------------------
/tests/pyportaltest/templates/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from dbusmock import DBusMockObject
6 | from typing import Dict, Any, NamedTuple, Optional
7 | from itertools import count
8 | from gi.repository import GLib
9 |
10 | import dbus
11 | import logging
12 |
13 |
14 | ASVType = Dict[str, Any]
15 |
16 | logging.basicConfig(format="%(levelname).1s|%(name)s: %(message)s", level=logging.DEBUG)
17 | logger = logging.getLogger("templates")
18 |
19 |
20 | class MockParams:
21 | """
22 | Helper class for storing template parameters. The Mock object passed into
23 | ``load()`` is shared between all templates. This makes it easy to have
24 | per-template parameters by calling:
25 |
26 | >>> params = MockParams.get(mock, MAIN_IFACE)
27 | >>> params.version = 1
28 |
29 | and later, inside a DBus method:
30 | >>> params = MockParams.get(self, MAIN_IFACE)
31 | >>> return params.version
32 | """
33 |
34 | @classmethod
35 | def get(cls, mock, interface_name):
36 | params = getattr(mock, "params", {})
37 | try:
38 | return params[interface_name]
39 | except KeyError:
40 | c = cls()
41 | params[interface_name] = c
42 | mock.params = params
43 | return c
44 |
45 |
46 | class Response(NamedTuple):
47 | response: int
48 | results: ASVType
49 |
50 |
51 | class Request:
52 | _token_counter = count()
53 |
54 | def __init__(
55 | self, bus_name: dbus.service.BusName, sender: str, options: Optional[ASVType]
56 | ):
57 | options = options or {}
58 | sender_token = sender.removeprefix(":").replace(".", "_")
59 | handle_token = options.get("handle_token", next(self._token_counter))
60 | self.sender = sender
61 | self.handle = (
62 | f"/org/freedesktop/portal/desktop/request/{sender_token}/{handle_token}"
63 | )
64 | self.mock = DBusMockObject(
65 | bus_name=bus_name,
66 | path=self.handle,
67 | interface="org.freedesktop.portal.Request",
68 | props={},
69 | )
70 | self.mock.AddMethod("", "Close", "", "", "self.RemoveObject(self.path)")
71 | logger.debug(f"Request created at {self.handle}")
72 |
73 | def respond(self, response: Response, delay: int = 0):
74 | def respond():
75 | logger.debug(f"Request.Response on {self.handle}: {response}")
76 | self.mock.EmitSignalDetailed(
77 | "",
78 | "Response",
79 | "ua{sv}",
80 | [dbus.UInt32(response.response), response.results],
81 | details={"destination": self.sender},
82 | )
83 |
84 | if delay > 0:
85 | GLib.timeout_add(delay, respond)
86 | else:
87 | respond()
88 |
89 |
90 | class Session:
91 | _token_counter = count()
92 |
93 | def __init__(
94 | self, bus_name: dbus.service.BusName, sender: str, options: Optional[ASVType]
95 | ):
96 | options = options or {}
97 | sender_token = sender.removeprefix(":").replace(".", "_")
98 | handle_token = options.get("session_handle_token", next(self._token_counter))
99 | self.sender = sender
100 | self.handle = (
101 | f"/org/freedesktop/portal/desktop/session/{sender_token}/{handle_token}"
102 | )
103 | self.mock = DBusMockObject(
104 | bus_name=bus_name,
105 | path=self.handle,
106 | interface="org.freedesktop.portal.Session",
107 | props={},
108 | )
109 | self.mock.AddMethod("", "Close", "", "", "self.RemoveObject(self.path)")
110 | logger.debug(f"Session created at {self.handle}")
111 |
112 | def close(self, details: ASVType, delay: int = 0):
113 | def respond():
114 | logger.debug(f"Session.Closed on {self.handle}: {details}")
115 | self.mock.EmitSignalDetailed(
116 | "", "Closed", "a{sv}", [details], details={"destination": self.sender}
117 | )
118 |
119 | if delay > 0:
120 | GLib.timeout_add(delay, respond)
121 | else:
122 | respond()
123 |
--------------------------------------------------------------------------------
/tests/pyportaltest/templates/notification.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from pyportaltest.templates import Request, Response, ASVType, MockParams
6 | from typing import Dict, List, Tuple, Iterator
7 |
8 | import dbus
9 | import dbus.service
10 | import logging
11 |
12 | logger = logging.getLogger(f"templates.{__name__}")
13 |
14 | BUS_NAME = "org.freedesktop.portal.Desktop"
15 | MAIN_OBJ = "/org/freedesktop/portal/desktop"
16 | SYSTEM_BUS = False
17 | MAIN_IFACE = "org.freedesktop.portal.Notification"
18 |
19 |
20 | def load(mock, parameters):
21 | logger.debug(f"loading {MAIN_IFACE} template")
22 |
23 | params = MockParams.get(mock, MAIN_IFACE)
24 | params.delay = 500
25 | params.version = parameters.get("version", 2)
26 | params.response = parameters.get("response", 0)
27 |
28 | mock.AddProperties(
29 | MAIN_IFACE,
30 | dbus.Dictionary({"version": dbus.UInt32(params.version)}),
31 | )
32 |
33 |
34 | @dbus.service.method(
35 | MAIN_IFACE,
36 | sender_keyword="sender",
37 | in_signature="sa{sv}",
38 | out_signature="",
39 | )
40 | def AddNotification(self, id, notification, sender):
41 | try:
42 | logger.debug(f"AddNotification: {id}, {notification}")
43 |
44 | except Exception as e:
45 | logger.critical(e)
46 |
--------------------------------------------------------------------------------
/tests/pyportaltest/templates/screencast.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from pyportaltest.templates import Request, Response, Session, ASVType, MockParams
6 | from typing import Dict, List, Tuple, Iterator
7 | from itertools import count
8 |
9 | import dbus
10 | import dbus.service
11 | import logging
12 | import socket
13 |
14 | logger = logging.getLogger(f"templates.{__name__}")
15 |
16 | BUS_NAME = "org.freedesktop.portal.Desktop"
17 | MAIN_OBJ = "/org/freedesktop/portal/desktop"
18 | SYSTEM_BUS = False
19 | MAIN_IFACE = "org.freedesktop.portal.ScreenCast"
20 |
21 | _restore_tokens = count()
22 |
23 |
24 | def load(mock, parameters):
25 | logger.debug(f"loading {MAIN_IFACE} template")
26 |
27 | params = MockParams.get(mock, MAIN_IFACE)
28 | params.delay = 500
29 | params.version = parameters.get("version", 4)
30 | params.response = parameters.get("response", 0)
31 | # streams returned in Start
32 | params.streams = parameters.get("streams", [])
33 | # persist_mode returned in Start
34 | params.persist_mode = parameters.get("persist-mode", 0)
35 | params.sessions: Dict[str, Session] = {}
36 |
37 | mock.AddProperties(
38 | MAIN_IFACE,
39 | dbus.Dictionary(
40 | {
41 | "version": dbus.UInt32(params.version),
42 | "AvailableSourceTypes": dbus.UInt32(
43 | parameters.get("source-types", 0b111)
44 | ),
45 | "AvailableCursorModes": dbus.UInt32(
46 | parameters.get("cursor-modes", 0b111)
47 | ),
48 | }
49 | ),
50 | )
51 |
52 |
53 | @dbus.service.method(
54 | MAIN_IFACE,
55 | sender_keyword="sender",
56 | in_signature="a{sv}",
57 | out_signature="o",
58 | )
59 | def CreateSession(self, options, sender):
60 | try:
61 | logger.debug(f"CreateSession: {options}")
62 | params = MockParams.get(self, MAIN_IFACE)
63 | request = Request(bus_name=self.bus_name, sender=sender, options=options)
64 |
65 | session = Session(bus_name=self.bus_name, sender=sender, options=options)
66 | params.sessions[session.handle] = session
67 |
68 | response = Response(params.response, {})
69 |
70 | request.respond(response, delay=params.delay)
71 |
72 | return request.handle
73 | except Exception as e:
74 | logger.critical(e)
75 |
76 |
77 | @dbus.service.method(
78 | MAIN_IFACE,
79 | sender_keyword="sender",
80 | in_signature="oa{sv}",
81 | out_signature="o",
82 | )
83 | def SelectSources(self, session_handle, options, sender):
84 | try:
85 | logger.debug(f"SelectSources: {session_handle} {options}")
86 | params = MockParams.get(self, MAIN_IFACE)
87 | request = Request(bus_name=self.bus_name, sender=sender, options=options)
88 |
89 | response = Response(params.response, {})
90 |
91 | request.respond(response, delay=params.delay)
92 |
93 | return request.handle
94 | except Exception as e:
95 | logger.critical(e)
96 |
97 |
98 | @dbus.service.method(
99 | MAIN_IFACE,
100 | sender_keyword="sender",
101 | in_signature="osa{sv}",
102 | out_signature="o",
103 | )
104 | def Start(self, session_handle, parent_window, options, sender):
105 | try:
106 | logger.debug(f"Start: {session_handle} {options}")
107 | params = MockParams.get(self, MAIN_IFACE)
108 | request = Request(bus_name=self.bus_name, sender=sender, options=options)
109 |
110 | results = {
111 | "streams": params.streams,
112 | }
113 |
114 | if params.version >= 4:
115 | results["persist_mode"] = dbus.UInt32(params.persist_mode)
116 | if params.persist_mode != 0:
117 | results["restore_token"] = f"restore_token{next(_restore_tokens)}"
118 |
119 | response = Response(params.response, results)
120 |
121 | request.respond(response, delay=params.delay)
122 |
123 | return request.handle
124 | except Exception as e:
125 | logger.critical(e)
126 |
127 |
128 | @dbus.service.method(
129 | MAIN_IFACE,
130 | sender_keyword="sender",
131 | in_signature="oa{sv}",
132 | out_signature="h",
133 | )
134 | def OpenPipeWireRemote(self, session_handle, options, sender):
135 | try:
136 | logger.debug(f"OpenPipeWireRemote: {session_handle} {options}")
137 |
138 | # libportal doesn't care about the socket, so let's use something we
139 | # can easily check
140 | sockets = socket.socketpair()
141 |
142 | pw_socket = sockets[0]
143 | pw_socket.send(b"I AM GROO^WPIPEWIRE")
144 |
145 | fd = sockets[1]
146 |
147 | logger.debug(f"OpenPipeWireRemote with fd {fd.fileno()}")
148 |
149 | return dbus.types.UnixFd(fd)
150 | except Exception as e:
151 | logger.critical(e)
152 |
--------------------------------------------------------------------------------
/tests/pyportaltest/templates/wallpaper.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from pyportaltest.templates import Request, Response, ASVType, MockParams
6 | from typing import Dict, List, Tuple, Iterator
7 |
8 | import dbus
9 | import dbus.service
10 | import logging
11 |
12 | logger = logging.getLogger(f"templates.{__name__}")
13 |
14 | BUS_NAME = "org.freedesktop.portal.Desktop"
15 | MAIN_OBJ = "/org/freedesktop/portal/desktop"
16 | SYSTEM_BUS = False
17 | MAIN_IFACE = "org.freedesktop.portal.Wallpaper"
18 |
19 |
20 | def load(mock, parameters):
21 | logger.debug(f"loading {MAIN_IFACE} template")
22 |
23 | params = MockParams.get(mock, MAIN_IFACE)
24 | params.delay = 500
25 | params.response = parameters.get("response", 0)
26 |
27 | mock.AddProperties(
28 | MAIN_IFACE,
29 | dbus.Dictionary({"version": dbus.UInt32(parameters.get("version", 1))}),
30 | )
31 |
32 |
33 | @dbus.service.method(
34 | MAIN_IFACE,
35 | sender_keyword="sender",
36 | in_signature="ssa{sv}",
37 | out_signature="o",
38 | )
39 | def SetWallpaperURI(self, parent_window, uri, options, sender):
40 | try:
41 | logger.debug(f"SetWallpaperURI: {parent_window}, {uri}, {options}")
42 | params = MockParams.get(self, MAIN_IFACE)
43 | request = Request(bus_name=self.bus_name, sender=sender, options=options)
44 |
45 | response = Response(params.response, {})
46 |
47 | request.respond(response, delay=params.delay)
48 |
49 | return request.handle
50 | except Exception as e:
51 | logger.critical(e)
52 |
--------------------------------------------------------------------------------
/tests/pyportaltest/test_wallpaper.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: LGPL-3.0-only
2 | #
3 | # This file is formatted with Python Black
4 |
5 | from . import PortalTest
6 |
7 | import gi
8 | import logging
9 |
10 | gi.require_version("Xdp", "1.0")
11 | from gi.repository import GLib, Xdp
12 |
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | class TestWallpaper(PortalTest):
17 | def test_version(self):
18 | self.assert_version_eq(1)
19 |
20 | def set_wallpaper(
21 | self, uri_to_set: str, set_on: Xdp.WallpaperFlags, show_preview: bool
22 | ):
23 | params = {}
24 | self.setup_daemon(params)
25 |
26 | xdp = Xdp.Portal.new()
27 | assert xdp is not None
28 |
29 | flags = {
30 | "background": Xdp.WallpaperFlags.BACKGROUND,
31 | "lockscreen": Xdp.WallpaperFlags.LOCKSCREEN,
32 | "both": Xdp.WallpaperFlags.BACKGROUND | Xdp.WallpaperFlags.LOCKSCREEN,
33 | }[set_on]
34 |
35 | if show_preview:
36 | flags |= Xdp.WallpaperFlags.PREVIEW
37 |
38 | wallpaper_was_set = False
39 |
40 | def set_wallpaper_done(portal, task, data):
41 | nonlocal wallpaper_was_set
42 | wallpaper_was_set = portal.set_wallpaper_finish(task)
43 | self.mainloop.quit()
44 |
45 | xdp.set_wallpaper(
46 | parent=None,
47 | uri=uri_to_set,
48 | flags=flags,
49 | cancellable=None,
50 | callback=set_wallpaper_done,
51 | data=None,
52 | )
53 |
54 | self.mainloop.run()
55 |
56 | method_calls = self.mock_interface.GetMethodCalls("SetWallpaperURI")
57 | assert len(method_calls) == 1
58 | timestamp, args = method_calls.pop(0)
59 | parent, uri, options = args
60 | assert uri == uri_to_set
61 | assert options["set-on"] == set_on
62 | assert options["show-preview"] == show_preview
63 |
64 | assert wallpaper_was_set
65 |
66 | def test_set_wallpaper_background(self):
67 | self.set_wallpaper("https://background.nopreview", "background", False)
68 |
69 | def test_set_wallpaper_background_preview(self):
70 | self.set_wallpaper("https://background.preview", "background", True)
71 |
72 | def test_set_wallpaper_lockscreen(self):
73 | self.set_wallpaper("https://lockscreen.nopreview", "lockscreen", False)
74 |
75 | def test_set_wallpaper_lockscreen_preview(self):
76 | self.set_wallpaper("https://lockscreen.preview", "lockscreen", True)
77 |
78 | def test_set_wallpaper_both(self):
79 | self.set_wallpaper("https://both.nopreview", "both", False)
80 |
81 | def test_set_wallpaper_both_preview(self):
82 | self.set_wallpaper("https://both.preview", "both", True)
83 |
84 | def test_set_wallpaper_cancel(self):
85 | params = {"response": 1}
86 | self.setup_daemon(params)
87 |
88 | xdp = Xdp.Portal.new()
89 | assert xdp is not None
90 |
91 | flags = Xdp.WallpaperFlags.BACKGROUND
92 |
93 | wallpaper_was_set = False
94 |
95 | def set_wallpaper_done(portal, task, data):
96 | nonlocal wallpaper_was_set
97 | try:
98 | wallpaper_was_set = portal.set_wallpaper_finish(task)
99 | except GLib.GError:
100 | pass
101 | self.mainloop.quit()
102 |
103 | xdp.set_wallpaper(
104 | parent=None,
105 | uri="https://ignored.anyway",
106 | flags=flags,
107 | cancellable=None,
108 | callback=set_wallpaper_done,
109 | data=None,
110 | )
111 |
112 | self.mainloop.run()
113 |
114 | method_calls = self.mock_interface.GetMethodCalls("SetWallpaperURI")
115 | assert len(method_calls) == 1
116 |
117 | assert not wallpaper_was_set
118 |
--------------------------------------------------------------------------------
/tests/qt5/meson.build:
--------------------------------------------------------------------------------
1 | add_languages('cpp', required : true, native : false)
2 |
3 | qt5_dep = dependency('qt5', modules: ['Core', 'Test'])
4 |
5 | src = [
6 | 'test.cpp',
7 | 'test.h',
8 | ]
9 |
10 | prep = qt5.preprocess(
11 | moc_headers : 'test.h',
12 | moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
13 | dependencies: qt5_dep,
14 | )
15 |
16 | exe = executable('qt5-test',
17 | [src, prep],
18 | include_directories: [top_inc, libportal_inc],
19 | dependencies: [qt5_dep, libportal_qt5_dep],
20 | cpp_args : '-std=c++11',
21 | )
22 |
23 | test('Qt 5 unit test', exe)
24 |
--------------------------------------------------------------------------------
/tests/qt5/test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Jan Grulich
3 | * Copyright (C) 2024 GNOME Foundation, Inc.
4 | *
5 | * This file is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as
7 | * published by the Free Software Foundation, version 3.0 of the
8 | * License.
9 | *
10 | * This file is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this program. If not, see .
17 | *
18 | * SPDX-License-Identifier: LGPL-3.0-only
19 | */
20 |
21 | #include "test.h"
22 |
23 | #undef signals
24 | #include "portal-qt5.h"
25 | #define signals Q_SIGNALS
26 |
27 | #include
28 | #include
29 |
30 | void Test::testFileChooserPortal()
31 | {
32 | XdpQt::FileChooserFilterRule rule;
33 | rule.type = XdpQt::FileChooserFilterRuleType::Mimetype;
34 | rule.rule = QStringLiteral("image/jpeg");
35 |
36 | XdpQt::FileChooserFilter filter;
37 | filter.label = QStringLiteral("Images");
38 | filter.rules << rule;
39 |
40 | g_autoptr(GVariant) filterVar = XdpQt::filechooserFiltersToGVariant({filter});
41 | const QString expectedFilterVarStr = QStringLiteral("[('Images', [(1, 'image/jpeg')])]");
42 | g_autofree char *variantStr = g_variant_print(filterVar, false);
43 | const QString filterVarStr = variantStr;
44 | QCOMPARE(expectedFilterVarStr, filterVarStr);
45 |
46 | XdpQt::FileChooserFilterRule rule2;
47 | rule2.type = XdpQt::FileChooserFilterRuleType::Pattern;
48 | rule2.rule = QStringLiteral("*.png");
49 | filter.rules << rule2;
50 |
51 | g_autoptr(GVariant) filterVar2 = XdpQt::filechooserFiltersToGVariant({filter});
52 | const QString expectedFilterVarStr2 = "[('Images', [(1, 'image/jpeg'), (0, '*.png')])]";
53 | g_autofree char *variantStr2 = g_variant_print(filterVar2, false);
54 | const QString filterVarStr2 = variantStr2;
55 | QCOMPARE(expectedFilterVarStr2, filterVarStr2);
56 |
57 | XdpQt::FileChooserChoice choice;
58 | choice.id = QStringLiteral("choice-id");
59 | choice.label = QStringLiteral("choice-label");
60 | choice.options.insert(QStringLiteral("option1-id"), QStringLiteral("option1-value"));
61 | choice.options.insert(QStringLiteral("option2-id"), QStringLiteral("option2-value"));
62 | choice.selected = QStringLiteral("option1-id");
63 |
64 | g_autoptr(GVariant) choiceVar = XdpQt::filechooserChoicesToGVariant({choice});
65 | const QString expectedChoiceVarStr = "[('choice-id', 'choice-label', [('option1-id', 'option1-value'), ('option2-id', 'option2-value')], 'option1-id')]";
66 | g_autofree char *variantChoiceStr = g_variant_print(choiceVar, false);
67 | const QString choiceVarStr = variantChoiceStr;
68 | QCOMPARE(expectedChoiceVarStr, choiceVarStr);
69 | }
70 |
71 | void Test::testNotificationPortal()
72 | {
73 | XdpQt::NotificationButton button;
74 | button.label = QStringLiteral("Some label");
75 | button.action = QStringLiteral("Some action");
76 |
77 | XdpQt::Notification notification;
78 | notification.title = QStringLiteral("Test notification");
79 | notification.body = QStringLiteral("Testing notification portal");
80 | notification.icon = QStringLiteral("applications-development");
81 | notification.buttons << button;
82 |
83 | g_autoptr(GVariant) notificationVar = XdpQt::notificationToGVariant(notification);
84 | const QString expectedNotificationVarStr = "{'title': <'Test notification'>, 'body': <'Testing notification portal'>, 'icon': <('themed', <['applications-development', 'applications-development-symbolic']>)>, 'buttons': <[{'label': <'Some label'>, 'action': <'Some action'>}]>}";
85 | g_autofree char *variantStr = g_variant_print(notificationVar, false);
86 | const QString notificationStr = variantStr;
87 | QCOMPARE(expectedNotificationVarStr, notificationStr);
88 | }
89 |
90 |
91 | QTEST_GUILESS_MAIN(Test)
92 |
--------------------------------------------------------------------------------
/tests/qt5/test.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Jan Grulich
3 | *
4 | * This file is free software; you can redistribute it and/or modify it
5 | * under the terms of the GNU Lesser General Public License as
6 | * published by the Free Software Foundation, version 3.0 of the
7 | * License.
8 | *
9 | * This file is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see .
16 | *
17 | * SPDX-License-Identifier: LGPL-3.0-only
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | class Test : public QObject
25 | {
26 | Q_OBJECT
27 | private Q_SLOTS:
28 | void testFileChooserPortal();
29 | void testNotificationPortal();
30 | };
31 |
--------------------------------------------------------------------------------
/tests/qt6/meson.build:
--------------------------------------------------------------------------------
1 | add_languages('cpp', required : true, native : false)
2 |
3 | qt6_dep = dependency('qt6', modules: ['Core', 'Test'])
4 |
5 | src = [
6 | 'test.cpp',
7 | 'test.h',
8 | ]
9 |
10 | prep = qt6.preprocess(
11 | moc_headers : 'test.h',
12 | moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
13 | dependencies: qt6_dep,
14 | )
15 |
16 | exe = executable('qt6-test',
17 | [src, prep],
18 | include_directories: [top_inc, libportal_inc],
19 | dependencies: [qt6_dep, libportal_qt6_dep],
20 | cpp_args : '-std=c++17',
21 | )
22 |
23 | test('Qt 6 unit test', exe)
24 |
--------------------------------------------------------------------------------
/tests/qt6/test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Jan Grulich
3 | * Copyright (C) 2023, Neal Gompa
4 | * Copyright (C) 2024 GNOME Foundation, Inc.
5 | *
6 | * This file is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as
8 | * published by the Free Software Foundation, version 3.0 of the
9 | * License.
10 | *
11 | * This file is distributed in the hope that it will be useful, but
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this program. If not, see .
18 | *
19 | * SPDX-License-Identifier: LGPL-3.0-only
20 | */
21 |
22 | #include "test.h"
23 |
24 | #undef signals
25 | #include "portal-qt6.h"
26 | #define signals Q_SIGNALS
27 |
28 | #include
29 | #include
30 |
31 | void Test::testFileChooserPortal()
32 | {
33 | XdpQt::FileChooserFilterRule rule;
34 | rule.type = XdpQt::FileChooserFilterRuleType::Mimetype;
35 | rule.rule = QStringLiteral("image/jpeg");
36 |
37 | XdpQt::FileChooserFilter filter;
38 | filter.label = QStringLiteral("Images");
39 | filter.rules << rule;
40 |
41 | g_autoptr(GVariant) filterVar = XdpQt::filechooserFiltersToGVariant({filter});
42 | const QString expectedFilterVarStr = QStringLiteral("[('Images', [(1, 'image/jpeg')])]");
43 | g_autofree char *variantFilterStr = g_variant_print(filterVar, false);
44 | const QString filterVarStr = variantFilterStr;
45 | QCOMPARE(expectedFilterVarStr, filterVarStr);
46 |
47 | XdpQt::FileChooserFilterRule rule2;
48 | rule2.type = XdpQt::FileChooserFilterRuleType::Pattern;
49 | rule2.rule = QStringLiteral("*.png");
50 | filter.rules << rule2;
51 |
52 | g_autoptr(GVariant) filterVar2 = XdpQt::filechooserFiltersToGVariant({filter});
53 | const QString expectedFilterVarStr2 = "[('Images', [(1, 'image/jpeg'), (0, '*.png')])]";
54 | g_autofree char *variantFilterStr2 = g_variant_print(filterVar2, false);
55 | const QString filterVarStr2 = variantFilterStr2;
56 | QCOMPARE(expectedFilterVarStr2, filterVarStr2);
57 |
58 | XdpQt::FileChooserChoice choice;
59 | choice.id = QStringLiteral("choice-id");
60 | choice.label = QStringLiteral("choice-label");
61 | choice.options.insert(QStringLiteral("option1-id"), QStringLiteral("option1-value"));
62 | choice.options.insert(QStringLiteral("option2-id"), QStringLiteral("option2-value"));
63 | choice.selected = QStringLiteral("option1-id");
64 |
65 | g_autoptr(GVariant) choiceVar = XdpQt::filechooserChoicesToGVariant({choice});
66 | const QString expectedChoiceVarStr = "[('choice-id', 'choice-label', [('option1-id', 'option1-value'), ('option2-id', 'option2-value')], 'option1-id')]";
67 | g_autofree char *variantChoiceStr = g_variant_print(choiceVar, false);
68 | const QString choiceVarStr = variantChoiceStr;
69 | QCOMPARE(expectedChoiceVarStr, choiceVarStr);
70 | }
71 |
72 | void Test::testNotificationPortal()
73 | {
74 | XdpQt::NotificationButton button;
75 | button.label = QStringLiteral("Some label");
76 | button.action = QStringLiteral("Some action");
77 |
78 | XdpQt::Notification notification;
79 | notification.title = QStringLiteral("Test notification");
80 | notification.body = QStringLiteral("Testing notification portal");
81 | notification.icon = QStringLiteral("applications-development");
82 | notification.buttons << button;
83 |
84 | g_autoptr(GVariant) notificationVar = XdpQt::notificationToGVariant(notification);
85 | const QString expectedNotificationVarStr = "{'title': <'Test notification'>, 'body': <'Testing notification portal'>, 'icon': <('themed', <['applications-development', 'applications-development-symbolic']>)>, 'buttons': <[{'label': <'Some label'>, 'action': <'Some action'>}]>}";
86 | g_autofree char *variantStr = g_variant_print(notificationVar, false);
87 | const QString notificationStr = variantStr;
88 | QCOMPARE(expectedNotificationVarStr, notificationStr);
89 | }
90 |
91 |
92 | QTEST_GUILESS_MAIN(Test)
93 |
--------------------------------------------------------------------------------
/tests/qt6/test.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022, Jan Grulich
3 | * Copyright (C) 2023, Neal Gompa
4 | *
5 | * This file is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as
7 | * published by the Free Software Foundation, version 3.0 of the
8 | * License.
9 | *
10 | * This file is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this program. If not, see .
17 | *
18 | * SPDX-License-Identifier: LGPL-3.0-only
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | class Test : public QObject
26 | {
27 | Q_OBJECT
28 | private Q_SLOTS:
29 | void testFileChooserPortal();
30 | void testNotificationPortal();
31 | };
32 |
--------------------------------------------------------------------------------