init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M6.662 4.586a1.143 1.143 0 00-.838.334l-.531.531c-.458.458-.442 1.21.037 1.69l2.873 2.87-2.873 2.874c-.479.479-.495 1.231-.037 1.69l.531.53c.458.458 1.213.442 1.692-.037l4.068-4.07a1.22 1.22 0 00.348-.986 1.22 1.22 0 00-.348-.985l-4.068-4.07a1.249 1.249 0 00-.854-.371z" fill="#9a9996"/></svg>

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="toc_bullet.svg"
inkscape:version="1.1-beta1 (77e7b44db3, 2021-03-28)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
objecttolerance="10.0"
gridtolerance="10.0"
guidetolerance="10.0"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="true"
inkscape:current-layer="svg4">
<inkscape:grid
type="xygrid"
id="grid49" />
</sodipodi:namedview>
<path
id="path2"
sodipodi:type="inkscape:offset"
inkscape:radius="-0.81220347"
inkscape:original="M 6.6621094 4.5859375 A 1.143 1.143 0 0 0 5.8242188 4.9199219 L 5.2929688 5.4511719 C 4.8349687 5.9091719 4.8510781 6.660625 5.3300781 7.140625 L 8.203125 10.011719 L 5.3300781 12.884766 C 4.8510781 13.363766 4.8349688 14.115219 5.2929688 14.574219 L 5.8242188 15.105469 C 6.2822188 15.563469 7.036625 15.547359 7.515625 15.068359 L 11.583984 10.998047 A 1.22 1.22 0 0 0 11.931641 10.011719 A 1.22 1.22 0 0 0 11.583984 9.0273438 L 7.515625 4.9570312 A 1.249 1.249 0 0 0 6.6621094 4.5859375 z "
d="m 6.6386719,5.3984375 c -0.088798,-0.00181 -0.1773948,0.032925 -0.2402344,0.095703 l -0.53125,0.53125 C 5.7300188,6.1625593 5.7182537,6.3799747 5.9042969,6.5664062 L 8.7773438,9.4375 a 0.81228469,0.81228469 0 0 1 0,1.148438 L 5.9042969,13.458984 C 5.719186,13.644095 5.7289844,13.861495 5.8671875,14 l 0.53125,0.53125 c 0.135934,0.135934 0.3590378,0.146822 0.5429687,-0.03711 l 4.0664058,-4.06836 0.002,-0.002 c 0.08366,-0.0854 0.125702,-0.209206 0.113281,-0.328125 a 0.81228469,0.81228469 0 0 1 0,-0.1679686 c 0.01222,-0.1187076 -0.0298,-0.2409206 -0.113281,-0.3261719 l -0.002,-0.00195 L 6.9414062,5.53125 A 0.81228469,0.81228469 0 0 1 6.9375,5.5273438 C 6.8598316,5.4486568 6.7511214,5.4020564 6.640625,5.3984375 Z"
style="fill:#deddda" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,452 @@
/* XDG CSS theme for Sphinx + Furo
https://www.sphinx-doc.org
https://pypi.org/project/furo/
*/
/* FONTS */
@font-face {
font-family: "Inter var";
font-weight: 100 900;
font-display: swap;
font-style: normal;
font-named-instance: "Regular";
src: url("inter.woff2") format("woff2");
}
:root {
--rounded-corner: 12px;
--blue1: rgb(153,193,241);
--blue2: rgb(98,160,234);
--blue3: rgb(53,132,228);
--blue4: rgb(28,113,216);
--blue5: rgb(26,95,180);
--green1: rgb(143,240,164);
--green2: rgb(87,227,137);
--green3: rgb(51,209,122);
--green4: rgb(46,194,126);
--green5: rgb(38,162,105);
--yellow1: rgb(249,240,107);
--yellow2: rgb(248,228,92);
--yellow3: rgb(246,211,45);
--yellow4: rgb(245,194,17);
--yellow5: rgb(229,165,10);
--orange1: rgb(255,190,111);
--orange2: rgb(255,163,72);
--orange3: rgb(255,120,0);
--orange4: rgb(230,97,0);
--orange5: rgb(198,70,0);
--red1: rgb(246,97,81);
--red2: rgb(237,51,59);
--red3: rgb(224,27,36);
--red4: rgb(192,28,40);
--red5: rgb(165,29,45);
--purple1: rgb(220,138,221);
--purple2: rgb(192,97,203);
--purple3: rgb(145,65,172);
--purple4: rgb(129,61,156);
--purple5: rgb(97,53,131);
--brown1: rgb(205,171,143);
--brown2: rgb(181,131,90);
--brown3: rgb(152,106,68);
--brown4: rgb(134,94,60);
--brown5: rgb(99,69,44);
--light1: rgb(255,255,255);
--light2: rgb(246,245,244);
--light3: rgb(222,221,218);
--light4: rgb(192,191,188);
--light5: rgb(154,153,150);
--dark1: rgb(119,118,123);
--dark2: rgb(94,92,100);
--dark3: rgb(61,56,70);
--dark4: rgb(36,31,49);
--dark5: rgb(0,0,0);
--text: #f6f5f4;
--tocbg: var(--light2);
--tocfg: var(--dark3);
--borders: var(--light3);
--link: var(--blue5);
--link-underline: var(--blue1);
}
::selection {
background-color: rgba(153,193,241,0.5);
}
@media (prefers-color-scheme: dark) {
:root {
--tocbg: var(--dark5);
--tocfg: var(--light5);
--borders: var(--dark3);
--link: var(--blue1);
--link-underline: var(--blue5);
}
::selection {
background-color: rgba(26,95,180,0.4);
}
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
font-size: 16px;
font-family: "Inter var", sans-serif;
font-weight: 400;
line-height: 1.6;
}
@media (min-width: 700px) {
html, body {
font-size: 18px;
}
}
a {
color: var(--link);
text-decoration-color: var(--link-underline);
}
p strong {
font-weight: 600;
opacity: 0.9;
}
h1 {
font-weight: 500;
font-size: 2rem;
margin-top: '0';
margin-bottom: 1.5rem;
font-family: "Inter var", sans-serif;
}
h2 {
font-weight: 800;
font-size: 1.7rem;
margin-top: 2.5rem;
margin-bottom: 1.2rem;
font-family: "Inter var", sans-serif;
}
h3 {
font-weight: 800;
font-size: 1.3rem;
margin-top: 2.2rem;
margin-bottom: 1rem;
font-family: "Inter var", sans-serif;
}
h4 {
font-weight: 700;
font-size: 1.1rem;
margin-top: 1rem;
margin-bottom: 1rem;
font-family: "Inter var", sans-serif;
}
h5 {
font-weight: 700;
font-size: 1rem;
margin-top: 1rem;
margin-bottom: 1rem;
font-family: "Inter var", sans-serif;
}
h2,h3,h4,h5 { opacity: 0.7; }
ul.simple {
margin: 1rem 1rem 3rem;
}
ul.simple li {
list-style-image: url(bullet.svg);
margin-inline-end: 1ch;
margin-bottom: 1rem;
}
ul.simple li:hover::marker { }
.related-pages {
font-size: 10pt;
font-weight: 800;
display: flex;
flex-direction: row-reverse;
align-items: stretch;
justify-content: space-between;
}
.related-pages a .title {
color: var(--dark1);
}
.related-pages a svg {
width: 32px; height: 32px;
}
.prev-page {
border-radius: 8px;
padding: 8px 24px 8px 8px;
}
.next-page {
border-radius: 8px;
padding: 8px 8px 8px 24px;
}
.related-pages a.prev-page,
.related-pages a.next-page {
float: none;
max-width: inherit; /* cancel furo's 50% */
}
.related-pages a.prev-page:hover, .related-pages a.next-page:hover {
background-color: var(--tocbg);
}
@media (min-width: 700px) {
.related-pages {
font-size: 14pt;
}
.prev-page {
padding: 16px 48px 16px 16px;
border-radius: 24px;
}
.next-page {
padding: 16px 16px 16px 48px;
border-radius: 24px;
}
}
.related-pages a.prev-page:only-child,
.related-pages a.next-page:only-child,
.page-info {
/* align-self: flex-end; i wish */
width: 100%; /* big buttons instead */
}
.toctree-wrapper ul {
margin: 0; padding: 0;
}
.toctree-wrapper li {
list-style: none;
margin: 0 0 1rem 0;
}
.toctree-wrapper li.toctree-l1 {
font-size: 14pt;
font-weight: 600;
}
.toctree-wrapper li.toctree-l1 > a { color: var(--tocfg); }
.toctree-wrapper li.toctree-l2 {
list-style-image: url(toc_bullet.svg);
margin: 0;
font-size: 12pt;
font-weight: 400;
padding: 0.2rem;
}
.toctree-wrapper > ul ul {
margin-top: 1rem;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
gap: .2rem;
}
.toctree-wrapper > ul ul a {
background-color: transparent;
}
/* tiled TOC with images */
ul.tiled-toc {
display: grid;
gap: 1rem;
grid-auto-flow: row;
margin: 1rem 0; padding: 0;
text-align: center;
margin-top: 2rem;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
ul.tiled-toc li {
display: block;
list-style: none;
}
ul.tiled-toc li img {
display: block;
width: 100%;
image-rendering: crisp-edges;
image-rendering: pixelated;
}
ul.tiled-toc li img::after {
content: "";
}
ul.tiled-toc a {
color: black;
text-decoration: none;
font-weight: 600;
}
@media (prefers-color-scheme: dark) {
ul.tiled-toc a { color: white; }
}
table.docutils {
font-size: 90%;
box-shadow: none;
border-collapse: collapse;
border-spacing: 0;
border-radius: 0;
text-align: left;
border-width: 0;
box-sizing: border-box;
}
/* reset crazy */
table.docutils th, table.docutils tr, table.docutils td {
background-color: transparent;
text-align: left;
}
table.docutils td, table.docutils th {
border-width: 0;
padding: .25rem;
}
table.docutils tr {
border-width: 0;
border-bottom: 1px solid var(--borders);
}
table.docutils thead tr {
font-weight: 800;
border-width: 0;
box-sizing: inherit;
border-bottom: 2px solid var(--borders);
}
.hig-palette-table.align-default {
display: table;
width: 100%;
}
img.hig-palette-swatch {
display: block;
width: 42px;
aspect-ratio: 1 / 1;
border-radius: 50%;
}
.hig-palette-table colgroup { display: none; }
.hig-palette-table .stub,
.hig-palette-table .head.stub {
width: 50px;
}
video {
width: 100%;
height: auto;
}
footer {
margin-bottom: 3rem;
}
.sidebar-drawer {
}
.sidebar-brand-text {
font-family: Cantarell, -apple-system, BlinkMacSystemFont, "Helvetica", sans-serif;
font-size: 14pt;
font-weight: 800;
}
.sidebar-search-container,
.sidebar-search {
border-radius: 99999px;
border: none;
}
.sidebar-search-container {
margin: 0 var(--sidebar-item-spacing-horizontal);
transition: background-color 0.2s linear;
background-color: rgba(0,0,0,0.06);
}
.sidebar-search-container:hover {
background-color: rgba(0,0,0,0.09);
}
.sidebar-search-container:focus-within {
background-color: rgba(0,0,0,0.12);
}
@media (prefers-color-scheme: dark) {
.sidebar-search-container {
background-color: rgba(255,255,255,0.06);
}
.sidebar-search-container:hover {
background-color: rgba(255,255,255,0.09);
}
.sidebar-search-container:focus-within {
background-color: rgba(255,255,255,0.12);
}
}
.sidebar-tree .toctree-l1,
.sidebar-tree .toctree-l2 {
margin: 1px 12px;
border-radius: 6px;
color: var(--link);
}
.sidebar-tree .toctree-l1 > .reference {
color: var(--link);
}
.sidebar-tree .toctree-l2 {
margin: 1px 0;
font-size: 90%;
text-wrap: balance;
overflow-wrap: break-word;
hyphens: manual;
}
.sidebar-tree li > ul {
margin-left: 0;
}
.sidebar-tree li > ul .reference {
padding-left: calc(1.5*var(--sidebar-item-spacing-horizontal));
}
.sidebar-tree label[for^="toctree-checkbox"] {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.sidebar-tree li.toctree-l3 a {
margin: 1px 0;
padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)
var(--sidebar-item-spacing-vertical) calc(2*var(--sidebar-item-spacing-horizontal)) ; /* extra indentation */
}
.sidebar-tree .reference {
background: rgba(0,0,0,0);
transition: background 0.2s linear;
border-radius: 6px;
padding: var(--sidebar-item-spacing-vertical) calc(0.75*var(--sidebar-item-spacing-horizontal));
}
.sidebar-tree .reference:hover,
.sidebar-tree .current > .reference:hover {
/* background: var(--color-background-hover); */
background: rgba(0,0,0,0.03);
}
.sidebar-tree .reference.current {
background: rgba(0,0,0,0.06);
}
.sidebar-tree .reference.current:hover {
background: rgba(0,0,0,0.09);
}
.sidebar-tree .current-page > .reference {
font-weight: 600;
}
.theme-toggle {
display: none; /* just go with auto */
}

View File

@@ -0,0 +1,69 @@
API Reference
=============
Portal interfaces are available to sandboxed applications with the default
filtered session bus access of Flatpak.
Desktop portals appear under the bus name ``org.freedesktop.portal.Desktop``
and the object path ``/org/freedesktop/portal/desktop`` on the session bus,
unless specified otherwise.
Apps running on the host system have access to a special interface for
registering themselves with XDG Desktop Portal. Registering a host app with
XDG Desktop Portal overwrites the automatic detection based on the
`XDG cgroup pathname standardization for applications
<https://systemd.io/DESKTOP_ENVIRONMENTS/#xdg-standardization-for-applications>`_.
This might improve the user experience when the host app was launched in a way
that doesn't follow the standard. See
:doc:`org.freedesktop.host.portal.Registry <doc-org.freedesktop.host.portal.Registry>`
Disclaimer: The host app registry is expected to eventually be deprecated and
may be removed. Applications should gracefully handle interface or method no
longer being available to be forward compatible. App launchers, or apps
themselves, should place the app in a cgroup named according to specific naming
conventions. When the host app registry becomes deprecated, the details of the
replacement will be documented in :doc:`org.freedesktop.host.portal.Registry
<doc-org.freedesktop.host.portal.Registry>`.
.. toctree::
:hidden:
doc-org.freedesktop.host.portal.Registry.rst
All apps have access to the portals below:
.. toctree::
:maxdepth: 1
doc-org.freedesktop.portal.Account.rst
doc-org.freedesktop.portal.Background.rst
doc-org.freedesktop.portal.Camera.rst
doc-org.freedesktop.portal.Clipboard.rst
doc-org.freedesktop.portal.Documents.rst
doc-org.freedesktop.portal.DynamicLauncher.rst
doc-org.freedesktop.portal.Email.rst
doc-org.freedesktop.portal.FileChooser.rst
doc-org.freedesktop.portal.FileTransfer.rst
doc-org.freedesktop.portal.GameMode.rst
doc-org.freedesktop.portal.GlobalShortcuts.rst
doc-org.freedesktop.portal.Inhibit.rst
doc-org.freedesktop.portal.InputCapture.rst
doc-org.freedesktop.portal.Location.rst
doc-org.freedesktop.portal.MemoryMonitor.rst
doc-org.freedesktop.portal.NetworkMonitor.rst
doc-org.freedesktop.portal.Notification.rst
doc-org.freedesktop.portal.OpenURI.rst
doc-org.freedesktop.portal.PowerProfileMonitor.rst
doc-org.freedesktop.portal.Print.rst
doc-org.freedesktop.portal.ProxyResolver.rst
doc-org.freedesktop.portal.Realtime.rst
doc-org.freedesktop.portal.RemoteDesktop.rst
doc-org.freedesktop.portal.Request.rst
doc-org.freedesktop.portal.ScreenCast.rst
doc-org.freedesktop.portal.Screenshot.rst
doc-org.freedesktop.portal.Secret.rst
doc-org.freedesktop.portal.Session.rst
doc-org.freedesktop.portal.Settings.rst
doc-org.freedesktop.portal.Trash.rst
doc-org.freedesktop.portal.Usb.rst
doc-org.freedesktop.portal.Wallpaper.rst

View File

@@ -0,0 +1,10 @@
Architecture
============
The pages under this section document the internal architecture of various parts
of XDG Desktop Portal.
.. toctree::
:maxdepth: 1
documents-and-fuse

View File

@@ -0,0 +1,89 @@
Building & Running
==================
Normally, XDG Desktop Portal runs as a user session service, initialized on
demand through D-Bus activation. It usually starts with the session though,
as many desktop environments try to talk to XDG Desktop Portal on startup.
XDG Desktop Portal initializes specific backends through D-Bus activation
as well.
Building
--------
To build XDG Desktop Portal, first make sure you have the build dependencies
installed through your distribution's package manager. With them installed,
run:
.. code-block:: shell
meson setup . _build
meson compile -C _build
Some distributions install portal configuration files in ``/usr``, while Meson
defaults to the prefix ``/usr/local``. If the portal configuration files in your
distribution are in ``/usr/share/xdg-desktop-portal/portals``, re-configure
Meson using ``meson setup --reconfigure . _build --prefix /usr`` and compile
again.
Running
-------
XDG Desktop Portal needs to own the D-Bus name and replace the user session
service that might already be running. To do so, run:
.. code-block:: shell
_build/src/xdg-desktop-portal --replace
If you are developing inside a ``toolbox`` container, you must use
``flatpak-spawn`` from ``flatpak-xdg-utils`` to run the service:
.. code-block:: shell
flatpak-spawn --host _build/src/xdg-desktop-portal --replace
You may need to restart backends after replacing XDG Desktop Portal (please
replace ``[name]`` with the backend name, e.g. ``gnome`` or ``kde`` or ``wlr``):
.. code-block:: shell
systemctl --user restart xdg-desktop-portal-[name].service
Testing
-------
To execute the test suite present in XDG Desktop Portal, run:
.. code-block:: shell
meson test -C _build
Enable the pre-commit hooks to catch issues early:
.. code-block:: shell
git config --local core.hooksPath .githooks/
When a branch is pushed to github, CI will also run tests in a few more
configurations.
Documentation
-------------
These instructions are for Fedora, where you will need these packages:
.. code-block::
sudo dnf install json-glib-devel fuse3-devel gdk-pixbuf2-devel pipewire-devel python3-sphinx flatpak-devel python3-furo python-sphinxext-opengraph python-sphinx-copybutton
Then you can build the website with:
.. code-block:: shell
meson setup . _build -Ddocumentation=enabled
ninja -C _build
Then just load the build website into a browser of your choice from
``_build/doc/html/index.html``

View File

@@ -0,0 +1,58 @@
Common Conventions
==================
XDG Desktop Portal uses D-Bus in a slightly uncommon way, due to the potentially
long-running nature of some of its requests. These different usage patterns are
documented in the pages below:
.. toctree::
:hidden:
terminology
requests
sessions
window-identifiers
icons
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Terminology-l.png
:target: terminology.html
:class: only-light
.. image:: _static/img/tiles/Terminology-d.png
:target: terminology.html
:class: only-dark
:doc:`Terminology </terminology>`
* .. image:: _static/img/tiles/Request-l.png
:target: requests.html
:class: only-light
.. image:: _static/img/tiles/Request-d.png
:target: requests.html
:class: only-dark
:doc:`Requests </requests>`
* .. image:: _static/img/tiles/Sessions-l.png
:target: sessions.html
:class: only-light
.. image:: _static/img/tiles/Sessions-d.png
:target: sessions.html
:class: only-dark
:doc:`Sessions </sessions>`
* .. image:: _static/img/tiles/Window-ids-l.png
:target: window-identifiers.html
:class: only-light
.. image:: _static/img/tiles/Window-ids-d.png
:target: window-identifiers.html
:class: only-dark
:doc:`Window Identifiers </window-identifiers>`
* .. image:: _static/img/tiles/Icons-l.png
:target: icons.html
:class: only-light
.. image:: _static/img/tiles/Icons-d.png
:target: icons.html
:class: only-dark
:doc:`Icons </icons>`

View File

@@ -0,0 +1,39 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = "XDG Desktop Portal"
copyright = "2023-2025, XDG Desktop Portal authors"
author = "XDG Desktop Portal authors"
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
html_favicon = "favicon.ico"
extensions = [
"sphinxext.opengraph",
"sphinx_copybutton",
]
templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "furo"
# add custom files that are stored in _static
html_css_files = ["xdg.css"]
html_static_path = ["_static"]
# -- Options for OpenGraph ---------------------------------------------------
ogp_site_url = "https://flatpak.github.io/xdg-desktop-portal/docs/"
ogp_image = "_static/card.png"
html_permalinks_icon = "🔗"

View File

@@ -0,0 +1,38 @@
Configuration File
==================
Portal backends are selected and can be configured by using one or more
configuration files.
Desktop systems may have multiple desktop environments and portal backends
installed in parallel, and automatically picking portal backends in this
situation has proven to be a challenge.
For this reason, XDG Desktop Portal uses a config-based matching system.
Usually, the configuration files are provided by the desktop environments
themselves, so that e.g. the GNOME-specific portal backends are picked in
GNOME sessions. No end user intervention is necessary in this case.
Here's an example of a config file distributed by GNOME:
.. code-block::
[preferred]
default=gnome;gtk;
org.freedesktop.impl.portal.Access=gnome-shell;gtk;
org.freedesktop.impl.portal.Secret=gnome-keyring;
This file specifies that, by default, the ``gnome`` and ``gtk`` portal backends
must be used. However, specifically for :doc:`org.freedesktop.impl.portal.Access
<doc-org.freedesktop.impl.portal.Access>`, the ``gnome-shell`` and ``gtk``
portal backends must be used; and for :doc:`org.freedesktop.impl.portal.Secret
<doc-org.freedesktop.impl.portal.Secret>`, the ``gnome-keyring`` portal
backend must be used.
You can read more about the config file syntax, install locations, and more, in
the portals.conf man page:
.. toctree::
:maxdepth: 1
portals.conf

View File

@@ -0,0 +1,19 @@
Convenience Libraries
=====================
Using the XDG Portals D-Bus APIs directly is often difficult and error-prone.
Fortunately, there are convenience libraries available that significantly ease
the development of apps:
* `ASHPD <https://bilelmoussaoui.github.io/ashpd/ashpd/>`_: a **Rust** crate that
provides the APIs to interact with portals in idiomatic Rust. It has support for
GTK4, direct X11 windows, and direct Wayland surfaces.
* `libportal <https://github.com/flatpak/libportal/>`_: small **C** library that
provides a GObject API to interact with portals. It provides language bindings
to a variety of other languages, such as **Python**, **JavaScript**, **Vala**,
and more. It has support for GTK3, GTK4, Qt 5, and Qt 6.
* `portal <https://github.com/rymdport/portal>`_: a **Go** module that provides
native APIs for interacting with portals from idiomatic Go code.
It aims to be both toolkit agnostic and easy to use.
* `xdg_desktop_portal <https://pub.dev/packages/xdg_desktop_portal>`_: a native
**Dart** package to interact with portals in **Dart** and **Flutter**.

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env python3
import os
import sys
import shutil
subdir = os.environ["MESON_SUBDIR"]
input_path = os.path.join(os.environ["MESON_SOURCE_ROOT"], subdir, sys.argv[1])
output_path = os.path.join(os.environ["MESON_BUILD_ROOT"], subdir, sys.argv[2])
os.makedirs(os.path.dirname(output_path), exist_ok=True)
shutil.copyfile(input_path, output_path)

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env python3
import os
import sys
import shutil
subdir = os.environ["MESON_SUBDIR"]
input_path = os.path.join(os.environ["MESON_SOURCE_ROOT"], subdir, sys.argv[1])
output_path = os.path.join(os.environ["MESON_BUILD_ROOT"], subdir, sys.argv[2])
os.makedirs(os.path.dirname(output_path), exist_ok=True)
shutil.copytree(input_path, output_path)

View File

@@ -0,0 +1,87 @@
Documents & FUSE
================
The Document portal exposes files (filesystem entries) to applications through
FUSE.
Files are scoped in a domain operations are restricted with a domain. The FUSE
filesystem will proxy the file access by referencing the inodes and presenting
the files in a virtual filesystem.
Much like with xdg-desktop-portal, to run the development version of
the Document portal, do:
.. code-block:: shell
_build/document-portal/xdg-document-portal --replace
FUSE
----
The Document portal is a separate executable, ``xdg-document-portal``, and it
implements the virtual filesystem using FUSE. The filesystem is mounted in the
user runtime ``doc`` directory. It usually is ``/run/user/[UID]/doc``, where
``[UID]`` is the user id on the system.
Inside the Flatpak sandbox, files for which the app has permission to access are
available at ``/run/flatpak/doc``.
Like any FUSE filesystem, it exposes inodes through the FUSE API.
Domains
"""""""
Domains specify the scope of an inode and organize the documents into
a hierarchy. It helps compartimentalize which documents the
applications have access to.
- ``XDP_DOMAIN_ROOT``: root domain.
- ``XDP_DOMAIN_BY_APP``: used to find app domains by app id.
- ``XDP_DOMAIN_APP``: contains the documents allowed for the app.
- ``XDP_DOMAIN_DOCUMENT``: a physical file or directory is a document
in the ``XDP_DOMAIN_DOCUMENT``.
The first three are considered to be virtual, which mean they are not
backed by a physical inode.
The Document portal defines a few globals to hold the inodes:
- ``root_inode`` is an inode that holds the root domain.
- ``by_app_inode`` is the inode for the by app domain.
- ``physical_inodes`` is a hash table for the physical inodes, the key
is ``devino``.
- ``all_inodes`` is a hash table for all the inodes, the key is the
inode number.
The domains are used to create the filesystem hierarchy presented by
the document portal through the FUSE filesystem. It looks like this:
.. code-block::
/
├─ by-app
│ ├─ org.foo.Bar
│ │ ├─ doc1
│ │ └─ doc3
│ └─ org.bar.Foo
│ ├─ doc2
│ └─ doc3
├─ doc1
├─ doc2
└─ doc3
``/`` is the root domain. ``by-app`` is the ``XDP_DOMAIN_BY_APP`` domain.
``org.foo.Bar`` and ``org.bar.Foo`` are application ids.
``doc1``, ``doc2``, ``doc3`` are unique identifiers for the documents. As
mentioned, they can be shared across apps.
Document identifiers are unique. They are created using the inode number of the
physical file or directory.
Custom xattrs
-------------
Files and folders mounted through the Document portal have a custom attribute
with the host system path: ``user.document-portal.host-path``. This attribute
is read-only and any attempt to modify it will result in an error.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python3
# This script massages the reStructuredText files generated by
# gdbus-codegen into something that's slightly more suitable for
# the online documentation of XDG Desktop Portal. It's not a
# general purpose script.
import os
import sys
output_dir = sys.argv[1]
filename_prefix = sys.argv[2]
inputs = sys.argv[3:]
def adjust_title(lines):
title = lines[3].strip()
if title.startswith("org.freedesktop.portal."):
adjusted_title = title.replace("org.freedesktop.portal.", "")
elif title.startswith("org.freedesktop.impl.portal"):
adjusted_title = title.replace("org.freedesktop.impl.portal.", "")
elif title.startswith("org.freedesktop.host.portal"):
adjusted_title = title.replace("org.freedesktop.host.portal.", "")
elif title.startswith("org.freedesktop.background.Monitor"):
adjusted_title = title.replace(
"org.freedesktop.background.Monitor", "Background Apps Monitor"
)
else:
adjusted_title = title
# CamelCase → Camel Case
if adjusted_title not in ["OpenURI", "ScreenCast"]:
adjusted_title = "".join(
map(lambda x: x if x.islower() else f" {x}", adjusted_title)
)
lines[3] = f"{adjusted_title}\n"
# Temporary fix for '.. {title}:' strings in the generated files. Should be
# removed after GLib 2.78.4 hits the CI images.
#
# See: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3751
def fix_title_template_string(lines):
for index, line in enumerate(lines):
if line.strip() == ".. _{title}:":
next_title = lines[index + 2].strip()
lines[index] = f".. _{next_title}:\n"
for file in inputs:
basename = os.path.basename(file)
fullpath = os.path.join(output_dir, f"{filename_prefix}-{basename}")
with open(fullpath) as f:
lines = f.readlines()
adjust_title(lines)
fix_title_template_string(lines)
with open(fullpath, "w") as f:
f.writelines(lines)

View File

@@ -0,0 +1,50 @@
For App Developers
==================
XDG Desktop Portal is a session service that provides D-Bus interfaces for apps
to interact with the desktop.
Portal interfaces can be used by sandboxed and unsandboxed apps alike, but
sandboxed apps benefit the most since they don't need special permissions to use
portal APIs. XDG Desktop Portal safeguards many resources and features with a
user-controlled permission system.
The primary goal of portals is to expose common functionality and integration
with the desktop without requiring apps to write desktop-specific code, or
loosen their sandbox restrictions.
.. toctree::
:hidden:
reasons-to-use-portals
convenience-libraries
api-reference
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Reasons-l.png
:target: reasons-to-use-portals.html
:class: only-light
.. image:: _static/img/tiles/Reasons-d.png
:target: reasons-to-use-portals.html
:class: only-dark
:doc:`Reasons to Use Portals </reasons-to-use-portals>`
* .. image:: _static/img/tiles/Libraries-l.png
:target: convenience-libraries.html
:class: only-light
.. image:: _static/img/tiles/Libraries-d.png
:target: convenience-libraries.html
:class: only-dark
:doc:`Convenience Libraries </convenience-libraries>`
* .. image:: _static/img/tiles/APIs-l.png
:target: api-reference.html
:class: only-light
.. image:: _static/img/tiles/APIs-d.png
:target: api-reference.html
:class: only-dark
:doc:`API Reference </api-reference>`

View File

@@ -0,0 +1,48 @@
For Contributors
================
Thanks for your interest in contributing to XDG Desktop Portal!
XDG Desktop Portal is a D-Bus oriented, security-sensitive service,
as it mediates the interactions between sandboxed apps and the host
system.
In the sections below you will find information about how to start
contributing to XDG Desktop Portal, the expected coding and code
submission practices, as well as internal documentation about
more complex parts of XDG Desktop Portal.
.. toctree::
:hidden:
building-and-running
pull-requests
architecture
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Building-running-l.png
:target: building-and-running.html
:class: only-light
.. image:: _static/img/tiles/Building-running-d.png
:target: building-and-running.html
:class: only-dark
:doc:`Building and Running </building-and-running>`
* .. image:: _static/img/tiles/Pull-request-l.png
:target: pull-requests.html
:class: only-light
.. image:: _static/img/tiles/Pull-request-d.png
:target: pull-requests.html
:class: only-dark
:doc:`Pull Requests </pull-requests>`
* .. image:: _static/img/tiles/Architecture-l.png
:target: architecture.html
:class: only-light
.. image:: _static/img/tiles/Architecture-d.png
:target: architecture.html
:class: only-dark
:doc:`Architecture </architecture>`

View File

@@ -0,0 +1,102 @@
For Desktop Developers
======================
The separation of the portal infrastructure into frontend and backend is a clean
way to provide suitable user interfaces that fit into different desktop
environments, while sharing the portal frontend.
The portal backends are focused on providing user interfaces and accessing
session- or host-specific APIs and resources. Details of interacting with the
containment infrastructure such as checking access, registering files in the
Document portal, etc., are handled by the portal frontend.
Portal backends can be layered together. For example, in a GNOME session, most
portal backend interfaces are implemented by the GNOME portal backend, but
the :doc:`org.freedesktop.impl.portal.Access <doc-org.freedesktop.impl.portal.Access>`
interface is implemented by GNOME Shell.
.. toctree::
:hidden:
writing-a-new-backend
configuration-file
system-integration
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Backend-l.png
:target: writing-a-new-backend.html
:class: only-light
.. image:: _static/img/tiles/Backend-d.png
:target: writing-a-new-backend.html
:class: only-dark
:doc:`Writing a New Backend </writing-a-new-backend>`
* .. image:: _static/img/tiles/Config-l.png
:target: configuration-file.html
:class: only-light
.. image:: _static/img/tiles/Config-d.png
:target: configuration-file.html
:class: only-dark
:doc:`Configuration File </configuration-file>`
* .. image:: _static/img/tiles/System-integration-l.png
:target: system-integration.html
:class: only-light
.. image:: _static/img/tiles/System-integration-d.png
:target: system-integration.html
:class: only-dark
:doc:`System Integration </system-integration>`
D-Bus Interfaces
----------------
Portal backends must implement one or more backend D-Bus interfaces. The list of
D-Bus interfaces can be found below:
.. toctree::
:hidden:
impl-dbus-interfaces
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Dbus-l.png
:target: impl-dbus-interfaces.html
:class: only-light
.. image:: _static/img/tiles/Dbus-d.png
:target: impl-dbus-interfaces.html
:class: only-dark
:doc:`Backend D-BUS Interfaces </impl-dbus-interfaces>`
Background Apps Monitor
-----------------------
In addition to managing the regular interfaces that sandboxed applications
use to interfact with the host system, XDG Desktop Portal also monitors
running applications without an active window - if the portal backend
provides an implementation of the Background portal.
This API can be used by host system services to provide rich interfaces to
manage background running applications.
.. toctree::
:hidden:
doc-org.freedesktop.background.Monitor.rst
.. cssclass:: tiled-toc
* .. image:: _static/img/tiles/Bmon-l.png
:target: doc-org.freedesktop.background.Monitor.html
:class: only-light
.. image:: _static/img/tiles/Bmon-d.png
:target: doc-org.freedesktop.background.Monitor.html
:class: only-dark
:doc:`Background Apps Monitor </doc-org.freedesktop.background.Monitor>`

View File

@@ -0,0 +1,14 @@
Icons
========
Some portal APIs accept Icon image data either as bytes or memfd sealed file descriptors.
These icons must pass validation by ``xdg-desktop-portal-validate-icon`` in order to be used
successfully. The requirements to pass validation are:
.. csv-table:: Icon Requirements
:header: "Icon Property", "Requirement", "Description"
"Shape", "Square", "All icons, whether PNG, JPEG, or SVG, must be square."
"Edge Length", "512 pixels", "For raster images, the maximum edge length is 512 pixels."
"SVG File Size", "4096 bytes", "For SVG images, the data describing the SVG must fit within 4096 bytes."
"Raster File Size", "4 MiB", "For raster images, the total data must fit within 4MB."

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,34 @@
Backend D-Bus Interfaces
========================
The backend interfaces are used by the portal frontend to carry out portal
requests. They are provided by a separate process (or processes), and are not
accessible to sandboxed applications.
.. toctree::
:maxdepth: 1
doc-org.freedesktop.impl.portal.Access.rst
doc-org.freedesktop.impl.portal.Account.rst
doc-org.freedesktop.impl.portal.AppChooser.rst
doc-org.freedesktop.impl.portal.Background.rst
doc-org.freedesktop.impl.portal.Clipboard.rst
doc-org.freedesktop.impl.portal.DynamicLauncher.rst
doc-org.freedesktop.impl.portal.Email.rst
doc-org.freedesktop.impl.portal.FileChooser.rst
doc-org.freedesktop.impl.portal.GlobalShortcuts.rst
doc-org.freedesktop.impl.portal.Inhibit.rst
doc-org.freedesktop.impl.portal.InputCapture.rst
doc-org.freedesktop.impl.portal.Lockdown.rst
doc-org.freedesktop.impl.portal.Notification.rst
doc-org.freedesktop.impl.portal.PermissionStore.rst
doc-org.freedesktop.impl.portal.Print.rst
doc-org.freedesktop.impl.portal.RemoteDesktop.rst
doc-org.freedesktop.impl.portal.Request.rst
doc-org.freedesktop.impl.portal.ScreenCast.rst
doc-org.freedesktop.impl.portal.Screenshot.rst
doc-org.freedesktop.impl.portal.Secret.rst
doc-org.freedesktop.impl.portal.Session.rst
doc-org.freedesktop.impl.portal.Settings.rst
doc-org.freedesktop.impl.portal.Usb.rst
doc-org.freedesktop.impl.portal.Wallpaper.rst

View File

@@ -0,0 +1,47 @@
.. XDG Desktop Portals documentation master file, created by
sphinx-quickstart on Thu Aug 24 16:58:13 2023.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. image:: _static/xdg-portal-light.png
:class: only-light
.. image:: _static/xdg-portal-dark.png
:class: only-dark
XDG Desktop Portal
==================
XDG Desktop Portal allow `Flatpak apps <http://www.flatpak.org>`_, and other desktop
containment frameworks, to interact with the system in a secure and well defined way.
This documentation covers everything you need to know to build apps that use portals,
write portal backends for your desktop environment, configure and distribute portals
as part of a distribution, as well as basic concepts and common conventions.
The documentation pages target primarily app developers, desktop developers, and
system distributors and administrators. The contents may also be relevant to those
who have a general interest in portals.
Content Overview
----------------
This documentation is made up of the following sections:
* :doc:`Common conventions <common-conventions>`: coding patterns and principles
common when **app and desktop developers** are working with portal APIs.
* :doc:`App Development <for-app-developers>`: portal APIs that **apps** can use
to interact with the host system.
* :doc:`Desktop Integration <for-desktop-developers>`: interfaces and
configuration files that **desktop developers** can implement and install in
order to write a portal backend.
* :doc:`Contributing <for-contributors>`: how **contributors** can contribute to
the project.
.. toctree::
:maxdepth: 2
:hidden:
common-conventions
for-app-developers
for-desktop-developers
for-contributors

View File

@@ -0,0 +1,148 @@
manpages = []
if rst2man.found()
manpage_conf = configuration_data()
manpage_conf.set('DATADIR', datadir)
manpage_conf.set('SYSCONFDIR', sysconfdir)
rst2man_flags = [
'--syntax-highlight=none',
]
man_pages = [
{ 'input': 'portals.conf.rst.in', 'output': 'portals.conf', 'section': '5' },
]
foreach man_page: man_pages
man_input = configure_file(
input: man_page.get('input'),
output: man_page.get('input').split('.in').get(0),
configuration: manpage_conf,
)
man_output = man_page.get('output', man_input)
man_section = man_page.get('section', '1')
man_full = '@0@.@1@'.format(man_output, man_section)
manpages += custom_target('man-' + man_output,
input: man_input,
output: man_full,
command: [ rst2man, rst2man_flags, '@INPUT@' ],
capture: true,
install: true,
install_dir: get_option('mandir') / 'man@0@'.format(man_section),
)
endforeach
endif
if build_documentation
# Gather the XML files under data
all_interfaces_xml = []
foreach i: portal_sources
all_interfaces_xml += i
endforeach
foreach i: portal_host_sources
all_interfaces_xml += i
endforeach
foreach i: portal_impl_sources
all_interfaces_xml += i
endforeach
foreach i: background_monitor_sources
all_interfaces_xml += i
endforeach
# Replace the extension for gdbus-codegen
all_interfaces_rst = []
foreach i: all_interfaces_xml
f = fs.name(i)
all_interfaces_rst += fs.replace_suffix(f, '.rst')
endforeach
interfaces_rst = custom_target('interfaces_rst',
input: all_interfaces_xml,
output: all_interfaces_rst,
command: [ gdbus_codegen, '--generate-rst', 'doc/doc', '@INPUT@' ],
)
fix_rst_dbus = find_program('fix-rst-dbus.py')
fixed_rst_files = custom_target('fix_rst_dbus',
input: interfaces_rst,
output: 'rst-dbus.fixed',
build_always_stale: true,
build_by_default: true,
command: [ fix_rst_dbus, meson.current_build_dir(), 'doc', '@INPUT@' ],
depends: interfaces_rst,
depend_files: all_interfaces_xml,
)
docs_sources = [
'conf.py',
'favicon.ico',
'api-reference.rst',
'architecture.rst',
'building-and-running.rst',
'common-conventions.rst',
'configuration-file.rst',
'convenience-libraries.rst',
'documents-and-fuse.rst',
'for-app-developers.rst',
'for-contributors.rst',
'for-desktop-developers.rst',
'icons.rst',
'impl-dbus-interfaces.rst',
'index.rst',
'pull-requests.rst',
'reasons-to-use-portals.rst',
'requests.rst',
'terminology.rst',
'sessions.rst',
'system-integration.rst',
'window-identifiers.rst',
'writing-a-new-backend.rst',
]
copied_docs_sources = []
foreach d: docs_sources
copied_docs_sources += configure_file(input: d, output: d, copy: true)
endforeach
docs_inputs = copied_docs_sources + interfaces_rst
if rst2man.found()
docs_inputs += manpages
endif
# Copy static files to the appropriate output subdir
copy = find_program('copy-subdir.py')
copytree = find_program('copy-subtree.py')
static_files = [
'bullet.svg',
'card.png',
'inter.woff2',
'toc_bullet.svg',
'xdg.css',
'xdg-portal-dark.png',
'xdg-portal-light.png',
]
foreach f: static_files
run_command(copy, '_static' / f, '_static' / f)
endforeach
run_command(copytree, 'img', '_static' / 'img')
sphinx_command = [ sphinx_build ]
if get_option('werror')
sphinx_command += [ '-W', '--keep-going' ]
endif
custom_target('docs',
input: docs_inputs,
output: 'html',
command: sphinx_command + [ meson.current_build_dir(), '@OUTPUT@' ],
build_by_default: true,
depends: fixed_rst_files,
depend_files: all_interfaces_xml,
)
endif

View File

@@ -0,0 +1,167 @@
============
portals.conf
============
--------------------------------
XDG desktop portal configuration
--------------------------------
:Manual section: 5
:Manual group: File Formats Manual
.. _synopsis:
SYNOPSIS
========
*$XDG_CONFIG_HOME/xdg-desktop-portal/{\*-}portals.conf*
*$XDG_CONFIG_DIRS/xdg-desktop-portal/{\*-}portals.conf*
*@SYSCONFDIR@/xdg-desktop-portal/{\*-}portals.conf*
*$XDG_DATA_HOME/xdg-desktop-portal/{\*-}portals.conf*
*$XDG_DATA_DIRS/xdg-desktop-portal/{\*-}portals.conf*
*@DATADIR@/xdg-desktop-portal/{\*-}portals.conf*
DESCRIPTION
===========
xdg-desktop-portal uses a configuration file to determine which portal backend
should be used to provide the implementation for the requested interface.
This mechanism is very similar to the freedesktop.org specification for
"Association between MIME types and applications" (mime-apps).
Desktop environments and OS vendors should provide a default configuration
for their chosen portal backends in
``/usr/share/xdg-desktop-portal/DESKTOP-portals.conf``, where ``DESKTOP``
is the desktop environment name as it would appear in the
``XDG_CURRENT_DESKTOP`` environment variable, after case-folding ASCII
upper case to lower case.
For example, KDE should provide ``/usr/share/xdg-desktop-portal/kde-portals.conf``.
Users can override those defaults, or provide configuration for an otherwise
unsupported desktop environment, by writing a file
``~/.config/xdg-desktop-portal/portals.conf``. Users of more than one
desktop environment can use desktop-specific filenames such as
``kde-portals.conf`` which will only be used in the appropriate desktop
environment.
Similarly, system administrators can provide a default configuration for
all users in ``/etc/xdg-desktop-portal/DESKTOP-portals.conf`` or
``/etc/xdg-desktop-portal/portals.conf``.
The following locations are searched for configuration, highest precedence
first:
- ``$XDG_CONFIG_HOME``, defaulting to ``~/.config``
- each directory in ``$XDG_CONFIG_DIRS``, defaulting to ``/etc/xdg``
- the build-time ``sysconfdir`` for xdg-desktop-portal, usually ``/etc``
- ``$XDG_DATA_HOME``, defaulting to ``~/.local/share``
(searched only for consistency with other specifications, writing
configuration here is not recommended)
- each directory in ``$XDG_DATA_DIRS``, defaulting to ``/usr/local/share:/usr/share``
- the build-time ``datadir`` for xdg-desktop-portal, usually ``/usr/share``
In each of those locations, for each desktop environment name listed in the
``XDG_CURRENT_DESKTOP`` environment variable, xdg-desktop-portal checks for
``xdg-desktop-portal/DESKTOP-portals.conf``, where ``DESKTOP`` is the
desktop environment name in lower-case. If a desktop-environment-specific
configuration file is not found, a non-desktop-specific file
``xdg-desktop-portal/portals.conf`` will be read.
For example, if ``XDG_CURRENT_DESKTOP`` is set to ``Budgie:GNOME``,
then xdg-desktop-portal will look for
``xdg-desktop-portal/budgie-portals.conf``,
``xdg-desktop-portal/gnome-portals.conf`` and
``xdg-desktop-portal/portals.conf`` in that order.
Only the first configuration file found is read, and lower-precedence
configuration files are ignored. All possible configuration files within
one directory are tried before moving on to the next directory, so for
example ``~/.config/xdg-desktop-portal/portals.conf`` is higher-precedence
than ``/usr/share/xdg-desktop-portal/kde-portals.conf``.
FILE FORMAT
-----------
The format of the portals configuration file is the same ``.ini`` format used by
systemd unit files or application desktop files.
``[preferred]``
The main configuration group for preferred portals.
The following keys can be present in the ``preferred`` group:
``default`` *(string)*
The default portal backend to use for every interface, unless the interface
is listed explicitly.
``org.freedesktop.impl.portal.*`` *(string)*
One of the valid portal interface implementations exposed by
xdg-desktop-portal.
Each key in the group contains a semi-colon separated list of portal backend
implementation, to be searched for an implementation of the requested interface,
in the same order as specified in the configuration file. Additionally, the
special values ``none`` and ``*`` can be used:
``none``
Do not provide a portal implementation for this interface.
``*``
Use the first portal implementation found, in lexicographical order.
EXAMPLE
-------
::
[preferred]
# Use xdg-desktop-portal-gtk for every portal interface...
default=gtk
# ... except for the ScreenCast interface
org.freedesktop.impl.portal.ScreenCast=gnome
ENVIRONMENT
-----------
``XDG_CURRENT_DESKTOP``
A colon-separated list of desktop environments, most specific first,
used to choose a desktop-specific portal configuration.
The default is an empty list.
``XDG_CONFIG_HOME``
The per-user ``portals.conf`` file is located in this directory. The default
is ``$HOME/.config``.
``XDG_CONFIG_DIRS``
A colon-separated list of system configuration directories and secondary
per-user configuration directories. The default is ``/etc/xdg``.
``XDG_DATA_HOME``
A per-user data directory, searched for consistency with other
specifications. The default is ``$HOME/.local/share``.
``XDG_DATA_DIRS``
A colon-separated list of system data directories and secondary per-user
data directories. The default is ``/usr/local/share:/usr/share``.
SEE ALSO
--------
- `XDG Base Directory Specification <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_
- `XDG Desktop Entry specification <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html>`_
- `XDG Association between MIME type and applications specification <https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-latest.html>`_

View File

@@ -0,0 +1,19 @@
Pull Requests & Issues
======================
XDG Desktop Portal uses GitHub to
`discuss new portals and features <https://github.com/flatpak/xdg-desktop-portal/discussions>`_,
`track issues <https://github.com/flatpak/xdg-desktop-portal/issues>`_ and
`take contributions <https://github.com/flatpak/xdg-desktop-portal/pulls>`_.
Please be kind and patient as code reviews can be long and be minutious, issue
triage takes effort and everyone has limited time and resources.
Before developing features or fixing bugs, please make sure you have done the
following:
- Your code is not on the ``main`` branch of your fork.
- The code has been tested.
- All commit messages are properly formatted and commits squashed where
appropriate.
- You have included updates to all appropriate documentation.

View File

@@ -0,0 +1,26 @@
Reasons to Use Portals
======================
Using XDG Desktop Portal brings major advantages over writing desktop-specific
code for app developers:
* **Strict sandbox**: portals enable sandboxed apps to access a curated set of
features from the desktop environment and the host system, without weakening
the sandbox of the app.
* **Unified code**: by using portal APIs, apps only need to write a single
desktop-agnostic code that runs on a variety of desktop environments. Portals
can be used by sandboxed and unsandboxed apps alike. App developers are
encouraged to use portal APIs even for unsandboxed apps.
* **Seamless integration**: portal backends provide cost-free integration with
the desktop. For example, simply using the :ref:`File Chooser portal<org.freedesktop.portal.FileChooser>`
will make apps use the file picker dialog native to the desktop environment
they're running on.
* **Permission system**: portals can restrict access to system resources through
a permission system. Permissions can be granted, revoked, and controlled
individually by the end user. This gives end users more control over apps.
In addition to the reasons above, some desktop features are primarily - and
sometimes exclusively - available through portals. For example, the primary way
of capturing screens and windows on Wayland desktops is through the
:ref:`ScreenCast portal<org.freedesktop.portal.ScreenCast>`, and some desktop
environments don't even expose other means to capture the screen or windows.

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Redirect to the new docs location</title>
<meta http-equiv="refresh" content="0; url = https://flatpak.github.io/xdg-desktop-portal/" />
</head>
<body>
<p style="text-align:center;">
If your browser supports Refresh,
you'll be redirected to the new xdg-desktop-portal <a
href="https://flatpak.github.io/xdg-desktop-portal/">documentations</a>.
</p>
</body>
</html>

View File

@@ -0,0 +1,33 @@
Requests
========
Requests made via portal interfaces generally involve user interaction, and
dialogs that can stay open for a long time. Therefore portal APIs don't just use
async method calls (which time out after at most 25 seconds), but instead return
results via a ``Response`` signal on :ref:`Request <org.freedesktop.portal.Request>`
objects.
Portal APIs don't use properties very much. This is partially because we need to
be careful about the flow of information, and partially because it would be
unexpected to have a dialog appear when you just set a property. However, every
portal has at least one version property that specifies the maximum version
supported by xdg-desktop-portal.
General Flow
------------
The general flow of the portal API is as follows:
1. The application makes a portal request
2. The portal replies to that method call with a handle (i.e. object path) to a
:ref:`Request <org.freedesktop.portal.Request>` object that corresponds to the
request
3. The object is exported on the bus and stays alive as long as the user
interaction lasts
4. When the user interaction is over, the portal sends a ``Response`` signal back
to the application with the results from the interaction, if any.
To avoid a race condition between the caller subscribing to the signal after
receiving the reply for the method call and the signal getting emitted, a
convention for Request object paths has been established that allows the caller
to subscribe to the signal before making the method call.

View File

@@ -0,0 +1,13 @@
Sessions
========
Some portal requests are connected to each other and need to be used in
sequence. The pattern used in such cases is a :ref:`Session <org.freedesktop.portal.Session>`
object. Just like :ref:`Request <org.freedesktop.portal.Request>`\s, sessions are
represented by an object path, that is returned by the initial ``CreateSession``
call of the respective portal. Subsequent calls take the object path of the
session they operate on as an argument.
Sessions can be ended from the application side by calling the ``Close()`` method
on the session. They can also be closed from the service side, in which case the
``::Closed`` signal is emitted on the Session object to inform the application.

View File

@@ -0,0 +1,54 @@
System Integration
==================
D-Bus Activation Environment
----------------------------
XDG Desktop Portal and its portal backends are activatable D-Bus services.
This means that they inherit environment variables from the "activation
environment" maintained by either ``systemd --user`` (on systems that use
systemd) or ``dbus-daemon`` (on systems that do not). They do not inherit
environment variables from the GUI environment or from the shell, unless
some component of the overall system takes responsibility for taking the
necessary environment variables from the GUI environment and sending them
to ``systemd`` or ``dbus-daemon`` to be added to the activation environment.
In integrated desktop environments such as GNOME and KDE Plasma, and in
OS distributions with a high level of integration, this should be done
automatically by desktop environment or OS infrastructure.
Variables that might need to be propagated in this way include, but are
not limited to:
- ``DISPLAY``
- ``PATH``
- ``WAYLAND_DISPLAY``
- ``XAUTHORITY``
- ``XDG_CURRENT_DESKTOP``
- ``XDG_DATA_DIRS``
In environments that are assembled out of individual components by
the user, it is the user's responsibility to ensure that this system
integration has been done, for example by using
`dbus-update-activation-environment(1)
<https://dbus.freedesktop.org/doc/dbus-update-activation-environment.1.html>`_
or `systemctl --user import-environment VAR…
<https://www.freedesktop.org/software/systemd/man/latest/systemctl.html>`_.
Desktop Environment Requirements
--------------------------------
The display manager or GUI environment is responsible for setting
``XDG_CURRENT_DESKTOP`` to an appropriate value.
The GUI environment should provide a
:doc:`portal configuration file </configuration-file>` with a name based on its
``XDG_CURRENT_DESKTOP``, to select appropriate portal backends.
The GUI environment should arrange for its required portal backend or
backends to be installed as dependencies (possibly as optional
dependencies, if it is packaged in a loosely-coupled operating system).
In environments that are assembled out of individual components by
the user, it is the user's responsibility to ensure that this system
integration has been done.

View File

@@ -0,0 +1,8 @@
Terminology
===========
- **Frontend**: the XDG Desktop Portal service itself. This is what provides the
APIs that *apps* interact with.
- **Backend**: desktop-specific implementation of portal interfaces. This is
what provides the user interfaces that *users* interact with.
- **Host system**: the privileged, unsandboxed part of the system stack.

View File

@@ -0,0 +1,119 @@
# USB portal
The USB portal is the middleman between sandboxed apps, and the
devices connected and available to the host system. This is the first
version of the portal.
This part was implemented by
- Hubert Figuière
- Georges Basile Stavracas Neto
funded by the STF (Sovereign Tech Fund) effort, based upon initial
work by
- Ryan Gonzalez
and with help from other contributors.
## Device filtering
Sandboxed apps must declare which USB devices they support ahead of
time. This information is read by the XDG Desktop Portal and used to
determine which USB devices will be exposed to requesting apps. On
Flatpak, these enumerable and hidden devices are set by the `--usb`
and `--nousb` arguments against `flatpak build-finish` and `flatpak
run`. Neither `--devices=all` nor `--device=usb` do influence the
portal.
Hidding a device always take precedence over making them enumerable,
even when a blanket permission (`--usb=all`) is set.
However out of the sandbox we assume all devices are allowed as there
is no restriction that can prevent seeing anything.
Individual devices are assigned a unique identifier by the portal,
which is used for all further interactions. This unique identifier is
completely random and independent of the device. Permission checks are
in place to not allow apps to try and guess device ids without having
permission to access then.
## Permissions
There are 2 dynamic permissions managed by the USB portal in the
permission store:
1. Blanket USB permission: per-app permission to use any methods of
the USB portal. Without this permission, apps must not be able to do
anything - enumerate, monitor, or acquire - with the USB portal.[^1]
2. Specific device permission: per-app permission to acquire a
specific USB device, down to the serial number.
## Enumerating devices
There are 2 ways for apps to learn about devices:
- Apps can call the EnumerateDevices() method, which gives a snapshot
of the current devices to the app.
- Apps can create a device monitoring session with CreateSession()
which sends the list of available devices on creation, and also
notifies the app about connected and disconnected devices.
Only devices that the app is allowed to see are reported in both
cases.
The udev properties exposed by device enumeration is limited to a
well known subset of properties.[^2]
## Device acquisition & release
Once an app has determined which devices it wants to access, the app
can call the AcquireDevices() method. This method may prompt a dialog
for the user to allow or deny the app from accessing specific devices.
If permission is granted, XDG Desktop Portal tries to open the device
file on the behalf of the requesting app, and pass down the file
descriptor to that file.[^3]
The caller must then call FinishAcquireDevices() until it indicate it
is finished. It's only necessary to call it more than once if there
are too many file descriptors to return. This is a D-Bus
limitation. Check the `finished` return argument.
### Using the file descriptor
The file descriptors returned by the portal are meant to be used with
USB library you use.
In the case of libusb 1.0.23 and later, use `libusb_wrap_sys_device()`
and pass the file descriptor as the `sys_dev` argument. It should be
noted that libusb must be compiled with udev support (it is the
default) in order to be able to work. Without this it looks for the
non existant `/dev/usb` that is not present.
If you use libhidapi, you need to use the function
`hid_libusb_wrap_sys_device()` provided by libhidapi-usb.
---
[^1]: Exceptionally, apps can release previously acquired devices,
even when this permission is disabled. This is so because we don't yet
have kernel-side USB revoking. With USB revoking in place, it would be
possible to hard-cut app access right when the app permission changes.
[^2]: This patch uses a hardcoded list. There is no mechanism for apps
to influence which other udev properties are fetched. This approach is
open to suggestions - it may be necessary to expose more information
more liberally through the portal. The initial attempt has been made
to provide sensible information usefull for display in a user
interface.
[^3]: This is clearly not ideal. The ideal approach is to go through
logind's TakeDevice() method. However, that will add significant
complexity to the portal, since this logind method can only be called
by the session controller (i.e. the only executable capable of calling
TakeControl() in the session - usually the compositor). This can and
probably should be implemented in a subsequent round of improvements
to the USB portal.

View File

@@ -0,0 +1,13 @@
---
layout: default
permalink: /404.html
---
![404]({{site.baseurl}}/assets/404.png){:.full.pixels}
# Document Not Found
The requested page could not be found. If you feel this is not normal, then you create an issue on the Gitlab.
[Go Back](<javascript:window.history.go(-1);>){: .inline-button} [File an issue]({{site.issuesurl}})
{: .dialog-buttons}

View File

@@ -0,0 +1,33 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 4.1.0"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
# gem 'jekyll-feed', '~> 0.13'
# gem 'jekyll-sitemap', '~> 1.4'
# gem 'jekyll-compose', '~> 0.12.0'
# gem 'jekyll-postfiles', '~> 3.1'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
# gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# Performance-booster for watching directories on Windows
# gem "wdm", "~> 0.1.0" if Gem.win_platform?
gem "webrick", "~> 1.8"

View File

@@ -0,0 +1,69 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
colorator (1.1.0)
concurrent-ruby (1.1.9)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
eventmachine (1.2.7)
ffi (1.15.4)
forwardable-extended (2.6.0)
http_parser.rb (0.6.0)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
jekyll (4.1.1)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (~> 2.0)
jekyll-watch (~> 2.0)
kramdown (~> 2.1)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (~> 0.4.0)
pathutil (~> 0.9)
rouge (~> 3.0)
safe_yaml (~> 1.0)
terminal-table (~> 1.8)
jekyll-sass-converter (2.1.0)
sassc (> 2.0.1, < 3.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.7.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.3.9)
rouge (3.26.1)
safe_yaml (1.0.5)
sassc (2.4.0)
ffi (~> 1.9)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.8.0)
webrick (1.8.2)
PLATFORMS
x86_64-linux
DEPENDENCIES
jekyll (~> 4.1.0)
webrick (~> 1.8)
BUNDLED WITH
2.2.7

View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@@ -0,0 +1,8 @@
# XDG Desktop Portal Website
This is the website for the [XDG Desktop Portal project](https://github.com/flatpak/xdg-desktop-portal).
## Development
The contribution guidelines have been moved to the online documentation:
https://flatpak.github.io/xdg-desktop-portal/docs/for-contributors.html

View File

@@ -0,0 +1,14 @@
# Site settings
title: XDG Desktop Portal
baseurl: "/xdg-desktop-portal" # the subpath of your site, e.g. /blog/
# usually empty. necessary for building absolute URIs
# for metadata header
url: "https://flatpak.github.io" # the base hostname & protocol for your site
sourceurl: "https://github.com/flatpak/xdg-desktop-portal/tree/main/doc/website" # "edit this website" link in the footer
description: ""
issuesurl: "https://github.com/flatpak/xdg-desktop-portal/issues" # issue tracker for website
permalink: /:title/
primary-color: "#26a269" #used in ios theme. further color customization in style.css
# Build settings
markdown: kramdown

View File

@@ -0,0 +1,5 @@
<footer class="site-footer">
<p>&copy; {{ site.title }}, 2023-2025</p>
<p><a href="{{ site.sourceurl }}">Website source</a></p>
</footer>

View File

@@ -0,0 +1,32 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="{{ site.primary-color }}"><!-- primary color -->
<title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}" />
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" />
<link rel="stylesheet" href="{{ "/style.css" | prepend: site.baseurl }}" />
<link rel="icon" type="image/png" href="{{ "/favicon.png" | prepend: site.baseurl }}" />
<link rel="apple-touch-icon" sizes="180x180" href="{{ "/apple-touch-icon.png" | prepend: site.baseurl }}" />
<link rel="icon" type="image/png" sizes="32x32" href="{{ "/favicon-32x32.png" | prepend: site.baseurl }}" />
<link rel="icon" type="image/png" sizes="16x16" href="{{ "/favicon-16x16.png" | prepend: site.baseurl }}" />
<link rel="manifest" href="{{ "/site.webmanifest" | prepend: site.baseurl }}" />
<link rel="mask-icon" href="{{ "/safari-pinned-tab.svg" | prepend: site.baseurl }}" color="#5bbad5" />
<!-- Twitter -->
<meta property="twitter:title" content="{{site.title}}" />
<meta property="twitter:image" content="{{ "/assets/card.png" | prepend: site.baseurl | prepend: site.url }}" />
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:description" content="{{site.description}}" />
<!-- Open Graph -->
<meta property="og:title" content="{{ site.title }}" />
<meta property="og:url" content="{{ site.url }}" />
<meta property="og:description" content="{{ site.description }}" />
<meta property="og:image" content="{{ "/assets/card.png" | prepend: site.baseurl | prepend: site.url }}" />
</head>

View File

@@ -0,0 +1,3 @@
<header class="site-header">
<h1 id="logo"><a href="{{ "/" | prepend: site.baseurl }}">{{ site.title }}</a></h1>
</header>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
{% include header.html %}
<div class="container">
{{ content }}
</div>
{% include footer.html %}
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
version="1.1"
id="svg14"
sodipodi:docname="favicon.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
inkscape:export-filename="favicon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs18" />
<sodipodi:namedview
id="namedview16"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:current-layer="g12"
inkscape:snap-nodes="false"
inkscape:snap-others="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:showpageshadow="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid20"
originx="0"
originy="0"
spacingy="1"
spacingx="1"
units="px"
visible="false" />
</sodipodi:namedview>
<g
transform="translate(380 -506.52)"
id="g12">
<rect
style="fill:#f6d32d;fill-opacity:1;stroke:none;stroke-width:0.177777;stroke-linecap:round;paint-order:markers stroke fill"
id="rect1"
width="15.999992"
height="15.999992"
x="-380"
y="506.51999"
rx="0.26666722"
ry="0.26666722" />
<g
id="g4-3"
inkscape:label="portal xdg freedesktop aperture science"
transform="matrix(0.99018293,0,0,0.99018293,-1045.3236,142.21168)"
style="fill:#000000">
<title
id="title2">xdg-portal</title>
<rect
y="368"
x="671.99994"
height="16"
width="16"
id="rect2-6"
style="fill:none" />
<path
style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none;paint-order:markers stroke fill"
d="m 743.46875,-221.62109 c -1.92109,0 -3.42383,1.66654 -3.42383,3.61132 v 6.0918 c 0,1.94479 1.50274,3.61133 3.42383,3.61133 h 6.46484 c 1.92109,0 3.42383,-1.66654 3.42383,-3.61133 v -6.0918 c 0,-1.94478 -1.50274,-3.61132 -3.42383,-3.61132 z m 0,2 h 6.46484 c 0.76512,0 1.42383,0.66327 1.42383,1.61132 v 6.0918 c 0,0.94805 -0.65871,1.61133 -1.42383,1.61133 h -6.46484 c -0.76511,0 -1.42383,-0.66328 -1.42383,-1.61133 v -6.0918 c 0,-0.94805 0.65872,-1.61132 1.42383,-1.61132 z"
id="rect8"
transform="rotate(45)" />
<path
style="color:#000000;opacity:1;fill:#000000;fill-rule:evenodd;stroke-width:0.832109;stroke-linecap:round;-inkscape-stroke:none"
d="m 680.29396,371.18645 c -1.30513,-0.0914 -2.63994,0.30838 -3.67623,1.25142 -1.85606,1.68902 -2.10977,4.67185 -0.37217,6.55448 1.53794,1.66631 4.23802,1.8872 5.9304,0.29741 1.47637,-1.38687 1.66557,-3.80461 0.22265,-5.30632 -1.23582,-1.28617 -3.37348,-1.44374 -4.68386,-0.14627 -1.0956,1.08482 -1.22093,2.94343 -0.0666,4.06141 0.93392,0.90452 2.51699,0.99723 3.44058,-0.0179 0.7127,-0.78334 0.76996,-2.09652 -0.11377,-2.82137 -0.31699,-0.26001 -0.7177,-0.38946 -1.1214,-0.36893 -0.4037,0.0205 -0.8255,0.21265 -1.08239,0.59808 -0.16449,0.24681 -0.22985,0.53729 -0.1869,0.83699 0.0429,0.29969 0.25013,0.63735 0.60621,0.75897 0.26803,0.0915 0.42549,0.0409 0.62733,-0.0715 0.10091,-0.0562 0.22585,-0.14782 0.28603,-0.32992 0.0602,-0.1821 -0.007,-0.40468 -0.10726,-0.52982 a 0.41605426,0.41605426 0 0 0 -0.56395,-0.0634 c 0.0106,-0.0527 0.0114,-0.1106 0.0309,-0.13977 0.10126,-0.15192 0.24405,-0.21795 0.43231,-0.22753 0.18826,-0.01 0.40579,0.06 0.55257,0.1804 0.47749,0.39164 0.44098,1.1592 0.0244,1.61709 -0.5816,0.63924 -1.62979,0.57736 -2.24605,-0.0195 -0.79642,-0.77136 -0.70658,-2.0997 0.0731,-2.87175 0.96089,-0.95143 2.57264,-0.83254 3.49908,0.13164 1.10523,1.15027 0.95629,3.04317 -0.1934,4.12317 -1.33952,1.25831 -3.51587,1.07913 -4.74887,-0.25679 -1.41093,-1.52868 -1.20085,-3.98733 0.3218,-5.37295 1.71779,-1.56321 4.45907,-1.32295 5.99703,0.3868 1.49098,1.65753 1.51331,4.23325 0.14789,5.98241 a 0.41605426,0.41605426 0 0 0 0.0731,0.58345 0.41605426,0.41605426 0 0 0 0.58345,-0.0715 c 1.61077,-2.06346 1.58742,-5.08109 -0.18527,-7.0518 -0.92006,-1.02283 -2.19558,-1.60528 -3.5007,-1.69672 z"
id="path8" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,112 @@
---
layout: default
---
<picture class="full pixels">
<source srcset="assets/splash-dark.png" media="(prefers-color-scheme: dark)">
<img src="assets/splash.png">
</picture>
# XDG Desktop Portal
A portal frontend service for [Flatpak](https://flatpak.org) and other
desktop containment frameworks.
xdg-desktop-portal works by exposing a series of D-Bus interfaces known as
_portals_ under a well-known name (`org.freedesktop.portal.Desktop`) and object
path (`/org/freedesktop/portal/desktop`).
The portal interfaces include APIs for file access, opening URIs, printing
and others.
<a href="https://flatpak.github.io/xdg-desktop-portal/docs" class="pixelbutton"><picture>
<source srcset="assets/docs-button-dark.png" media="(prefers-color-scheme: dark)">
<img alt="Documentation for the available D-Bus interfaces" src="assets/docs-button.png">
</picture></a>
## Version Numbering
xdg-desktop-portal uses even minor version numbers for stable versions, and odd
minor version numbers for unstable versions. During an unstable version cycle,
portal APIs can make backward incompatible changes, meaning that applications
should only depend on APIs defined in stable xdg-desktop-portal versions in
production.
## Building xdg-desktop-portal
xdg-desktop-portal depends on GLib and Flatpak. To build the documentation, you
will need xmlto and the docbook stylesheets. For more instructions, please read
[CONTRIBUTING.md](https://github.com/flatpak/xdg-desktop-portal/blob/main/CONTRIBUTING.md).
## Using Portals
Flatpak grants sandboxed applications _talk_ access to names in the
org.freedesktop.portal.\* prefix. One possible way to use the portal APIs
is thus just to make D-Bus calls. For many of the portals, toolkits (e.g.
GTK) are expected to support portals transparently if you use suitable
high-level APIs.
To implement most portals, xdg-desktop-portal relies on a backend
that provides implementations of the org.freedesktop.impl.portal.\* interfaces.
Here are some examples of available backends:
- GTK [xdg-desktop-portal-gtk](http://github.com/flatpak/xdg-desktop-portal-gtk)
- GNOME [xdg-desktop-portal-gnome](https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/)
- KDE [xdg-desktop-portal-kde](https://invent.kde.org/plasma/xdg-desktop-portal-kde)
- LXQt [xdg-desktop-portal-lxqt](https://github.com/lxqt/xdg-desktop-portal-lxqt)
- Pantheon (elementary OS) [xdg-desktop-portal-pantheon](https://github.com/elementary/portals)
- wlroots [xdg-desktop-portal-wlr](https://github.com/emersion/xdg-desktop-portal-wlr)
- Deepin [xdg-desktop-portal-dde](https://github.com/linuxdeepin/xdg-desktop-portal-dde)
- Xapp (Cinnamon, MATE, Xfce) [xdg-desktop-portal-xapp](https://github.com/linuxmint/xdg-desktop-portal-xapp)
- COSMIC [xdg-desktop-portal-cosmic](https://github.com/pop-os/xdg-desktop-portal-cosmic)
## Design Considerations
There are several reasons for the frontend/backend separation of the portal
code:
- We want to have _native_ portal dialogs that match the session desktop (i.e.
GTK dialogs for GNOME, Qt dialogs for KDE)
- One of the limitations of the D-Bus proxying in flatpak is that allowing a
sandboxed app to talk to a name implicitly also allows it to talk to any other
name owned by the same unique name. Therefore, sandbox-facing D-Bus APIs
should generally be hosted on a dedicated bus connection. For portals, the
frontend takes care of this for us.
- The frontend can handle all the interaction with _portal infrastructure_, such
as the permission store and the document store, freeing the backends to focus
on just providing a user interface.
- The frontend can also handle argument validation, and be strict about only
letting valid requests through to the backend.
The portal apis are all following the pattern of an initial method call, whose
response returns an object handle for an _org.freedesktop.portal.Request_ object
that represents the portal interaction. The end of the interaction is done via a
_Response_ signal that gets emitted on that object. This pattern was chosen over
a simple method call with return, since portal APIs are expected to show dialogs
and interact with the user, which may well take longer than the maximum method
call timeout of D-Bus. Another advantage is that the caller can cancel an
ongoing interaction by calling the _Cancel_ method on the request object.
One consideration for deciding the shape of portal APIs is that we want them to
'hide' behind existing library APIs where possible, to make it as easy as
possible to have apps use them _transparently_. For example, the OpenFile portal
is working well as a backend for the GtkFileChooserNative API.
When it comes to files, we need to be careful to not let portal APIs subvert the
limited filesystem view that apps have in their sandbox. Therefore, files should
only be passed into portal APIs in one of two forms:
- As a document ID referring to a file that has been exported in the document
portal
- As an open fd. The portal can work its way back to a file path from the fd,
and passing an fd proves that the app inside the sandbox has access to the
file to open it.
When it comes to processes, passing PIDs around is not useful in a sandboxed
world where apps are likely in their own PID namespace. And passing PIDs from
inside the sandbox is problematic, since the app can just lie.
## Contributing
XDG Desktop Portals is [Free Software](https://www.gnu.org/philosophy/free-sw.html). Contributions [welcome](https://github.com/flatpak/xdg-desktop-portal/blob/main/CONTRIBUTING.md).

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3385 6944 c-22 -3 -88 -14 -148 -25 -304 -56 -566 -191 -814 -419
-216 -197 -1977 -1972 -2035 -2050 -331 -447 -421 -986 -248 -1475 42 -116 83
-199 161 -316 55 -84 184 -216 1163 -1195 974 -974 1112 -1108 1194 -1163 162
-106 332 -177 522 -218 67 -14 130 -18 295 -18 182 0 223 3 312 23 253 57 456
149 652 298 117 88 2122 2094 2192 2192 213 300 312 602 312 952 0 240 -40
424 -137 626 -63 130 -113 208 -207 319 -37 44 -535 546 -1106 1116 -966 964
-1045 1041 -1145 1107 -176 116 -363 193 -553 227 -90 16 -334 27 -410 19z
m325 -890 c41 -13 102 -41 135 -63 34 -23 190 -170 365 -346 l305 -306 -85 39
c-196 91 -399 152 -625 189 -170 28 -526 25 -699 -6 -184 -32 -351 -83 -541
-165 -33 -14 5 28 210 234 138 138 273 268 300 290 202 157 419 203 635 134z
m-80 -834 c807 -72 1462 -621 1669 -1401 55 -206 65 -292 65 -539 -1 -187 -4
-245 -22 -344 -39 -211 -106 -416 -195 -591 -38 -77 -64 -104 -626 -668 -324
-325 -612 -607 -645 -629 -137 -95 -266 -132 -426 -125 -117 5 -202 30 -287
85 -26 17 -232 216 -458 443 -386 387 -406 409 -345 376 149 -81 372 -158 560
-193 115 -22 410 -30 541 -14 140 16 341 69 471 123 384 162 703 467 878 839
236 505 204 1111 -84 1553 -261 401 -650 638 -1121 685 -554 55 -1095 -235
-1334 -714 -103 -207 -136 -352 -135 -591 0 -142 4 -185 23 -265 111 -453 439
-772 886 -862 82 -16 125 -19 235 -14 201 7 350 52 497 148 199 130 344 329
404 553 26 96 31 296 10 390 -29 135 -98 268 -188 366 -269 290 -703 319 -958
64 -80 -79 -127 -160 -150 -256 -38 -162 -1 -311 106 -424 68 -72 143 -107
240 -113 67 -4 84 -1 130 21 84 38 134 80 159 133 51 104 15 247 -76 300 -38
22 -53 26 -102 22 -31 -3 -65 -9 -74 -13 -28 -11 -23 28 8 65 95 112 308 96
437 -32 73 -73 109 -158 115 -272 9 -169 -41 -300 -157 -417 -169 -169 -435
-221 -682 -133 -346 123 -555 493 -495 879 30 200 118 377 255 516 124 124
257 202 436 255 112 32 320 44 442 24 462 -74 806 -389 930 -850 35 -131 43
-371 18 -521 -45 -268 -159 -498 -346 -694 -189 -197 -423 -324 -713 -387
-145 -32 -425 -31 -573 0 -409 88 -738 307 -959 639 -417 624 -331 1496 202
2052 372 388 887 579 1434 531z m-2094 -877 c-114 -267 -166 -523 -166 -818 0
-333 62 -605 201 -882 l59 -118 -309 310 c-288 289 -311 315 -344 385 -47 99
-61 176 -55 303 4 81 12 119 36 184 52 141 104 207 365 471 133 133 242 242
244 242 1 0 -13 -35 -31 -77z m4448 -493 c68 -103 88 -166 94 -300 5 -141 -9
-206 -74 -339 -41 -83 -61 -109 -172 -223 -69 -70 -127 -126 -129 -124 -2 2 1
32 6 67 6 35 15 130 20 212 26 384 -51 796 -210 1137 l-50 105 236 -235 c140
-139 254 -262 279 -300z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,18 @@
{
"name": "XDG Desktop Portal",
"short_name": "XDG Desktop Portal",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#F6D32D",
"background_color": "#F6D32D"
}

View File

@@ -0,0 +1,498 @@
/*
OS Component Website
====================
shamelessly stolen CSS from systemd
https://github.com/systemd/systemd/tree/main/docs
*/
/* GNOME Color Palette */
:root {
--rounded-corner: 12px;
--blue1: rgb(153,193,241);
--blue2: rgb(98,160,234);
--blue3: rgb(53,132,228);
--blue4: rgb(28,113,216);
--blue5: rgb(26,95,180);
--green1: rgb(143,240,164);
--green2: rgb(87,227,137);
--green3: rgb(51,209,122);
--green4: rgb(46,194,126);
--green5: rgb(38,162,105);
--yellow1: rgb(249,240,107);
--yellow2: rgb(248,228,92);
--yellow3: rgb(246,211,45);
--yellow4: rgb(245,194,17);
--yellow5: rgb(229,165,10);
--orange1: rgb(255,190,111);
--orange2: rgb(255,163,72);
--orange3: rgb(255,120,0);
--orange4: rgb(230,97,0);
--orange5: rgb(198,70,0);
--red1: rgb(246,97,81);
--red2: rgb(237,51,59);
--red3: rgb(224,27,36);
--red4: rgb(192,28,40);
--red5: rgb(165,29,45);
--purple1: rgb(220,138,221);
--purple2: rgb(192,97,203);
--purple3: rgb(145,65,172);
--purple4: rgb(129,61,156);
--purple5: rgb(97,53,131);
--brown1: rgb(205,171,143);
--brown2: rgb(181,131,90);
--brown3: rgb(152,106,68);
--brown4: rgb(134,94,60);
--brown5: rgb(99,69,44);
--light1: rgb(255,255,255);
--light2: rgb(246,245,244);
--light3: rgb(222,221,218);
--light4: rgb(192,191,188);
--light5: rgb(154,153,150);
--dark1: rgb(119,118,123);
--dark2: rgb(94,92,100);
--dark3: rgb(61,56,70);
--dark4: rgb(36,31,49);
--dark5: rgb(0,0,0);
--primary-color: var(--green5); /* Set your project color */
--borders: var(--light3);
--fg-color: #241f31;
--bg-color: var(--light2);
--term-fg: var(--dark3);
--term-bg: var(--light1);
--term-br: 9px;
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--fg-color: #eee;
--bg-color: #0d2542;
--term-fg: var(--light1);
--term-bg: var(--dark4);
--primary-color: var(--orange1);
}
}
/* Typography */
@font-face {
font-family: 'Inter Var';
font-weight: 100 900;
font-display: swap;
font-style: oblique italic 0deg 10deg;
src: url("fonts/Inter.var.woff2?v=3.19") format("woff2");
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
font-size: 16px;
font-family: "Inter Var", sans-serif;
font-weight: 400;
line-height: 1.6;
scroll-behavior: smooth;
}
body {
color: var(--fg-color);
background-color: var(--bg-color);
/* ⇩⇩ put footer at the bottom for short pages, such as the 404 ⇩⇩ */
display: grid;
min-height: 100vh;
grid-template-rows: auto minmax(auto,1fr) auto; /* header, stuff, footer */
}
h1, h2, h3, h4, h5, h6 {
margin: 3rem 0 1rem;
font-weight: 600;
line-height: 1.25;
font-variation-settings: "wght" 600; /* needed for webkit */
}
h1 {
font-size: 1.5rem;
font-weight: 100;
font-style: normal;
margin: 3rem 0 1rem;
}
@media screen and (min-width: 650px) {
h1 {
font-size: 1.6rem;
}
}
h2 {
font-size: 1.2rem;
}
a {
font-weight: 600;
text-decoration: none;
color: var(--primary-color);
cursor: pointer;
font-variation-settings: "wght" 600; /* needed for webkit */
}
a:hover {
text-decoration: underline;
}
b {
font-weight: 600;
}
small {
color: #777;
}
hr {
margin: 3rem auto 4rem;
width: 40%;
opacity: 40%;
}
img {
display: block;
margin: 2rem auto;
max-width: 100%;
}
img.full, picture.full img { width: 100%; }
img.pixels, picture.pixels img {
image-rendering: crisp-edges; /* older firefox browsers */
image-rendering: pixelated;
}
/* Layout */
.container {
width: 80%;
margin-left: auto;
margin-right: auto;
max-width: 720px;
}
/* Singletons */
#logo {
display: block;
width: 251px; height: 26px;
background: url('assets/page-logo.svg') no-repeat center;
padding: 5rem 0 3rem;
margin: 0 auto;
position: relative;
}
#logo a {
display: block;
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
color: rgba(0,0,0,0); /* make text transparent */
cursor: pointer;
}
.page-logo > img {
margin: 0 auto;
}
@media (prefers-color-scheme: dark) {
#logo {
background-image: url('assets/page-logo-i.svg');
}
}
.brand-white {
background-color: #fff;
}
.brand-green {
background-color: #30D475;
}
.brand-black {
background-color: #201A26;
color: white;
}
.page-link::after {
content: " ➜";
}
/* Footer */
footer {
text-align: center;
padding: 3em 0 3em;
font-size: 1em;
margin-top: 4rem;
}
/* Make tables vertically aligned to the top */
tbody td {
vertical-align: top;
}
/* Github Code Highlighting */
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight .cm {
color: #999988;
font-style: italic;
}
.highlight .cp {
color: #999999;
font-weight: bold;
}
.highlight .c1 {
color: #999988;
font-style: italic;
}
.highlight .cs {
color: #999999;
font-weight: bold;
font-style: italic;
}
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cpf {
color: #999988;
font-style: italic;
}
.highlight .err {
color: #a61717;
background-color: #e3d2d2;
}
.highlight .gd {
color: #000000;
background-color: #ffdddd;
}
.highlight .ge {
color: #000000;
font-style: italic;
}
.highlight .gr {
color: #aa0000;
}
.highlight .gh {
color: #999999;
}
.highlight .gi {
color: #000000;
background-color: #ddffdd;
}
.highlight .go {
color: #888888;
}
.highlight .gp {
color: #555555;
}
.highlight .gs {
font-weight: bold;
}
.highlight .gu {
color: #aaaaaa;
}
.highlight .gt {
color: #aa0000;
}
.highlight .kc {
color: #000000;
font-weight: bold;
}
.highlight .kd {
color: #000000;
font-weight: bold;
}
.highlight .kn {
color: #000000;
font-weight: bold;
}
.highlight .kp {
color: #000000;
font-weight: bold;
}
.highlight .kr {
color: #000000;
font-weight: bold;
}
.highlight .kt {
color: #445588;
font-weight: bold;
}
.highlight .k, .highlight .kv {
color: #000000;
font-weight: bold;
}
.highlight .mf {
color: #009999;
}
.highlight .mh {
color: #009999;
}
.highlight .il {
color: #009999;
}
.highlight .mi {
color: #009999;
}
.highlight .mo {
color: #009999;
}
.highlight .m, .highlight .mb, .highlight .mx {
color: #009999;
}
.highlight .sb {
color: #d14;
}
.highlight .sc {
color: #d14;
}
.highlight .sd {
color: #d14;
}
.highlight .s2 {
color: #d14;
}
.highlight .se {
color: #d14;
}
.highlight .sh {
color: #d14;
}
.highlight .si {
color: #d14;
}
.highlight .sx {
color: #d14;
}
.highlight .sr {
color: #009926;
}
.highlight .s1 {
color: #d14;
}
.highlight .ss {
color: #990073;
}
.highlight .s, .highlight .sa, .highlight .dl {
color: #d14;
}
.highlight .na {
color: #008080;
}
.highlight .bp {
color: #999999;
}
.highlight .nb {
color: #0086B3;
}
.highlight .nc {
color: #445588;
font-weight: bold;
}
.highlight .no {
color: #008080;
}
.highlight .nd {
color: #3c5d5d;
font-weight: bold;
}
.highlight .ni {
color: #800080;
}
.highlight .ne {
color: #990000;
font-weight: bold;
}
.highlight .nf, .highlight .fm {
color: #990000;
font-weight: bold;
}
.highlight .nl {
color: #990000;
font-weight: bold;
}
.highlight .nn {
color: #555555;
}
.highlight .nt {
color: #000080;
}
.highlight .vc {
color: #008080;
}
.highlight .vg {
color: #008080;
}
.highlight .vi {
color: #008080;
}
.highlight .nv, .highlight .vm {
color: #008080;
}
.highlight .ow {
color: #000000;
font-weight: bold;
}
.highlight .o {
color: #000000;
font-weight: bold;
}
.highlight .w {
color: #bbbbbb;
}
.highlight {
}
/* Code Blocks */
.highlighter-rouge {
font-size: 80%;
line-height: normal;
padding: 2px 1rem;
border-radius: var(--term-br);
background-color: var(--term-bg);
max-width: 100vw;
overflow-x: auto;
margin: 1rem 0;
}
@media only screen and (max-device-width : 480px) {
/*mobile*/
.highlighter-rouge { max-width: 80vw; }
}
.highlighter-rouge * {
}
/* Inline Code */
code.highlighter-rouge {
padding: 2px 6px;
background-color: var(--term-bg);
}
/* Buttons */
.dialog-buttons {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: space-between;
margin-top: 6rem;
}
.inline-button {
display: inline-block;
font-weight: 900;
font-size: 90%;
padding: .4rem 1rem;
border-radius: var(--rounded-corner);
background-color: var(--term-bg);
color: var(--fg-color);
}
a.pixelbutton img { transition: all ease-out 300ms; }
a.pixelbutton:hover img {
filter: brightness(1.3) hue-rotate(-2deg) contrast(130%) drop-shadow(0px 2px 2px rgba(0,0,0,0.5));
}
a.pixelbutton:active img {
filter: brightness(0.9) hue-rotate(-2deg) contrast(130%);
translate: 0 2px;
}

View File

@@ -0,0 +1,19 @@
Window Identifiers
==================
Most portals interact with the user by showing dialogs. These dialogs should
generally be placed on top of the application window that triggered them. To
arrange this, the compositor needs to know about the application window. Many
portal requests expect a ``"parent_window"`` string argument for this reason.
Under X11, the ``"parent_window"`` argument should have the form ``x11:<XID>``,
where ``<XID>`` is the XID of the application window in hexadecimal notation.
For example, ``x11:1234``.
Under Wayland, it should have the form ``wayland:<HANDLE>``, where ``<HANDLE>``
is a surface handle obtained with the `xdg_foreign
<https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml>`_
protocol. For example, ``wayland:~12l9jdl.-a``.
For other windowing systems, or if you don't have a suitable handle, just pass
an empty string for ``"parent_window"``.

Some files were not shown because too many files have changed in this diff Show More