Commit 4a41f3a9 authored by Kirill Unitsaev's avatar Kirill Unitsaev

just import…

just import https://github.com/flatpak/xdg-desktop-portal-gtk/archive/refs/tags/1.15.3.tar.gz to xdg-desktop-portal-gtk subdir with rpmgs script
parents
# This Containerfile builds the image that we use in all github workflows.
# When this file is changed, or one needs to rebuild the image for another
# reason, bump the `IMAGE_TAG` in the container.yml workflow.
FROM ubuntu:latest
RUN apt update
RUN apt upgrade -y
# Install dependencies
RUN apt install -y --no-install-recommends \
gcc clang \
ca-certificates \
desktop-file-utils \
fuse3 \
gettext \
git \
gtk-doc-tools \
jq \
libcap2-bin \
libflatpak-dev \
libfontconfig1-dev \
libfuse3-dev \
libgdk-pixbuf-2.0-dev \
librsvg2-2 \
librsvg2-common \
libgstreamer-plugins-base1.0-dev \
gstreamer1.0-plugins-good \
libgstreamer-plugins-good1.0-dev \
gstreamer1.0-tools \
libgeoclue-2-dev \
libglib2.0-dev \
libgudev-1.0-dev \
libjson-glib-dev \
libpipewire-0.3-dev \
libsystemd-dev \
llvm \
libclang-rt-18-dev \
shared-mime-info \
libglib2.0-dev \
libgtk-3-dev \
gsettings-desktop-schemas-dev \
libgnome-desktop-3-dev \
dbus-user-session \
dbus-x11
# Install meson
RUN apt install -y --no-install-recommends meson
# Install latest xdg-desktop-portal
RUN git clone -b 1.20.0 https://github.com/flatpak/xdg-desktop-portal.git ./xdg-desktop-portal && \
cd ./xdg-desktop-portal && \
meson setup -Dsysconfdir=/etc -Dprefix=/usr -Dtests=disabled _build . && \
meson compile -C _build && \
meson install -C _build && \
cd ..
env:
TESTS_TIMEOUT: 10 # in minutes
on:
workflow_call:
inputs:
image:
required: true
type: string
image_options:
required: true
type: string
jobs:
build-and-test:
name: Build and Test
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['gcc', 'clang']
container:
image: ${{ inputs.image }}
env:
CFLAGS: -Wp,-D_FORTIFY_SOURCE=2
CC: ${{ matrix.compiler }}
XDP_TEST_IN_CI: 1
G_MESSAGES_DEBUG: all
options: ${{ inputs.image_options }}
steps:
- name: Configure environment
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
echo XDG_DATA_DIRS=$GITHUB_WORKSPACE/tests/share:/usr/local/share:/usr/share | tee -a $GITHUB_ENV
- name: Check out xdg-desktop-portal-gtk
uses: actions/checkout@v4
- name: Build xdg-desktop-portal-gtk
run: |
meson setup _build
meson compile -C _build
- name: Run xdg-desktop-portal-gtk tests
run: timeout --signal=KILL -v ${TESTS_TIMEOUT}m meson test -C _build
- name: Install xdg-desktop-portal-gtk
run: meson install -C _build
- name: Create dist tarball
run: |
ls -la
timeout --signal=KILL -v ${TESTS_TIMEOUT}m meson dist -C _build
- name: Upload test logs
uses: actions/upload-artifact@v4
if: success() || failure()
with:
name: test logs (${{ matrix.compiler }}, ${{ matrix.sanitizer }})
path: |
_build/meson-logs/testlog.txt
env:
IMAGE_TAG: 20250321-1
on:
workflow_call:
outputs:
image:
description: "The build image"
value: ${{ jobs.build-container.outputs.image }}
image_options:
description: "The options to use with the image"
value: --device /dev/fuse --cap-add SYS_ADMIN --security-opt apparmor:unconfined --privileged
jobs:
build-container:
name: Create build container
runs-on: ubuntu-latest
outputs:
image: ${{ steps.check.outputs.image }}
steps:
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Check if image already exists on GHCR
id: check
run: |
ACTOR="${{ github.actor }}"
OWNER="${{ github.repository_owner }}"
image_actor="ghcr.io/${ACTOR,,}/xdg-desktop-portal-gtk:${{ env.IMAGE_TAG }}"
image_owner="ghcr.io/${OWNER,,}/xdg-desktop-portal-gtk:${{ env.IMAGE_TAG }}"
if docker manifest inspect "${image_owner}" >/dev/null ; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "image=${image_owner}" >> "$GITHUB_OUTPUT"
exit 0
fi
if docker manifest inspect "${image_actor}" >/dev/null ; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "image=${image_actor}" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "image=${image_owner}" >> "$GITHUB_OUTPUT"
- name: Build and push
if: ${{ steps.check.outputs.exists == 'false' }}
uses: docker/build-push-action@v5
with:
push: true
file: .github/workflows/Containerfile
tags: ${{ steps.check.outputs.image }}
name: CI
on: [push, pull_request]
jobs:
build-container:
name: Container
uses: ./.github/workflows/container.yml
permissions:
packages: write
build-and-test:
name: Build and Test
uses: ./.github/workflows/build-and-test.yml
needs: build-container
with:
image: ${{ needs.build-container.outputs.image }}
image_options: ${{ needs.build-container.outputs.image_options }}
name: Release new version
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
jobs:
build-container:
name: Container
uses: ./.github/workflows/container.yml
permissions:
packages: write
release:
name: Build and publish a release
runs-on: ubuntu-latest
needs: build-container
permissions:
contents: write
container:
image: ${{ needs.build-container.outputs.image }}
options: ${{ needs.build-container.outputs.image_options }}
steps:
- name: Configure environment
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Checkout the repository
uses: actions/checkout@v4
- name: Build xdg-desktop-portal-gtk
run: |
meson setup . _build
meson dist -C _build
- name: Extract release information
run: |
# Extract the release version
releaseVersion=`meson introspect --projectinfo _build/ | jq -r .version`
echo "releaseVersion=$releaseVersion" | tee -a $GITHUB_ENV
echo $releaseVersion
# Extract the changelog
{
echo "releaseChangelog<<EOF"
perl -0777nE 'print $& if /(?<=\n\n).*?(?=\nChanges in)/sg' NEWS.md
echo "\nEOF"
} | tee -a $GITHUB_ENV
echo $releaseChangelog
- name: Create release
uses: ncipollo/release-action@v1.15.0
with:
tag: ${{ env.releaseVersion }}
body: ${{ env.releaseChangelog }}
artifacts: _build/meson-dist/*
INSTALL
Makefile
Makefile.in
config.*
configure
depcomp
install-sh
libtool
ltmain.sh
m4
missing
stamp-h1
.deps
*.o
aclocal.m4
autom4te.cache
compile
*.service
xdg-desktop-portal-gtk
.dirstamp
xdg-desktop-portal-dbus.[ch]
/ABOUT-NLS
/po/*.gmo
/po/*.header
/po/*.pot
/po/Makefile.in.in
/po/Makevars.template
/po/POTFILES
/po/Rules-quot
/po/boldquot.sed
/po/insert-header.sin
/po/quot.sed
/po/remove-potcdate.sed
/po/remove-potcdate.sin
/po/stamp-po
/src/resources.c
/src/shell-dbus.[ch]
/testappchooser
/xdg-desktop-portal-*.tar.xz
/xdg-desktop-portal-*/
/xdg-desktop-portal-gtk.desktop
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
Changes in 1.15.3
=================
Released: 2025-03-21
- Fix build against newer xdg-desktop-portal
- Fix return value for the access portal
Changes in 1.15.2
=================
Released: 2025-01-09
- Plug memory leak in the notification portal backend
- Implement the contrast setting
- Set correct platform data for notification activation
- Drop use of private GNOME Shell notification API
- Depend on the graphical-session target
- Ensure proper shutdown target
- Build against xdg-desktop-portal >= 1.19.1
- Translation updates
Changes in 1.15.1
=================
Released: 2023-10-21
- Fix build of feature-gated portals
Changes in 1.15.0
=================
Released: 2023-10-20
- Switch to the Meson build system, and drop Autotools
- Drop most use of private GNOME API; the following portal interfaces
have been removed:
- org.freedesktop.impl.portal.Screenshot
- org.freedesktop.impl.portal.ScreenCast
- org.freedesktop.impl.portal.RemoteDesktop
- org.freedesktop.impl.portsl.Background
- Do not add duplicate notifications
- Expose the org.gnome.desktop.calendar settings
- Fix type for org.gnome.desktop.background.picture-uri setting
- Support current_folder in org.freedesktop.impl.portal.FileChooser
- Update list of translatable files
- Translation updates
Changes in 1.14.1, 2022-11-29
=============================
- printing, wallpaper: Fix some memory leaks
- printing: Consistently include .desktop in the fallback app name
- screencast: Fall back to desktop ID if we don't know the app name
- appchooser: Fix a use-after-free
- wallpaper: Handle errors storing images in the cache
- email: Fix a crash if no addresses are provided
- notification: Fix notifications for apps with no ID not appearing
- screenshot: Report whether PickColor is implemented, if possible
(this requires a sufficiently new xdg-desktop-portal at runtime)
Changes in 1.14.0, 2022-03-18
=============================
- Add an implementation of the dynamic launcher portal
- notification: Fix activation of default action with target
- New translations: oc, pt
- Translation updates
Changes in 1.12.0, 2021-12-21
=============================
- settings: Provide org.freedesktop.appearance.color-scheme key
- settings: Handle org.gnome.desktop.a11y.interface schema
- notification: Handle actions with targets properly
- Enable settings and appchooser portals by default
- Translation updates
Changes in 1.10.0
=================
- filechooser: Fix a focus issue
- inhibit: Autostart org.gnome.ScreenSaver
- screencast: Force window icon size
- Make portal backends with GNOME dependencies optional and
disable them by default. Use xdg-desktop-portal-gnome, or use
--enable-wallpaper to build with the wallpaper backend
--enable-screenshot to build with the screenshot backend
--enable-screencast to build with screencast/remoting backends
--enable-background to build with the background backend
--enable-settings to build with the settings backend
--enable-appchooser to build with the appchooser backend
- Translation updates
Changes in 1.8.0
================
- filechooser: Return the current filter
- screenshot: Fix cancellation
- appchooser: Avoid a crash
- wallpaper: Properly preview placement settings
- wallpaper: Drop the lockscreen option
- printing: Improve the notification
- Translation updates
Changes in 1.7.1
================
- filechooser: Handle the "directory" option to select directories
- filechooser: Only show preview when we have an image
- Translation updates
Changes in 1.7.0
================
- screencast: Support mutter version 3
- settings: Fall back to gsettings for enable-animations
- Translation updates
Changes in 1.6.0
================
- Translation updates
Changes in 1.5.2
================
- email: Work with sandboxed email clients
- wallpaper: Support http: uris
- wallpaper: Improve preview
- appchooser: Modernize the appearance
- background: Improve application monitoring
- Require xdg-desktop-portal 1.5
Changes in 1.5.1
================
* settings: Get animations-enabled setting from gnome-shell
* wallpaper: Add a portal backend for setting desktop backgrounds
* email: Support multiple addresses, cc and bcc
* filechooser: Support saving multiple files
* Translation updates
Changes in 1.5.0
================
* screencast: Support window selection
* screencast: Fix a crash
* settings: Add a settings portal backend
* settings: Handle enable-animations setting like gsd
* Translation updates
Changes in 1.4.0
================
* Translation updates
* inhibit: Implement session state tracking
* screencast: Allow selecting source types
* screencast: Support cursor modes
* Add a background & autostart portal
Changes in 1.2.0
================
* Translation updates
* file chooser: Support setting current filter
Changes in 1.1.1
================
* lockdown: Implement the lockdown backend
* email: Be more careful when selecting a handler
* Translation updates
Changes in 1.1.0
================
* Respect GNOME lockdown settings for printing, save-to-disk and app choosing
* filechooser: Set proper default accept label
* appchooser: Implement UpdateChoices and update the dialog
* Translation updates
Major changes in 1.0.2
======================
* filechooser: Add returned files to recent files
* inhibit: Implement screensaver monitoring
Major changes in 1.0.1
======================
* Use gvfs
* Unset GTK_USE_PORTAL
* Require xdg-desktop-portal 1.0
* Translation updates
Major changes in 1.0
====================
* screenshot: Add a PickColor method
* screencast: Some UI improvements
* Improve --help output
Major changes in 0.99
=====================
* Shorten excessively long filenames in the app chooser dialog
* Fixes for the screencast portal
* Support more email clients in the Email portal
* Fix a crash in the print portal
Major changes in 0.11
=====================
* Add dependency on gio-unix-2.0.
* remotedesktop: Add support for the 'finish' flag of NotifyPointerAxis.
* remotedesktop: Correctly expose device types supporting remote control.
* print: Add a 'Print Preview' button (requires evince-previewer).
* screenshot: Make sure the dialog is shown in the interactive case.
* Translation updates
Brazilian Portuguese
Chinese (Taiwan)
Czech
Hungarian
Indonesian
Italian
Lithuanian
Spanish
Ukrainian
Major changes in 0.10
=====================
* Fix critical in file chooser
* Add options to screenshot portals
* Add screencast and remote portal implementations
Major changes in 0.9
====================
* Improve the app picker ui
* Fix error reporting in the email portal
* Translation updates
Brazilian Portuguese
Czech
Galician
Indonesian
Italian
Polish
Slovak
Turkish
Ukrainian
* Version 0.8 was skipped
Major changes in 0.7
====================
* Add a more complete app chooser dialog
* Fix problems with the notification portal
* Translation updates:
Brazilian Portuguese
Czech
Italian
Polish
Major changes in 0.6
====================
* Implement the portal for composing email. Currently supported
clients: evolution, thunderbird
* Install a systemd service file to put xdg-desktop-portal-gtk
into its own cgroup
* Install a desktop file to provide an icon and name for
xdg-desktop-portal-gtk
* Apply image rotations in the file chooser preview
* Add a new app chooser dialog
* Translation updates
Brazilian Portuguese
French
German
Hungarian
Swedish
Ukrainian
Major changes in 0.5
====================
* Add Wayland transient parent support to all portals
* Support non-exported actions in the notification portal
* Add image preview to the filechooser portal
* Added backend interfaces:
- org.freedesktop.impl.portal.Account
* Translation updates
Czech
Serbian
Simplified Chinese
Swedish
Major changes in 0.3
====================
* Add Wayland support for transient-for dialogs
* Translation updates:
Brazilian Portuguese
Hungarian
Slovak
Ukrainian
Major changes in 0.2
====================
* Make app chooser use app ids without .desktop
* Added backend interfaces:
- org.freedesktop.impl.portal.Access
* Translation updates
German
Polish
Initial release 0.1
===================
Implemented portal backend interfaces:
* org.freedesktop.impl.portal.FileChooser
* org.freedesktop.impl.portal.Print
* org.freedesktop.impl.portal.AppChooser
* org.freedesktop.impl.portal.Screenshot
* org.freedesktop.impl.portal.Inhibit
* org.freedestkop.impl.portal.Notification
# xdg-desktop-portal-gtk
A backend implementation for [xdg-desktop-portal](http://github.com/flatpak/xdg-desktop-portal)
that is using GTK and various pieces of GNOME infrastructure, such as
org.gnome.desktop.* GSettings schemas and the org.gnome.SessionManager and
org.gnome.Screensaver D-Bus interfaces.
## Building xdg-desktop-portal-gtk
xdg-desktop-portal-gtk depends on xdg-desktop-portal and GTK.
## Versioning
The xdg-desktop-portal-gtk version has three components:
- major, incremented for backward compatibility breaking changes
- minor, incremented for changes in dependencies and exposed interfaces
- micro, incremented for bug fixes
# Security policy for xdg-desktop-portal-gtk
See the [Flatpak security policy](https://github.com/flatpak/flatpak/blob/master/SECURITY.md)
## Supported Versions
In stable branches and released packages, this table is likely to be outdated;
please check
[the latest version](https://github.com/flatpak/xdg-desktop-portal-gtk/blob/master/SECURITY.md).
| Version | Supported | Status
| --------- | ------------------ | ----------------------------------------------------------- |
| 1.15.x | :white_check_mark: | Current stable branch, recommended for use in distributions |
| 1.14.x | :white_check_mark: | Old stable branch, will receive only security fixes |
| <= 1.13.x | :x: | Older branches, no longer supported |
[portal]
DBusName=org.freedesktop.impl.portal.desktop.gtk
Interfaces=org.freedesktop.impl.portal.FileChooser;@appchooser_iface@org.freedesktop.impl.portal.Print;org.freedesktop.impl.portal.Notification;org.freedesktop.impl.portal.Inhibit;org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.Account;org.freedesktop.impl.portal.Email;org.freedesktop.impl.portal.DynamicLauncher;@lockdown_iface@@settings_iface@@wallpaper_iface@
UseIn=gnome
portal_dbus_interfaces = [
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Request.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Session.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.FileChooser.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Print.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Notification.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Inhibit.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Access.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Account.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Email.xml',
desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.DynamicLauncher.xml',
]
fdo_dbus_interfaces = files(
'org.freedesktop.ScreenSaver.xml',
'org.freedesktop.Accounts.xml',
'org.freedesktop.Accounts.User.xml',
)
gnome_dbus_interfaces = files(
'org.gnome.SessionManager.xml',
'org.gnome.ScreenSaver.xml',
)
gtk_portal = configuration_data()
if get_option('wallpaper').allowed()
portal_dbus_interfaces += desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Wallpaper.xml'
gtk_portal.set('wallpaper_iface', 'org.freedesktop.impl.portal.Wallpaper;')
else
gtk_portal.set('wallpaper_iface', '')
endif
if get_option('settings').allowed()
portal_dbus_interfaces += desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Settings.xml'
gtk_portal.set('settings_iface', 'org.freedesktop.impl.portal.Settings;')
else
gtk_portal.set('settings_iface', '')
endif
if get_option('appchooser').allowed()
portal_dbus_interfaces += desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.AppChooser.xml'
gtk_portal.set('appchooser_iface', 'org.freedesktop.impl.portal.AppChooser;')
else
gtk_portal.set('appchooser_iface', '')
endif
if get_option('lockdown').allowed()
portal_dbus_interfaces += desktop_portal_interfaces_dir / 'org.freedesktop.impl.portal.Lockdown.xml'
gtk_portal.set('lockdown_iface', 'org.freedesktop.impl.portal.Lockdown;')
else
gtk_portal.set('lockdown_iface', '')
endif
configure_file(
input: 'gtk.portal.in',
output: 'gtk.portal',
configuration: gtk_portal,
install: true,
install_dir: datadir / 'xdg-desktop-portal/portals',
)
service_conf = configuration_data()
service_conf.set('libexecdir', libexecdir)
configure_file(
input: 'org.freedesktop.impl.portal.desktop.gtk.service.in',
output: 'org.freedesktop.impl.portal.desktop.gtk.service',
configuration: service_conf,
install: true,
install_dir: dbus_service_dir,
)
configure_file(
input: 'xdg-desktop-portal-gtk.service.in',
output: 'xdg-desktop-portal-gtk.service',
configuration: service_conf,
install: true,
install_dir: systemd_userunit_dir,
)
desktop_conf = configuration_data()
desktop_conf.set('libexecdir', libexecdir)
i18n.merge_file(
type: 'desktop',
input: configure_file(
input: 'xdg-desktop-portal-gtk.desktop.in.in',
output: 'xdg-desktop-portal-gtk.desktop.in',
configuration: desktop_conf,
),
output: 'xdg-desktop-portal-gtk.desktop',
po_dir: '../po',
install: true,
install_dir: datadir / 'applications',
)
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" >
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="org.freedesktop.Accounts.User">
<method name="SetUserName">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc>
<doc:summary>
The new username.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users username. Note that it is usually not allowed
to have multiple users with the same username.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the username of any user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetRealName">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc>
<doc:summary>
The new name, typically in the form "Firstname Lastname".
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users real name.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own name</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the name of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetEmail">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="email" direction="in" type="s">
<doc:doc>
<doc:summary>
The new email address.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users email address.
</doc:para>
<doc:para>
Note that setting an email address in the AccountsService is
not the same as configuring a mail client. Mail clients might
default to email address that is configured here, though.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own email address</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the email address of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetLanguage">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="language" direction="in" type="s">
<doc:doc>
<doc:summary>
The new language, as a locale specification like "de_DE.UTF-8".
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users language.
</doc:para>
<doc:para>
The expectation is that display managers will start the
users session with this locale.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own language</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the language of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetXSession">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_x_session"/>
<arg name="x_session" direction="in" type="s">
<doc:doc>
<doc:summary>
The new xsession to start (e.g. "gnome")
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users x session.
</doc:para>
<doc:para>
The expectation is that display managers will log the user in to this
specified session, if available.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own language</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the language of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetLocation">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="location" direction="in" type="s">
<doc:doc>
<doc:summary>
The new location as a freeform string.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users location.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own location</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the location of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetHomeDirectory">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="homedir" direction="in" type="s">
<doc:doc>
<doc:summary>
The new homedir as an absolute path.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users home directory.
</doc:para>
<doc:para>
Note that changing the users home directory moves all the content
from the old location to the new one, and is potentially an
expensive operation.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the home directory of a user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetShell">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="shell" direction="in" type="s">
<doc:doc>
<doc:summary>
The new user shell.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users shell.
</doc:para>
<doc:para>
Note that setting the shell to a non-allowed program may
prevent the user from logging in.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the shell of a user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetIconFile">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="filename" direction="in" type="s">
<doc:doc>
<doc:summary>
The absolute filename of a png file to use as the users icon.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users icon.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own icon</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the icon of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetLocked">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="locked" direction="in" type="b">
<doc:doc>
<doc:summary>
Whether to lock or unlock the users account.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Locks or unlocks a users account.
</doc:para>
<doc:para>
Locking an account prevents the user from logging in.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To lock or unlock user accounts</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetAccountType">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="accountType" direction="in" type="i">
<doc:doc>
<doc:summary>
The new account type, encoded as an integer:
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Standard user</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Administrator</doc:definition>
</doc:item>
</doc:list>
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Changes the users account type.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change an account type</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetPasswordMode">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="mode" direction="in" type="i">
<doc:doc>
<doc:summary>
The new password mode, encoded as an integer:
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Regular password</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Password must be set at next login</doc:definition>
</doc:item>
<doc:item>
<doc:term>2</doc:term>
<doc:definition>No password</doc:definition>
</doc:item>
</doc:list>
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Changes the users password mode.
</doc:para>
<doc:para>
Note that changing the password mode has the side-effect of
unlocking the account.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change a users password mode</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetPassword">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="password" direction="in" type="s">
<doc:doc>
<doc:summary>
The crypted password.
</doc:summary>
</doc:doc>
</arg>
<arg name="hint" direction="in" type="s">
<doc:doc>
<doc:summary>
The password hint.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets a new password for this user.
</doc:para>
<doc:para>
Note that setting a password has the side-effect of
unlocking the account.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the password of a user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetPasswordHint">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="hint" direction="in" type="s">
<doc:doc>
<doc:summary>
The password hint.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Sets the users password hint.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.change-own-user-data</doc:term>
<doc:definition>To change his own language</doc:definition>
</doc:item>
<doc:item>
<doc:term>org.freedesktop.accounts.user-administration</doc:term>
<doc:definition>To change the language of another user</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="SetAutomaticLogin">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="enabled" direction="in" type="b">
<doc:doc>
<doc:summary>
Whether to enable automatic login for this user.
</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Enables or disables automatic login for a user.
</doc:para>
<doc:para>
Note that usually only one user can have automatic login
enabled, so turning it on for a user will disable it for
the previously configured autologin user.
</doc:para>
</doc:description>
<doc:permission>
The caller needs one of the following PolicyKit authorizations:
<doc:list>
<doc:item>
<doc:term>org.freedesktop.accounts.set-login-option</doc:term>
<doc:definition>To change the login screen configuration</doc:definition>
</doc:item>
</doc:list>
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<property name="Uid" type="t" access="read">
<doc:doc>
<doc:description>
<doc:para>
The uid of the user.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="UserName" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The username of the user.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="RealName" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users real name.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="AccountType" type="i" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users account type, encoded as an integer:
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Standard user</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Administrator</doc:definition>
</doc:item>
</doc:list>
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="HomeDirectory" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users home directory.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="Shell" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users shell.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="Email" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The email address.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="Language" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users language, as a locale specification like "de_DE.UTF-8".
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="XSession" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users x session.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="Location" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The users location.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="LoginFrequency" type="t" access="read">
<doc:doc>
<doc:description>
<doc:para>
How often the user has logged in.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="LoginTime" type="x" access="read">
<doc:doc>
<doc:description>
<doc:para>
The last login time.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="LoginHistory" type="a(xxa{sv})" access="read">
<doc:doc>
<doc:description>
<doc:para>
The login history for this user.
Each entry in the array represents a login session. The first two
members are the login time and logout time, as timestamps (seconds since the epoch). If the session is still running, the logout time
is 0.
</doc:para>
<doc:para>
The a{sv} member is a dictionary containing additional information
about the session. Possible members include 'type' (with values like ':0', 'tty0', 'pts/0' etc).
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="IconFile" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The filename of a png file containing the users icon.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="Locked" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether the users account is locked.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="PasswordMode" type="i" access="read">
<doc:doc>
<doc:description>
<doc:para>
The password mode for the user account, encoded as an integer:
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Regular password</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Password must be set at next login</doc:definition>
</doc:item>
<doc:item>
<doc:term>2</doc:term>
<doc:definition>No password</doc:definition>
</doc:item>
</doc:list>
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="PasswordHint" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The password hint for the user.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="AutomaticLogin" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether automatic login is enabled for the user.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="SystemAccount" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether this is a 'system' account, like 'root' or 'nobody'.
System accounts should normally not appear in lists of
users, and ListCachedUsers will not include such accounts.
</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="LocalAccount" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>
Whether the user is a local account or not.
</doc:para>
</doc:description>
</doc:doc>
</property>
<signal name="Changed">
<doc:doc>
<doc:description>
<doc:para>
Emitted when the user is changed.
</doc:para>
</doc:description>
</doc:doc>
</signal>
</interface>
</node>
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" >
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="org.freedesktop.Accounts">
<!-- ************************************************************ -->
<method name="ListCachedUsers">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="users" direction="out" type="ao">
<doc:doc><doc:summary>Object paths of cached users</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Lists users which have logged into the system locally before.
This is not meant to return an exhaustive list of all users.
It is possible for <doc:ref type="method" to="Accounts.FindUserByName">FindUserByName()</doc:ref>
to return a user that's not on the list.
</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="FindUserById">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="id" direction="in" type="x">
<doc:doc><doc:summary>The uid to look up</doc:summary></doc:doc>
</arg>
<arg name="user" direction="out" type="o">
<doc:doc><doc:summary>Object path of user</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Finds a user by uid.
</doc:para>
</doc:description>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if no user with the given uid exists</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="FindUserByName">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc><doc:summary>The username to look up</doc:summary></doc:doc>
</arg>
<arg name="user" direction="out" type="o">
<doc:doc><doc:summary>Object path of user</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Finds a user by its username.
</doc:para>
</doc:description>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if no user with the given username exists</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="CreateUser">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc><doc:summary>The username for the new user</doc:summary></doc:doc>
</arg>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="fullname" direction="in" type="s">
<doc:doc><doc:summary>The real name for the new user</doc:summary></doc:doc>
</arg>
<arg name="user" direction="out" type="o">
<doc:doc><doc:summary>Object path of the new user</doc:summary></doc:doc>
</arg>
<arg name="accountType" direction="in" type="i">
<doc:doc>
<doc:summary>The account type, encoded as an integer</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Creates a new user account.
</doc:para>
<doc:para>
The accountType argument can take the following values:
</doc:para>
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Standard user</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Administrator</doc:definition>
</doc:item>
</doc:list>
</doc:description>
<doc:permission>
The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="CacheUser">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc><doc:summary>The username for the user</doc:summary></doc:doc>
</arg>
<arg name="user" direction="out" type="o">
<doc:doc><doc:summary>Object path of user</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Caches a user account, so that it shows up in ListCachedUsers() output.
The user name may be a remote user, but the system must be able to lookup
the user name and resolve the user information.
</doc:para>
</doc:description>
<doc:permission>
The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.UserDoesNotExist">if the user name cannot be resolved</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="UncacheUser">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
<doc:doc><doc:summary>The username for the user</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Releases all metadata about a user account, including icon, language and session. If the user account is
from a remote server and the user has never logged in before, then that account will no longer show up
in ListCachedUsers() output.
</doc:para>
</doc:description>
<doc:permission>
The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.UserDoesNotExist">if the user name cannot be resolved</doc:error>
</doc:errors>
</doc:doc>
</method>
<method name="DeleteUser">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="id" direction="in" type="x">
<doc:doc><doc:summary>The uid to delete</doc:summary></doc:doc>
</arg>
<arg name="removeFiles" direction="in" type="b">
<doc:doc><doc:summary>Whether to remove the users files</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Deletes a user account.
</doc:para>
</doc:description>
<doc:permission>
The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
</method>
<signal name="UserAdded">
<arg name="user" type="o">
<doc:doc><doc:summary>Object path of the user that was added.</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Emitted when a user is added.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="UserDeleted">
<arg name="user" type="o">
<doc:doc><doc:summary>Object path of the user that was deleted.</doc:summary></doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>
Emitted when a user is deleted.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<property name="DaemonVersion" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>
The version of the running daemon.
</doc:para>
</doc:description>
</doc:doc>
</property>
</interface>
</node>
<node name='/org/freedesktop/ScreenSaver'>
<interface name='org.freedesktop.ScreenSaver'>
<method name='Lock'/>
<method name='SimulateUserActivity'/>
<method name='GetActive'>
<arg type='b' direction='out'/>
</method>
<method name='GetActiveTime'>
<arg name='seconds' type='u' direction='out'/>
</method>
<method name='GetSessionIdleTime'>
<arg name='seconds' type='u' direction='out'/>
</method>
<method name='SetActive'>
<arg type='b' direction='out'/>
<arg name='e' type='b' direction='in'/>
</method>
<method name='Inhibit'>
<arg name='application_name' type='s' direction='in'/>
<arg name='reason_for_inhibit' type='s' direction='in'/>
<arg name='cookie' type='u' direction='out'/>
</method>
<method name='UnInhibit'>
<arg name='cookie' type='u' direction='in'/>
</method>
<method name='Throttle'>
<arg name='application_name' type='s' direction='in'/>
<arg name='reason_for_inhibit' type='s' direction='in'/>
<arg name='cookie' type='u' direction='out'/>
</method>
<method name='UnThrottle'>
<arg name='cookie' type='u' direction='in'/>
</method>
<signal name='ActiveChanged'>
<arg type='b'/>
</signal>
</interface>
</node>
[D-BUS Service]
Name=org.freedesktop.impl.portal.desktop.gtk
Exec=@libexecdir@/xdg-desktop-portal-gtk
SystemdService=xdg-desktop-portal-gtk.service
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!--
Copyright (C) 2013 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.gnome.ScreenSaver:
An interface used for managing the lock screen.
-->
<interface name="org.gnome.ScreenSaver">
<method name="Lock" />
<method name="GetActive">
<arg name="active" direction="out" type="b" />
</method>
<method name="SetActive">
<arg name="value" direction="in" type="b" />
</method>
<method name="GetActiveTime">
<arg name="value" direction="out" type="u" />
</method>
<signal name="ActiveChanged">
<arg name="new_value" type="b" />
</signal>
</interface>
</node>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="org.gnome.SessionManager">
<!-- Initialization phase interfaces -->
<method name="Setenv">
<arg name="variable" type="s" direction="in">
<doc:doc>
<doc:summary>The variable name</doc:summary>
</doc:doc>
</arg>
<arg name="value" type="s" direction="in">
<doc:doc>
<doc:summary>The value</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Adds the variable name to the application launch environment with the specified value. May only be used during the Session Manager initialization phase.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="GetLocale">
<arg name="category" type="i" direction="in">
<doc:doc>
<doc:summary>The locale category</doc:summary>
</doc:doc>
</arg>
<arg name="value" type="s" direction="out">
<doc:doc>
<doc:summary>The value</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Reads the current state of the specific locale category.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="InitializationError">
<arg name="message" type="s" direction="in">
<doc:doc>
<doc:summary>The error message</doc:summary>
</doc:doc>
</arg>
<arg name="fatal" type="b" direction="in">
<doc:doc>
<doc:summary>Whether the error should be treated as fatal</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>May be used by applications launched during the Session Manager initialization phase to indicate there was a problem.</doc:para>
</doc:description>
</doc:doc>
</method>
<!-- Running phase interfaces -->
<method name="RegisterClient">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="s" name="app_id" direction="in">
<doc:doc>
<doc:summary>The application identifier</doc:summary>
</doc:doc>
</arg>
<arg type="s" name="client_startup_id" direction="in">
<doc:doc>
<doc:summary>Client startup identifier</doc:summary>
</doc:doc>
</arg>
<arg type="o" name="client_id" direction="out">
<doc:doc>
<doc:summary>The object path of the newly registered client</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Register the caller as a Session Management client.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="UnregisterClient">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="o" name="client_id" direction="in">
<doc:doc>
<doc:summary>The object path of the client</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Unregister the specified client from Session Management.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="Inhibit">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="s" name="app_id" direction="in">
<doc:doc>
<doc:summary>The application identifier</doc:summary>
</doc:doc>
</arg>
<arg type="u" name="toplevel_xid" direction="in">
<doc:doc>
<doc:summary>The toplevel X window identifier</doc:summary>
</doc:doc>
</arg>
<arg type="s" name="reason" direction="in">
<doc:doc>
<doc:summary>The reason for the inhibit</doc:summary>
</doc:doc>
</arg>
<arg type="u" name="flags" direction="in">
<doc:doc>
<doc:summary>Flags that specify what should be inhibited</doc:summary>
</doc:doc>
</arg>
<arg type="u" name="inhibit_cookie" direction="out">
<doc:doc>
<doc:summary>The cookie</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:summary>
Proactively indicates that the calling application is performing an action that should not be interrupted and sets a reason to be displayed to the user when an interruption is about to take placea.
</doc:summary>
<doc:description>
<doc:para>Applications should invoke this method when they begin an operation that
should not be interrupted, such as creating a CD or DVD. The types of actions
that may be blocked are specified by the flags parameter. When the application
completes the operation it should call <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref>
or disconnect from the session bus.
</doc:para>
<doc:para>
Applications should not expect that they will always be able to block the
action. In most cases, users will be given the option to force the action
to take place.
</doc:para>
<doc:para>
Reasons should be short and to the point.
</doc:para>
<doc:para>
The flags parameter must include at least one of the following:
<doc:list>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>Inhibit logging out</doc:definition>
</doc:item>
<doc:item>
<doc:term>2</doc:term>
<doc:definition>Inhibit user switching</doc:definition>
</doc:item>
<doc:item>
<doc:term>4</doc:term>
<doc:definition>Inhibit suspending the session or computer</doc:definition>
</doc:item>
<doc:item>
<doc:term>8</doc:term>
<doc:definition>Inhibit the session being marked as idle</doc:definition>
</doc:item>
<doc:item>
<doc:term>16</doc:term>
<doc:definition>Inhibit auto-mounting removable media for the session</doc:definition>
</doc:item>
</doc:list>
Values for flags may be bitwise or'ed together.
</doc:para>
<doc:para>
The returned cookie is used to uniquely identify this request. It should be used
as an argument to <doc:ref type="method" to="org.gnome.SessionManager.Uninhibit">Uninhibit()</doc:ref> in
order to remove the request.
</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="Uninhibit">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="u" name="inhibit_cookie" direction="in">
<doc:doc>
<doc:summary>The cookie</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Cancel a previous call to <doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref> identified by the cookie.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="IsInhibited">
<arg type="u" name="flags" direction="in">
<doc:doc>
<doc:summary>Flags that spefify what should be inhibited</doc:summary>
</doc:doc>
</arg>
<arg type="b" name="is_inhibited" direction="out">
<doc:doc>
<doc:summary>Returns TRUE if any of the operations in the bitfield flags are inhibited</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Determine if operation(s) specified by the flags
are currently inhibited. Flags are same as those accepted
by the
<doc:ref type="method" to="org.gnome.SessionManager.Inhibit">Inhibit()</doc:ref>
method.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="GetClients">
<arg name="clients" direction="out" type="ao">
<doc:doc>
<doc:summary>an array of client IDs</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Client">Clients</doc:ref>
that are currently known to the session manager.</doc:para>
<doc:para>Each Client ID is an D-Bus object path for the object that implements the
<doc:ref type="interface" to="org.gnome.SessionManager.Client">Client</doc:ref> interface.</doc:para>
</doc:description>
<doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Client">org.gnome.SessionManager.Client</doc:ref></doc:seealso>
</doc:doc>
</method>
<method name="GetInhibitors">
<arg name="inhibitors" direction="out" type="ao">
<doc:doc>
<doc:summary>an array of inhibitor IDs</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>This gets a list of all the <doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitors</doc:ref>
that are currently known to the session manager.</doc:para>
<doc:para>Each Inhibitor ID is an D-Bus object path for the object that implements the
<doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">Inhibitor</doc:ref> interface.</doc:para>
</doc:description>
<doc:seealso><doc:ref type="interface" to="org.gnome.SessionManager.Inhibitor">org.gnome.SessionManager.Inhibitor</doc:ref></doc:seealso>
</doc:doc>
</method>
<method name="IsAutostartConditionHandled">
<arg name="condition" direction="in" type="s">
<doc:doc>
<doc:summary>The autostart condition string</doc:summary>
</doc:doc>
</arg>
<arg name="handled" direction="out" type="b">
<doc:doc>
<doc:summary>True if condition is handled, false otherwise</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Allows the caller to determine whether the session manager is
handling changes to the specified autostart condition.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="Shutdown">
<doc:doc>
<doc:description>
<doc:para>Request a shutdown dialog.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="Reboot">
<doc:doc>
<doc:description>
<doc:para>Request a reboot dialog.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="CanShutdown">
<arg name="is_available" direction="out" type="b">
<doc:doc>
<doc:summary>True if shutdown is available to the user, false otherwise</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Allows the caller to determine whether or not it's okay to show
a shutdown option in the UI</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="Logout">
<arg name="mode" type="u" direction="in">
<doc:doc>
<doc:summary>The type of logout that is being requested</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Request a logout dialog</doc:para>
<doc:para>
Allowed values for the mode parameter are:
<doc:list>
<doc:item>
<doc:term>0</doc:term>
<doc:definition>Normal.</doc:definition>
</doc:item>
<doc:item>
<doc:term>1</doc:term>
<doc:definition>No confirmation inferface should be shown.</doc:definition>
</doc:item>
<doc:item>
<doc:term>2</doc:term>
<doc:definition>Forcefully logout. No confirmation will be shown and any inhibitors will be ignored.</doc:definition>
</doc:item>
</doc:list>
Values for flags may be bitwise or'ed together.
</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="IsSessionRunning">
<arg name="running" direction="out" type="b">
<doc:doc>
<doc:summary>True if the session has entered the Running phase, false otherwise</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Allows the caller to determine whether the session manager
has entered the Running phase, in case the client missed the
SessionRunning signal.</doc:para>
</doc:description>
</doc:doc>
</method>
<!-- Signals -->
<signal name="ClientAdded">
<arg name="id" type="o">
<doc:doc>
<doc:summary>The object path for the added client</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Emitted when a client has been added to the session manager.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="ClientRemoved">
<arg name="id" type="o">
<doc:doc>
<doc:summary>The object path for the removed client</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Emitted when a client has been removed from the session manager.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="InhibitorAdded">
<arg name="id" type="o">
<doc:doc>
<doc:summary>The object path for the added inhibitor</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Emitted when an inhibitor has been added to the session manager.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="InhibitorRemoved">
<arg name="id" type="o">
<doc:doc>
<doc:summary>The object path for the removed inhibitor</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Emitted when an inhibitor has been removed from the session manager.
</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="SessionRunning">
<doc:doc>
<doc:description>
<doc:para>Indicates the session has entered the Running phase.</doc:para>
</doc:description>
</doc:doc>
</signal>
<signal name="SessionOver">
<doc:doc>
<doc:description>
<doc:para>Indicates the session is about to end.</doc:para>
</doc:description>
</doc:doc>
</signal>
<!-- Properties -->
<property name="SessionName" type="s" access="read">
<doc:doc>
<doc:description>
<doc:para>The name of the session that has been loaded.</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="SessionIsActive" type="b" access="read">
<doc:doc>
<doc:description>
<doc:para>If true, the session is currently in the
foreground and available for user input.</doc:para>
</doc:description>
</doc:doc>
</property>
<property name="InhibitedActions" type="u" access="read">
<doc:doc>
<doc:description>
<doc:para>A bitmask of flags to indicate which actions
are inhibited. See the Inhibit() function's description
for a list of possible values.</doc:para>
</doc:description>
</doc:doc>
</property>
</interface>
</node>
[Desktop Entry]
Type=Application
Name=Portal
# TRANSLATORS: Don't translate this text (this is icon name)
Icon=applications-system-symbolic
Exec=@libexecdir@/xdg-desktop-portal-gtk
NoDisplay=true
[Unit]
Description=Portal service (GTK/GNOME implementation)
PartOf=graphical-session.target
After=graphical-session.target
[Service]
Type=dbus
BusName=org.freedesktop.impl.portal.desktop.gtk
ExecStart=@libexecdir@/xdg-desktop-portal-gtk
project(
'xdg-desktop-portal-gtk',
'c',
version: '1.15.3',
meson_version: '>= 0.61.2',
license: 'LGPL-2.1-or-later',
default_options: ['warning_level=2'],
)
prefix = get_option('prefix')
datadir = prefix / get_option('datadir')
libexecdir = prefix / get_option('libexecdir')
sysconfdir = prefix / get_option('sysconfdir')
localedir = prefix / get_option('localedir')
dbus_service_dir = get_option('dbus-service-dir')
if dbus_service_dir == ''
dbus_service_dir = prefix / datadir / 'dbus-1' / 'services'
endif
systemd_userunit_dir = get_option('systemd-user-unit-dir')
if systemd_userunit_dir == ''
# This is deliberately not ${libdir}: systemd units always go in
# .../lib, never .../lib64 or .../lib/x86_64-linux-gnu
systemd_userunit_dir = prefix / 'lib' / 'systemd' / 'user'
endif
dataroot_dir = get_option('datarootdir')
if dataroot_dir == ''
dataroot_dir = datadir
endif
i18n = import('i18n')
gnome = import('gnome')
pkgconfig = import('pkgconfig')
root_inc = include_directories('.')
config_h = configuration_data()
config_h.set_quoted('G_LOG_DOMAIN', 'xdg-desktop-portal-gtk')
config_h.set_quoted('DATADIR', datadir)
config_h.set_quoted('LIBEXECDIR', libexecdir)
config_h.set_quoted('LOCALEDIR', localedir)
config_h.set_quoted('SYSCONFDIR', sysconfdir)
config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name())
config_h.set_quoted('PACKAGE_NAME', meson.project_name())
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
config_h.set_quoted('PACKAGE_STRING', '@0@ @1@'.format(meson.project_name(), meson.project_version()))
xdp_dep = dependency('xdg-desktop-portal', version: '>=1.14.0')
desktop_portal_interfaces_dir = xdp_dep.get_variable(pkgconfig: 'interfaces_dir')
if xdp_dep.version().version_compare('>= 1.19.1')
config_h.set('HAVE_XDP_1_19_1', 1)
endif
portal_deps = [
xdp_dep,
dependency('glib-2.0', version: '>=2.44'),
dependency('gio-unix-2.0'),
dependency('gtk+-3.0', version: '>=3.14'),
dependency('gtk+-unix-print-3.0'),
]
gtkx11_dep = dependency('gtk+-x11-3.0', required: false)
config_h.set('HAVE_GTK_X11', gtkx11_dep.found())
gtkwayland_dep = dependency('gtk+-wayland-3.0', version: '>=3.21.5', required: false)
config_h.set('HAVE_GTK_WAYLAND', gtkwayland_dep.found())
configure_file(output: 'config.h', configuration: config_h)
subdir('data')
subdir('src')
subdir('po')
summary({
'DBus service dir': dbus_service_dir,
'Portal interfaces dir': desktop_portal_interfaces_dir,
'systemd user unit dir': systemd_userunit_dir,
},
section: 'Directories',
)
summary({
'X11': gtkx11_dep.found(),
'Wayland': gtkwayland_dep.found(),
},
bool_yn: true,
section: 'Dependencies',
)
summary({
'Wallpaper': get_option('wallpaper'),
'Settings': get_option('settings'),
'AppChooser': get_option('appchooser'),
'Lockdown': get_option('lockdown'),
},
bool_yn: true,
section: 'Portals',
)
option('dbus-service-dir',
type: 'string',
value: '',
description: 'directory for dbus service files (default: PREFIX/share/dbus-1/services)')
option('systemd-user-unit-dir',
type: 'string',
value: '',
description: 'directory for systemd user service files (default: PREFIX/lib/systemd/user)')
option('datarootdir',
type: 'string',
value: '',
description: 'Define the datarootdir for the pkgconf file')
# Features
option('wallpaper',
type: 'feature',
value: 'auto',
description: 'Enable Wallpaper portal (requires: gnome-desktop)')
option('settings',
type: 'feature',
value: 'auto',
description: 'Enable Settings portal (requires: fontconfig, gsettings-desktop-schemas)')
option('appchooser',
type: 'feature',
value: 'auto',
description: 'Enable AppChooser portal')
option('lockdown',
type: 'feature',
value: 'auto',
description: 'Enable Lockdown portal')
be
ca
cs
da
de
en_GB
es
fr
gl
he
hi
hr
hu
id
ie
it
ja
ka
lt
nl
oc
pl
pt
pt_BR
ro
ru
sk
sl
sr
sv
tr
uk
zh_CN
zh_TW
# List of source files containing translatable strings.
data/xdg-desktop-portal-gtk.desktop.in.in
src/access.c
src/accountdialog.c
src/accountdialog.ui
src/appchooserdialog.c
src/appchooserdialog.ui
src/dynamic-launcher.c
src/filechooser.c
src/settings.c
src/wallpaperdialog.c
src/wallpaperdialog.ui
src/wallpaperpreview.ui
# Belarusian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2023 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Yuras Shumovich <shumovichy@gmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-01-03 15:31+0000\n"
"PO-Revision-Date: 2023-01-03 23:22+0300\n"
"Last-Translator: Yuras Shumovich <shumovichy@gmail.com>\n"
"Language-Team: Belarusian <i18n-bel-gnome@googlegroups.com>\n"
"Language: be\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.2.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Партал"
#: src/access.c:271
msgid "Deny Access"
msgstr "Забараніць доступ"
#: src/access.c:274
msgid "Grant Access"
msgstr "Дазволіць доступ"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Выберыце выяву"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Скасаваць"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Выбраць"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Ачысціць"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Выявы"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Даць доступ да персанальнай інфармацыі для %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Даць доступ да персанальнай інфармацыі для праграмы?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Падрабязнасці"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Скасаваць"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Даць доступ"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Унясіце змены, перш чым даць доступ да інфармацыі"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Не ўдалося запусціць кіраўнік праграмнага забеспячэнне"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Выберыце праграму, каб адкрыць файл «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Выберыце праграму."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Не ўсталявана праграмы, якая можа адкрываць «%s». Больш праграм можна "
"знайсці ў кіраўніку праграмнага забеспячэння"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Не ўсталявана адпаведнай праграмы. Больш праграм можна знайсці ў кіраўніку "
"праграмнага забеспячэння."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Адкрыць праз…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Адкрыць"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Няма даступных праграм"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Шукаць у кіраўніку праграмнага забеспячэнне"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» выконваецца ў фонавым рэжыме"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Гэта можа мець аб'ектыўную прычыну, але праграма яе не ўказала.\n"
"\n"
"Звярніце ўвагу, што прымусовае завяршэнне працы праграмы можа прывесці да "
"страты даныя."
#: src/background.c:220
msgid "Force quit"
msgstr "Прымусова завяршыць"
#: src/background.c:221
msgid "Allow"
msgstr "Дазволіць"
#: src/background.c:306
msgid "Background activity"
msgstr "Фонавая актыўнасць"
#: src/background.c:314
msgid "Find out more"
msgstr "Даведацца больш"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Выбраць"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Захаваць"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Адкрыць файлы ў рэжыме толькі для чытання"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Указальнік"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Клавіятура"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Сэнсарны экран"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Выберыце прылады, да якіх будзе доступ у %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Выберыце прылады, да якіх будзе доступ у праграмы"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Аддалены працоўны стол"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Доступ да экрана"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Выберыце манітор, да якога будзе доступ у %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Выберыце акно, да якога будзе доступ у %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Выберыце манітор, да якога будзе доступ у праграмы"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Выберыце акно, да якога будзе доступ у праграмы"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Асобнае акно"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Увесь экран"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Даць доступ да здымкаў для %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Даць доступ да здымкаў для праграмы?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Здымак экрана"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Параметры…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Зрабіць _здымак экрана"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Зрабіць здымак экрана"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Здымка ўсяго _экрана"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Здымка бягучага _акна"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Вылучыце _вобласць здымкі"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Затрымка перад _здымкай"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "секунд"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Эфекты"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Улучыць _указальнік мышы"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Улучыць _мяжу акна"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Запытаная налада не знойдзена"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Задаць як фон"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Задаць"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Не ўдалося загрузіць выяву"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Дзейнасць"
#, c-format
#~ msgid "Share your personal information with %1$s? %2$s"
#~ msgstr "Даць доступ да персанальнай інфармацыі для %1$s? %2$s"
#, c-format
#~ msgid "Share your personal information with the requesting application? %s"
#~ msgstr "Даць доступ да персанальнай інфармацыі для праграмы? %s"
#~ msgid "Name"
#~ msgstr "Імя"
#~ msgid "Username"
#~ msgstr "Імя карыстальніка"
#~ msgid "Create Web Application"
#~ msgstr "Стварыць вэб-праграму"
#~ msgid "Create Application"
#~ msgstr "Стварыць праграму"
#~ msgid "C_reate"
#~ msgstr "С_тварыць"
#~ msgid "Allow remote interaction"
#~ msgstr "Дазволіць аддаленае ўзаемадзеянне"
#~ msgid "Virtual monitor"
#~ msgstr "Віртуальны манітор"
#~ msgid "Remember this selection"
#~ msgstr "Запомніць гэты выбар"
# Catalan translation for xdg-desktop-portal-gtk.
# Copyright (C) 2021 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# maite <maite.guix@gmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/issues\n"
"POT-Creation-Date: 2023-02-21 03:33+0000\n"
"PO-Revision-Date: 2021-11-10 17:35+0100\n"
"Last-Translator: maite guix <maite.guix@me.com>\n"
"Language-Team: Catalan <gnome@llistes.softcatala.org>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Denega l'accés"
#: src/access.c:274
msgid "Grant Access"
msgstr "Permet l'accés"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Seleccioneu una imatge"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancel·la"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Selecciona"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Neteja"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imatges"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Voleu compartir informació personal amb %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Voleu compartir informació personal amb l'aplicació sol·licitant?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Comparteix detalls"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Cancel·la"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Comparteix"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Fer canvis abans de compartir la informació"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Ha fallat en iniciar el programari"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Trieu una aplicació per a obrir el fitxer «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Trieu una aplicació."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"No hi ha cap app instal·lada que pugui obrir «%s». Podeu trobar més "
"aplicacions a Programari"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"No s'ha instal·lat cap app adequada. Podeu trobar més aplicacions al "
"Programari."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Obre amb…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Obre"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "No hi ha cap app disponible"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Cerca més a Programari"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» s'està executant en segon pla"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Això pot ser una raó legítima, però l'aplicació no ha proporcionat cap.\n"
"\n"
"Tingueu en compte que forçar la sortida d'una aplicació pot causar la pèrdua de dades."
#: src/background.c:220
msgid "Force quit"
msgstr "Força la sortida"
#: src/background.c:221
msgid "Allow"
msgstr "Permet"
#: src/background.c:306
msgid "Background activity"
msgstr "Activitat en segon pla"
#: src/background.c:314
msgid "Find out more"
msgstr "Troba'n més"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Crea una aplicació web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Crea una aplicació"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "C_rea"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Selecciona"
#: src/filechooser.c:465
msgid "_Save"
msgstr "De_sa"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "Obre fitxers de només lectura"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Punter"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Teclat"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Pantalla tàctil"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Seleccioneu els dispositius a compartir amb %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Seleccioneu els dispositius a compartir amb l'aplicació sol·licitant"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Escriptori remot"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Compartició de pantalla"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Seleccioneu el monitor que voleu compartir amb %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Seleccioneu la finestra a compartir amb %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr ""
"Seleccioneu el monitor que voleu compartir amb l'aplicació sol·licitant"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr ""
"Seleccioneu la finestra que voleu compartir amb l'aplicació sol·licitant"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Una sola finestra"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Tota la pantalla"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Voleu compartir aquesta captura de pantalla amb %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr ""
"Voleu compartir aquesta captura de pantalla amb l'aplicació sol·licitant?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Captura de pantalla"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opcions…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "_Fes una captura de pantalla"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Fes una captura de pantalla"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "_Captura tota la pantalla"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "C_aptura la finestra actual"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "_Selecciona l'àrea a capturar"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "_Captura després d'un retard de"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "segons"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efectes"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "_Inclou el punter"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "In_clou la vora de la finestra"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "No s'ha trobat la configuració sol·licitada"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Estableix el fons"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Estableix"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "No s'ha pogut carregar la imatge"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Activitats"
# Czech translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016-2017 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
#
# Marek Černocký <marek@manet.cz>, 2016.
# Daniel Rusek <mail@asciiwolf.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-03-04 13:38+0000\n"
"PO-Revision-Date: 2023-03-13 13:14+0100\n"
"Last-Translator: Daniel Rusek <mail@asciiwolf.com>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Poedit 3.2.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portál"
#: src/access.c:271
msgid "Deny Access"
msgstr "Zamítnout přístup"
#: src/access.c:274
msgid "Grant Access"
msgstr "Udělit přístup"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Vyberte obrázek"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Zrušit"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Vybrat"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Vymazat"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Obrázky"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Sdílet vaše osobní informace s aplikací %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Sdílet vaše osobní informace s aplikací, která o to žádá?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Sdílet detaily"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Zrušit"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Sdílet"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Provést změny před sdílením informací"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Nepodařilo se spustit Software"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Vyberte aplikaci pro otevření souboru „%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Vyberte aplikaci."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nejsou nainstalovány žádné aplikace pro otevření „%s”. Více aplikací můžete "
"najít v Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Není nainstalována žádná vhodná aplikace. Více aplikací můžete najít v "
"Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Otevřít pomocí…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Otevřít"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nejsou dostupné žádné aplikace"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "N_ajít další v Software"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "Aplikace „%s” běží na pozadí"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Může to být z legitimního důvodu, aplikace však žádný důvod neposkytla.\n"
"\n"
"Berte prosím na vědomí, že vynucení ukončení aplikace může způsobit ztrátu "
"dat."
#: src/background.c:220
msgid "Force quit"
msgstr "Vynutit ukončení"
#: src/background.c:221
msgid "Allow"
msgstr "Povolit"
#: src/background.c:306
msgid "Background activity"
msgstr "Aktivita na pozadí"
#: src/background.c:314
msgid "Find out more"
msgstr "Zjistit více"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Vytvořit webovou aplikaci"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Vytvořit aplikaci"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "_Vytvořit"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Vybrat"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Uložit"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "Otevřít soubory pouze pro čtení"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Kurzor"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Klávesnice"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Dotyková obrazovka"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Vyberte zařízení pro sdílení s aplikací %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Vyberte zařízení pro sdílení s aplikací, která o to žádá"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Vzdálená plocha"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Sdílení obrazovky"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Vyberte monitor pro sdílení s aplikací %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Vyberte okno pro sdílení s aplikací %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Vyberte monitor pro sdílení s aplikací, která o to žádá"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Vyberte okno pro sdílení s aplikací, která o to žádá"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Samostatné okno"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Celá obrazovka"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Sdílet tento snímek obrazovky s aplikací %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Sdílet tento snímek obrazovky s aplikací, která o to žádá?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Snímek obrazovky"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Volby…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Zachytit _snímek obrazovky"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Zachytit snímek obrazovky"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Zachytit celou ob_razovku"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Zachytit akt_uální okno"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Vybr_at zachytávanou oblast"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Zachytit po pro_dlevě"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "sekund"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efekty"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Zahrnout _kurzor myši"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Zahrnout _rámeček okna"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Požadované nastavení nebylo nalezeno"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Nastavit pozadí"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Nastavit"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Selhalo načtení souboru obrázku"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Činnosti"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "Aplikace %s běží na pozadí."
#~ msgid "Set Lock Screen"
#~ msgstr "Nastavit uzamknutou obrazovku"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Nastavit pozadí a uzamknutou obrazovku"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Vyberte aplikaci pro otevření „%s”. Další aplikace jsou k dispozici v <a "
#~ "href='software'>Software.</a>"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Vyberte aplikaci. Další aplikace jsou k dispozici v <a "
#~ "href='software'>Software.</a>"
#~ msgid "Unable to find a suitable application."
#~ msgstr "Nenalezena žádná vhodná aplikace."
#~ msgid "No Applications Found"
#~ msgstr "Nenalezeny žádné aplikace"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Najít kompatibilní aplikace v Software"
#~ msgid "Forbid"
#~ msgstr "Zakázat"
#~ msgid "Ignore"
#~ msgstr "Ignorovat"
#~ msgid "Screen casting"
#~ msgstr "Záznam obrazovky"
# Danish translation for xdg-desktop-portal-gtk
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# scootergrisen, 2018-2020.
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-10-12 01:17+0200\n"
"Last-Translator: scootergrisen\n"
"Language-Team: Danish\n"
"Language: da\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Nægt adgang"
#: src/access.c:274
msgid "Grant Access"
msgstr "Giv adgang"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Vælg et billede"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Annuller"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Vælg"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Ryd"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Billeder"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Del dine personlige informationer med %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Del dine personlige informationer med det anmodede program?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Delingsdetaljer"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Annuller"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Del"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Foretag ændringer inden informationen deles"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Kunne ikke starte Software"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Vælg et program til at åbne filen “%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Vælg et program."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Der er ikke installeret nogle programmer som kan åbne “%s”. Du kan finde "
"flere programmer i Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Der er ikke installeret noget egnet program. Du kan finde flere programmer i "
"Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Åbn med …"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Åbn"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Der er ikke nogle programmer tilgængelige"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Find flere i Software"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "“%s” kører i baggrunden."
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Der kan være en legitim årsag men programmet har ikke angivet en.\n"
"\n"
"Bemærk, at det kan føre til tab af data hvis et program tvinges til at "
"afslutte."
#: src/background.c:220
msgid "Force quit"
msgstr "Gennemtving afslutning"
#: src/background.c:221
msgid "Allow"
msgstr "Tillad"
#: src/background.c:306
msgid "Background activity"
msgstr "Baggrundsaktivitet"
#: src/background.c:314
msgid "Find out more"
msgstr "Find ud af mere"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Vælg"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Gem"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Åbn filer som skrivebeskyttede"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Markør"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Tastatur"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Berøringsfølsom skærm"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Vælg enheder som skal deles med %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Vælg enheder som skal deles med det anmodede program"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Fjernskrivebord"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Skærmdeling"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Vælg skærm som skal deles med %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Vælg vindue som skal deles med %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Vælg skærm som skal deles med det anmodede program"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Vælg vindue som skal deles med det anmodede program"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Ét vindue"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Hele skærmen"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Del skærmbilledet med %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Del skærmbilledet med det anmodede program?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Skærmbillede"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Valgmuligheder …"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Tag _skærmbillede"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Tag skærmbillede"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Indfang _hele skærmen"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Indfang det nuværende _vindue"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Vælg _område som skal indfanges"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Indfang efter en _forsinkelse på"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "sekunder"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Effekter"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Medtag _markør"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Medtag vinduets _kant"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Anmodede indstilling ikke fundet"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Indstil baggrund"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Indstil"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Kunne ikke indlæse billedfil"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Aktiviteter"
# German translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Christian Kirbach <Christian.Kirbach@gmail.com>, 2016, 2018.
# Mario Blättermann <mario.blaettermann@gmail.com>, 2018.
# Ettore Atalan <atalanttore@gmail.com>, 2022.
# Jürgen Benvenuti <gastornis@posteo.org>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-09-12 15:31+0000\n"
"PO-Revision-Date: 2023-09-12 20:10+0200\n"
"Last-Translator: Jürgen Benvenuti <gastornis@posteo.org>\n"
"Language-Team: German <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Zugriff verweigern"
#: src/access.c:274
msgid "Grant Access"
msgstr "Zugriff gewähren"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Ein Bild auswählen"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Abbrechen"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Auswählen"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Löschen"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Bilder"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Möchten Sie Ihre persönlichen Daten mit %s teilen?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr ""
"Möchten Sie Ihre persönlichen Daten mit der anfragenden Anwendung teilen?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Details freigeben"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "Abbre_chen"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Teilen"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Änderungen vor der Freigabe der Informationen durchführen"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Software konnte nicht gestartet werden"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Wählen Sie eine Anwendung zum Öffnen der Datei »%s«."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Eine Anwendung wählen."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Es sind keine Anwendungen installiert, die »%s« öffnen können. Weitere "
"Anwendungen finden Sie unter Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Keine passende Anwendung installiert. Weitere Anwendungen finden Sie unter "
"Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Öffnen mit …"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Öffnen"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Keine Anwendungen verfügbar"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Finden Sie mehr in Software"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Web-Anwendung erstellen"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Anwendung erstellen"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "E_rstellen"
#: src/filechooser.c:463
msgid "_Select"
msgstr "Au_swählen"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Speichern"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Dateien schreibgeschützt öffnen"
#: src/settings.c:216
msgid "Requested setting not found"
msgstr "Angeforderte Einstellung nicht gefunden"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Hintergrund festlegen"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Festlegen"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Bilddatei konnte nicht geladen werden"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Aktivitäten"
#, c-format
#~ msgid "“%s” is running in the background"
#~ msgstr "»%s« läuft im Hintergrund"
#~ msgid ""
#~ "This might be for a legitimate reason, but the application has not "
#~ "provided one.\n"
#~ "\n"
#~ "Note that forcing an application to quit might cause data loss."
#~ msgstr ""
#~ "Dies könnte einen legitimen Grund haben, aber die Anwendung hat keinen "
#~ "solchen angegeben.\n"
#~ "\n"
#~ "Beachten Sie, dass das erzwungene Beenden einer Anwendung zu Datenverlust "
#~ "führen kann."
#~ msgid "Force quit"
#~ msgstr "Beenden erzwingen"
#~ msgid "Allow"
#~ msgstr "Erlauben"
#~ msgid "Background activity"
#~ msgstr "Hintergrundaktivität"
#~ msgid "Find out more"
#~ msgstr "Mehr dazu erfahren"
#~ msgid "Pointer"
#~ msgstr "Zeiger"
#~ msgid "Keyboard"
#~ msgstr "Tastatur"
#~ msgid "Touch screen"
#~ msgstr "Tastbildschirm"
#, c-format
#~ msgid "Select devices to share with %s"
#~ msgstr "Geräte auswählen, die mit %s geteilt werden sollen"
#~ msgid "Select devices to share with the requesting application"
#~ msgstr ""
#~ "Geräte auswählen, die mit der anfragenden Anwendung geteilt werden sollen"
#~ msgid "Remote desktop"
#~ msgstr "Entfernter Bildschirm"
#~ msgid "Screen Share"
#~ msgstr "Bildschirm teilen"
#, c-format
#~ msgid "Select monitor to share with %s"
#~ msgstr "Bildschirm auswählen, der mit %s geteilt werden soll"
#, c-format
#~ msgid "Select window to share with %s"
#~ msgstr "Fenster auswählen, das mit %s geteilt werden soll"
#~ msgid "Select monitor to share with the requesting application"
#~ msgstr ""
#~ "Bildschirm auswählen, der mit der anfragenden Anwendung geteilt werden "
#~ "soll"
#~ msgid "Select window to share with the requesting application"
#~ msgstr ""
#~ "Fenster auswählen, das mit der anfordernden Anwendung geteilt werden soll"
#~ msgid "Single Window"
#~ msgstr "Einzelnes Fenster"
#~ msgid "Entire Screen"
#~ msgstr "Gesamter Bildschirm"
#, c-format
#~ msgid "Share this screenshot with %s?"
#~ msgstr "Soll dieses Bildschirmfoto mit %s geteilt werden?"
#~ msgid "Share this screenshot with the requesting application?"
#~ msgstr ""
#~ "Soll dieses Bildschirmfoto mit der anfragenden Anwendung geteilt werden?"
#~ msgid "Screenshot"
#~ msgstr "Bildschirmfoto"
#~ msgid "_Options…"
#~ msgstr "_Optionen …"
#~ msgid "Take _Screenshot"
#~ msgstr "Bild_schirmfoto aufnehmen"
#~ msgid "Take Screenshot"
#~ msgstr "Bildschirmfoto aufnehmen"
#~ msgid "Grab the whole sc_reen"
#~ msgstr "Gesamten _Bildschirm aufnehmen"
#~ msgid "Grab the current _window"
#~ msgstr "Aktuelles _Fenster aufnehmen"
#~ msgid "Select _area to grab"
#~ msgstr "Aufnahmebereich _auswählen"
#~ msgid "Grab after a _delay of"
#~ msgstr "Bildschirmfoto _verzögert aufnehmen nach"
#~ msgid "seconds"
#~ msgstr "Sekunden"
#~ msgid "Effects"
#~ msgstr "Effekte"
#~ msgid "Include _pointer"
#~ msgstr "_Zeiger einbeziehen"
#~ msgid "Include the window _border"
#~ msgstr "Fensterrahmen ein_beziehen"
# soll nicht übersetzt werden
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Wählen Sie eine Anwendung zum Öffnen von »%s«. Weitere Anwendungen sind "
#~ "in <a href='software'>Software</a> verfügbar."
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Wählen Sie eine Anwendung. Weitere Anwendungen sind in <a "
#~ "href='software'>Software</a> verfügbar."
#~ msgid "Unable to find a suitable application."
#~ msgstr "Es kann keine passende Anwendung gefunden werden."
#~ msgid "No Applications Found"
#~ msgstr "Keine Anwendungen gefunden"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Kompatible Anwendungen in Software suchen"
#~ msgid "Screen casting"
#~ msgstr "Bildschirmaufzeichnung"
# British English translation for xdg-desktop-portal-gtk.
# Copyright (C) 2019 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Zander Brown <zbrown@gnome.org>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2019-08-24 23:53+0100\n"
"Last-Translator: Zander Brown <zbrown@gnome.org>\n"
"Language-Team: English - United Kingdom <en_GB@li.org>\n"
"Language: en_GB\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 3.32.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Deny Access"
#: src/access.c:274
msgid "Grant Access"
msgstr "Grant Access"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Select an Image"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancel"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Select"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Clear"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Images"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Share your personal information with %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Share your personal information with the requesting application?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Share Details"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Cancel"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Share"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Make changes before sharing the information"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Failed to start Software"
#: src/appchooserdialog.c:385
#, fuzzy, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Unable to find an application that is able to open “%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr ""
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
#: src/appchooserdialog.ui:10
#, fuzzy
msgid "Open With…"
msgstr "Open With"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Open"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr ""
#: src/appchooserdialog.ui:159
#, fuzzy
msgid "_Find More in Software"
msgstr "Failed to start Software"
#: src/background.c:215 src/background.c:308
#, fuzzy, c-format
msgid "“%s” is running in the background"
msgstr "%s is running in the background."
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
#: src/background.c:220
msgid "Force quit"
msgstr ""
#: src/background.c:221
msgid "Allow"
msgstr "Allow"
#: src/background.c:306
msgid "Background activity"
msgstr "Background activity"
#: src/background.c:314
msgid "Find out more"
msgstr ""
#: src/filechooser.c:462
#, fuzzy
msgid "_Select"
msgstr "Select"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Save"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Open files read-only"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Pointer"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Keyboard"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Touch screen"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Select devices to share with %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Select devices to share with the requesting application"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Remote desktop"
#: src/screencastdialog.ui:12
#, fuzzy
msgid "Screen Share"
msgstr "Screenshot"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Select monitor to share with %s"
#: src/screencastwidget.c:489
#, fuzzy, c-format
msgid "Select window to share with %s"
msgstr "Select monitor to share with %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Select monitor to share with the requesting application"
#: src/screencastwidget.c:495
#, fuzzy
msgid "Select window to share with the requesting application"
msgstr "Select monitor to share with the requesting application"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr ""
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr ""
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Share this screenshot with %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Share this screenshot with the requesting application?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Screenshot"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Options…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Take _Screenshot"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Take Screenshot"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Grab the whole sc_reen"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Grab the current _window"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Select _area to grab"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Grab after a _delay of"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "seconds"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Effects"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Include _pointer"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Include the window _border"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr ""
#: src/wallpaperdialog.ui:13
#, fuzzy
msgid "Set Background"
msgstr "Background activity"
#: src/wallpaperdialog.ui:26
#, fuzzy
msgid "Set"
msgstr "Select"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr ""
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr ""
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "%s is running in the background."
#, c-format
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgid "Unable to find a suitable application."
#~ msgstr "Unable to find a suitable application."
#~ msgid "No Applications Found"
#~ msgstr "No Applications Found"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Find Compatible Applications in Software"
#~ msgid "Forbid"
#~ msgstr "Forbid"
#~ msgid "Ignore"
#~ msgstr "Ignore"
#~ msgid "Screen casting"
#~ msgstr "Screen casting"
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# Mario Sanchez Prada <mario@endlessm.com>, 2016.
# leo <daniel.mustieles@gmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2021-12-05 10:47+0100\n"
"Last-Translator: leo <daniel.mustieles@gmail.com>\n"
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 3.38.0\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Denegar el acceso"
#: src/access.c:274
msgid "Grant Access"
msgstr "Conceder el acceso"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Seleccione una imagen"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancelar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Seleccionar"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Vaciar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imágenes"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "¿Quiere compartir su información personal con %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr ""
"¿Quiere compartir su información personal con la aplicación solicitante?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Compartir los datos"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Cancelar"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "Co_mpartir"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Realizar cambios antes de compartir la información"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "No se pudo iniciar Software"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Elija una aplicación para abrir el archivo «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Elija una aplicación."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"No hay aplicaciones instaladas que puedan abrir «%s». Puede encontrar más "
"aplicaciones en Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"No hay ninguna aplicación adecuada instalada. Puede encontrar más "
"aplicaciones en Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Abrir con…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Abrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "No hay aplicaciones disponibles"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Encontrar más en Software"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» se está ejecutando en segundo plano"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Esto podría ser por una buena razón, pero la aplicación no ha proporcionado "
"ninguna.\n"
"\n"
"Tenga en cuenta que forzar el cierre de una aplicación puede causar la "
"pérdida de datos."
#: src/background.c:220
msgid "Force quit"
msgstr "Forzar la salida"
#: src/background.c:221
msgid "Allow"
msgstr "Permitir"
#: src/background.c:306
msgid "Background activity"
msgstr "Actividad en segundo plano"
#: src/background.c:314
msgid "Find out more"
msgstr "Más información"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Seleccionar"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Guardar"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Abrir archivos de sólo lectura"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Puntero"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Teclado"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Pantalla táctil"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Seleccione qué dispositivos compartir con %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Seleccione qué dispositivos compartir con la aplicación solicitante"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Escritorio remoto"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Compartir pantalla"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Seleccione el monitor que quiera compartir con %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Seleccione la ventana que quiera compartir con %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr ""
"Seleccione el monitor que quiera compartir con la aplicación solicitante"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr ""
"Seleccione la ventana que quiera compartir con la aplicación solicitante"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Ventana única"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Toda la pantalla"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "¿Quiere compartir esta captura de pantalla con %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr ""
"¿Quiere compartir esta captura de pantalla con la aplicación solicitante?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Captura de pantalla"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opciones…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Capturar la panta_lla"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Capturar la pantalla"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Capturar _toda la pantalla"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Capturar la _ventana actual"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Seleccionar la _zona que capturar"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Capturar tras un _retardo de"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "segundos"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efectos"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Incluir el _puntero"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Incluir el _borde de la ventana"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "No se ha encontrado la configuración solicitada"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Establecer el fondo"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Establecer"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Fallo al cargar el archivo de imagen"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Actividades"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Seleccione una aplicación para abrir «%s». Hay más aplicaciones "
#~ "disponibles en <a href='software'>Software</a>."
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Seleccione una aplicación. Hay más aplicaciones disponibles en <a "
#~ "href='software'>Software</a>."
#~ msgid "Unable to find a suitable application."
#~ msgstr "No se encontró ninguna aplicación adecuada."
#~ msgid "No Applications Found"
#~ msgstr "No se encontró ninguna aplicación"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Encuentre aplicaciones compatibles en Software"
#~ msgid "Screen casting"
#~ msgstr "Captura de vídeo"
# French translation for xdg-desktop-portal-gtk.
# Copyright (C) 2017 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Claude Paroz <claude@2xlibre.net>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2017-03-02 11:43+0100\n"
"Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
"Language-Team: French <gnomefr@traduc.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr ""
#: src/access.c:271
msgid "Deny Access"
msgstr "Refuser l'accès"
#: src/access.c:274
msgid "Grant Access"
msgstr "Accorder l'accès"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Choisir une image"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Annuler"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Choisir"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Effacer"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Images"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Partager mes informations personelles avec %s ?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr ""
"Partager mes informations personelles avec l'application qui le demande ?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Partager les détails"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "A_nnuler"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Partager"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Effectuer des changements avant de partager les informations"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr ""
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr ""
#: src/appchooserdialog.c:390
#, fuzzy
msgid "Choose an application."
msgstr "Choisir une application"
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
#: src/appchooserdialog.ui:10
#, fuzzy
msgid "Open With…"
msgstr "Ouvrir avec"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Ouvrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr ""
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr ""
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr ""
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
#: src/background.c:220
msgid "Force quit"
msgstr ""
#: src/background.c:221
msgid "Allow"
msgstr ""
#: src/background.c:306
msgid "Background activity"
msgstr ""
#: src/background.c:314
msgid "Find out more"
msgstr ""
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Choisir"
#: src/filechooser.c:464
msgid "_Save"
msgstr ""
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr ""
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr ""
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr ""
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr ""
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr ""
#: src/remotedesktopdialog.c:312
#, fuzzy
msgid "Select devices to share with the requesting application"
msgstr "Partager la capture d'écran avec l'application qui le demande ?"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr ""
#: src/screencastdialog.ui:12
#, fuzzy
msgid "Screen Share"
msgstr "Capture d'écran"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr ""
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr ""
#: src/screencastwidget.c:494
#, fuzzy
msgid "Select monitor to share with the requesting application"
msgstr "Partager la capture d'écran avec l'application qui le demande ?"
#: src/screencastwidget.c:495
#, fuzzy
msgid "Select window to share with the requesting application"
msgstr "Partager la capture d'écran avec l'application qui le demande ?"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr ""
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr ""
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Partager la capture d'écran avec %s ?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Partager la capture d'écran avec l'application qui le demande ?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Capture d'écran"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr ""
#: src/screenshotdialog.ui:55
#, fuzzy
msgid "Take _Screenshot"
msgstr "Capture d'écran"
#: src/screenshotdialog.ui:111
#, fuzzy
msgid "Take Screenshot"
msgstr "Capture d'écran"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr ""
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr ""
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr ""
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr ""
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr ""
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr ""
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr ""
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr ""
#: src/settings.c:217
msgid "Requested setting not found"
msgstr ""
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr ""
#: src/wallpaperdialog.ui:26
#, fuzzy
msgid "Set"
msgstr "Choisir"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr ""
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr ""
#, fuzzy
#~ msgid "No Applications Found"
#~ msgstr "Choisir une application"
#, fuzzy
#~ msgid "Screen casting"
#~ msgstr "Capture d'écran"
# Galician translation for xdg-desktop-portal-gtk.
# Copyright (C) 2017 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Fran Dieguez <frandieguez@gnome.org>, 2017, 2019.
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-30 03:33+0000\n"
"PO-Revision-Date: 2023-02-08 21:12+0100\n"
"Last-Translator: Fran Diéguez <frandieguez@gnome.org>\n"
"Language-Team: Galician\n"
"Language: gl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Denegar acceso"
#: src/access.c:274
msgid "Grant Access"
msgstr "Conceder acceso"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Seleccione unha imaxe"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancelar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Seleccionar"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Limpar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imaxes"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Compartir a súa información persoal con %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Compartir a súa información persoal coa aplicación que o solicita?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Compartir detalles"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Cancelar"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Compartir"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Facer cambios antes de compartir a información"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Produciuse un fallo ao iniciar o Software"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Escolla unha aplicación para abrir «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Escolla unha aplicación."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Non hai ningunha aplicación que poida abrir «%s». Pode atopar máis en "
"Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Non hai ningunha aplicación axeitada instalada. Pode atopar máis aplicacións "
"en Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Abrir con…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Abrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Non hai ningunha aplicación dispoñíbel"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Buscar máis en Software"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» está executándose en segundo plano"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Isto pode ser por unha razón lexítima, pero a aplicación non forneceu "
"ningunha.\n"
"\n"
"Teña en conta que forzar a saída dunha unha aplicación pode causar a perda "
"de datos."
#: src/background.c:220
msgid "Force quit"
msgstr "Forzar a saída"
#: src/background.c:221
msgid "Allow"
msgstr "Permitir"
#: src/background.c:306
msgid "Background activity"
msgstr "Actividade en segundo plano"
#: src/background.c:314
msgid "Find out more"
msgstr "Saber máis"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Seleccionar"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Gardar"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Abrir ficheiros en modo só lectura"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Punteiro"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Teclado"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Pantalla táctil"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Seleccione os dispositivos a compartir con %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Seleccione os dispositivos a compartir coa aplicación que o solicita"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Escritorio remoto"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Compartición de pantalla"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Seleccione o monitor a compartir con %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Seleccione a xanela a compartir con %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Compartir o monitor para compartir coa aplicación que o solicita"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Escolla a xanela que quere compartir coa aplicación que o solicita"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Unha sola xanela"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Toda a pantalla"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Compartir esta captura de pantalla con %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Compartir esta captura de pantalla coa aplicación que o solicita?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Captura de pantalla"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opcións…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Facer unha _captura de pantalla"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Facer unha captura de pantalla"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Capturar toda a _pantalla"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Capturar a _xanela actual"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Seleccione o _área a capturar"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Capturar despois dun _atraso de"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "segundos"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efectos"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Incluír o _punteiro"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Incluír o _bordo da xanela"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "A preferencia solicitada non se atopou"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Estabelecer fondo de pantalla"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Estabelecer"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Produciuse un fallo ao cargar o ficheiro da imaxe"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Actividades"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "%s está executándose en segundo plano."
#~ msgid "Set Lock Screen"
#~ msgstr "Estabelecer a pantalla de bloqueo"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Estabelecer fondo e pantalla de bloqueo"
# Hebrew translation for xdg-desktop-portal-gtk.
# Copyright (C) 2022 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Yosef Or Boczko <yoseforb@gmail.com>, 2022-2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-09-01 03:33+0000\n"
"PO-Revision-Date: 2024-09-26 13:11+0300\n"
"Last-Translator: Yosef Or Boczko <yoseforb@gmail.com>\n"
"Language-Team: Hebrew <yoseforb@gmail.com>\n"
"Language: he\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 46.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "שער"
#: src/access.c:271
msgid "Deny Access"
msgstr "מניעת גישה"
#: src/access.c:274
msgid "Grant Access"
msgstr "הענקת גישה"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "בחירת תמונה"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "ביטול"
#: src/accountdialog.c:180
msgid "Select"
msgstr "בחירה"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "ניקוי"
#: src/accountdialog.c:195
msgid "Images"
msgstr "תמונות"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "לשתף את המידע האישי שלך עם %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "לשתף את המידע האישי שלך עם היישומים הדורשים זאת?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "שיתוף פרטים"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "_ביטול"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_שיתוף"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "ביצוע שינויים לפני שיתוף המידע"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "הפעלת תכנה נכשלה"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "נא לבחור יישום לפתיחת הקובץ „%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "בחירת יישום."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"לא מותקנים יישומים שיכולים לפתוח „%s”. ניתן למצוא יישומים נוספים דרך תכנה"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr "לא מותקן יישום מתאים. ניתן למצוא יישומים נוספים בתכנה."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "פתיחה באמצעות…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_פתיחה"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "אין יישומים זמינים"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_איתור נוספים בתכנה"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "יצירת יישום רשת"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "יצירת יישום"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "י_צירה"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_בחירה"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_שמירה"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "פתיחת קבצים לקריאה בלבד"
#: src/settings.c:216
msgid "Requested setting not found"
msgstr "ההגדרה המבוקשת לא נמצאה"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "הגדרת רקע"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "הגדרה"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "טעינת קובץ התמונה נכשלה"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "פעילויות"
#, c-format
#~ msgid "“%s” is running in the background"
#~ msgstr "‫„%s” פועל ברקע"
#~ msgid ""
#~ "This might be for a legitimate reason, but the application has not "
#~ "provided one.\n"
#~ "\n"
#~ "Note that forcing an application to quit might cause data loss."
#~ msgstr ""
#~ "יכול להיות שישנה סיבה מוצדקת לכך, אך זו לא סופקה על ידי היישום.\n"
#~ "‬\n"
#~ "‫‫יש לשים לב שאילוץ יציאה מהיישום עשויה להוביל לאבדן נתונים."
#~ msgid "Force quit"
#~ msgstr "אילוץ יציאה"
#~ msgid "Allow"
#~ msgstr "לאפשר"
#~ msgid "Background activity"
#~ msgstr "פעילות רקע"
#~ msgid "Find out more"
#~ msgstr "למצוא עוד"
#~ msgid "Pointer"
#~ msgstr "סמן"
#~ msgid "Keyboard"
#~ msgstr "מקלדת"
#~ msgid "Touch screen"
#~ msgstr "מסך מגע"
#, c-format
#~ msgid "Select devices to share with %s"
#~ msgstr "נא לבחור התקנים לשיתוף עם %s"
#~ msgid "Select devices to share with the requesting application"
#~ msgstr "נא לבחור התקנים לשיתוף עם היישום שביקש"
#~ msgid "Remote desktop"
#~ msgstr "שולחן עבודה מרוחק"
#~ msgid "Screen Share"
#~ msgstr "שיתוף מסך"
#, c-format
#~ msgid "Select monitor to share with %s"
#~ msgstr "נא לבחור מסך לשיתוף עם %s"
#, c-format
#~ msgid "Select window to share with %s"
#~ msgstr "נא לבחור חלון לשיתוף עם %s"
#~ msgid "Select monitor to share with the requesting application"
#~ msgstr "נא לבחור מסך לשיתוף עם היישום שביקש"
#~ msgid "Select window to share with the requesting application"
#~ msgstr "נא לבחור חלון לשיתוף עם היישום שביקש"
#~ msgid "Single Window"
#~ msgstr "חלון בודד"
#~ msgid "Entire Screen"
#~ msgstr "כל המסך"
#, c-format
#~ msgid "Share this screenshot with %s?"
#~ msgstr "לשתף את הצילום הזה עם %s?"
#~ msgid "Share this screenshot with the requesting application?"
#~ msgstr "לשתף את צילום המסך הזה עם היישום שביקש?"
#~ msgid "Screenshot"
#~ msgstr "צילום מסך"
#~ msgid "_Options…"
#~ msgstr "_אפשרויות…"
#~ msgid "Take _Screenshot"
#~ msgstr "_צילום המסך"
#~ msgid "Take Screenshot"
#~ msgstr "צילום המסך"
#~ msgid "Grab the whole sc_reen"
#~ msgstr "צילום המסך _כולו"
#~ msgid "Grab the current _window"
#~ msgstr "צילום המסך ה_נוכחי"
#~ msgid "Select _area to grab"
#~ msgstr "בחירת _אזור לצילום"
#~ msgid "Grab after a _delay of"
#~ msgstr "לצלם לאחר ה_שהיה של"
#~ msgid "seconds"
#~ msgstr "שניות"
#~ msgid "Effects"
#~ msgstr "אפקטים"
#~ msgid "Include _pointer"
#~ msgstr "_כולל הסמן"
#~ msgid "Include the window _border"
#~ msgstr "כולל _גבולות החלון"
# Hindi translation for xdg-desktop-portal-gtk.
# Copyright (C) 2021 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Translators:
# Dmitry <dmitrydmitry761@gmail.com>, 2021.
# Hemish <hemish04082005@gmail.com>, 2022.
# Scrambled777 <weblate.scrambled777@simplelogin.com>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2024-05-18 03:33+0000\n"
"PO-Revision-Date: 2024-05-18 10:05+0530\n"
"Last-Translator: Scrambled777 <weblate.scrambled777@simplelogin.com>\n"
"Language-Team: Hindi <indlinux-hindi@lists.sourceforge.net>\n"
"Language: hi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 46.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "पोर्टल"
#: src/access.c:271
msgid "Deny Access"
msgstr "पहुंच अस्वीकारें"
#: src/access.c:274
msgid "Grant Access"
msgstr "पहुंच स्वीकारें"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "एक छवि चुनें"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "रद्द करें"
#: src/accountdialog.c:180
msgid "Select"
msgstr "चुनें"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "साफ करे"
#: src/accountdialog.c:195
msgid "Images"
msgstr "छवियां"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "%s के साथ अपनी व्यक्तिगत जानकारी साझा करें?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "अनुरोध करने वाले अनुप्रयोग के साथ अपनी व्यक्तिगत जानकारी साझा करें?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "जानकारी साझा करें"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "रद्द करें (_C)"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "साझा करें (_S)"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "जानकारी साझा करने से पहले बदलाव करें"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "सॉफ्टवेयर प्रारंभ करने में विफल"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "फाइल “%s” को खोलने के लिए एक अनुप्रयोग चुनें।"
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "एक अनुप्रयोग चुनें।"
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"कोई ऐप स्थापित नहीं है जो “%s” खोल सके। आप 'सॉफ्टवेयर' में और भी अनुप्रयोग पा सकते हैं"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr "कोई उपयुक्त ऐप स्थापित नहीं है। आप 'सॉफ्टवेयर' में और अनुप्रयोग पा सकते हैं।"
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "इससे खोलें…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "खोलें (_O)"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "कोई ऐप उपलब्ध नहीं है"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "'सॉफ्टवेयर' में अधिक पाएं (_F)"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "वेब अनुप्रयोग बनाएं"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "अनुप्रयोग बनाएं"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "बनाएं (_r)"
#: src/filechooser.c:463
msgid "_Select"
msgstr "चुनें (_S)"
#: src/filechooser.c:465
msgid "_Save"
msgstr "सहेजें (_S)"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "फाइलें केवल-पढ़ने के लिए खोलें"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "अनुरोधित सेटिंग नहीं मिली"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "पृष्ठभूमि निर्धारित करें"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "निर्धारित करें"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "छवि फाइल लोड करने में विफल"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "गतिविधियां"
# Croatian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Milo Ivir <mail@milotype.de>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-04-27 07:43+0200\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n"
"Language-Team: \n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.3\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Zabrani pristup"
#: src/access.c:274
msgid "Grant Access"
msgstr "Dozvoli pristup"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Odaberi sliku"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Odustani"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Odaberi"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Izbriši"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Slike"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Osobne podatke dijeliti s %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Osobne podatke dijeliti s programom koji ih zahtijeva?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Dijeli detalje"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Odustani"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Dijeli"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Izradi promjene prije dijeljenja podataka"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Neuspjelo pokretanje Softvera"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Odaberi program za otvaranje datoteke „%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Odaberi program."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nema programa za otvaranje datoteke „%s”. Nađi daljnje programe u Softveru"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr "Nema odgovarajućeg programa. Nađi daljnje programe u Softveru."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Otvori s …"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Otvori"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nema programa"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Nađi daljnje u Softveru"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "„%s” radi u pozadini"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Ovo može biti iz opravdanog razloga, ali program ga nije naveo.\n"
"\n"
"Napomena: prisilno zatvaranje programa može prouzročiti gubitak podataka."
#: src/background.c:220
msgid "Force quit"
msgstr "Prisilno zatvori"
#: src/background.c:221
msgid "Allow"
msgstr "Dozvoli"
#: src/background.c:306
msgid "Background activity"
msgstr "Radnje u pozadini"
#: src/background.c:314
msgid "Find out more"
msgstr "Saznaj više"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Odaberi"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Spremi"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Otvori datoteke u zaštićenom stanju"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Pokazivač"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Tipkovnica"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Ekran na dodir"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Odaberi uređaje za dijeljenje s %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Odaberi uređaje za dijeljenje s programom koji ih zahtijeva"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Udaljena radna površina"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Dijeljenje ekrana"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Odaberi monitor za dijeljenje s %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Odaberi prozor za dijeljenje s %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Odaberi monitor za dijeljenje s programom koji ga zahtijeva"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Odaberi prozor za dijeljenje s programom koji ga zahtijeva"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Jedan prozor"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Cijeli ekran"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Ovu snimku ekrana dijeliti s %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Ovu snimku ekrana dijeliti s programom koji je zahtijeva?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Snimka ekrana"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opcije …"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "_Snimi ekran"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Snimi ekran"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Snimi cijeli ek_ran"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Snimi trenutačni pro_zor"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Od_aberi područje za snimku"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Snimi s kašnjenjem o_d"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "s"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efekti"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Snimi s _pokazivačem"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Snimi s _okvirom prozora"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Zatražena postavka nije nađena"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Postavi pozadinu"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Postavi"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Neuspjelo učitavanje slike"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Radnje"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "„%s” radi u pozadini."
#~ msgid "Set Lock Screen"
#~ msgstr "Postavi zaključani erkan"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Postavi pozadinu i zaključani erkan"
# Hungarian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016, 2017, 2018, 2019, 2022 Free Software Foundation, Inc.
# This file is distributed under the same license as the xdg-sesktop-portal-gtk package.
#
# Balázs Úr <ur.balazs at fsf dot hu>, 2016, 2017, 2018, 2019, 2022.
# Dévényi Benedek <rdbende@proton.me>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2024-03-09 18:19+0100\n"
"Last-Translator: Dévényi Benedek <rdbende@proton.me>\n"
"Language-Team: Hungarian <>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 45.3\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portál"
#: src/access.c:271
msgid "Deny Access"
msgstr "Hozzáférés megtagadása"
#: src/access.c:274
msgid "Grant Access"
msgstr "Hozzáférés megadása"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Válasszon képet"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Mégse"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Kiválasztás"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Törlés"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Képek"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Megosztja a személyes információit ezzel: %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Megosztja a személyes információit a kérelmező alkalmazással?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Részletek megosztása"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Mégse"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "Meg_osztás"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Megváltoztatás az információk megosztása előtt"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Nem sikerült elindítani a Szoftvert"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Válasszon egy alkalmazást a(z) „%s” fájl megnyitásához."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Válasszon egy alkalmazást."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nincsenek olyan alkalmazások telepítve, amelyek meg tudják nyitni a(z) „%s” "
"fájlt. További alkalmazásokat találhat a Szoftverben"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nincs megfelelő alkalmazás telepítve. További alkalmazásokat találhat a "
"Szoftverben."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Megnyitás ezzel…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Megnyitás"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nem érhetők el alkalmazások"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Továbbiak keresése a Szoftverben"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "A(z) „%s” a háttérben fut"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Ez jogos okból is lehet, de az alkalmazás nem adott meg egyet sem.\n"
"\n"
"Vegye figyelembe, hogy az alkalmazás kilépésre kényszerítése adatvesztést "
"okozhat."
#: src/background.c:220
msgid "Force quit"
msgstr "Erőltetett kilépés"
#: src/background.c:221
msgid "Allow"
msgstr "Engedélyezés"
#: src/background.c:306
msgid "Background activity"
msgstr "Háttérbeli tevékenység"
#: src/background.c:314
msgid "Find out more"
msgstr "Tudjon meg többet"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Kiválasztás"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Mentés"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Fájlok megnyitása csak olvasásra"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Mutató"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Billentyűzet"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Érintőképernyő"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Válassza ki az ezzel megosztani kívánt eszközöket: %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Válassza ki a kérelmező alkalmazással megosztani kívánt eszközöket"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Távoli asztal"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Képernyőmegosztás"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Válasszon képernyőt az ezzel történő megosztáshoz: %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Válasszon ablakot az ezzel történő megosztáshoz: %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Válasszon képernyőt a kérő alkalmazással történő megosztáshoz"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Válasszon ablakot a kérő alkalmazással történő megosztáshoz"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Egyetlen ablak"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Teljes képernyő"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Megosztja ezt a képernyőképet ezzel: %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Megosztja ezt a képernyőképet a kérő alkalmazással?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Képernyőkép"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Beállítások…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "_Képernyőkép készítése"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Képernyőkép készítése"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "A teljes képernyő _rögzítése"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "A jelenlegi _ablak rögzítése"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Rögzítendő _terület kijelölése"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Rögzítés ennyi késleltetés _után"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "másodperc"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Hatások"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "_Mutató felvétele"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Az ablak _szegélyét is tartalmazza"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "A kért beállítás nem található"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Háttérkép beállítása"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Beállítás"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "A képfájl betöltése sikertelen"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Tevékenységek"
# Indonesian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2017 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Kukuh Syafaat <kukuhsyafaat@gnome.org>, 2017-2020.
# Andika Triwidada <andika@gmail.com>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-09-01 03:33+0000\n"
"PO-Revision-Date: 2024-10-31 18:42+0700\n"
"Last-Translator: Kukuh Syafaat <kukuhsyafaat@gnome.org>\n"
"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.5\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Tolak Akses"
#: src/access.c:274
msgid "Grant Access"
msgstr "Beri Akses"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Pilih Gambar"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Batal"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Pilih"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Bersihkan"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Gambar"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Bagikan informasi pribadi Anda dengan %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Bagikan informasi pribadi Anda dengan aplikasi yang meminta?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Bagikan Detail"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "Ba_tal"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Bagikan"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Buat perubahan sebelum membagikan informasi"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Gagal memulai Perangkat Lunak"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Pilih aplikasi untuk membuka berkas \"%s\"."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Pilih aplikasi."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Tidak ada aplikasi yang dipasang yang dapat membuka \"%s\". Anda dapat "
"menemukan lebih banyak aplikasi di Perangkat Lunak"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Tidak ada aplikasi yang cocok dipasang. Anda dapat menemukan lebih banyak "
"aplikasi di Perangkat Lunak."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Buka Dengan…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "B_uka"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Tidak ada Aplikasi yang tersedia"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "T_emukan Lebih Banyak dalam Perangkat Lunak"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Buat Aplikasi Web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Buat Aplikasi"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "_Buat"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Pilih"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Simpan"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Buka berkas hanya-baca"
#: src/settings.c:216
msgid "Requested setting not found"
msgstr "Pengaturan yang diminta tidak ditemukan"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Atur Latar Belakang"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Atur"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Gagal memuat berkas gambar"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Aktivitas"
# Interlingue translation for xdg-desktop-portal-gtk.
# Copyright (C) 2024 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Olga Smirnova <mistresssilvara@hotmail.com>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2024-08-17 15:32+0000\n"
"PO-Revision-Date: 2024-08-18 08:06+0700\n"
"Last-Translator: OIS <mistresssilvara@hotmail.com>\n"
"Language-Team: Interlingue\n"
"Language: ie\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Gtranslator 46.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portale"
#: src/access.c:271
msgid "Deny Access"
msgstr "Refusar li accesse"
#: src/access.c:274
msgid "Grant Access"
msgstr "Permisser li accesse"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Selecter un image"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Anullar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Selecter"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Vacuar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Images"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Esque partir vor personal information con %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Esque partir vor personal information con li demandant application?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Detallies de partite"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "A_nullar"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Partir"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Far modificationes ante que partir li information"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Ne successat lansar li Programmarium"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Selecte un application por aperter li file «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Selecte un application."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Null applicationes quel posse aperter «%s» es installat. On posse trovar "
"additional applicationes in li Programmarium."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Null convenent applicationes es installat. On posse trovar additional "
"applicationes in li Programmarium."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Aperter per…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Aperter"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Null applicationes disponibil"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Trovar plu in li Programmarium"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Crear un application web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Crear un application"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "C_rear"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Selecter"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Gardar"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Aperter files solmen por letion"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "Un besonat parametre ne esset trovat"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Assignar quam li funde"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Assignar"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Ne successat cargar li file de image"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Activitás"
# Italian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2017, 2018, 2019, 2020 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Milo Casagrande <milo@milo.name>, 2017, 2018, 2019, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-08-06 08:43+0200\n"
"Last-Translator: Milo Casagrande <milo@milo.name>\n"
"Language-Team: Italian <gnome-it-list@gnome.org>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portale"
#: src/access.c:271
msgid "Deny Access"
msgstr "Nega accesso"
#: src/access.c:274
msgid "Grant Access"
msgstr "Consenti accesso"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Seleziona una immagine"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Annulla"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Seleziona"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Azzera"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Immagini"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Condividere le proprie informazioni personali con %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr ""
"Condividere le proprie informazioni personali con l'applicazione che le "
"richiede?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Dettagli"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "A_nnulla"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "Co_ndividi"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Applica modifiche prima di condividere"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Avvio di «Software» non riuscito"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Scegliere un'applicazione per aprire il file «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Scegliere un'applicazione."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nessuna app installata può aprire «%s»; è possibile trovare altre "
"applicazioni in Software."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nessuna app compatibile installata; è possibile trovare altre applicazioni "
"in Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Apri con…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "A_pri"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nessuna app disponibile"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Trova in Software"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» è in esecuzione sullo sfondo"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Ciò potrebbe essere per un motivo ben definito, ma l'applicazione non ne ha "
"fornito alcuno.\n"
"\n"
"Attenzione: forzare l'uscita di un'applicazione potrebbe causare la perdita "
"di dati."
#: src/background.c:220
msgid "Force quit"
msgstr "Uscita forzata"
#: src/background.c:221
msgid "Allow"
msgstr "Consenti"
#: src/background.c:306
msgid "Background activity"
msgstr "Attività sullo sfondo"
#: src/background.c:314
msgid "Find out more"
msgstr "Maggiori informazioni"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Seleziona"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Salva"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Apri file in sola-lettura"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Puntatore"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Tastiera"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Schermo tattile"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Selezionare i dispositivi da condividere con %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr ""
"Selezionare i dispositivi da condividere con l'applicazione che li richiede"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Desktop remoto"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Condivisione dello schermo"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Selezionare la schermata da condividere con %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Selezionare la finestra da condividere con %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr ""
"Selezionare la schermata da condividere con l'applicazione che la richiede"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr ""
"Selezionare la finestra da condividere con l'applicazione che la richiede"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Finestra singola"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Schermo intero"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Condividere questa schermata con %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Condividere questa schermata con l'applicazione che la richiede?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Schermata"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "Op_zioni…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Cattura _schermata"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Cattura schermata"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Cattura l'intero sc_hermo"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Cattura la _finestra corrente"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Seleziona l'_area da catturare"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "C_attura dopo un ritardo di"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "secondi"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Effetti"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Includere il _puntatore"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Includere il _bordo finestra"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Impostazione richiesta non trovata"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Imposta sfondo"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Imposta"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Caricamento immagine non riuscito"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Attività"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#~ msgid "%s is running in the background."
#~ msgstr "%s è in esecuzione sullo sfondo."
#~ msgid "Set Lock Screen"
#~ msgstr "Imposta blocca schermo"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Imposta sfondo e blocca schermo"
# Japanese translations for xdg-desktop-portal-gtk package.
# Copyright (C) 2024 THE xdg-desktop-portal-gtk'S COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Ryo Nakano <ryonakaknock3@gmail.com>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-06-08 19:50+0900\n"
"PO-Revision-Date: 2024-06-08 20:45+0900\n"
"Last-Translator: Ryo Nakano <ryonakaknock3@gmail.com>\n"
"Language-Team: none\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "ポータル"
#: src/access.c:271
msgid "Deny Access"
msgstr "アクセスを拒否"
#: src/access.c:274
msgid "Grant Access"
msgstr "アクセスを許可"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "画像を選択"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "キャンセル"
#: src/accountdialog.c:180
msgid "Select"
msgstr "選択"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "クリア"
#: src/accountdialog.c:195
msgid "Images"
msgstr "画像"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "あなたの個人情報を %s で共有しますか?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "あなたの個人情報を、要求しているアプリケーションで共有しますか?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "共有の詳細"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "キャンセル(_C)"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "共有(_S)"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "情報の共有前に変更を加える"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "“ソフトウェア”の起動に失敗しました"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "“%s”を開くアプリケーションを選択してください。"
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "アプリケーションを選択してください。"
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"“%s”を開くことができるアプリがインストールされていません。“ソフトウェア”でア"
"プリを探してください。"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"適切なアプリがインストールされていません。“ソフトウェア”でアプリを探してくだ"
"さい。"
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "次で開く…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "開く(_O)"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "利用可能なアプリなし"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "“ソフトウェア”で探す(_F)"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Web アプリケーションを作成"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "アプリケーションを作成"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "作成(_R)"
#: src/filechooser.c:463
msgid "_Select"
msgstr "選択(_S)"
#: src/filechooser.c:465
msgid "_Save"
msgstr "保存(_S)"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "読み取り専用でファイルを開く"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "要求された設定が見つかりませんでした"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "背景を設定"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "設定"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "画像ファイルの読み込みに失敗しました"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "アクティビティ"
# xdg-desktop-portal-gtk translation to Georgian.
# Copyright (C) 2022 Copyright © 2016 Red Hat
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk 1.14.0\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2022-10-29 06:00+0200\n"
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
"Language-Team: Georgian <(nothing)>\n"
"Language: ka\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "პორტალი"
#: src/access.c:271
msgid "Deny Access"
msgstr "წვდომის უარყოფა"
#: src/access.c:274
msgid "Grant Access"
msgstr "წვდომის მინიჭება"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "მონიშნეთ გამოსახულება"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "გაუქმება"
#: src/accountdialog.c:180
msgid "Select"
msgstr "აირჩიეთ"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "გაწმენდა"
#: src/accountdialog.c:195
msgid "Images"
msgstr "გამოსახულებები"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "გავუზიაროთ თქვენი პირადი ინფორმაცია %s -ს?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "გავუზიარო თქვენი პირადი ინფორმაცია მომთხოვნ აპლიკაციას?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "დეტალების გაზიარება"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_გაუქმება"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_გაზიარება"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "შეცვალეთ ინფორმაციის გაზიარებამდე"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "პროგრამის გაშვების შეცდომა"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "აირჩიეთ \"%s\" ფაილის გასახნელი აპლიკაცია."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "აირჩიეთ აპლიკაცია."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"დაყენებული პროგრამებიდან %s-ის გახსნა არც ერთს არ შეუძლია. დააყენეთ მეტი "
"პროგრამა"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"შესაბამისი აპლიკაცია დაყენებული არაა. მეტი აპლიკაციების პოვნა პროგრამებში "
"შეგიძლიათ."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "გამხსნელი პროგრამა…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_გახსნა"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "აპები მიუწვდომელია"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_მეტის პროგრამის პოვნა"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "\"%s\" ფონურადაა გაშვებული"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"ეს შეიძლება კანონიერი მიზეზიც კი იყოს, მაგრამ აპლიკაციას ეს გათვალისწინებული "
"არ აქვს.\n"
"\n"
"გაითვალისწინეთ, რომ აპლიკაციის ძალით დახურვამ შეიძლება მონაცემების კარგვაც "
"გამოიწვიოს."
#: src/background.c:220
msgid "Force quit"
msgstr "ძალით გასვლა"
#: src/background.c:221
msgid "Allow"
msgstr "დაშვება"
#: src/background.c:306
msgid "Background activity"
msgstr "ფონური აქტივობა"
#: src/background.c:314
msgid "Find out more"
msgstr "მეტის გაგება"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_არჩევა"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_შენახვა"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "ფაილის მხოლოდ-წაკითხვად რეჟიმში გახსნა"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "კურსორი"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "კლავიატურა"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "სენსორული ეკრანი"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "აირჩიეთ %s-სთან გასაზიარებელი მოწყობილობები"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "აირჩიეთ მომთხოვნი აპლიკაციისთვის გასაზიარებელი მოწყობილობები"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "დაშორებული სამუშაო მაგიდა"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "ეკრანის გაზიარება"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "აირჩიეთ %s-სთან გასაზიარებელი ეკრანი"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "აირჩიეთ %s-სთან გასაზიარებელი ფანჯარა"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "აირჩიეთ მომთხოვნი აპლიკაციისთვის გასაზიარებელი ეკრანი"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "აირჩიეთ მომთხოვნი აპლიკაციისთვის გასაზიარებელი აპლიკაცია"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "ერთი ფანჯარა"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "მთელ ეკრანზე"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "გავუზიარო ეკრანის ანაბეჭდი %s-ს?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "გავუზიარო ეკრანის ანაბეჭდი მომთხოვნ აპლიკაციას?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "ეკრანის ანაბეჭდი"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_მორგება…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "ეკრანის ანაბეჭდის გადაღება"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "ეკრანის ანაბეჭდის გადაღება"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "მთლიანი _ეკრანის დათრევა"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "_მიმდინარე ფანჯრის დათრევა"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "მონიშნეთ დასათრევი ადგილი"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "დათრევის _პაუზა"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "წამები"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "ეფექტები"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "გამოჩნდება კურსორიც"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "ფანჯრის _ჩარჩოც გამოჩნდება"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "მოთხოვნილი პარამეტრი ვერ მოიძებნა"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "ფონის დაყენება"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "დაყენება"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "გამოსახულების ფაილის ჩატვირთვის შეცდომა"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "ქმედებები"
# Lithuanian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2018 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Moo, 2018, 2019, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-03-07 20:21+0200\n"
"Last-Translator: Moo\n"
"Language-Team: Lithuanian <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.3\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portalas"
#: src/access.c:271
msgid "Deny Access"
msgstr "Drausti prieigą"
#: src/access.c:274
msgid "Grant Access"
msgstr "Suteikti prieigą"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Pasirinkti paveikslą"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Atsisakyti"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Pasirinkti"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Išvalyti"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Paveikslai"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Bendrinti jūsų asmeninę informaciją su %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Bendrinti jūsų asmeninę informaciją su prašančia programa?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Bendrinti išsamesnę informaciją"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Atsisakyti"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Bendrinti"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Prieš bendrinant informaciją, atlikti pakeitimus"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Nepavyko paleisti Programinės įrangos"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Pasirinkite programą, skirtą atverti \"%s\"."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Pasirinkite programą."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nėra programų, kurios galėtų atverti \"%s\". Daugiau programų galite rasti "
"Programinėje įrangoje"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Neįdiegta jokia tinkama programa. Daugiau programų galite rasti Programinėje "
"įrangoje."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Atverti naudojant…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Atverti"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nėra prieinamų programų"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Rasti daugiau Programinėje įrangoje"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "\"%s\" veikia fone"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Taip gali būti dėl pagrįstos priežasties, tačiau programa priežasties "
"nenurodė.\n"
"\n"
"Turėkite omenyje, kad privertus programą užbaigti darbą, gali būti prarasti "
"duomenys."
#: src/background.c:220
msgid "Force quit"
msgstr "Priverstinai baigti darbą"
#: src/background.c:221
msgid "Allow"
msgstr "Leisti"
#: src/background.c:306
msgid "Background activity"
msgstr "Foninė veikla"
#: src/background.c:314
msgid "Find out more"
msgstr "Sužinoti daugiau"
#: src/filechooser.c:462
#, fuzzy
msgid "_Select"
msgstr "Pasirinkti"
#: src/filechooser.c:464
msgid "_Save"
msgstr "Į_rašyti"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Atverti failus tik skaitymui"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Rodyklė"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Klaviatūra"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Jutiklinis ekranas"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Pasirinkti įrenginius, kuriuos bendrinti su %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Pasirinkti įrenginius, kuriuos bendrinti su prašančia programa"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Nuotolinis darbalaukis"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Ekrano bendrinimas"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Pasirinkti vaizduoklį, kurį bendrinti su %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Pasirinkti langą, kurį bendrinti su %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Pasirinkti vaizduoklį, kurį bendrinti su prašančia programa"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Pasirinkti langą, kurį bendrinti su prašančia programa"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Vienas langas"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Visas ekranas"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Bendrinti šią ekrano kopiją su %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Bendrinti šią ekrano kopiją su prašančia programa?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Ekrano kopija"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Parametrai…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Padaryti _ekrano kopiją"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Padaryti ekrano kopiją"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Fotografuoti visą ek_raną"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Fotografuoti esamą _langą"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Pasirinkti sr_itį, kurią fotografuoti"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "_Delsti fotografuoti"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "sekundes"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efektai"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Įtraukti _rodyklę"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Įtraukti lango rė_melį"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Užklaustas nustatymas nerastas"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Nustatyti foną"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Nustatyti"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Nepavyko įkelti paveikslo failo"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Apžvalga"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "%s yra vykdoma fone."
#~ msgid "Set Lock Screen"
#~ msgstr "Nustatyti užrakto ekraną"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Nustatyti foną ir užrakto ekraną"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Pasirinkite programą, skirtą atverti \"%s\". Daugiau programų yra "
#~ "prieinama <a href='software'>Programinėje įrangoje.</a>"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Pasirinkite programą. Daugiau programų yra prieinama <a "
#~ "href='software'>Programinėje įrangoje.</a>"
#~ msgid "Unable to find a suitable application."
#~ msgstr "Nepavyko rasti tinkamos programos."
#~ msgid "No Applications Found"
#~ msgstr "Nerasta jokių programų"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Rasti suderinamas programas Programinėje įrangoje"
#~ msgid "Forbid"
#~ msgstr "Drausti"
#~ msgid "Ignore"
#~ msgstr "Nepaisyti"
#~ msgid "Screen casting"
#~ msgstr "Ekrano įrašymas"
i18n.gettext(meson.project_name(), preset: 'glib')
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Copyright © 2016 Red Hat
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk 1.8.0\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2021-07-17 17:58+0200\n"
"Last-Translator: Heimen Stoffels <vistausss@fastmail.com>\n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portaal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Toegang weigeren"
#: src/access.c:274
msgid "Grant Access"
msgstr "Toegang verlenen"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Kies een afbeelding"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Annuleren"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Kiezen"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Wissen"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Afbeeldingen"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Wilt u persoonlijke gegevens delen met %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Wilt u persoonlijke gegevens delen met de toepassing in kwestie?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Gegevens delen"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Annuleren"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Delen"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Maak aanpassingen alvorens te delen"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "GNOME Software kan niet worden gestart"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Kies een toepassing om ‘%s’ mee te openen."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Kies een toepassing."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Er zijn geen toepassingen geïnstalleerd die ‘%s’ kunnen openen. Open GNOME "
"Software om een toepassing te zoeken."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Er zijn geen geschikte toepassingen geïnstalleerd. Open GNOME Software om "
"een toepassing te zoeken."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Openen met…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Openen"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Er zijn geen toepassingen beschikbaar"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "Zoeken in GNOME So_ftware"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "‘%s’ wordt uitgevoerd op de achtergrond"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"De reden hiervoor kan legitiem zijn, maar de toepassing heeft geen reden "
"opgegeven.\n"
"\n"
"Let op: het gedwongen afsluiten van een toepassing kan leiden tot "
"gegevensverlies!"
#: src/background.c:220
msgid "Force quit"
msgstr "Gedwongen afsluiten"
#: src/background.c:221
msgid "Allow"
msgstr "Toestaan"
#: src/background.c:306
msgid "Background activity"
msgstr "Achtergrondactiviteit"
#: src/background.c:314
msgid "Find out more"
msgstr "Meer informatie"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Kiezen"
#: src/filechooser.c:464
msgid "_Save"
msgstr "Op_slaan"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Bestanden openen als alleen-lezen"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Cursor"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Toetsenbord"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Touchscreen"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Kies de apparaten die u wilt delen met %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Kies de apparaten die u wilt delen met de toepassing in kwestie"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Extern bureaublad"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Schermdeling"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Kies het beeldscherm dat u wilt delen met %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Kies het venster dat u wilt delen met %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Kies het beeldscherm dat u wilt delen met de toepassing in kwestie"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Kies het venster dat u wilt delen met de toepassing in kwestie"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Venster"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Gehele scherm"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Wilt u deze schermfoto delen met %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Wilt u deze schermfoto delen met de toepassing in kwestie?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Schermfoto"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opties…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "_Schermfoto maken"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Schermfoto maken"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Gehele sche_rm vastleggen"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Huidige venster _vastleggen"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "V_astleggebied selecteren"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Vastleggen na een wachttij_d van"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "seconden"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Effecten"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Cursor _tonen"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Vensterrand t_onen"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "De opgevraagde instelling bestaat niet"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Achtergrond instellen"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Instellen"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Het bestand kan niet worden geladen"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Activiteiten"
# Occitan translation for xdg-desktop-portal-gtk.
# Copyright (C) 2022 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Quentin PAGÈS <pages_quentin@hotmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2022-01-13 19:22+0100\n"
"Last-Translator: Quentin PAGÈS\n"
"Language-Team: Occitan <totenoc@gmail.com>\n"
"Language: oc\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Refusar l'accès"
#: src/access.c:274
msgid "Grant Access"
msgstr "Acordar l'accès"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Seleccionar un imatge"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Anullar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Causir"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Escafar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imatges"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Partejar vòstras informacions personalas amb %s ?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Partejar vòstras informacions personalas amb l’aplicacion requerenta ?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Partejar los detalhs"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "A_nullar"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Partejar"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Realizar modificacions abans lo partiment d’entresenhas"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Fracàs del lançament de Logicial"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Causissètz una aplicacion per dobrir lo fichièr « %s »."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Causir una aplicacion."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Cap d’aplicacion pas installada per dobrir « %s ». Podètz trobar mai "
"d’aplicacions dins la logitèca."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Cap d’aplicacion adeqüada pas installada. Podètz trapar mai d’aplicacions "
"dins la logitèca."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Dobrir amb…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Dobrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Cap d’aplicacion pas disponibla"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Ne trobar mai dins Logicial"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "« %s » s’executa en rèireplan"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"I a benlèu una rason legitima mas l'aplicacion n’a pas provesida.\n"
"\n"
"Notatz que forçar una aplicacion a quitar pòt menar a una pèrda de donada."
#: src/background.c:220
msgid "Force quit"
msgstr "Forçar a quitar"
#: src/background.c:221
msgid "Allow"
msgstr "Autorizar"
#: src/background.c:306
msgid "Background activity"
msgstr "Activitat en rèireplan"
#: src/background.c:314
msgid "Find out more"
msgstr "Ne saber mai"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Causir"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Enregistrar"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Dobrir los fichièrs en lectura sola"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Puntador"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Clavièr"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Ecran tactil"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Seleccionar los aparelhs de partejar amb %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Seleccionar los aparelhs de partejar amb l’aplicacion requerenta"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Burèu distant"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Partiment d’ecran"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Seleccionatz lo monitor de partejar amb %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Seleccionatz la fenèstra de partejar amb %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Seleccionar lo monitor de partejar amb l’aplicacion requerenta"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Seleccionar la fenèstra de partejar amb l’aplicacion requerenta"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Fenèstra sola"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Ecran entièr"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Partejar aquesta captura d’ecran amb %s ?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Partejar aquesta captura d’ecran amb l’aplicacion demandada ?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Captura d'ecran"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opcions…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Prendre una _captura d'ecran"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Prene una captura d’ecran"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Capturar l'ensemble de l'ec_ran"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Capturar la _fenèstra actuala"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Seleccionar la _zòna de capturar"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Capturar _aprèp un relambi de"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "milisegondas"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efèits"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Inclure lo _puntador"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "_Inclure la bordadura de la fenèstra"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Paramètre demandat pas trobat"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Definir lo rèireplan"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Definir"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Fracàs del cargament del fichièr imatge"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Activitats"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
# Polish translation for xdg-desktop-portal-gtk.
# Copyright © 2016-2023 the xdg-desktop-portal-gtk authors.
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Piotr Drąg <piotrdrag@gmail.com>, 2016-2023.
# Aviary.pl <community-poland@mozilla.org>, 2016-2023.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-03-04 13:38+0000\n"
"PO-Revision-Date: 2023-03-04 14:40+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Odmów dostępu"
#: src/access.c:274
msgid "Grant Access"
msgstr "Udziel dostępu"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Wybór obrazu"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Anuluj"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Wybierz"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Wyczyść"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Obrazy"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Udostępnić informacje o użytkowniku programowi „%s”?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Udostępnić informacje o użytkowniku proszącemu o to programowi?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Udostępnianie informacji"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Anuluj"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Udostępnij"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Umożliwia wprowadzenie zmian przed udostępnieniem informacji"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Uruchomienie Menedżera oprogramowania się nie powiodło"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Proszę wybrać program do otwarcia pliku „%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Proszę wybrać program."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nie zainstalowano żadnych programów, które mogą otwierać pliki „%s”. "
"W Menedżerze oprogramowania można znaleźć więcej programów."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nie zainstalowano odpowiedniego programu. W Menedżerze oprogramowania można "
"znaleźć więcej programów."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Otwarcie za pomocą…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Otwórz"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Brak dostępnych programów"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Znajdź więcej w Menedżerze oprogramowania"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "Program „%s” działa w tle."
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Może się tak dziać z uzasadnionego powodu, ale program go nie podał.\n"
"\n"
"Proszę pamiętać, że wymuszenie zakończenia działania programu może "
"spowodować utratę danych."
#: src/background.c:220
msgid "Force quit"
msgstr "Wymuś zakończenie"
#: src/background.c:221
msgid "Allow"
msgstr "Zezwól"
#: src/background.c:306
msgid "Background activity"
msgstr "Działanie w tle"
#: src/background.c:314
msgid "Find out more"
msgstr "Więcej informacji"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Utworzenie programu WWW"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Utworzenie programu"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "_Utwórz"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Wybierz"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Zapisz"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "Otwarcie plików tylko do odczytu"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Kursor"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Klawiatura"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Ekran dotykowy"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Wybór urządzeń do udostępnienia programowi „%s”"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Wybór urządzeń do udostępnienia proszącemu o to programowi"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Zdalny pulpit"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Udostępnianie ekranu"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Wybór monitora do udostępnienia programowi „%s”"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Wybór okna do udostępnienia programowi „%s”"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Wybór monitora do udostępnienia proszącemu o to programowi"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Wybór okna do udostępnienia proszącemu o to programowi"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Jedno okno"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Cały ekran"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Udostępnić ten zrzut ekranu programowi „%s”?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Udostępnić ten zrzut ekranu proszącemu o to programowi?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Zrzut ekranu"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Opcje…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "_Wykonaj zrzut ekranu"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Zrzut ekranu"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "_Cały ekran"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "O_becne okno"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Zaznaczony ob_szar"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Po _upływie"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "s"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efekty"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Wi_doczny kursor"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "_Krawędź okna"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Nie odnaleziono żądanego ustawienia"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Ustawienie tła"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Ustaw"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Wczytanie pliku obrazu się nie powiodło"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Podgląd"
# Portuguese translation for xdg-desktop-portal-gtk.
# Copyright (C) 2022 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Juliano de Souza Camargo <julianosc@protonmail.com>, 2022.
# Hugo Carvalho <hugokarvalho@hotmail.com>, 2023, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2024-10-16 03:33+0000\n"
"PO-Revision-Date: 2024-10-16 13:33+0100\n"
"Last-Translator: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
"Language-Team: Portuguese < https://l10n.gnome.org/teams/pt/>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-DL-Team: pt\n"
"X-DL-Module: xdg-desktop-portal-gtk\n"
"X-DL-Branch: master\n"
"X-DL-Domain: po\n"
"X-DL-State: None\n"
"X-Generator: Poedit 3.5\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Negar acesso"
#: src/access.c:274
msgid "Grant Access"
msgstr "Conceder acesso"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Selecionar uma imagem"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancelar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Selecionar"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Limpar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imagens"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Partilhar sua informação pessoal com %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Partilhar a sua informação pessoal com a aplicação requerente?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Partilhar detalhes"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "_Cancelar"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Partilhar"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Fazer alterações antes de partilhar informação"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Falha ao iniciar o Software"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Escolha uma aplicação para abrir o ficheiro “%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Escolha uma aplicação."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nenhuma aplicação instalada que possa abrir “%s”. Pode encontrar mais "
"aplicações em Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nenhuma aplicação adequada instalada. Pode encontrar mais aplicações em "
"Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Abrir com…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Abrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Sem aplicações disponíveis"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Encontrar mais em Software"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Criar aplicação Web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Criar aplicação"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "C_riar"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Selecionar"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Gravar"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Abrir ficheiros apenas de leitura"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "Definição solicitada não encontrada"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Definir fundo"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Definir"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Falha ao carregar o ficheiro de imagem"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Atividades"
#, c-format
#~ msgid "“%s” is running in the background"
#~ msgstr "“%s” está a correr em segundo plano"
#~ msgid ""
#~ "This might be for a legitimate reason, but the application has not "
#~ "provided one.\n"
#~ "\n"
#~ "Note that forcing an application to quit might cause data loss."
#~ msgstr ""
#~ "Este pode ser por um motivo legítimo, mas a aplicação não forneceu um.\n"
#~ "\n"
#~ "Note-se que forçar o encerramento de uma aplicação pode causar perda de "
#~ "dados."
#~ msgid "Force quit"
#~ msgstr "Forçar o encerramento"
#~ msgid "Allow"
#~ msgstr "Permitir"
#~ msgid "Background activity"
#~ msgstr "Atividade em segundo plano"
#~ msgid "Find out more"
#~ msgstr "Saiba mais"
#~ msgid "Pointer"
#~ msgstr "Ponteiro"
#~ msgid "Keyboard"
#~ msgstr "Teclado"
#~ msgid "Touch screen"
#~ msgstr "Ecrã tátil"
#, c-format
#~ msgid "Select devices to share with %s"
#~ msgstr "Selecionar dispositivos para partilhar com %s"
#~ msgid "Select devices to share with the requesting application"
#~ msgstr "Selecionar dispositivos a partilhar com a aplicação requerente"
#~ msgid "Remote desktop"
#~ msgstr "Área de trabalho remota"
#~ msgid "Screen Share"
#~ msgstr "Partilha de ecrã"
#, c-format
#~ msgid "Select monitor to share with %s"
#~ msgstr "Selecionar o monitor a partilhar com %s"
#, c-format
#~ msgid "Select window to share with %s"
#~ msgstr "Selecionar a janela a partilhar com %s"
#~ msgid "Select monitor to share with the requesting application"
#~ msgstr "Selecionar o monitor a partilhar com a aplicação requerente"
#~ msgid "Select window to share with the requesting application"
#~ msgstr "Selecionar a janela a partilhar com a aplicação requerente"
#~ msgid "Single Window"
#~ msgstr "Janela individual"
#~ msgid "Entire Screen"
#~ msgstr "Ecrã inteiro"
#, c-format
#~ msgid "Share this screenshot with %s?"
#~ msgstr "Partilhar esta captura de ecrã com %s?"
#~ msgid "Share this screenshot with the requesting application?"
#~ msgstr "Partilhar esta captura de ecrã com a aplicação requerente?"
#~ msgid "Screenshot"
#~ msgstr "Captura de ecrã"
#~ msgid "_Options…"
#~ msgstr "_Opções…"
#~ msgid "Take _Screenshot"
#~ msgstr "Capturar _ecrã"
#~ msgid "Take Screenshot"
#~ msgstr "Capturar ecrã"
#~ msgid "Grab the whole sc_reen"
#~ msgstr "Capturar o ecrã _inteiro"
#~ msgid "Grab the current _window"
#~ msgstr "Capturar a janela at_ual"
#~ msgid "Select _area to grab"
#~ msgstr "Selecion_ar a área a capturar"
#~ msgid "Grab after a _delay of"
#~ msgstr "Capturar após um atraso _de"
#~ msgid "seconds"
#~ msgstr "segundos"
#~ msgid "Effects"
#~ msgstr "Efeitos"
#~ msgid "Include _pointer"
#~ msgstr "Incluir cu_rsor"
#~ msgid "Include the window _border"
#~ msgstr "Incluir o con_torno da janela"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
# Brazilian Portuguese translation for xdg-desktop-portal-gtk.
# Copyright (C) 2024 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Rafael Fontenelle <rafaelff@gnome.org>, 2016-2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-09-01 03:33+0000\n"
"PO-Revision-Date: 2024-09-21 14:34-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <https://br.gnome.org/traducao>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"X-Generator: Gtranslator 46.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Negar acesso"
#: src/access.c:274
msgid "Grant Access"
msgstr "Conceder acesso"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Selecionar uma imagem"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Cancelar"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Selecionar"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Limpar"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imagens"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Compartilhar suas informações pessoais com %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Compartilhar suas informações pessoais com o aplicativo requisitante?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Compartilhar detalhes"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "_Cancelar"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Compartilhar"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Fazer alterações antes de compartilhar as informações"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Falha ao iniciar Programas"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Escolha um aplicativo para abrir o arquivo “%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Escolha um aplicativo."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nenhum aplicativo instalado que pode abrir “%s”. Você pode encontrar mais "
"aplicativos no Software"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nenhum aplicativo adequado instalado. Você pode encontrar mais aplicativos "
"no Software."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Abrir com…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Abrir"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nenhum aplicativo disponível"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Encontrar mais no Programas"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Criar aplicativo web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Criar aplicativo"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "C_riar"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Selecionar"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Salvar"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Abrir arquivos em somente leitura"
#: src/settings.c:216
msgid "Requested setting not found"
msgstr "Configuração solicitada não foi encontrada"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Definir plano de fundo"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Definir"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Falha ao carregar o arquivo de imagem"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Atividades"
#, c-format
#~ msgid "“%s” is running in the background"
#~ msgstr "“%s” está em execução em segundo plano"
#~ msgid ""
#~ "This might be for a legitimate reason, but the application has not "
#~ "provided one.\n"
#~ "\n"
#~ "Note that forcing an application to quit might cause data loss."
#~ msgstr ""
#~ "Isso pode ser por um motivo legítimo, mas o aplicativo não forneceu um.\n"
#~ "\n"
#~ "Observe que forçar o encerramento de um aplicativo pode causar perda de "
#~ "dados."
#~ msgid "Force quit"
#~ msgstr "Forçar encerramento"
#~ msgid "Allow"
#~ msgstr "Permitir"
#~ msgid "Background activity"
#~ msgstr "Atividade em segundo plano"
#~ msgid "Find out more"
#~ msgstr "Encontrar mais"
#~ msgid "Pointer"
#~ msgstr "Cursor do mouse"
#~ msgid "Keyboard"
#~ msgstr "Teclado"
#~ msgid "Touch screen"
#~ msgstr "Tela sensível ao toque"
#, c-format
#~ msgid "Select devices to share with %s"
#~ msgstr "Selecione os dispositivos para compartilhar com %s"
#~ msgid "Select devices to share with the requesting application"
#~ msgstr ""
#~ "Selecione os dispositivos para compartilhar com aplicativo requisitante"
#~ msgid "Remote desktop"
#~ msgstr "Área de trabalho remota"
#~ msgid "Screen Share"
#~ msgstr "Compartilhamento de tela"
#, c-format
#~ msgid "Select monitor to share with %s"
#~ msgstr "Selecione o monitor para compartilhar com %s"
#, c-format
#~ msgid "Select window to share with %s"
#~ msgstr "Selecione a janela para compartilhar com %s"
#~ msgid "Select monitor to share with the requesting application"
#~ msgstr "Selecione o monitor para compartilhar com aplicativo requisitante"
#~ msgid "Select window to share with the requesting application"
#~ msgstr "Selecione a janela para compartilhar com aplicativo requisitante"
#~ msgid "Single Window"
#~ msgstr "Janela individual"
#~ msgid "Entire Screen"
#~ msgstr "Toda a tela"
#, c-format
#~ msgid "Share this screenshot with %s?"
#~ msgstr "Compartilhar essa captura de tela com %s?"
#~ msgid "Share this screenshot with the requesting application?"
#~ msgstr "Compartilhar essa captura de tela com o aplicativo requisitante?"
#~ msgid "Screenshot"
#~ msgstr "Captura de tela"
#~ msgid "_Options…"
#~ msgstr "_Opções…"
#~ msgid "Take _Screenshot"
#~ msgstr "Capturar de t_ela"
#~ msgid "Take Screenshot"
#~ msgstr "Capturar de tela"
#~ msgid "Grab the whole sc_reen"
#~ msgstr "Pegar a tela _inteira"
#~ msgid "Grab the current _window"
#~ msgstr "Pegar a janela at_ual"
#~ msgid "Select _area to grab"
#~ msgstr "_Selecionar área para capturar"
#~ msgid "Grab after a _delay of"
#~ msgstr "Capturar após intervalo _de"
#~ msgid "seconds"
#~ msgstr "segundos"
#~ msgid "Effects"
#~ msgstr "Efeitos"
#~ msgid "Include _pointer"
#~ msgstr "Incluir cu_rsor"
#~ msgid "Include the window _border"
#~ msgstr "Incluir a _borda da janela"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#~ msgid "%s is running in the background."
#~ msgstr "%s está em execução em segundo plano."
#~ msgid "Set Lock Screen"
#~ msgstr "Definir tela de bloqueio"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Definir plano de fundo & tela de bloqueio"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Selecione um aplicativo para abrir “%s”. Mais aplicativos estão "
#~ "disponíveis no <a href='software'>Software</a>."
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Selecione um aplicativo. Mais aplicativos estão disponíveis no <a "
#~ "href='software'>Software</a>."
#~ msgid "Unable to find a suitable application."
#~ msgstr "Não foi possível localizar um aplicativo adequado."
#~ msgid "No Applications Found"
#~ msgstr "Nenhum aplicativo localizado"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Localizar aplicativos compatíveis no Software"
#~ msgid "Forbid"
#~ msgstr "Proibir"
#~ msgid "Ignore"
#~ msgstr "Ignorar"
#~ msgid "Screen casting"
#~ msgstr "Compartilhamento de tela"
# Romanian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2024 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2024-10-13 03:34+0000\n"
"PO-Revision-Date: 2024-10-12 10:34+0200\n"
"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
"Language-Team: Romanian <gnomero-list@lists.sourceforge.net>\n"
"Language: ro\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2);;\n"
"X-Generator: Poedit 3.4.3\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Refuză accesul"
#: src/access.c:274
msgid "Grant Access"
msgstr "Acordă accesul"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Selectează o imagine"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Anulează"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Selectează"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Șterge"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Imagini"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Partajați informațiile dvs. personale cu %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Partajați informațiile dvs. personale cu aplicația care le solicită?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Partajare detalii"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "_Anulare"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Partajare"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Faceți modificări înainte de a partaja informațiile"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Eșec la lansarea programului «Aplicații»"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Alegeți o aplicație pentru a deschide fișierul „%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Alegeți o aplicație."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nu sunt instalate aplicații care pot deschide „%s”. Puteți găsi mai multe "
"aplicații recomandate în «Aplicații»"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nu sunt instalate aplicații care pot deschide „%s”. Puteți găsi mai multe "
"aplicații în «Aplicații»."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Deschide cu…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Deschide"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Nu există aplicații disponibile"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Găsiți mai multe în «Aplicații»"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Creează o aplicație web"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Creează o aplicație"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "C_reează"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Selectează"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Salvează"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Deschide fișiere numai-pentru-citire"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "Configurația solicitată nu a fost găsită"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Stabilește fundalul"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Stabilește"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Încărcarea fișierului imagine a eșuat"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Activități"
# Russian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2019 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Andrew Sazonow <sazonow1980.@gmail.com>, 2019.
# Артемий Судаков <finziyr@yandex.ru>, 2020.
# Ivan Molodetskikh <yalterz@gmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-09-01 03:33+0000\n"
"PO-Revision-Date: 2023-12-22 22:56+0300\n"
"Last-Translator: Aleksandr Melman <Alexmelman88@gmail.com>\n"
"Language-Team: Russian <gnome-cyr@gnome.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.4.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Портал"
#: src/access.c:271
msgid "Deny Access"
msgstr "Отказать в доступе"
#: src/access.c:274
msgid "Grant Access"
msgstr "Предоставить доступ"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Выбрать изображение"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Отменить"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Выбрать"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Очистить"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Изображения"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Дать приложению «%s» доступ к вашей личной информации?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Дать запрашивающему приложению доступ к вашей личной информации?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Подробности"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "_Отменить"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Дать доступ"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Внесите изменения, прежде чем делиться информацией"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Не удалось запустить Центр приложений"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Выберите приложение для открытия «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Выберите приложение."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Нет установленных приложений, способных открыть «%s». Вы можете найти больше "
"приложений в Центре приложений"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Не найдено подходящее установленное приложение. Вы можете найти больше "
"приложений в Центре приложений."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Открыть с помощью…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Открыть"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Нет доступных приложений"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Найти в Центре приложений"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Создать веб-приложение"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Создать приложение"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "С_оздать"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Выбрать"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Сохранить"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Открыть файлы только для чтения"
#: src/settings.c:216
msgid "Requested setting not found"
msgstr "Запрашиваемая настройка не найдена"
# В текущей версии диалога ширина по умолчанию достаточно маленькая, поэтому длинная фраза не влезает без многоточия.
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Установить как фон"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Установить"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Не удалось загрузить файл изображения"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Обзор"
#, c-format
#~ msgid "“%s” is running in the background"
#~ msgstr "Приложение «%s» работает в фоне"
#~ msgid ""
#~ "This might be for a legitimate reason, but the application has not "
#~ "provided one.\n"
#~ "\n"
#~ "Note that forcing an application to quit might cause data loss."
#~ msgstr ""
#~ "Возможно, так и должно быть, но приложение не предоставило явной "
#~ "причины.\n"
#~ "\n"
#~ "Обратите внимание, что принудительное завершение приложения может "
#~ "привести к потере данных."
#~ msgid "Force quit"
#~ msgstr "Завершить принудительно"
#~ msgid "Allow"
#~ msgstr "Разрешить"
#~ msgid "Background activity"
#~ msgstr "Фоновая активность"
#~ msgid "Find out more"
#~ msgstr "Узнать больше"
#~ msgid "Pointer"
#~ msgstr "Курсор мыши"
#~ msgid "Keyboard"
#~ msgstr "Клавиатура"
#~ msgid "Touch screen"
#~ msgstr "Сенсорный экран"
#, c-format
#~ msgid "Select devices to share with %s"
#~ msgstr "Выберите устройства для совместного использования с «%s»"
#~ msgid "Select devices to share with the requesting application"
#~ msgstr ""
#~ "Выберите устройства для совместного использования с запрашивающим "
#~ "приложением"
#~ msgid "Remote desktop"
#~ msgstr "Удалённый рабочий стол"
#~ msgid "Screen Share"
#~ msgstr "Доступ к экрану"
#, c-format
#~ msgid "Select monitor to share with %s"
#~ msgstr "Выберите монитор, который сможет записывать «%s»"
#, c-format
#~ msgid "Select window to share with %s"
#~ msgstr "Выберите окно, которое сможет записывать «%s»"
#~ msgid "Select monitor to share with the requesting application"
#~ msgstr ""
#~ "Выберите монитор, который сможет записывать запрашивающее приложение"
#~ msgid "Select window to share with the requesting application"
#~ msgstr "Выберите окно, которое сможет записывать запрашивающее приложение"
#~ msgid "Single Window"
#~ msgstr "Одно окно"
#~ msgid "Entire Screen"
#~ msgstr "Весь экран"
#, c-format
#~ msgid "Share this screenshot with %s?"
#~ msgstr "Дать приложению «%s» доступ к этому снимку экрана?"
#~ msgid "Share this screenshot with the requesting application?"
#~ msgstr "Дать запрашивающему приложению доступ к этому снимку экрана?"
#~ msgid "Screenshot"
#~ msgstr "Снимок экрана"
#~ msgid "_Options…"
#~ msgstr "_Варианты…"
#~ msgid "Take _Screenshot"
#~ msgstr "Сделать _снимок экрана"
#~ msgid "Take Screenshot"
#~ msgstr "Сделать снимок экрана"
#~ msgid "Grab the whole sc_reen"
#~ msgstr "Снимок всего эк_рана"
#~ msgid "Grab the current _window"
#~ msgstr "Снимок текущего о_кна"
#~ msgid "Select _area to grab"
#~ msgstr "Выбрать _область для снимка"
#~ msgid "Grab after a _delay of"
#~ msgstr "_Задержка перед снимком"
#~ msgid "seconds"
#~ msgstr "сек"
#~ msgid "Effects"
#~ msgstr "Эффекты"
#~ msgid "Include _pointer"
#~ msgstr "Показать курсор _мыши"
#~ msgid "Include the window _border"
#~ msgstr "Показать _границу окна"
#~ msgid "Name"
#~ msgstr "Имя"
#~ msgid "Username"
#~ msgstr "Имя пользователя"
#~ msgid "Allow remote interaction"
#~ msgstr "Разрешить удалённое взаимодействие"
#~ msgid "Virtual monitor"
#~ msgstr "Виртуальный монитор"
#~ msgid "Remember this selection"
#~ msgstr "Запомнить этот выбор"
# Slovak translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Dušan Kazik <prescott66@gmail.com>, 2016-2020.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-09-22 14:20+0200\n"
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"Language: sk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
"X-Generator: Poedit 2.4.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portál"
#: src/access.c:271
msgid "Deny Access"
msgstr "Zamietnuť prístup"
#: src/access.c:274
msgid "Grant Access"
msgstr "Udeliť prístup"
# dialog title
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Výber obrázku"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Zrušiť"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Vybrať"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Vymazať"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Obrázky"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Sprístupniť vaše osobné informácie aplikácii %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Sprístupniť vaše osobné informácie požadovanej aplikácii?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Podrobnosti o sprístupnení"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Zrušiť"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Sprístupniť"
# tooltip
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Vykoná zmeny pred sprístupnením informácií"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Zlyhalo spustenie aplikácie Softvér"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Zvoľte aplikáciu, ktorou otvoriť súbor „%s“."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Zvoľte aplikáciu."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Nie sú nainštalované žiadne aplikácie, ktoré dokážu otvoriť „%s“. Viac "
"aplikácií môžete nájsť v aplikácii Softvér."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Nie je nainštalovaná žiadna vhodná aplikácia. Viac aplikácií môžete nájsť v "
"aplikácii Softvér."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Otvoriť pomocou…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Otvoriť"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Žiadne dostupné aplikácie"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Nájsť viac v aplikácii Softvér"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "Aplikácia „%s“ je spustená na pozadí"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"To môže byť kvôli určitému dôvodu, ale aplikácia ho neudala.\n"
"\n"
"Vedzte, že núteným ukončením aplikácie môžete zapríčiniť stratu údajov."
#: src/background.c:220
msgid "Force quit"
msgstr "Vynútiť ukončenie"
#: src/background.c:221
msgid "Allow"
msgstr "Povoliť"
#: src/background.c:306
msgid "Background activity"
msgstr "Aktivita na pozadí"
#: src/background.c:314
msgid "Find out more"
msgstr "Zistiť viac"
#: src/filechooser.c:462
msgid "_Select"
msgstr "Vy_brať"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Uložiť"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Otvoriť súbory iba na čítanie"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Ukazovateľ"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Klávesnica"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Dotyková obrazovka"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Vyberte zariadenia, ktoré sprístupniť aplikácii %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Vyberte zariadenia, ktoré sprístupniť požadovanej aplikácii"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Vzdialená plocha"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Sprístupnenie obrazovky"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Vyberte monitor, ktorý sprístupniť aplikácii %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Vyberte okno, ktoré sprístupniť aplikácii %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Vyberte monitor, ktorý sprístupniť požadovanej aplikácii"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Vyberte okno, ktoré sprístupniť požadovanej aplikácii"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Jedno okno"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Celá obrazovka"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Sprístupniť túto snímku obrazovky aplikácii %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Sprístupniť túto snímku obrazovky požadovanej aplikácii?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Snímka obrazovky"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Voľby…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Zachytiť _snímku obrazovky"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Zachytenie snímky obrazovky"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Zachytiť celú ob_razovku"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Zachytiť aktuálne o_kno"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Označiť obl_asť na zachytenie"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Zachytiť s _oneskorením"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "sekundy"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Efekty"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Zahrnúť k_urzor"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Zahrnúť ok_raj okna"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Požadované nastavenie sa nenašlo"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Nastavenie pozadia"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Nastaviť"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Zlyhalo načítanie súboru s obrázkom"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Aktivity"
# Slovenian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2024 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
#
# Martin <miles@filmsi.net>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk main\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2024-07-28 03:32+0000\n"
"PO-Revision-Date: 2024-07-28 15:35+0200\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups."
"com>\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
"n%100==4 ? 3 : 0);\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"X-Generator: Poedit 2.2.1\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Zavrni dostop"
#: src/access.c:274
msgid "Grant Access"
msgstr "Dovoli dostop"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Izberite sliko"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Prekliči"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Izberi"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Počisti"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Slike"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Želie deliti svoje osebne podatke s/z %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Želite deliti svoje osebne podatke s programom, ki to zahteva?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Deli podrobnosti"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
msgid "_Cancel"
msgstr "Pre_kliči"
#: src/accountdialog.ui:22
msgid "_Share"
msgstr "_Deli"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Opravi spremembe pred skupno rabo informacij"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Zagon Programske opreme ni uspel"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Izberite program, da odprete datoteko »%s«."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Izberite program."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Ni nameščenih programov, ki bi lahko odprli »%s«. Več programov lahko "
"najdete v Programski opremi"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Primeren program ni nameščen. Več programov najdete v razdelku Programska "
"oprema."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Odpri z …"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Odpri"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Noben program ni na voljo"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Najdi več v Programski opremi"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Ustvari spletni program"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Ustvari program"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "Ustva_ri"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Izberi"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Shrani"
#: src/filechooser.c:647
msgid "Open files read-only"
msgstr "Odpri datoteke samo za branje"
#: src/settings.c:239
msgid "Requested setting not found"
msgstr "Zahtevane nastavitve ni bilo mogoče najti"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Nastavi ozadje"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Določi"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Ni bilo mogoče naložiti slikovne datoteke"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Dejavnosti"
# Serbian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# MirosNik <miroslavnikolic@rocketmail.com>, 2016.
# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2016.
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2016-09-14 12:56+0200\n"
"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: српски <gnome-sr@googlegroups.org>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr ""
#: src/access.c:271
msgid "Deny Access"
msgstr "Забрани приступ"
#: src/access.c:274
msgid "Grant Access"
msgstr "Дозволи приступ"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr ""
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
#, fuzzy
msgid "Cancel"
msgstr "От_кажи"
#: src/accountdialog.c:180
#, fuzzy
msgid "Select"
msgstr "_Изабери"
#: src/accountdialog.c:181
msgid "Clear"
msgstr ""
#: src/accountdialog.c:195
msgid "Images"
msgstr ""
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr ""
#: src/accountdialog.c:275
#, fuzzy
msgid "Share your personal information with the requesting application?"
msgstr "Да поделим овај снимак екрана са програмом који то захтева?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr ""
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "От_кажи"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Дели"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr ""
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr ""
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr ""
#: src/appchooserdialog.c:390
#, fuzzy
msgid "Choose an application."
msgstr "Изаберите програм"
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
#: src/appchooserdialog.ui:10
#, fuzzy
msgid "Open With…"
msgstr "Отвори програмом"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "От_вори"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr ""
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr ""
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr ""
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
#: src/background.c:220
msgid "Force quit"
msgstr ""
#: src/background.c:221
msgid "Allow"
msgstr ""
#: src/background.c:306
msgid "Background activity"
msgstr ""
#: src/background.c:314
msgid "Find out more"
msgstr ""
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Изабери"
#: src/filechooser.c:464
msgid "_Save"
msgstr ""
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr ""
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr ""
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr ""
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr ""
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr ""
#: src/remotedesktopdialog.c:312
#, fuzzy
msgid "Select devices to share with the requesting application"
msgstr "Да поделим овај снимак екрана са програмом који то захтева?"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr ""
#: src/screencastdialog.ui:12
#, fuzzy
msgid "Screen Share"
msgstr "Снимак екрана"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr ""
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr ""
#: src/screencastwidget.c:494
#, fuzzy
msgid "Select monitor to share with the requesting application"
msgstr "Да поделим овај снимак екрана са програмом који то захтева?"
#: src/screencastwidget.c:495
#, fuzzy
msgid "Select window to share with the requesting application"
msgstr "Да поделим овај снимак екрана са програмом који то захтева?"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr ""
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr ""
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Да поделим овај снимак екрана са „%s“?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Да поделим овај снимак екрана са програмом који то захтева?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Снимак екрана"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr ""
#: src/screenshotdialog.ui:55
#, fuzzy
msgid "Take _Screenshot"
msgstr "Снимак екрана"
#: src/screenshotdialog.ui:111
#, fuzzy
msgid "Take Screenshot"
msgstr "Снимак екрана"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr ""
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr ""
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr ""
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr ""
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr ""
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr ""
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr ""
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr ""
#: src/settings.c:217
msgid "Requested setting not found"
msgstr ""
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr ""
#: src/wallpaperdialog.ui:26
#, fuzzy
msgid "Set"
msgstr "_Изабери"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr ""
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr ""
#, fuzzy
#~ msgid "No Applications Found"
#~ msgstr "Изаберите програм"
#, fuzzy
#~ msgid "Screen casting"
#~ msgstr "Снимак екрана"
# Swedish translation for xdg-desktop-portal-gtk.
# Copyright © 2016-2023 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Sebastian Rasmussen <sebras@gmail.com>, 2016.
# Josef Andersson <l10nl18nsweja@gmail.com>, 2017, 2019.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2020, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-02-21 03:33+0000\n"
"PO-Revision-Date: 2023-02-21 11:25+0100\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Portal"
#: src/access.c:271
msgid "Deny Access"
msgstr "Neka åtkomst"
#: src/access.c:274
msgid "Grant Access"
msgstr "Bevilja åtkomst"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Välj en bild"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Avbryt"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Välj"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Rensa"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Bilder"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Dela din personliga information med %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Dela din personliga information med programmet som begär den?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Dela detaljer"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Avbryt"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Dela"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Ändra informationen innan den delas"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Misslyckades med att starta Programvara"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Välj ett program för att öppna filen ”%s”."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Välj ett program."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Inga program som kan öppna ”%s” finns installerade. Du kan hitta fler "
"program i Programvara"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Inget lämpligt program finns installerat. Du kan hitta fler program i "
"Programvara."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Öppna med…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Öppna"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Inga program tillgängliga"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "_Hitta fler i Programvara"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "”%s” körs i bakgrunden"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Det kan finnas en giltig orsak för detta, men programmet har inte "
"tillhandahållit någon.\n"
"\n"
"Observera att tvinga ett program att avsluta kan orsaka dataförlust."
#: src/background.c:220
msgid "Force quit"
msgstr "Tvinga avslut"
#: src/background.c:221
msgid "Allow"
msgstr "Tillåt"
#: src/background.c:306
msgid "Background activity"
msgstr "Bakgrundsaktivitet"
#: src/background.c:314
msgid "Find out more"
msgstr "Lär dig mer"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Skapa webbapplikation"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Skapa program"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "S_kapa"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Välj"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Spara"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "Öppna filer som skrivskyddade"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Pekare"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Tangentbord"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Pekskärm"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Välj enheter att dela med %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "Välj enheter att dela med programmet"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Fjärrskrivbord"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Skärmdelning"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Välj bildskärm att dela med %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Välj fönster att dela med %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "Välj vilken bildskärm du vill dela med programmet"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "Välj vilket fönster du vill dela med programmet"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Ett fönster"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Hela skärmen"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Dela denna skärmbild med %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Dela denna skärmbild med programmet som begär den?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Skärmbild"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Alternativ…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Ta en _skärmbild"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Ta en skärmbild"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Fånga hela sk_ärmen"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Fånga aktuellt _fönster"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Välj _område att fånga"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Fånga _efter fördröjning av"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "sekunder"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Effekter"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Inkludera _pekare"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Inkludera fönster_ramen"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Begärd inställning hittades inte"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Ställ in bakgrund"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Ställ in"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Misslyckades med att läsa in bildfil"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Aktiviteter"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Välj ett program för att öppna ”%s”. Fler program finns tillgängliga i <a "
#~ "href='software'>Programvara.</a>"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "Välj ett program. Fler program finns tillgängliga i <a "
#~ "href='software'>Programvara.</a>"
#~ msgid "Unable to find a suitable application."
#~ msgstr "Det går inte att hitta ett passande program."
#~ msgid "No Applications Found"
#~ msgstr "Inga program funna"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "Sök efter kompatibla program i Programvara"
#~ msgid "Screen casting"
#~ msgstr "Skärminspelning"
# Turkish translation for xdg-desktop-portal-gtk.
# Copyright (C) 2017-2023 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
#
# Muhammet Kara <muhammetk@gnome.org>, 2017, 2018.
# Sabri Ünal <libreajans@gmail.com>, 2019-2020, 2023.
# Emin Tufan Çetin <etcetin@gmail.com>, 2020-2021.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-02-27 15:33+0000\n"
"PO-Revision-Date: 2024-04-01 16:20+0300\n"
"Last-Translator: Sabri Ünal <yakushabb@gmail.com>\n"
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4.2\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Kapı"
#: src/access.c:271
msgid "Deny Access"
msgstr "Erişimi Reddet"
#: src/access.c:274
msgid "Grant Access"
msgstr "Erişime İzin Ver"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Resim Seç"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "İptal"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Seç"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Temizle"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Resimler"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Kişisel bilgileriniz %s ile paylaşılsın mı?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Kişisel bilgileriniz, istekte bulunan uygulamayla paylaşılsın mı?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Ayrıntıları Paylaş"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_İptal"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Paylaş"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Bilgileri paylaşmadan önce değişiklik yap"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Yazılımlar başlatılamadı"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "“%s” dosyasını açmak için uygulama seç."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Uygulama seç."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"“%s” dosyasını açabilen uygulama kurulmadı. Daha çok uygulamayı "
"Yazılımlar’da bulabilirsiniz"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Kullanılabilir uygulama kurulmadı. Daha çok uygulamayı Yazılımlar’da "
"bulabilirsiniz."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Birlikte Aç…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "_Aç"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Kullanılabilir uygulama yok"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "Yazılımlar’da Daha Çoğunu _Bul"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "“%s” arka planda çalışıyor"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Bu geçerli nedenden kaynaklanabilir ancak uygulama neden sunmadı.\n"
"\n"
"Uygulamayı çıkmaya zorlamak veri yitimine neden olabilir."
#: src/background.c:220
msgid "Force quit"
msgstr "Kapanmaya zorla"
#: src/background.c:221
msgid "Allow"
msgstr "İzin ver"
#: src/background.c:306
msgid "Background activity"
msgstr "Arka plan etkinliği"
#: src/background.c:314
msgid "Find out more"
msgstr "Daha çoğunu keşfet"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "Web Uygulaması Oluştur"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "Uygulama Oluştur"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "_Oluştur"
#: src/filechooser.c:463
msgid "_Select"
msgstr "_Seç"
#: src/filechooser.c:465
msgid "_Save"
msgstr "_Kaydet"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "Dosyaları salt okunur aç"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "İmleç"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Klavye"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Dokunmatik ekran"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "%s ile paylaşılacak aygıtları seç"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "İstekte bulunan uygulama ile paylaşılacak aygıtları seç"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Uzak masaüstü"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Ekran Paylaşımı"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "%s ile paylaşılacak monitörü seç"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "%s ile paylaşılacak pencereyi seç"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "İstekte bulunan uygulama ile paylaşılacak monitörü seç"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "İstekte bulunan uygulama ile paylaşılacak pencereyi seç"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Tek Pencere"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Tüm Ekran"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Bu ekran görüntüsü %s ile paylaşılsın mı?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Bu ekran görüntüsü, istekte bulunan uygulama ile paylaşılsın mı?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Ekran Görüntüsü"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "_Seçenekler…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "Ekran Görüntüsü _Al"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Ekran Görüntüsü Al"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Tüm _masaüstünü yakala"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Geçerli _pencereyi yakala"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Yakalanacak _alan seç"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Yakalamadan ö_nce beklenecek süre"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "saniye"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Etkiler"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "İ_mleci içer"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Pencere _kenarlığını içer"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "İstenen ayar bulunamadı"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Arka Plan Belirle"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Belirle"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Resim dosyası yüklenirken hata oluştu"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Etkinlikler"
# Ukrainian translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
#
# Yuri Chornoivan <yurchor@ukr.net>, 2016, 2017, 2018, 2019, 2020.
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2020-03-28 22:00+0200\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Lokalize 20.03.70\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "Портал"
#: src/access.c:271
msgid "Deny Access"
msgstr "Заборонити доступ"
#: src/access.c:274
msgid "Grant Access"
msgstr "Надати доступ"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "Виберіть образ"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "Скасувати"
#: src/accountdialog.c:180
msgid "Select"
msgstr "Вибрати"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "Спорожнити"
#: src/accountdialog.c:195
msgid "Images"
msgstr "Образи"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "Поділитися вашими особистими даними з %s?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "Поділитися вашими особистими даними з програмою, яка про це просить?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "Оприлюднити подробиці"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "_Скасувати"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "_Оприлюднити"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "Внести зміни до оприлюднення даних"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "Не вдалося запустити «Програмні засоби»"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "Виберіть програму для відкриття файла «%s»."
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "Виберіть програму."
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
"Не встановлено жодної програми, яка придатна для відкриття «%s». Потрібні "
"вам програми ви можете знайти за допомогою програми «Програмні засоби»."
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
"Не встановлено відповідної програми. Потрібні вам програми ви можете знайти "
"за допомогою програми «Програмні засоби»."
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "Відкрити за допомогою…"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "_Відкрити"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "Немає доступних програм"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "З_найти інші у програмі «Програмні засоби»"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "«%s» працює у фоновому режимі"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"Можливо, причина є вагомою, але програма не надала її.\n"
"\n"
"Зауважте, що примусове завершення роботи, ймовірно, може призвести до втрати "
"даних."
#: src/background.c:220
msgid "Force quit"
msgstr "Примусове завершення роботи"
#: src/background.c:221
msgid "Allow"
msgstr "Дозволити"
#: src/background.c:306
msgid "Background activity"
msgstr "Фонова робота"
#: src/background.c:314
msgid "Find out more"
msgstr "Дізнатися більше"
#: src/filechooser.c:462
msgid "_Select"
msgstr "_Вибрати"
#: src/filechooser.c:464
msgid "_Save"
msgstr "_Зберегти"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr "Відкрити файли лише для читання"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "Координатний пристрій"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "Клавіатура"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "Сенсорна панель"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "Виберіть пристрої, які слід оприлюднити для %s"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr ""
"Виберіть пристрої, які слід оприлюднити за допомогою відповідної програми"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "Віддалена стільниця"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "Оприлюднення екрана"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "Виберіть монітор, дані з якого слід оприлюднити для %s"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "Виберіть вікно, дані з якого слід оприлюднити для %s"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr ""
"Виберіть монітор, дані з якого слід оприлюднити за допомогою відповідної "
"програми"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr ""
"Виберіть вікно, дані з якого слід оприлюднити за допомогою відповідної "
"програми"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "Окреме вікно"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "Увесь екран"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "Оприлюднити цей знімок екрана за допомогою %s?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "Оприлюднити цей знімок екрана за допомогою відповідної програми?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "Знімок екрана"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "П_араметри…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "З_робити знімок екрана"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "Зробити знімок екрана"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "Захопити увесь е_кран"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "Захопити поточне _вікно"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "Вибрати _область для захоплення"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "Захопити із з_атримкою у"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "секунд"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "Ефекти"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "Разом із в_казівником"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "Включити _рамку вікна"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "Потрібного вам параметра не знайдено"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "Встановити тло"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "Встановити"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "Не вдалося завантажити файл зображення"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "Діяльність"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid "%s is running in the background."
#~ msgstr "%s працює у фоновому режимі."
#~ msgid "Set Lock Screen"
#~ msgstr "Встановити екран блокування"
#~ msgid "Set Background & Lock Screen"
#~ msgstr "Встановити зображення тла і екран блокування"
# Chinese (China) translation for xdg-desktop-portal-gtk.
# Copyright (C) 2016 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Mingye Wang <arthur2e5@aosc.xyz>, 2016.
# 王滋涵 Zephyr Waitzman <i@wi24rd.ml>, 2019.
# Dingzhong Chen <wsxy162@gmail.com>, 2020.
# lumingzh <lumingzh@qq.com>, 2020-2023.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2023-03-04 13:38+0000\n"
"PO-Revision-Date: 2023-05-27 09:50+0800\n"
"Last-Translator: lumingzh <lumingzh@qq.com>\n"
"Language-Team: Chinese - China <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Gtranslator 42.0\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "门户"
#: src/access.c:271
msgid "Deny Access"
msgstr "拒绝访问"
#: src/access.c:274
msgid "Grant Access"
msgstr "授权访问"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "选择一张图像"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "取消"
#: src/accountdialog.c:180
msgid "Select"
msgstr "选择"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "清除"
#: src/accountdialog.c:195
msgid "Images"
msgstr "图像"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "与 %s 共享您的个人信息吗?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "与正在请求的应用共享您的个人信息吗?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "分享详情"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14
#: src/dynamic-launcher.c:267 src/filechooser.c:468
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "取消(_C)"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "分享(_S)"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "在共享信息之前进行更改"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "无法启动软件"
#: src/appchooserdialog.c:385
#, c-format
msgid "Choose an application to open the file “%s”."
msgstr "选择一个应用程序来打开文件“%s”。"
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr "选择一个应用程序。"
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr "没有安装可以打开“%s”的应用。您可以在“软件”中查找更多应用程序。"
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr "没有安装合适的应用。您可以在“软件”中查找更多应用程序。"
#: src/appchooserdialog.ui:10
msgid "Open With…"
msgstr "打开方式…"
#: src/appchooserdialog.ui:23 src/filechooser.c:463
msgid "_Open"
msgstr "打开(_O)"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr "无可用应用"
#: src/appchooserdialog.ui:159
msgid "_Find More in Software"
msgstr "在 软件 中查找更多(_F)"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr "“%s”正在后台运行"
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
"这可能有合理的原因,但该应用程序并未提供。\n"
"请注意强制应用程序退出可能导致数据丢失。"
#: src/background.c:220
msgid "Force quit"
msgstr "强制退出"
#: src/background.c:221
msgid "Allow"
msgstr "允许"
#: src/background.c:306
msgid "Background activity"
msgstr "后台活动"
#: src/background.c:314
msgid "Find out more"
msgstr "查找更多"
#: src/dynamic-launcher.c:259
msgid "Create Web Application"
msgstr "创建网页应用程序"
#: src/dynamic-launcher.c:261
msgid "Create Application"
msgstr "创建应用程序"
#: src/dynamic-launcher.c:269
msgid "C_reate"
msgstr "创建(_R)"
#: src/filechooser.c:463
msgid "_Select"
msgstr "选择(_S)"
#: src/filechooser.c:465
msgid "_Save"
msgstr "保存(_S)"
#: src/filechooser.c:642
msgid "Open files read-only"
msgstr "以只读方式打开文件"
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "指针"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "键盘"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "触摸屏"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "选择要与 %s 共享的设备"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "选择要与正在请求的应用程序共享的设备"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "远程桌面"
#: src/screencastdialog.ui:12
msgid "Screen Share"
msgstr "共享屏幕"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "选择与 %s 共享的监视器"
#: src/screencastwidget.c:489
#, c-format
msgid "Select window to share with %s"
msgstr "选择与 %s 共享的窗口"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "选择与正在请求的应用共享的监视器"
#: src/screencastwidget.c:495
msgid "Select window to share with the requesting application"
msgstr "选择与正在请求的应用共享的窗口"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr "单个窗口"
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr "整个屏幕"
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "要与 %s 分享截屏吗?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "与正发出请求的应用程序共享此截图吗?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "截屏"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "选项(_O)…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "截图(_S)"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "截图"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "抓取当前屏幕(_R)"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "抓取当前窗口(_W)"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "选择截取区域(_A)"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "在延迟后抓取(_D)"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "秒"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "效果"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "包含指针(_P)"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "包含窗口边框(_B)"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr "未找到请求的设置"
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr "设置背景"
#: src/wallpaperdialog.ui:26
msgid "Set"
msgstr "设置"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr "加载图像文件失败"
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr "活动"
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "选择一款打开 “%s” 的应用。<a href='software'>软件中心</a>有更多应用。"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr "选择一款应用。<a href='software'>软件中心</a>有更多应用。"
#~ msgid "Unable to find a suitable application."
#~ msgstr "找不到适合的应用。"
#~ msgid "No Applications Found"
#~ msgstr "非找到应用"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "在软件中查找兼容的应用程序"
#~ msgid "Screen casting"
#~ msgstr "录屏"
# Chinese (Taiwan) translation for xdg-desktop-portal-gtk.
# Copyright (C) 2018 xdg-desktop-portal-gtk's COPYRIGHT HOLDER
# This file is distributed under the same license as the xdg-desktop-portal-gtk package.
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: xdg-desktop-portal-gtk master\n"
"Report-Msgid-Bugs-To: https://github.com/flatpak/xdg-desktop-portal-gtk/"
"issues\n"
"POT-Creation-Date: 2022-11-29 13:45+0000\n"
"PO-Revision-Date: 2018-10-10 12:22+0800\n"
"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
"Language-Team: Chinese (Taiwan) <chinese-l10n@googlegroups.com>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n"
#: data/xdg-desktop-portal-gtk.desktop.in.in:4
msgid "Portal"
msgstr "入口"
#: src/access.c:271
msgid "Deny Access"
msgstr "拒絕存取"
#: src/access.c:274
msgid "Grant Access"
msgstr "允許存取"
#: src/accountdialog.c:176
msgid "Select an Image"
msgstr "選取影像"
#: src/accountdialog.c:179 src/wallpaperdialog.ui:18
msgid "Cancel"
msgstr "取消"
#: src/accountdialog.c:180
msgid "Select"
msgstr "選取"
#: src/accountdialog.c:181
msgid "Clear"
msgstr "清除"
#: src/accountdialog.c:195
msgid "Images"
msgstr "影像"
#: src/accountdialog.c:272
#, c-format
msgid "Share your personal information with %s?"
msgstr "是否要和 %s 分享您的個人資訊?"
#: src/accountdialog.c:275
msgid "Share your personal information with the requesting application?"
msgstr "是否要和請求程式分享您的個人資訊?"
#: src/accountdialog.ui:10
msgid "Share Details"
msgstr "分享細節"
#: src/accountdialog.ui:14 src/appchooserdialog.ui:14 src/filechooser.c:467
#: src/remotedesktopdialog.ui:16 src/screencastdialog.ui:16
#: src/screenshotdialog.ui:14
msgid "_Cancel"
msgstr "取消(_C)"
#: src/accountdialog.ui:22 src/remotedesktopdialog.ui:28
#: src/screencastdialog.ui:28 src/screenshotdialog.ui:38
msgid "_Share"
msgstr "分享(_S)"
#: src/accountdialog.ui:148
msgid "Make changes before sharing the information"
msgstr "在分享資訊前做出修改"
#: src/appchooserdialog.c:229
msgid "Failed to start Software"
msgstr "無法啟動《軟體》"
#: src/appchooserdialog.c:385
#, fuzzy, c-format
msgid "Choose an application to open the file “%s”."
msgstr "找不到可開啟「%s」的應用程式。"
#: src/appchooserdialog.c:390
msgid "Choose an application."
msgstr ""
#: src/appchooserdialog.c:407
#, c-format
msgid ""
"No apps installed that can open “%s”. You can find more applications in "
"Software"
msgstr ""
#: src/appchooserdialog.c:412
msgid "No suitable app installed. You can find more applications in Software."
msgstr ""
#: src/appchooserdialog.ui:10
#, fuzzy
msgid "Open With…"
msgstr "開啟方式"
#: src/appchooserdialog.ui:23 src/filechooser.c:462
msgid "_Open"
msgstr "開啟(_O)"
#: src/appchooserdialog.ui:115
msgid "No Apps available"
msgstr ""
#: src/appchooserdialog.ui:159
#, fuzzy
msgid "_Find More in Software"
msgstr "無法啟動《軟體》"
#: src/background.c:215 src/background.c:308
#, c-format
msgid "“%s” is running in the background"
msgstr ""
#: src/background.c:217
msgid ""
"This might be for a legitimate reason, but the application has not provided "
"one.\n"
"\n"
"Note that forcing an application to quit might cause data loss."
msgstr ""
#: src/background.c:220
msgid "Force quit"
msgstr ""
#: src/background.c:221
msgid "Allow"
msgstr ""
#: src/background.c:306
msgid "Background activity"
msgstr ""
#: src/background.c:314
msgid "Find out more"
msgstr ""
#: src/filechooser.c:462
#, fuzzy
msgid "_Select"
msgstr "選取"
#: src/filechooser.c:464
msgid "_Save"
msgstr "儲存(_S)"
#: src/filechooser.c:641
msgid "Open files read-only"
msgstr ""
#: src/remotedesktopdialog.c:188
msgid "Pointer"
msgstr "指標"
#: src/remotedesktopdialog.c:191
msgid "Keyboard"
msgstr "鍵盤"
#: src/remotedesktopdialog.c:194
msgid "Touch screen"
msgstr "觸控螢幕"
#: src/remotedesktopdialog.c:307
#, c-format
msgid "Select devices to share with %s"
msgstr "選取要和 %s 分享的裝置"
#: src/remotedesktopdialog.c:312
msgid "Select devices to share with the requesting application"
msgstr "選取您想和請求程式分享的裝置"
#: src/remotedesktopdialog.ui:12
msgid "Remote desktop"
msgstr "遠端桌面"
#: src/screencastdialog.ui:12
#, fuzzy
msgid "Screen Share"
msgstr "畫面快照"
#: src/screencastwidget.c:487
#, c-format
msgid "Select monitor to share with %s"
msgstr "選取您想要和 %s 分享的螢幕"
#: src/screencastwidget.c:489
#, fuzzy, c-format
msgid "Select window to share with %s"
msgstr "選取您想和 %s 分享的項目"
#: src/screencastwidget.c:494
msgid "Select monitor to share with the requesting application"
msgstr "選取您想和請求程式分享的螢幕"
#: src/screencastwidget.c:495
#, fuzzy
msgid "Select window to share with the requesting application"
msgstr "選取您想和請求程式分享的項目"
#: src/screencastwidget.ui:100
msgid "Single Window"
msgstr ""
#: src/screencastwidget.ui:176
msgid "Entire Screen"
msgstr ""
#: src/screenshotdialog.c:442
#, c-format
msgid "Share this screenshot with %s?"
msgstr "是否要和 %s 分享此畫面快照?"
#: src/screenshotdialog.c:446
msgid "Share this screenshot with the requesting application?"
msgstr "是否要和請求程式分享此畫面快照?"
#: src/screenshotdialog.ui:10
msgid "Screenshot"
msgstr "畫面快照"
#: src/screenshotdialog.ui:30
msgid "_Options…"
msgstr "選項(_O)…"
#: src/screenshotdialog.ui:55
msgid "Take _Screenshot"
msgstr "拍攝畫面快照(_S)"
#: src/screenshotdialog.ui:111
msgid "Take Screenshot"
msgstr "拍攝畫面快照"
#: src/screenshotdialog.ui:122
msgid "Grab the whole sc_reen"
msgstr "擷取整個螢幕(_R)"
#: src/screenshotdialog.ui:133
msgid "Grab the current _window"
msgstr "擷取目前視窗(_W)"
#: src/screenshotdialog.ui:144
msgid "Select _area to grab"
msgstr "選取擷取區域(_A)"
#: src/screenshotdialog.ui:158
msgid "Grab after a _delay of"
msgstr "擷取倒數時間為(_D)"
#: src/screenshotdialog.ui:171
msgid "seconds"
msgstr "秒"
#: src/screenshotdialog.ui:181
msgid "Effects"
msgstr "效果"
#: src/screenshotdialog.ui:192
msgid "Include _pointer"
msgstr "包含指標(_P)"
#: src/screenshotdialog.ui:201
msgid "Include the window _border"
msgstr "包含視窗邊框(_B)"
#: src/settings.c:217
msgid "Requested setting not found"
msgstr ""
#: src/wallpaperdialog.ui:13
msgid "Set Background"
msgstr ""
#: src/wallpaperdialog.ui:26
#, fuzzy
msgid "Set"
msgstr "選取"
#: src/wallpaperdialog.ui:57
msgid "Failed to load image file"
msgstr ""
#: src/wallpaperpreview.ui:57
msgid "Activities"
msgstr ""
#~ msgid "applications-system-symbolic"
#~ msgstr "applications-system-symbolic"
#, c-format
#~ msgid ""
#~ "Select an application to open “%s”. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr ""
#~ "選取開啟「%s」的應用程式。《<a href='software'>軟體</a>》中有更多應用程式"
#~ "可用。"
#~ msgid ""
#~ "Select an application. More applications are available in <a "
#~ "href='software'>Software.</a>"
#~ msgstr "選取應用程式。《<a href='software'>軟體</a>》中有更多應用程式可用。"
#~ msgid "Unable to find a suitable application."
#~ msgstr "找不到適合的應用程式。"
#~ msgid "No Applications Found"
#~ msgstr "找不到應用程式"
#~ msgid "Find Compatible Applications in Software"
#~ msgstr "在《軟體》中尋找相容的應用程式"
#~ msgid "Screen casting"
#~ msgstr "螢幕投放"
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "request.h"
#include "utils.h"
#include "externalwindow.h"
typedef struct {
XdpImplAccess *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
ExternalWindow *external_parent;
GHashTable *choices;
int response;
} AccessDialogHandle;
static void
access_dialog_handle_free (gpointer data)
{
AccessDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_object_unref (handle->request);
g_object_unref (handle->dialog);
if (handle->choices)
g_hash_table_unref (handle->choices);
g_free (handle);
}
static void
access_dialog_handle_close (AccessDialogHandle *handle)
{
gtk_widget_destroy (handle->dialog);
access_dialog_handle_free (handle);
}
static void
send_response (AccessDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
if (handle->request->exported)
request_unexport (handle->request);
if (handle->response == 0 && handle->choices != NULL)
{
GVariantBuilder choice_builder;
GHashTableIter iter;
const char *key;
GtkWidget *widget;
g_variant_builder_init (&choice_builder, G_VARIANT_TYPE ("a(ss)"));
g_hash_table_iter_init (&iter, handle->choices);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&widget))
{
if (GTK_IS_RADIO_BUTTON (widget))
{
gchar **str;
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
continue;
str = g_strsplit (key, ":", -1);
g_variant_builder_add (&choice_builder, "(ss)", str[0], str[1]);
g_strfreev (str);
}
else if (GTK_IS_CHECK_BUTTON (widget))
{
gboolean active;
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
g_variant_builder_add (&choice_builder, "(ss)", key, active ? "true" : "false");
}
}
g_variant_builder_add (&opt_builder, "{sv}", "choices", g_variant_builder_end (&choice_builder));
}
xdp_impl_access_complete_access_dialog (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
access_dialog_handle_close (handle);
}
static void
access_dialog_response (GtkWidget *widget,
int response,
gpointer user_data)
{
AccessDialogHandle *handle = user_data;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_OK:
handle->response = 0;
break;
}
send_response (handle);
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
AccessDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_access_complete_access_dialog (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
access_dialog_handle_close (handle);
return FALSE;
}
static void
add_choice (GtkWidget *box,
GVariant *choice,
GHashTable *table)
{
const char *id;
const char *name;
g_autoptr(GVariant) options = NULL;
const char *selected;
g_variant_get (choice, "(&s&s@a(ss)&s)", &id, &name, &options, &selected);
if (g_variant_n_children (options) == 0)
{
GtkWidget *button;
button = gtk_check_button_new_with_label (name);
g_object_set (button, "margin-top", 10, NULL);
gtk_widget_show (button);
if (strcmp (selected, "true") == 0)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_container_add (GTK_CONTAINER (box), button);
g_hash_table_insert (table, g_strdup (id), button);
}
else
{
GtkWidget *label;
GtkWidget *group = NULL;
int i;
label = gtk_label_new (name);
gtk_widget_show (label);
gtk_widget_set_halign (label, GTK_ALIGN_START);
g_object_set (label, "margin-top", 10, NULL);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
gtk_container_add (GTK_CONTAINER (box), label);
for (i = 0; i < g_variant_n_children (options); i++)
{
const char *option_id;
const char *option_name;
GtkWidget *radio;
g_variant_get_child (options, i, "(&s&s)", &option_id, &option_name);
radio = gtk_radio_button_new_with_label (NULL, option_name);
gtk_widget_show (radio);
g_hash_table_insert (table, g_strconcat (id, ":", option_id, NULL), radio);
if (group)
gtk_radio_button_join_group (GTK_RADIO_BUTTON (radio),
GTK_RADIO_BUTTON (group));
else
group = radio;
gtk_container_add (GTK_CONTAINER (box), radio);
if (strcmp (selected, option_id) == 0)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
}
}
}
static void
fix_up_label_alignment (GtkWidget *area)
{
GList *children, *l;
/* Hack! Necessary because we're (mis)using GtkMessageDialog */
children = gtk_container_get_children (GTK_CONTAINER (area));
for (l = children; l; l = l->next)
{
GtkWidget *child = l->data;
gtk_widget_set_halign (child, GTK_ALIGN_START);
}
g_list_free (children);
}
static gboolean
handle_access_dialog (XdpImplAccess *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_title,
const char *arg_subtitle,
const char *arg_body,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
AccessDialogHandle *handle;
g_autoptr(GError) error = NULL;
g_autofree char *filename = NULL;
gboolean modal;
GtkWidget *dialog;
const char *deny_label;
const char *grant_label;
const char *icon;
g_autoptr(GVariant) choices = NULL;
GtkWidget *area;
GtkWidget *image;
GHashTable *choice_table = NULL;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
if (!g_variant_lookup (arg_options, "deny_label", "&s", &deny_label))
deny_label = _("Deny Access");
if (!g_variant_lookup (arg_options, "grant_label", "&s", &grant_label))
grant_label = _("Grant Access");
if (!g_variant_lookup (arg_options, "icon", "&s", &icon))
icon = NULL;
choices = g_variant_lookup_value (arg_options, "choices", G_VARIANT_TYPE ("a(ssa(ss)s)"));
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
dialog = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
arg_title,
NULL);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
gtk_window_set_modal (GTK_WINDOW (dialog), modal);
gtk_dialog_add_button (GTK_DIALOG (dialog), deny_label, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog), grant_label, GTK_RESPONSE_OK);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", arg_subtitle);
area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog));
fix_up_label_alignment (area);
if (choices)
{
int i;
choice_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < g_variant_n_children (choices); i++)
add_choice (area, g_variant_get_child_value (choices, i), choice_table);
}
if (!g_str_equal (arg_body, ""))
{
GtkWidget *body_label;
body_label = gtk_label_new (arg_body);
gtk_widget_set_halign (body_label, GTK_ALIGN_START);
g_object_set (body_label, "margin-top", 10, NULL);
#if GTK_CHECK_VERSION (3,16,0)
gtk_label_set_xalign (GTK_LABEL (body_label), 0);
#else
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/* This is deprecated in 3.14, but gtk_label_set_xalign() is not
* available until 3.16. */
gtk_misc_set_alignment (GTK_MISC (body_label), 0.0, 0.5);
G_GNUC_END_IGNORE_DEPRECATIONS
#endif
gtk_label_set_line_wrap (GTK_LABEL (body_label), TRUE);
gtk_label_set_max_width_chars (GTK_LABEL (body_label), 50);
gtk_widget_show (body_label);
gtk_container_add (GTK_CONTAINER (area), body_label);
}
image = gtk_image_new_from_icon_name (icon ? icon : "image-missing", GTK_ICON_SIZE_DIALOG);
gtk_widget_set_opacity (image, icon ? 1.0 : 0.0);
gtk_widget_show (image);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
G_GNUC_END_IGNORE_DEPRECATIONS
handle = g_new0 (AccessDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->external_parent = external_parent;
handle->choices = choice_table;
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "response", G_CALLBACK (access_dialog_response), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
gtk_widget_show (dialog);
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
gboolean
access_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_access_skeleton_new ());
g_signal_connect (helper, "handle-access-dialog", G_CALLBACK (handle_access_dialog), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean access_init (GDBusConnection *bus, GError **error);
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "account.h"
#include "accountdialog.h"
#include "request.h"
#include "utils.h"
#include "externalwindow.h"
static OrgFreedesktopAccountsUser *user;
typedef struct {
XdpImplAccount *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
ExternalWindow *external_parent;
int response;
char *user_name;
char *real_name;
char *icon_uri;
} AccountDialogHandle;
static void
account_dialog_handle_free (gpointer data)
{
AccountDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_object_unref (handle->request);
g_object_unref (handle->dialog);
g_free (handle->user_name);
g_free (handle->real_name);
g_free (handle->icon_uri);
g_free (handle);
}
static void
account_dialog_handle_close (AccountDialogHandle *handle)
{
gtk_widget_destroy (handle->dialog);
account_dialog_handle_free (handle);
}
static void
send_response (AccountDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&opt_builder, "{sv}", "id", g_variant_new_string (handle->user_name ? handle->user_name : ""));
g_variant_builder_add (&opt_builder, "{sv}", "name", g_variant_new_string (handle->real_name ? handle->real_name : ""));
g_variant_builder_add (&opt_builder, "{sv}", "image", g_variant_new_string (handle->icon_uri ? handle->icon_uri : ""));
if (handle->request->exported)
request_unexport (handle->request);
xdp_impl_account_complete_get_user_information (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
account_dialog_handle_close (handle);
}
static void
account_dialog_done (GtkWidget *widget,
int response,
const char *user_name,
const char *real_name,
const char *icon_file,
gpointer user_data)
{
AccountDialogHandle *handle = user_data;
g_clear_pointer (&handle->user_name, g_free);
g_clear_pointer (&handle->real_name, g_free);
g_clear_pointer (&handle->icon_uri, g_free);
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_OK:
handle->user_name = g_strdup (user_name);
handle->real_name = g_strdup (real_name);
if (icon_file)
handle->icon_uri = g_filename_to_uri (icon_file, NULL, NULL);
handle->response = 0;
break;
}
send_response (handle);
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
AccountDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_account_complete_get_user_information (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
account_dialog_handle_close (handle);
return FALSE;
}
static gboolean
handle_get_user_information (XdpImplAccount *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
AccountDialogHandle *handle;
g_autoptr(GError) error = NULL;
const char *user_name;
const char *real_name;
const char *icon_file;
GtkWidget *dialog;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
const char *reason;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
user_name = org_freedesktop_accounts_user_get_user_name (user);
real_name = org_freedesktop_accounts_user_get_real_name (user);
icon_file = org_freedesktop_accounts_user_get_icon_file (user);
if (!g_variant_lookup (arg_options, "reason", "&s", &reason))
reason = NULL;
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
dialog = GTK_WIDGET (account_dialog_new (arg_app_id, user_name, real_name, icon_file, reason));
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
handle = g_new0 (AccountDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->external_parent = external_parent;
handle->user_name = g_strdup (user_name);
handle->real_name = g_strdup (real_name);
handle->icon_uri = g_filename_to_uri (icon_file, NULL, NULL);
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "done", G_CALLBACK (account_dialog_done), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
gtk_widget_show (dialog);
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
static GDBusConnection *system_bus;
gboolean
account_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
g_autofree char *object_path = NULL;
system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (system_bus == NULL)
return FALSE;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_account_skeleton_new ());
g_signal_connect (helper, "handle-get-user-information", G_CALLBACK (handle_get_user_information), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", getuid ());
user = org_freedesktop_accounts_user_proxy_new_sync (system_bus,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.Accounts",
object_path,
NULL,
error);
if (user == NULL)
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean account_init (GDBusConnection *bus, GError **error);
#define _GNU_SOURCE 1
#include <string.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <glib/gi18n.h>
#include "accountdialog.h"
struct _AccountDialog {
GtkWindow parent;
GtkWidget *heading;
GtkWidget *reason;
GtkWidget *accept_button;
GtkWidget *name;
GtkWidget *name_readonly;
GtkWidget *name_stack;
GtkWidget *fullname;
GtkWidget *fullname_readonly;
GtkWidget *fullname_stack;
GtkWidget *image;
GtkWidget *image_readonly;
GtkWidget *image_stack;
char *icon_file;
};
struct _AccountDialogClass {
GtkWindowClass parent_class;
};
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (AccountDialog, account_dialog, GTK_TYPE_WINDOW)
static void
account_dialog_init (AccountDialog *dialog)
{
gtk_widget_init_template (GTK_WIDGET (dialog));
}
static void
account_dialog_finalize (GObject *object)
{
AccountDialog *dialog = ACCOUNT_DIALOG (object);
g_clear_pointer (&dialog->icon_file, g_free);
G_OBJECT_CLASS (account_dialog_parent_class)->finalize (object);
}
static gboolean
account_dialog_delete_event (GtkWidget *dialog, GdkEventAny *event)
{
gtk_widget_hide (dialog);
g_signal_emit (dialog, signals[DONE], 0, GTK_RESPONSE_CANCEL, NULL);
return TRUE;
}
static void
button_clicked (GtkWidget *button,
AccountDialog *dialog)
{
int response;
const char *user_name;
const char *real_name;
gtk_widget_hide (GTK_WIDGET (dialog));
if (button == dialog->accept_button)
response = GTK_RESPONSE_OK;
else
response = GTK_RESPONSE_CANCEL;
user_name = gtk_entry_get_text (GTK_ENTRY (dialog->name));
real_name = gtk_entry_get_text (GTK_ENTRY (dialog->fullname));
g_signal_emit (dialog, signals[DONE], 0, response, user_name, real_name, dialog->icon_file);
}
static void
dialog_set_icon_file (AccountDialog *dialog,
const char *icon_file)
{
g_clear_pointer (&dialog->icon_file, g_free);
dialog->icon_file = g_strdup (icon_file);
if (icon_file)
{
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GError) error = NULL;
pixbuf = gdk_pixbuf_new_from_file_at_scale (icon_file, 64, 64, TRUE, &error);
if (error)
g_warning ("Failed to load account %s: %s", icon_file, error->message);
gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image), pixbuf);
gtk_style_context_remove_class (gtk_widget_get_style_context (dialog->image), "dim-label");
}
else
{
gtk_image_set_from_icon_name (GTK_IMAGE (dialog->image), "camera-photo-symbolic", 1);
gtk_image_set_pixel_size (GTK_IMAGE (dialog->image), 64);
gtk_style_context_add_class (gtk_widget_get_style_context (dialog->image), "dim-label");
}
}
static void
file_chooser_response (GtkWidget *widget,
int response,
gpointer user_data)
{
AccountDialog *dialog = user_data;
g_autofree char *file = NULL;
file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
gtk_widget_destroy (widget);
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
case GTK_RESPONSE_CANCEL:
break;
case GTK_RESPONSE_OK:
dialog_set_icon_file (dialog, file);
break;
case GTK_RESPONSE_CLOSE:
dialog_set_icon_file (dialog, NULL);
break;
}
}
static void
update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
{
GtkWidget *preview;
char *filename;
GdkPixbuf *pixbuf;
gboolean have_preview;
preview = GTK_WIDGET (data);
filename = gtk_file_chooser_get_preview_filename (file_chooser);
pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL);
have_preview = (pixbuf != NULL);
g_free (filename);
gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
}
static void
image_button_clicked (AccountDialog *dialog)
{
GtkWidget *chooser;
GtkWidget *preview;
GtkFileFilter *filter;
chooser = gtk_file_chooser_dialog_new (_("Select an Image"),
GTK_WINDOW (dialog),
GTK_FILE_CHOOSER_ACTION_OPEN,
_("Cancel"), GTK_RESPONSE_CANCEL,
_("Select"), GTK_RESPONSE_OK,
_("Clear"), GTK_RESPONSE_CLOSE,
NULL);
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
preview = gtk_image_new ();
g_object_set (preview, "margin", 10, NULL);
gtk_widget_show (preview);
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (chooser), preview);
gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (chooser), FALSE);
g_signal_connect (chooser, "update-preview", G_CALLBACK (update_preview_cb), preview);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Images"));
gtk_file_filter_add_pixbuf_formats (filter);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
g_signal_connect (chooser, "response", G_CALLBACK (file_chooser_response), dialog);
gtk_widget_show (chooser);
}
static void
override_button_clicked (GtkButton *button,
AccountDialog *dialog)
{
gtk_stack_set_visible_child_name (GTK_STACK (dialog->name_stack), "edit");
gtk_stack_set_visible_child_name (GTK_STACK (dialog->fullname_stack), "edit");
gtk_stack_set_visible_child_name (GTK_STACK (dialog->image_stack), "edit");
gtk_widget_set_opacity (GTK_WIDGET (button), 0);
}
static void
account_dialog_class_init (AccountDialogClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->finalize = account_dialog_finalize;
widget_class->delete_event = account_dialog_delete_event;
signals[DONE] = g_signal_new ("done",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 4,
G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/portal/desktop/gtk/accountdialog.ui");
gtk_widget_class_bind_template_child (widget_class, AccountDialog, accept_button);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, heading);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, reason);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, name);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, name_readonly);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, name_stack);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, fullname);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, fullname_readonly);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, fullname_stack);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, image);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, image_readonly);
gtk_widget_class_bind_template_child (widget_class, AccountDialog, image_stack);
gtk_widget_class_bind_template_callback (widget_class, button_clicked);
gtk_widget_class_bind_template_callback (widget_class, image_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, override_button_clicked);
}
AccountDialog *
account_dialog_new (const char *app_id,
const char *user_name,
const char *real_name,
const char *icon_file,
const char *reason)
{
AccountDialog *dialog;
g_autofree char *heading = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GError) error = NULL;
dialog = g_object_new (account_dialog_get_type (), NULL);
if (strcmp (app_id, "") != 0)
{
g_autofree char *id = NULL;
g_autoptr(GAppInfo) info = NULL;
id = g_strconcat (app_id, ".desktop", NULL);
info = G_APP_INFO (g_desktop_app_info_new (id));
heading = g_strdup_printf (_("Share your personal information with %s?"), g_app_info_get_display_name (info));
}
else
heading = g_strdup (_("Share your personal information with the requesting application?"));
gtk_label_set_label (GTK_LABEL (dialog->heading), heading);
gtk_entry_set_text (GTK_ENTRY (dialog->name), user_name);
gtk_label_set_label (GTK_LABEL (dialog->name_readonly), user_name);
gtk_entry_set_text (GTK_ENTRY (dialog->fullname), real_name);
gtk_label_set_label (GTK_LABEL (dialog->fullname_readonly), real_name);
if (reason)
gtk_label_set_label (GTK_LABEL (dialog->reason), reason);
else
gtk_widget_hide (dialog->reason);
pixbuf = gdk_pixbuf_new_from_file_at_scale (icon_file, 64, 64, TRUE, &error);
if (error)
g_warning ("Failed to load account %s: %s", icon_file, error->message);
else
{
gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image), pixbuf);
gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image_readonly), pixbuf);
}
dialog->icon_file = g_strdup (icon_file);
return dialog;
}
#include <gtk/gtk.h>
#define ACCOUNT_TYPE_DIALOG (account_dialog_get_type ())
#define ACCOUNT_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST (object, ACCOUNT_TYPE_DIALOG, AccountDialog))
typedef struct _AccountDialog AccountDialog;
typedef struct _AccountDialogClass AccountDialogClass;
AccountDialog * account_dialog_new (const char *app_id,
const char *user_name,
const char *real_name,
const char *icon_file,
const char *reason);
const char *account_dialog_get_user_name (AccountDialog *dialog);
const char *account_dialog_get_real_name (AccountDialog *dialog);
const char *account_dialog_get_icon_file (AccountDialog *dialog);
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="xdg-desktop-portal-gtk">
<!-- interface-requires gtk+ 3.22 -->
<template class="AccountDialog" parent="GtkWindow">
<property name="type-hint">dialog</property>
<property name="resizable">0</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="titlebar">
<property name="visible">1</property>
<property name="title" translatable="yes">Share Details</property>
<child>
<object class="GtkButton" id="cancel_button">
<property name="visible">1</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="use-underline">1</property>
<signal name="clicked" handler="button_clicked"/>
</object>
</child>
<child>
<object class="GtkButton" id="accept_button">
<property name="visible">1</property>
<property name="label" translatable="yes">_Share</property>
<property name="use-underline">1</property>
<signal name="clicked" handler="button_clicked"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">1</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<property name="margin">20</property>
<property name="halign">center</property>
<child>
<object class="GtkStack" id="name_stack">
<property name="visible">1</property>
<child>
<object class="GtkLabel" id="name_readonly">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="valign">start</property>
<property name="margin-start">10</property>
</object>
<packing>
<property name="name">show</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="visible">1</property>
</object>
<packing>
<property name="name">edit</property>
</packing>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkStack" id="fullname_stack">
<property name="visible">1</property>
<child>
<object class="GtkLabel" id="fullname_readonly">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="margin-start">10</property>
<attributes>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
<packing>
<property name="name">show</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="fullname">
<property name="visible">1</property>
</object>
<packing>
<property name="name">edit</property>
</packing>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkStack" id="image_stack">
<property name="visible">1</property>
<property name="halign">start</property>
<child>
<object class="GtkImage" id="image_readonly">
<property name="visible">1</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
<style> <class name="frame"/> </style>
</object>
<packing>
<property name="name">show</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button">
<property name="visible">1</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
<signal name="clicked" handler="image_button_clicked" swapped="yes"/>
<child>
<object class="GtkImage" id="image">
<property name="visible">1</property>
</object>
</child>
</object>
<packing>
<property name="name">edit</property>
</packing>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="override_button">
<property name="visible">1</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="relief">none</property>
<property name="tooltip-text" translatable="yes">Make changes before sharing the information</property>
<signal name="clicked" handler="override_button_clicked"/>
<style>
<class name="image-button"/>
<class name="circular"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">document-edit-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">0</property>
<property name="height">2</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="heading">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="max-width-chars">26</property>
<property name="width-chars">26</property>
<property name="valign">start</property>
<property name="margin">20</property>
<property name="margin-top">0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="reason">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="max-width-chars">26</property>
<property name="width-chars">26</property>
<property name="valign">start</property>
<property name="margin">20</property>
<property name="margin-top">0</property>
</object>
</child>
</object>
</child>
</template>
</interface>
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include "appchooser.h"
#include "request.h"
#include "utils.h"
#include <string.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include <glib/gi18n.h>
#include "xdg-desktop-portal-dbus.h"
#include "appchooserdialog.h"
#include "externalwindow.h"
static GHashTable *handles;
typedef struct {
XdpImplAppChooser *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
ExternalWindow *external_parent;
char *chosen;
int response;
} AppDialogHandle;
static void
app_dialog_handle_free (gpointer data)
{
AppDialogHandle *handle = data;
g_hash_table_remove (handles, handle->request->id);
g_clear_object (&handle->external_parent);
g_object_unref (handle->request);
g_object_unref (handle->dialog);
g_free (handle->chosen);
g_free (handle);
}
static void
app_dialog_handle_close (AppDialogHandle *handle)
{
gtk_widget_destroy (handle->dialog);
app_dialog_handle_free (handle);
}
static void
send_response (AppDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&opt_builder, "{sv}", "choice", g_variant_new_string (handle->chosen ? handle->chosen : ""));
if (handle->request->exported)
request_unexport (handle->request);
xdp_impl_app_chooser_complete_choose_application (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
app_dialog_handle_close (handle);
}
static void
handle_app_chooser_close (AppChooserDialog *dialog,
gpointer data)
{
AppDialogHandle *handle = data;
GAppInfo *info;
info = app_chooser_dialog_get_info (dialog);
if (info != NULL)
{
const char *desktop_id = g_app_info_get_id (info);
handle->response = 0;
handle->chosen = g_strndup (desktop_id, strlen (desktop_id) - strlen (".desktop"));
}
else
{
handle->response = 1;
handle->chosen = NULL;
}
send_response (handle);
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
AppDialogHandle *handle)
{
GVariantBuilder opt_builder;
if (handle->request->exported)
request_unexport (handle->request);
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_app_chooser_complete_choose_application (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
app_dialog_handle_close (handle);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static gboolean
handle_choose_application (XdpImplAppChooser *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char **choices,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
GtkWidget *dialog;
AppDialogHandle *handle;
const char *sender;
const char *latest_chosen_id;
const char *content_type;
const char *location;
gboolean modal;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (!g_variant_lookup (arg_options, "last_choice", "&s", &latest_chosen_id))
latest_chosen_id = NULL;
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
if (!g_variant_lookup (arg_options, "content_type", "&s", &content_type))
content_type = NULL;
if (!g_variant_lookup (arg_options, "filename", "&s", &location) &&
!g_variant_lookup (arg_options, "uri", "&s", &location))
location = NULL;
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
dialog = GTK_WIDGET (app_chooser_dialog_new (choices, latest_chosen_id, content_type, location));
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
gtk_window_set_modal (GTK_WINDOW (dialog), modal);
handle = g_new0 (AppDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->external_parent = external_parent;
g_hash_table_insert (handles, handle->request->id, handle);
g_signal_connect (request, "handle-close",
G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "close",
G_CALLBACK (handle_app_chooser_close), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
gtk_window_present (GTK_WINDOW (dialog));
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
static gboolean
handle_update_choices (XdpImplAppChooser *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char **choices)
{
AppDialogHandle *handle;
g_autofree char *a = NULL;
handle = g_hash_table_lookup (handles, arg_handle);
if (handle == NULL)
{
g_dbus_method_invocation_return_error (invocation,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_NOT_FOUND,
"Request not found");
return TRUE;
}
g_debug ("Updating choices: %s\n", a = g_strjoinv (", ", (char **)choices));
app_chooser_dialog_update_choices (APP_CHOOSER_DIALOG (handle->dialog), choices);
g_dbus_method_invocation_return_value (invocation, NULL);
return TRUE;
}
gboolean
app_chooser_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_app_chooser_skeleton_new ());
g_signal_connect (helper, "handle-choose-application", G_CALLBACK (handle_choose_application), NULL);
g_signal_connect (helper, "handle-update-choices", G_CALLBACK (handle_update_choices), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
handles = g_hash_table_new (g_str_hash, g_str_equal);
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean app_chooser_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gio/gio.h>
#include <glib/gi18n.h>
#include <gio/gdesktopappinfo.h>
#include "appchooserdialog.h"
#include "appchooserrow.h"
#define LOCATION_MAX_LENGTH 40
#define INITIAL_LIST_SIZE 3
struct _AppChooserDialog {
GtkWindow parent;
GtkWidget *scrolled_window;
GtkWidget *titlebar;
GtkWidget *cancel_button;
GtkWidget *open_button;
GtkWidget *find_software_button;
GtkWidget *list;
GtkWidget *heading;
GtkWidget *stack;
GtkWidget *empty_box;
GtkWidget *empty_label;
char *content_type;
char **choices;
GtkWidget *selected_row;
GtkWidget *more_row;
GAppInfo *info;
};
struct _AppChooserDialogClass {
GtkWindowClass parent_class;
void (* close) (AppChooserDialog *dialog);
};
enum {
CLOSE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (AppChooserDialog, app_chooser_dialog, GTK_TYPE_WINDOW)
static void
update_header (GtkListBoxRow *row,
GtkListBoxRow *before,
gpointer data)
{
if (before != NULL &&
gtk_list_box_row_get_header (row) == NULL)
{
GtkWidget *separator;
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_show (separator);
gtk_list_box_row_set_header (row, separator);
}
}
static void
app_chooser_dialog_init (AppChooserDialog *dialog)
{
gtk_widget_init_template (GTK_WIDGET (dialog));
gtk_list_box_set_header_func (GTK_LIST_BOX (dialog->list), update_header, NULL, NULL);
}
static void
app_chooser_dialog_finalize (GObject *object)
{
AppChooserDialog *dialog = APP_CHOOSER_DIALOG (object);
g_free (dialog->content_type);
g_strfreev (dialog->choices);
G_OBJECT_CLASS (app_chooser_dialog_parent_class)->finalize (object);
}
GAppInfo *
app_chooser_dialog_get_info (AppChooserDialog *dialog)
{
return dialog->info;
}
static void
close_dialog (AppChooserDialog *dialog,
GAppInfo *info)
{
dialog->info = info;
g_signal_emit (dialog, signals[CLOSE], 0);
}
static void
show_more (AppChooserDialog *dialog)
{
int i;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->scrolled_window),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
gtk_widget_hide (dialog->more_row);
g_return_if_fail (g_strv_length ((char **)dialog->choices) > INITIAL_LIST_SIZE);
for (i = INITIAL_LIST_SIZE; dialog->choices[i]; i++)
{
g_autofree char *desktop_id = g_strconcat (dialog->choices[i], ".desktop", NULL);
g_autoptr(GAppInfo) info = G_APP_INFO (g_desktop_app_info_new (desktop_id));
GtkWidget *row;
row = GTK_WIDGET (app_chooser_row_new (info));
gtk_widget_set_visible (row, TRUE);
gtk_list_box_insert (GTK_LIST_BOX (dialog->list), row, -1);
}
}
static void
row_activated (GtkListBox *list,
GtkWidget *row,
AppChooserDialog *dialog)
{
GAppInfo *info = NULL;
if (row == dialog->more_row)
{
show_more (dialog);
return;
}
if (dialog->selected_row)
info = app_chooser_row_get_info (APP_CHOOSER_ROW (dialog->selected_row));
close_dialog (dialog, info);
}
static void
row_selected (GtkListBox *list,
GtkWidget *row,
AppChooserDialog *dialog)
{
gtk_widget_set_sensitive (dialog->open_button, TRUE);
dialog->selected_row = row;
}
static void
cancel_clicked (GtkWidget *button,
AppChooserDialog *dialog)
{
close_dialog (dialog, NULL);
}
static void
open_clicked (GtkWidget *button,
AppChooserDialog *dialog)
{
GAppInfo *info = NULL;
if (dialog->selected_row)
info = app_chooser_row_get_info (APP_CHOOSER_ROW (dialog->selected_row));
close_dialog (dialog, info);
}
static void
show_error_dialog (const gchar *primary,
const gchar *secondary,
GtkWindow *parent)
{
GtkWidget *message_dialog;
message_dialog = gtk_message_dialog_new (parent, 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
NULL);
g_object_set (message_dialog,
"text", primary,
"secondary-text", secondary,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_OK);
gtk_widget_show (message_dialog);
g_signal_connect (message_dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
}
static void
launch_software (AppChooserDialog *dialog)
{
g_autofree char *option = NULL;
g_autoptr(GSubprocess) process = NULL;
g_autoptr(GError) error = NULL;
if (dialog->content_type)
option = g_strconcat ("--search=", dialog->content_type, NULL);
else
option = g_strdup ("--mode=overview");
process = g_subprocess_new (0, &error, "gnome-software", option, NULL);
if (!process)
show_error_dialog (_("Failed to start Software"), error->message, GTK_WINDOW (dialog));
}
static void
find_in_software (GtkWidget *button,
AppChooserDialog *dialog)
{
launch_software (dialog);
}
static gboolean
app_chooser_delete_event (GtkWidget *dialog, GdkEventAny *event)
{
close_dialog (APP_CHOOSER_DIALOG (dialog), NULL);
return TRUE;
}
static void
app_chooser_dialog_close (AppChooserDialog *dialog)
{
gtk_window_close (GTK_WINDOW (dialog));
}
static void
app_chooser_dialog_class_init (AppChooserDialogClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkBindingSet *binding_set;
object_class->finalize = app_chooser_dialog_finalize;
widget_class->delete_event = app_chooser_delete_event;
class->close = app_chooser_dialog_close;
signals[CLOSE] = g_signal_new ("close",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/portal/desktop/gtk/appchooserdialog.ui");
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, scrolled_window);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, titlebar);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, cancel_button);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, open_button);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, find_software_button);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, list);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, heading);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, stack);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, empty_box);
gtk_widget_class_bind_template_child (widget_class, AppChooserDialog, empty_label);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_callback (widget_class, row_selected);
gtk_widget_class_bind_template_callback (widget_class, cancel_clicked);
gtk_widget_class_bind_template_callback (widget_class, open_clicked);
gtk_widget_class_bind_template_callback (widget_class, find_in_software);
}
/* Ellipsize the location, keeping the suffix which is likely
* to have more relevant information, such as filename and extension.
*/
static char *
shorten_location (const char *location)
{
int len;
if (location == NULL)
return NULL;
len = g_utf8_strlen (location, -1);
if (len < LOCATION_MAX_LENGTH)
return g_strdup (location);
for (; len >= LOCATION_MAX_LENGTH; len--)
location = g_utf8_next_char (location);
return g_strconcat ("…", location, NULL);
}
static void
ensure_default_in_initial_list (const char **choices,
const char *default_id)
{
int i;
guint n_choices;
if (default_id == NULL)
return;
n_choices = g_strv_length ((char **)choices);
if (n_choices <= INITIAL_LIST_SIZE)
return;
for (i = 0; i < INITIAL_LIST_SIZE; i++)
{
if (strcmp (choices[i], default_id) == 0)
return;
}
for (i = INITIAL_LIST_SIZE; i < n_choices; i++)
{
if (strcmp (choices[i], default_id) == 0)
{
const char *tmp = choices[0];
choices[0] = choices[i];
choices[i] = tmp;
return;
}
}
g_warning ("default_id not found\n");
}
static void
more_pressed (GtkGestureMultiPress *gesture,
int n_press,
double x,
double y,
AppChooserDialog *dialog)
{
if (n_press != 1)
return;
if (gtk_list_box_get_row_at_y (GTK_LIST_BOX (dialog->list), y) == GTK_LIST_BOX_ROW (dialog->more_row))
show_more (dialog);
}
AppChooserDialog *
app_chooser_dialog_new (const char **choices,
const char *default_id,
const char *content_type,
const char *location)
{
AppChooserDialog *dialog;
int n_choices;
int i;
g_autofree char *short_location = shorten_location (location);
dialog = g_object_new (app_chooser_dialog_get_type (), NULL);
dialog->content_type = g_strdup (content_type);
if (location)
{
g_autofree char *heading = NULL;
heading = g_strdup_printf (_("Choose an application to open the file “%s”."), short_location);
gtk_label_set_label (GTK_LABEL (dialog->heading), heading);
}
else
{
gtk_label_set_label (GTK_LABEL (dialog->heading), _("Choose an application."));
}
ensure_default_in_initial_list (choices, default_id);
dialog->choices = g_strdupv ((char **)choices);
n_choices = g_strv_length ((char **)choices);
if (n_choices == 0)
{
gtk_widget_show (dialog->empty_box);
gtk_stack_set_visible_child_name (GTK_STACK (dialog->stack), "empty");
gtk_widget_grab_default (dialog->find_software_button);
if (location)
{
g_autofree char *label = NULL;
label = g_strdup_printf (_("No apps installed that can open “%s”. You can find more applications in Software"), short_location);
gtk_label_set_label (GTK_LABEL (dialog->empty_label), label);
}
else
{
gtk_label_set_label (GTK_LABEL (dialog->empty_label), _("No suitable app installed. You can find more applications in Software."));
}
}
else
{
gtk_stack_set_visible_child_name (GTK_STACK (dialog->stack), "list");
gtk_widget_grab_default (dialog->open_button);
for (i = 0; i < MIN (n_choices, INITIAL_LIST_SIZE); i++)
{
g_autofree char *desktop_id = g_strconcat (choices[i], ".desktop", NULL);
g_autoptr(GAppInfo) info = G_APP_INFO (g_desktop_app_info_new (desktop_id));
GtkWidget *row;
row = GTK_WIDGET (app_chooser_row_new (info));
gtk_widget_set_visible (row, TRUE);
gtk_list_box_insert (GTK_LIST_BOX (dialog->list), row, -1);
if (default_id && strcmp (choices[i], default_id) == 0)
{
gtk_list_box_select_row (GTK_LIST_BOX (dialog->list), GTK_LIST_BOX_ROW (row));
gtk_widget_set_sensitive (dialog->open_button, TRUE);
dialog->selected_row = row;
}
}
if (n_choices > INITIAL_LIST_SIZE)
{
GtkWidget *row;
GtkWidget *image;
GtkGesture *gesture;
row = GTK_WIDGET (gtk_list_box_row_new ());
gesture = gtk_gesture_multi_press_new (dialog->list);
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), GTK_PHASE_BUBBLE);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_PRIMARY);
g_signal_connect (gesture, "pressed", G_CALLBACK (more_pressed), dialog);
gtk_list_box_row_set_selectable (GTK_LIST_BOX_ROW (row), FALSE);
image = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_BUTTON);
g_object_set (image, "margin", 14, NULL);
gtk_container_add (GTK_CONTAINER (row), image);
gtk_widget_set_visible (row, TRUE);
gtk_widget_set_visible (image, TRUE);
gtk_list_box_insert (GTK_LIST_BOX (dialog->list), row, -1);
dialog->more_row = row;
}
}
return dialog;
}
void
app_chooser_dialog_update_choices (AppChooserDialog *dialog,
const char **choices)
{
int i;
GPtrArray *new_choices;
new_choices = g_ptr_array_new ();
g_ptr_array_set_size (new_choices, g_strv_length (dialog->choices));
for (i = 0; dialog->choices[i]; i++)
new_choices->pdata[i] = dialog->choices[i];
for (i = 0; choices[i]; i++)
{
if (g_strv_contains ((const char * const *)dialog->choices, choices[i]))
continue;
g_ptr_array_add (new_choices, g_strdup (choices[i]));
if (dialog->more_row && !gtk_widget_get_visible (dialog->more_row))
{
g_autofree char *desktop_id = NULL;
g_autoptr(GAppInfo) info = NULL;
GtkWidget *row;
desktop_id = g_strconcat (choices[i], ".desktop", NULL);
info = G_APP_INFO (g_desktop_app_info_new (desktop_id));
row = GTK_WIDGET (app_chooser_row_new (info));
gtk_widget_set_visible (row, TRUE);
gtk_list_box_insert (GTK_LIST_BOX (dialog->list), row, -1);
}
}
g_ptr_array_add (new_choices, NULL);
g_free (dialog->choices);
dialog->choices = (char **) g_ptr_array_free (new_choices, FALSE);
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gtk/gtk.h>
#define APP_TYPE_CHOOSER_DIALOG (app_chooser_dialog_get_type ())
#define APP_CHOOSER_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST (object, APP_TYPE_CHOOSER_DIALOG, AppChooserDialog))
typedef struct _AppChooserDialog AppChooserDialog;
typedef struct _AppChooserDialogClass AppChooserDialogClass;
GType app_chooser_dialog_get_type (void) G_GNUC_CONST;
AppChooserDialog * app_chooser_dialog_new (const char **app_ids,
const char *default_id,
const char *content_type,
const char *filename);
void app_chooser_dialog_update_choices (AppChooserDialog *dialog,
const char **app_ids);
GAppInfo *app_chooser_dialog_get_info (AppChooserDialog *dialog);
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="xdg-desktop-portal-gtk">
<!-- interface-requires gtk+ 3.22 -->
<template class="AppChooserDialog" parent="GtkWindow">
<property name="type-hint">dialog</property>
<property name="resizable">0</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="titlebar">
<property name="visible">1</property>
<property name="title" translatable="yes">Open With…</property>
<child>
<object class="GtkButton" id="cancel_button">
<property name="visible">1</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="use-underline">1</property>
<signal name="clicked" handler="cancel_clicked"/>
</object>
</child>
<child>
<object class="GtkButton" id="open_button">
<property name="visible">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">1</property>
<property name="can-default">1</property>
<signal name="clicked" handler="open_clicked"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">1</property>
<child>
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="visible">1</property>
<property name="expand">1</property>
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">never</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
<child>
<object class="GtkLabel" id="heading">
<property name="visible">1</property>
<property name="halign">start</property>
<property name="xalign">0</property>
<property name="margin">20</property>
</object>
</child>
<child>
<object class="GtkListBox" id="list">
<style>
<class name="frame"/>
<class name="view"/>
</style>
<signal name="row-activated" handler="row_activated"/>
<signal name="row-selected" handler="row_selected"/>
<property name="selection-mode">single</property>
<property name="activate-on-single-click">0</property>
<property name="visible">1</property>
<property name="margin-left">20</property>
<property name="margin-right">20</property>
<property name="margin-bottom">20</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">list</property>
</packing>
</child>
<child>
<object class="GtkBox" id="empty_box">
<property name="visible">0</property>
<property name="orientation">vertical</property>
<style>
<class name="view"/>
</style>
<child type="center">
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkImage" id="empty_image">
<property name="margin-top">40</property>
<property name="visible">1</property>
<property name="icon-name">org.gnome.Software-symbolic</property>
<property name="pixel-size">128</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="empty_heading">
<property name="margin-top">40</property>
<property name="visible">1</property>
<property name="label" translatable="yes">No Apps available</property>
<attributes>
<attribute name="weight" value="600"/>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel" id="empty_label">
<property name="margin-top">20</property>
<property name="margin-start">40</property>
<property name="margin-end">40</property>
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="max-width-chars">45</property>
<property name="wrap-mode">word</property>
<property name="label">No apps installed that are able to open file.extension. You can find more applications in Software.</property>
</object>
</child>
<child>
<object class="GtkButton" id="find_software_button">
<property name="visible">1</property>
<property name="halign">center</property>
<property name="margin">30</property>
<property name="can-default">1</property>
<style>
<class name="suggested-action"/>
</style>
<signal name="clicked" handler="find_in_software"/>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="spacing">6</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">org.gnome.Software-symbolic</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="label" translatable="yes">_Find More in Software</property>
<property name="use-underline">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">empty</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "appchooserrow.h"
struct _AppChooserRow {
GtkListBoxRow parent;
GAppInfo *info;
gboolean selected;
GtkWidget *icon;
GtkWidget *name;
GtkWidget *check;
};
struct _AppChooserRowClass {
GtkListBoxRowClass parent_class;
};
G_DEFINE_TYPE (AppChooserRow, app_chooser_row, GTK_TYPE_LIST_BOX_ROW)
static void
app_chooser_row_init (AppChooserRow *row)
{
gtk_widget_init_template (GTK_WIDGET (row));
}
static void
app_chooser_row_finalize (GObject *object)
{
AppChooserRow *row = APP_CHOOSER_ROW (object);
g_clear_object (&row->info);
G_OBJECT_CLASS (app_chooser_row_parent_class)->finalize (object);
}
static void
app_chooser_row_class_init (AppChooserRowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->finalize = app_chooser_row_finalize;
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/portal/desktop/gtk/appchooserrow.ui");
gtk_widget_class_bind_template_child (widget_class, AppChooserRow, icon);
gtk_widget_class_bind_template_child (widget_class, AppChooserRow, name);
gtk_widget_class_bind_template_child (widget_class, AppChooserRow, check);
}
AppChooserRow *
app_chooser_row_new (GAppInfo *info)
{
AppChooserRow *row;
GIcon *icon;
row = g_object_new (app_chooser_row_get_type (), NULL);
g_set_object (&row->info, info);
icon = g_app_info_get_icon (info);
if (!icon)
icon = g_themed_icon_new ("application-x-executable");
gtk_image_set_from_gicon (GTK_IMAGE (row->icon), icon, GTK_ICON_SIZE_DIALOG);
gtk_image_set_pixel_size (GTK_IMAGE (row->icon), 32);
gtk_label_set_label (GTK_LABEL (row->name), g_app_info_get_name (info));
return row;
}
GAppInfo *
app_chooser_row_get_info (AppChooserRow *row)
{
return row->info;
}
void
app_chooser_row_set_selected (AppChooserRow *row,
gboolean selected)
{
gtk_widget_set_opacity (row->check, selected ? 1.0 : 0.0);
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gtk/gtk.h>
#define APP_TYPE_CHOOSER_ROW (app_chooser_row_get_type ())
#define APP_CHOOSER_ROW(object) (G_TYPE_CHECK_INSTANCE_CAST (object, APP_TYPE_CHOOSER_ROW, AppChooserRow))
typedef struct _AppChooserRow AppChooserRow;
typedef struct _AppChooserRowClass AppChooserRowClass;
GType app_chooser_row_get_type (void);
AppChooserRow *app_chooser_row_new (GAppInfo *info);
GAppInfo *app_chooser_row_get_info (AppChooserRow *row);
void app_chooser_row_set_selected (AppChooserRow *row,
gboolean selected);
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="xdg-desktop-portal-gtk">
<!-- interface-requires gtk+ 3.22 -->
<template class="AppChooserRow" parent="GtkListBoxRow">
<property name="visible">1</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">horizontal</property>
<property name="spacing">10</property>
<property name="halign">fill</property>
<child>
<object class="GtkImage" id="icon">
<property name="visible">1</property>
<property name="margin">10</property>
</object>
</child>
<child>
<object class="GtkLabel" id="name">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="width-chars">30</property>
<property name="max-width-chars">30</property>
<property name="hexpand">1</property>
<property name="ellipsize">end</property>
</object>
</child>
<child>
<object class="GtkImage" id="check">
<property name="visible">1</property>
<property name="margin">10</property>
<property name="opacity">0</property>
<property name="icon-name">object-select-symbolic</property>
</object>
</child>
</object>
</child>
</template>
</interface>
/*
* Copyright © 2022 Matthew Leeds
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthew Leeds <mwleeds@protonmail.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <gio/gunixinputstream.h>
#include <glib/gi18n.h>
#include "xdg-desktop-portal-dbus.h"
#include "dynamic-launcher.h"
#include "request.h"
#include "utils.h"
#include "externalwindow.h"
#define DEFAULT_ICON_SIZE 192
typedef enum {
DYNAMIC_LAUNCHER_TYPE_APPLICATION = 1,
DYNAMIC_LAUNCHER_TYPE_WEBAPP = 2,
} DynamicLauncherType;
typedef struct {
XdpImplDynamicLauncher *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
GtkWidget *entry;
ExternalWindow *external_parent;
GVariant *icon_v;
int response;
} InstallDialogHandle;
static void
install_dialog_handle_free (gpointer data)
{
InstallDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_object_unref (handle->request);
if (handle->dialog)
g_object_unref (handle->dialog);
g_variant_unref (handle->icon_v);
g_free (handle);
}
static void
install_dialog_handle_close (InstallDialogHandle *handle)
{
if (handle->dialog)
gtk_widget_destroy (handle->dialog);
install_dialog_handle_free (handle);
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
InstallDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_dynamic_launcher_complete_prepare_install (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
if (handle->request->exported)
request_unexport (handle->request);
install_dialog_handle_close (handle);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static void
send_prepare_install_response (InstallDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
if (handle->response == 0)
{
const char *chosen_name = gtk_entry_get_text (GTK_ENTRY (handle->entry));
if (chosen_name == NULL || chosen_name[0] == '\0')
{
handle->response = 3;
}
else
{
g_variant_builder_add (&opt_builder, "{sv}", "name", g_variant_new_string (chosen_name));
g_variant_builder_add (&opt_builder, "{sv}", "icon", handle->icon_v);
}
}
if (handle->request->exported)
request_unexport (handle->request);
xdp_impl_dynamic_launcher_complete_prepare_install (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
install_dialog_handle_close (handle);
}
static void
handle_prepare_install_response (GtkDialog *dialog,
gint response,
gpointer data)
{
InstallDialogHandle *handle = data;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_APPLY:
/* fall thru */
case GTK_RESPONSE_OK:
handle->response = 0;
break;
}
send_prepare_install_response (handle);
}
static gboolean
handle_prepare_install (XdpImplDynamicLauncher *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_name,
GVariant *arg_icon_v,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
InstallDialogHandle *handle;
GtkWidget *dialog, *content_area, *box, *image, *label, *entry;
GtkDialogFlags dialog_flags;
const char *url = NULL;
const char *title;
gboolean modal, editable_name, editable_icon;
DynamicLauncherType launcher_type;
g_autoptr(GVariant) icon_v = NULL;
g_autoptr(GInputStream) icon_stream = NULL;
g_autoptr(GIcon) icon = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GError) error = NULL;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
handle = g_new0 (InstallDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->external_parent = external_parent;
/* FIXME: Implement editable-icon option rather than passing along the default */
handle->icon_v = g_variant_ref (arg_icon_v);
icon_v = g_variant_get_variant (arg_icon_v);
if (icon_v)
icon = g_icon_deserialize (icon_v);
if (!icon || !G_IS_BYTES_ICON (icon))
{
g_warning ("Icon deserialization failed");
goto err;
}
if (!g_variant_lookup (arg_options, "launcher_type", "u", &launcher_type))
launcher_type = DYNAMIC_LAUNCHER_TYPE_APPLICATION;
if (launcher_type == DYNAMIC_LAUNCHER_TYPE_WEBAPP &&
!g_variant_lookup (arg_options, "target", "&s", &url))
url = NULL;
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
if (!g_variant_lookup (arg_options, "editable_name", "b", &editable_name))
editable_name = TRUE;
if (!g_variant_lookup (arg_options, "editable_icon", "b", &editable_icon))
editable_icon = FALSE;
if (modal)
dialog_flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR;
else
dialog_flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR;
if (launcher_type == DYNAMIC_LAUNCHER_TYPE_WEBAPP)
title = _("Create Web Application");
else
title = _("Create Application");
/* Show dialog with icon, title. */
dialog = gtk_dialog_new_with_buttons (title,
GTK_WINDOW (fake_parent),
dialog_flags,
_("_Cancel"),
GTK_RESPONSE_CANCEL,
_("C_reate"),
GTK_RESPONSE_OK,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_widget_set_margin_top (box, 15);
gtk_widget_set_margin_bottom (box, 15);
gtk_widget_set_margin_start (box, 15);
gtk_widget_set_margin_end (box, 15);
gtk_container_add (GTK_CONTAINER (content_area), box);
image = gtk_image_new ();
gtk_widget_set_vexpand (image, TRUE);
gtk_widget_set_size_request (image, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
gtk_widget_set_margin_bottom (image, 10);
gtk_container_add (GTK_CONTAINER (box), image);
icon_stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), 0, NULL, NULL, &error);
if (icon_stream)
pixbuf = gdk_pixbuf_new_from_stream_at_scale (icon_stream,
DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE,
TRUE, NULL, &error);
if (error)
{
g_warning ("Loading icon into pixbuf failed: %s", error->message);
goto err;
}
gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (entry), arg_name);
gtk_widget_set_sensitive (entry, editable_name);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_box_pack_start (GTK_BOX (box), entry, FALSE, TRUE, 0);
if (launcher_type == DYNAMIC_LAUNCHER_TYPE_WEBAPP)
{
g_autofree char *escaped_address = NULL;
g_autofree char *markup = NULL;
GtkStyleContext *context;
escaped_address = g_markup_escape_text (url, -1);
markup = g_strdup_printf ("<small>%s</small>", escaped_address);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
gtk_label_set_max_width_chars (GTK_LABEL (label), 40);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
context = gtk_widget_get_style_context (label);
gtk_style_context_add_class (context, "dim-label");
}
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
handle->dialog = g_object_ref (dialog);
handle->entry = entry;
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "response", G_CALLBACK (handle_prepare_install_response), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
request_export (request, g_dbus_method_invocation_get_connection (invocation));
gtk_widget_show_all (dialog);
return TRUE;
err:
handle->response = 2;
send_prepare_install_response (handle);
return TRUE;
}
static gboolean
handle_request_install_token (XdpImplDynamicLauncher *object,
GDBusMethodInvocation *invocation,
const char *arg_app_id,
GVariant *arg_options)
{
/* Generally these should be allowed in each desktop specific x-d-p backend,
* but add them here as well as a fallback.
*/
static const char *allowlist[] = {"org.gnome.Software",
"org.gnome.SoftwareDevel",
"io.elementary.appcenter",
"org.kde.discover",
NULL };
guint response;
if (arg_app_id != NULL && g_strv_contains (allowlist, arg_app_id))
response = 0;
else
response = 2;
xdp_impl_dynamic_launcher_complete_request_install_token (object,
invocation,
response);
return TRUE;
}
gboolean
dynamic_launcher_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
DynamicLauncherType supported_types = DYNAMIC_LAUNCHER_TYPE_APPLICATION |
DYNAMIC_LAUNCHER_TYPE_WEBAPP;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_dynamic_launcher_skeleton_new ());
xdp_impl_dynamic_launcher_set_supported_launcher_types (XDP_IMPL_DYNAMIC_LAUNCHER (helper),
supported_types);
g_signal_connect (helper, "handle-prepare-install", G_CALLBACK (handle_prepare_install), NULL);
g_signal_connect (helper, "handle-request-install-token", G_CALLBACK (handle_request_install_token), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2022 Matthew Leeds
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthew Leeds <mwleeds@protonmail.com>
*/
#pragma once
#include <gio/gio.h>
gboolean dynamic_launcher_init (GDBusConnection *bus,
GError **error);
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "email.h"
#include "request.h"
#include "utils.h"
static gboolean
compose_mail_mailto (GAppInfo *info,
const char * const *addrs,
const char * const *cc,
const char * const *bcc,
const char *subject,
const char *body,
const char **attachments,
GError **error)
{
g_autofree char *enc_subject = NULL;
g_autofree char *enc_body = NULL;
g_autoptr(GString) url = NULL;
g_autoptr(GList) uris = NULL;
int i;
gboolean success;
const char *sep;
enc_subject = g_uri_escape_string (subject ? subject : "", NULL, FALSE);
enc_body = g_uri_escape_string (body ? body : "", NULL, FALSE);
url = g_string_new ("mailto:");
sep = "?";
if (addrs)
{
for (i = 0; addrs[i]; i++)
{
if (i > 0)
g_string_append (url, ",");
g_string_append_printf (url, "%s", addrs[i]);
}
}
if (cc)
{
g_string_append_printf (url, "%scc=", sep);
sep = "&";
for (i = 0; cc[i]; i++)
{
if (i > 0)
g_string_append (url, ",");
g_string_append_printf (url, "%s", cc[i]);
}
}
if (bcc)
{
g_string_append_printf (url, "%sbcc=", sep);
sep = "&";
for (i = 0; bcc[i]; i++)
{
if (i > 0)
g_string_append (url, ",");
g_string_append_printf (url, "%s", bcc[i]);
}
}
g_string_append_printf (url, "%ssubject=%s", sep, enc_subject);
g_string_append_printf (url, "&body=%s", enc_body);
for (i = 0; attachments[i]; i++)
g_string_append_printf (url, "&attachment=%s", attachments[i]);
uris = g_list_append (uris, url->str);
g_debug ("Launching: %s\n", url->str);
success = g_app_info_launch_uris (info, uris, NULL, error);
return success;
}
static gboolean
compose_mail (const char * const *addrs,
const char * const *cc,
const char * const *bcc,
const char *subject,
const char *body,
const char **attachments,
GError **error)
{
g_autoptr(GAppInfo) info = NULL;
info = g_app_info_get_default_for_uri_scheme ("mailto");
if (info == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No mailto handler");
return FALSE;
}
return compose_mail_mailto (info, addrs, cc, bcc, subject, body, attachments, error);
}
static gboolean
handle_compose_email (XdpImplEmail *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
g_autoptr(GError) error = NULL;
const char *address = NULL;
const char *subject = NULL;
const char *body = NULL;
const char *no_att[1] = { NULL };
const char **attachments = no_att;
guint response = 0;
GVariantBuilder opt_builder;
const char * const *addresses = NULL;
const char * const *cc = NULL;
const char * const *bcc = NULL;
g_auto(GStrv) addrs = NULL;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
g_variant_lookup (arg_options, "address", "&s", &address);
g_variant_lookup (arg_options, "addresses", "^a&s", &addresses);
g_variant_lookup (arg_options, "cc", "^a&s", &cc);
g_variant_lookup (arg_options, "bcc", "^a&s", &bcc);
g_variant_lookup (arg_options, "subject", "&s", &subject);
g_variant_lookup (arg_options, "body", "&s", &body);
g_variant_lookup (arg_options, "attachments", "^a&s", &attachments);
if (address)
{
if (addresses)
{
gsize len = g_strv_length ((char **)addresses);
addrs = g_new (char *, len + 2);
addrs[0] = g_strdup (address);
memcpy (addrs + 1, addresses, sizeof (char *) * (len + 1));
}
else
{
addrs = g_new (char *, 2);
addrs[0] = g_strdup (address);
addrs[1] = NULL;
}
}
else
addrs = g_strdupv ((char **)addresses);
if (!compose_mail ((const char * const *)addrs, cc, bcc, subject, body, attachments, NULL))
response = 2;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_email_complete_compose_email (object,
invocation,
response,
g_variant_builder_end (&opt_builder));
return TRUE;
}
gboolean
email_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_email_skeleton_new ());
g_signal_connect (helper, "handle-compose-email", G_CALLBACK (handle_compose_email), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean email_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#include "config.h"
#include <gdk/gdk.h>
#include <gdk/gdkwayland.h>
#include "externalwindow-wayland.h"
static GdkDisplay *wayland_display;
struct _ExternalWindowWayland
{
ExternalWindow parent;
char *handle_str;
};
struct _ExternalWindowWaylandClass
{
ExternalWindowClass parent_class;
};
G_DEFINE_TYPE (ExternalWindowWayland, external_window_wayland,
EXTERNAL_TYPE_WINDOW)
static GdkDisplay *
get_wayland_display (void)
{
if (wayland_display)
return wayland_display;
gdk_set_allowed_backends ("wayland");
wayland_display = gdk_display_open (NULL);
gdk_set_allowed_backends (NULL);
if (!wayland_display)
g_warning ("Failed to open Wayland display");
return wayland_display;
}
ExternalWindowWayland *
external_window_wayland_new (const char *handle_str)
{
ExternalWindowWayland *external_window_wayland;
GdkDisplay *display;
display = get_wayland_display ();
if (!display)
{
g_warning ("No Wayland display connection, ignoring Wayland parent");
return NULL;
}
external_window_wayland = g_object_new (EXTERNAL_TYPE_WINDOW_WAYLAND,
"display", display,
NULL);
external_window_wayland->handle_str = g_strdup (handle_str);
return external_window_wayland;
}
static void
external_window_wayland_set_parent_of (ExternalWindow *external_window,
GdkWindow *child_window)
{
ExternalWindowWayland *external_window_wayland =
EXTERNAL_WINDOW_WAYLAND (external_window);
char *handle_str = external_window_wayland->handle_str;
if (!gdk_wayland_window_set_transient_for_exported (child_window, handle_str))
g_warning ("Failed to set portal window transient for external parent");
}
static void
external_window_wayland_dispose (GObject *object)
{
ExternalWindowWayland *external_window_wayland =
EXTERNAL_WINDOW_WAYLAND (object);
g_free (external_window_wayland->handle_str);
G_OBJECT_CLASS (external_window_wayland_parent_class)->dispose (object);
}
static void
external_window_wayland_init (ExternalWindowWayland *external_window_wayland)
{
}
static void
external_window_wayland_class_init (ExternalWindowWaylandClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ExternalWindowClass *external_window_class = EXTERNAL_WINDOW_CLASS (klass);
object_class->dispose = external_window_wayland_dispose;
external_window_class->set_parent_of = external_window_wayland_set_parent_of;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#pragma once
#include <glib-object.h>
#include "externalwindow.h"
#define EXTERNAL_TYPE_WINDOW_WAYLAND (external_window_wayland_get_type ())
#define EXTERNAL_WINDOW_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_CAST (object, EXTERNAL_TYPE_WINDOW_WAYLAND, ExternalWindowWayland))
typedef struct _ExternalWindowWayland ExternalWindowWayland;
typedef struct _ExternalWindowWaylandClass ExternalWindowWaylandClass;
GType external_window_wayland_get_type (void);
ExternalWindowWayland *external_window_wayland_new (const char *handle_str);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#include "config.h"
#include <errno.h>
#include <gdk/gdkx.h>
#include <gdk/gdk.h>
#include <stdlib.h>
#include "externalwindow-x11.h"
static GdkDisplay *x11_display;
struct _ExternalWindowX11
{
ExternalWindow parent;
GdkWindow *foreign_gdk_window;
};
struct _ExternalWindowX11Class
{
ExternalWindowClass parent_class;
};
G_DEFINE_TYPE (ExternalWindowX11, external_window_x11,
EXTERNAL_TYPE_WINDOW)
static GdkDisplay *
get_x11_display (void)
{
if (x11_display)
return x11_display;
gdk_set_allowed_backends ("x11");
x11_display = gdk_display_open (NULL);
gdk_set_allowed_backends (NULL);
if (!x11_display)
g_warning ("Failed to open X11 display");
return x11_display;
}
ExternalWindowX11 *
external_window_x11_new (const char *handle_str)
{
ExternalWindowX11 *external_window_x11;
GdkDisplay *display;
int xid;
GdkWindow *foreign_gdk_window;
display = get_x11_display ();
if (!display)
{
g_warning ("No X display connection, ignoring X11 parent");
return NULL;
}
errno = 0;
xid = strtol (handle_str, NULL, 16);
if (errno != 0)
{
g_warning ("Failed to reference external X11 window, invalid XID %s", handle_str);
return NULL;
}
foreign_gdk_window = gdk_x11_window_foreign_new_for_display (display, xid);
if (!foreign_gdk_window)
{
g_warning ("Failed to create foreign window for XID %d", xid);
return NULL;
}
external_window_x11 = g_object_new (EXTERNAL_TYPE_WINDOW_X11,
"display", display,
NULL);
external_window_x11->foreign_gdk_window = foreign_gdk_window;
return external_window_x11;
}
static void
external_window_x11_set_parent_of (ExternalWindow *external_window,
GdkWindow *child_window)
{
ExternalWindowX11 *external_window_x11 =
EXTERNAL_WINDOW_X11 (external_window);
gdk_window_set_transient_for (child_window,
external_window_x11->foreign_gdk_window);
}
static void
external_window_x11_dispose (GObject *object)
{
ExternalWindowX11 *external_window_x11 = EXTERNAL_WINDOW_X11 (object);
g_clear_object (&external_window_x11->foreign_gdk_window);
G_OBJECT_CLASS (external_window_x11_parent_class)->dispose (object);
}
static void
external_window_x11_init (ExternalWindowX11 *external_window_x11)
{
}
static void
external_window_x11_class_init (ExternalWindowX11Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ExternalWindowClass *external_window_class = EXTERNAL_WINDOW_CLASS (klass);
object_class->dispose = external_window_x11_dispose;
external_window_class->set_parent_of = external_window_x11_set_parent_of;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#pragma once
#include <glib-object.h>
#include "externalwindow.h"
#define EXTERNAL_TYPE_WINDOW_X11 (external_window_x11_get_type ())
#define EXTERNAL_WINDOW_X11(object) (G_TYPE_CHECK_INSTANCE_CAST (object, EXTERNAL_TYPE_WINDOW_X11, ExternalWindowX11))
typedef struct _ExternalWindowX11 ExternalWindowX11;
typedef struct _ExternalWindowX11Class ExternalWindowX11Class;
GType external_window_get_type (void);
ExternalWindowX11 *external_window_x11_new (const char *handle_str);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#include "config.h"
#include <string.h>
#include "externalwindow.h"
#ifdef HAVE_GTK_X11
#include "externalwindow-x11.h"
#endif
#ifdef HAVE_GTK_WAYLAND
#include "externalwindow-wayland.h"
#endif
enum
{
PROP_0,
PROP_DISPLAY,
};
typedef struct _ExternalWindowPrivate
{
GdkDisplay *display;
} ExternalWindowPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (ExternalWindow, external_window, G_TYPE_OBJECT)
ExternalWindow *
create_external_window_from_handle (const char *handle_str)
{
#ifdef HAVE_GTK_X11
{
const char x11_prefix[] = "x11:";
if (g_str_has_prefix (handle_str, x11_prefix))
{
ExternalWindowX11 *external_window_x11;
const char *x11_handle_str = handle_str + strlen (x11_prefix);
external_window_x11 = external_window_x11_new (x11_handle_str);
return EXTERNAL_WINDOW (external_window_x11);
}
}
#endif
#ifdef HAVE_GTK_WAYLAND
{
const char wayland_prefix[] = "wayland:";
if (g_str_has_prefix (handle_str, wayland_prefix))
{
ExternalWindowWayland *external_window_wayland;
const char *wayland_handle_str = handle_str + strlen (wayland_prefix);
external_window_wayland =
external_window_wayland_new (wayland_handle_str);
return EXTERNAL_WINDOW (external_window_wayland);
}
}
#endif
g_warning ("Unhandled parent window type %s\n", handle_str);
return NULL;
}
void
external_window_set_parent_of (ExternalWindow *external_window,
GdkWindow *child_window)
{
EXTERNAL_WINDOW_GET_CLASS (external_window)->set_parent_of (external_window,
child_window);
}
GdkDisplay *
external_window_get_display (ExternalWindow *external_window)
{
ExternalWindowPrivate *priv =
external_window_get_instance_private (external_window);
return priv->display;
}
static void
external_window_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ExternalWindow *external_window = EXTERNAL_WINDOW (object);
ExternalWindowPrivate *priv =
external_window_get_instance_private (external_window);
switch (prop_id)
{
case PROP_DISPLAY:
g_set_object (&priv->display, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
external_window_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ExternalWindow *external_window = EXTERNAL_WINDOW (object);
ExternalWindowPrivate *priv =
external_window_get_instance_private (external_window);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
external_window_init (ExternalWindow *external_window)
{
}
static void
external_window_class_init (ExternalWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = external_window_get_property;
object_class->set_property = external_window_set_property;
g_object_class_install_property (object_class,
PROP_DISPLAY,
g_param_spec_object ("display",
"GdkDisplay",
"The GdkDisplay instance",
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jonas Ådahl <jadahl@redhat.com>
*/
#pragma once
#include <glib-object.h>
#include <gtk/gtk.h>
#define EXTERNAL_TYPE_WINDOW (external_window_get_type ())
#define EXTERNAL_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST (object, EXTERNAL_TYPE_WINDOW, ExternalWindow))
#define EXTERNAL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, EXTERNAL_TYPE_WINDOW, ExternalWindowClass))
#define EXTERNAL_WINDOW_GET_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS (klass, EXTERNAL_TYPE_WINDOW, ExternalWindowClass))
typedef struct _ExternalWindow ExternalWindow;
typedef struct _ExternalWindowClass ExternalWindowClass;
struct _ExternalWindow
{
GObject parent_instance;
};
struct _ExternalWindowClass
{
GObjectClass parent_class;
void (*set_parent_of) (ExternalWindow *external_window,
GdkWindow *child_window);
};
GType external_window_get_type (void);
ExternalWindow *create_external_window_from_handle (const char *handle_str);
void external_window_set_parent_of (ExternalWindow *external_window,
GdkWindow *child_window);
GdkDisplay *external_window_get_display (ExternalWindow *external_window);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
* Copyright (C) 2017 Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Behdad Esfahbod, Red Hat, Inc.
*/
/* NOTE: This file is copied from gnome-settings-daemon, please keep it in sync */
#include "fc-monitor.h"
#include <gio/gio.h>
#include <fontconfig/fontconfig.h>
#define TIMEOUT_MILLISECONDS 1000
static void
fontconfig_cache_update_thread (GTask *task,
gpointer source_object G_GNUC_UNUSED,
gpointer task_data G_GNUC_UNUSED,
GCancellable *cancellable G_GNUC_UNUSED)
{
if (FcConfigUptoDate (NULL)) {
g_task_return_boolean (task, FALSE);
return;
}
if (!FcInitReinitialize ()) {
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
"FcInitReinitialize failed");
return;
}
g_task_return_boolean (task, TRUE);
}
static void
fontconfig_cache_update_async (GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task = g_task_new (NULL, NULL, callback, user_data);
g_task_run_in_thread (task, fontconfig_cache_update_thread);
g_object_unref (task);
}
static gboolean
fontconfig_cache_update_finish (GAsyncResult *result,
GError **error)
{
return g_task_propagate_boolean (G_TASK (result), error);
}
typedef enum {
UPDATE_IDLE,
UPDATE_PENDING,
UPDATE_RUNNING,
UPDATE_RESTART,
} UpdateState;
struct _FcMonitor {
GObject parent_instance;
GPtrArray *monitors;
guint timeout;
UpdateState state;
gboolean notify;
};
enum {
SIGNAL_UPDATED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0, };
static void fc_monitor_finalize (GObject *object);
static void monitor_files (FcMonitor *self, FcStrList *list);
static void stuff_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
GFileMonitorEvent event_type, gpointer data);
static void start_timeout (FcMonitor *self);
static gboolean start_update (gpointer data);
static void update_done (GObject *source_object, GAsyncResult *result, gpointer user_data);
G_DEFINE_TYPE (FcMonitor, fc_monitor, G_TYPE_OBJECT);
static void
fc_monitor_class_init (FcMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fc_monitor_finalize;
signals[SIGNAL_UPDATED] = g_signal_new ("updated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
}
FcMonitor *
fc_monitor_new (void)
{
return g_object_new (FC_TYPE_MONITOR, NULL);
}
static void
fc_monitor_init (FcMonitor *self G_GNUC_UNUSED)
{
FcInit ();
}
static void
fc_monitor_finalize (GObject *object)
{
FcMonitor *self = FC_MONITOR (object);
if (self->timeout)
g_source_remove (self->timeout);
self->timeout = 0;
g_clear_pointer (&self->monitors, g_ptr_array_unref);
G_OBJECT_CLASS (fc_monitor_parent_class)->finalize (object);
}
void
fc_monitor_start (FcMonitor *self)
{
g_return_if_fail (FC_IS_MONITOR (self));
g_return_if_fail (self->monitors == NULL);
self->monitors = g_ptr_array_new_with_free_func (g_object_unref);
monitor_files (self, FcConfigGetConfigFiles (NULL));
monitor_files (self, FcConfigGetFontDirs (NULL));
}
void
fc_monitor_stop (FcMonitor *self)
{
g_return_if_fail (FC_IS_MONITOR (self));
g_clear_pointer (&self->monitors, g_ptr_array_unref);
}
static void
monitor_files (FcMonitor *self,
FcStrList *list)
{
const char *str;
while ((str = (const char *) FcStrListNext (list))) {
GFile *file;
GFileMonitor *monitor;
file = g_file_new_for_path (str);
g_debug ("Monitoring %s", str);
monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
if (!monitor)
continue;
g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), self);
g_ptr_array_add (self->monitors, monitor);
}
FcStrListDone (list);
}
static const gchar *
get_name (GType enum_type,
gint enum_value)
{
GEnumClass *klass = g_type_class_ref (enum_type);
GEnumValue *value = g_enum_get_value (klass, enum_value);
const gchar *name = value ? value->value_name : "(unknown)";
g_type_class_unref (klass);
return name;
}
static void
stuff_changed (GFileMonitor *monitor G_GNUC_UNUSED,
GFile *file G_GNUC_UNUSED,
GFile *other_file G_GNUC_UNUSED,
GFileMonitorEvent event_type,
gpointer data)
{
FcMonitor *self = FC_MONITOR (data);
const gchar *event_name = get_name (G_TYPE_FILE_MONITOR_EVENT, event_type);
char *path = g_file_get_path (file);
switch (self->state) {
case UPDATE_IDLE:
g_debug ("Got %-38s for %s: starting fontconfig update timeout", event_name, path);
start_timeout (self);
break;
case UPDATE_PENDING:
/* wait for quiescence */
g_debug ("Got %-38s for %s: restarting fontconfig update timeout", event_name, path);
g_source_remove (self->timeout);
start_timeout (self);
break;
case UPDATE_RUNNING:
g_debug ("Got %-38s for %s: restarting fontconfig update", event_name, path);
self->state = UPDATE_RESTART;
break;
case UPDATE_RESTART:
g_debug ("Got %-38s for %s: waiting on fontconfig update", event_name, path);
break;
}
g_free (path);
}
static void
start_timeout (FcMonitor *self)
{
self->state = UPDATE_PENDING;
self->timeout = g_timeout_add (TIMEOUT_MILLISECONDS, start_update, self);
g_source_set_name_by_id (self->timeout, "[gnome-settings-daemon] update");
}
static gboolean
start_update (gpointer data)
{
FcMonitor *self = FC_MONITOR (data);
self->state = UPDATE_RUNNING;
self->timeout = 0;
g_debug ("Timeout completed: starting fontconfig update");
fontconfig_cache_update_async (update_done, g_object_ref (self));
return G_SOURCE_REMOVE;
}
static void
update_done (GObject *source_object G_GNUC_UNUSED,
GAsyncResult *result,
gpointer data)
{
FcMonitor *self = FC_MONITOR (data);
gboolean restart = self->state == UPDATE_RESTART;
GError *error = NULL;
self->state = UPDATE_IDLE;
if (fontconfig_cache_update_finish (result, &error)) {
g_debug ("Fontconfig update successful");
/* Remember we had a successful update even if we have to restart it */
self->notify = TRUE;
} else if (error) {
g_warning ("Fontconfig update failed: %s", error->message);
g_error_free (error);
} else
g_debug ("Fontconfig update was unnecessary");
if (restart) {
g_debug ("Concurrent change: restarting fontconfig update timeout");
start_timeout (self);
} else if (self->notify) {
self->notify = FALSE;
if (self->monitors) {
fc_monitor_stop (self);
fc_monitor_start (self);
}
/* we finish modifying self before emitting the signal,
* allowing the callback to stop us if it decides to. */
g_signal_emit (self, signals[SIGNAL_UPDATED], 0);
}
/* release ref taken in start_update */
g_object_unref (self);
}
#ifdef FONTCONFIG_MONITOR_TEST
static void
yay (void)
{
g_message ("yay");
}
int
main (void)
{
GMainLoop *loop = g_main_loop_new (NULL, TRUE);
FcMonitor *monitor = fc_monitor_new ();
fc_monitor_start (monitor);
g_signal_connect (monitor, "updated", G_CALLBACK (yay), NULL);
g_main_loop_run (loop);
return 0;
}
#endif
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2017 Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef FC_MONITOR_H
#define FC_MONITOR_H
/* NOTE: this file is copied from gnome-settings-daemon, please keep it in sync */
#include <glib-object.h>
G_BEGIN_DECLS
#define FC_TYPE_MONITOR (fc_monitor_get_type ())
G_DECLARE_FINAL_TYPE (FcMonitor, fc_monitor, FC, MONITOR, GObject)
FcMonitor *fc_monitor_new (void);
void fc_monitor_start (FcMonitor *monitor);
void fc_monitor_stop (FcMonitor *monitor);
G_END_DECLS
#endif /* FC_MONITOR_H */
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "notification.h"
#include "fdonotification.h"
#include "request.h"
#include "utils.h"
/* org.freedesktop.Notifications support.
* This code is adapted from the GFdoNotificationBackend in GIO.
*/
static guint fdo_notify_subscription;
static GSList *fdo_notifications;
typedef struct
{
char *app_id;
char *id;
guint32 notify_id;
char *default_action;
GVariant *default_action_target;
ActivateAction activate_action;
char *activation_token;
gpointer data;
} FdoNotification;
static void
fdo_notification_free (gpointer data)
{
FdoNotification *n = data;
g_free (n->app_id);
g_free (n->id);
g_free (n->default_action);
g_free (n->activation_token);
if (n->default_action_target)
g_variant_unref (n->default_action_target);
g_slice_free (FdoNotification, n);
}
FdoNotification *
fdo_find_notification (const char *app_id,
const char *id)
{
GSList *l;
for (l = fdo_notifications; l != NULL; l = l->next)
{
FdoNotification *n = l->data;
if (g_str_equal (n->app_id, app_id) &&
g_str_equal (n->id, id))
return n;
}
return NULL;
}
FdoNotification *
fdo_find_notification_by_notify_id (guint32 id)
{
GSList *l;
for (l = fdo_notifications; l != NULL; l = l->next)
{
FdoNotification *n = l->data;
if (n->notify_id == id)
return n;
}
return NULL;
}
static void
notify_signal (GDBusConnection *connection,
const char *sender_name,
const char *object_path,
const char *interface_name,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
{
guint32 id = 0;
const char *action = NULL;
const char *activation_token = NULL;
FdoNotification *n;
if (g_str_equal (signal_name, "NotificationClosed") &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)")))
{
g_variant_get (parameters, "(uu)", &id, NULL);
}
else if (g_str_equal (signal_name, "ActionInvoked") &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(us)")))
{
g_variant_get (parameters, "(u&s)", &id, &action);
}
else if (g_str_equal (signal_name, "ActivationToken") &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(us)")))
{
g_variant_get (parameters, "(u&s)", &id, &activation_token);
}
else
return;
n = fdo_find_notification_by_notify_id (id);
if (n == NULL)
return;
if (activation_token)
{
g_clear_pointer (&n->activation_token, g_free);
n->activation_token = g_strdup (activation_token);
return;
}
if (action)
{
if (g_str_equal (action, "default"))
{
n->activate_action (connection,
n->app_id,
n->id,
n->default_action,
n->default_action_target,
n->activation_token,
n->data);
}
else
{
gchar *name;
GVariant *target;
if (g_action_parse_detailed_name (action, &name, &target, NULL))
{
n->activate_action (connection,
n->app_id,
n->id,
name,
target,
n->activation_token,
n->data);
g_free (name);
if (target)
g_variant_unref (target);
}
else
g_debug ("Could not parse action name %s", action);
}
}
fdo_notifications = g_slist_remove (fdo_notifications, n);
fdo_notification_free (n);
}
static guchar
urgency_from_priority (const char *priority)
{
if (strcmp (priority, "low") == 0)
return 0;
else if (strcmp (priority, "normal") == 0)
return 1;
else if (strcmp (priority, "high") == 0)
return 1;
else // critical
return 2;
}
static void
notification_sent (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
FdoNotification *n = user_data;
GVariant *val;
GError *error = NULL;
static gboolean warning_printed = FALSE;
val = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), result, &error);
if (val)
{
g_variant_get (val, "(u)", &n->notify_id);
g_variant_unref (val);
}
else
{
if (!warning_printed)
{
g_warning ("Unable to send notifications through org.freedesktop.Notifications: %s",
error->message);
warning_printed = TRUE;
}
fdo_notifications = g_slist_remove (fdo_notifications, n);
fdo_notification_free (n);
g_error_free (error);
}
}
static void
call_notify (GDBusConnection *connection,
FdoNotification *fdo,
GVariant *notification)
{
GVariantBuilder action_builder;
guint i;
GVariantBuilder hints_builder;
GVariant *icon;
const char *body;
const char *title;
g_autofree char *icon_name = NULL;
guchar urgency;
const char *dummy;
g_autoptr(GVariant) buttons = NULL;
const char *priority;
if (fdo_notify_subscription == 0)
{
fdo_notify_subscription =
g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.Notifications",
"org.freedesktop.Notifications", NULL,
"/org/freedesktop/Notifications", NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
notify_signal, NULL, NULL);
}
g_variant_builder_init (&action_builder, G_VARIANT_TYPE_STRING_ARRAY);
if (g_variant_lookup (notification, "default-action", "&s", &dummy))
{
g_variant_builder_add (&action_builder, "s", "default");
g_variant_builder_add (&action_builder, "s", "");
}
buttons = g_variant_lookup_value (notification, "buttons", G_VARIANT_TYPE("aa{sv}"));
if (buttons)
for (i = 0; i < g_variant_n_children (buttons); i++)
{
g_autoptr(GVariant) button = NULL;
const char *label;
const char *action;
g_autoptr(GVariant) target = NULL;
g_autofree char *detailed_name = NULL;
button = g_variant_get_child_value (buttons, i);
g_variant_lookup (button, "label", "&s", &label);
g_variant_lookup (button, "action", "&s", &action);
target = g_variant_lookup_value (button, "target", NULL);
detailed_name = g_action_print_detailed_name (action, target);
/* Actions named 'default' collide with libnotify's naming of the
* default action. Rewriting them to something unique is enough,
* because those actions can never be activated (they aren't
* prefixed with 'app.').
*/
if (g_str_equal (detailed_name, "default"))
{
g_free (detailed_name);
detailed_name = g_dbus_generate_guid ();
}
g_variant_builder_add_value (&action_builder, g_variant_new_string (detailed_name));
g_variant_builder_add_value (&action_builder, g_variant_new_string (label));
}
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&hints_builder, "{sv}", "desktop-entry", g_variant_new_string (fdo->app_id));
if (g_variant_lookup (notification, "priority", "&s", &priority))
urgency = urgency_from_priority (priority);
else
urgency = 1;
g_variant_builder_add (&hints_builder, "{sv}", "urgency", g_variant_new_byte (urgency));
icon = g_variant_lookup_value (notification, "icon", NULL);
if (icon != NULL)
{
g_autoptr(GIcon) gicon = g_icon_deserialize (icon);
if (G_IS_FILE_ICON (gicon))
{
GFile *file;
file = g_file_icon_get_file (G_FILE_ICON (gicon));
icon_name = g_file_get_path (file);
}
else if (G_IS_THEMED_ICON (gicon))
{
const gchar* const* icon_names = g_themed_icon_get_names (G_THEMED_ICON (gicon));
icon_name = g_strdup (icon_names[0]);
}
else if (G_IS_BYTES_ICON (gicon))
{
g_autoptr(GInputStream) istream = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
int width, height, rowstride, n_channels, bits_per_sample;
GVariant *image;
gsize image_len;
istream = g_loadable_icon_load (G_LOADABLE_ICON (gicon),
-1 /* unused */,
NULL /* type */,
NULL,
NULL);
pixbuf = gdk_pixbuf_new_from_stream (istream, NULL, NULL);
g_input_stream_close (istream, NULL, NULL);
g_object_get (pixbuf,
"width", &width,
"height", &height,
"rowstride", &rowstride,
"n-channels", &n_channels,
"bits-per-sample", &bits_per_sample,
NULL);
image_len = (height - 1) * rowstride + width *
((n_channels * bits_per_sample + 7) / 8);
image = g_variant_new ("(iiibii@ay)",
width,
height,
rowstride,
gdk_pixbuf_get_has_alpha (pixbuf),
bits_per_sample,
n_channels,
g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
gdk_pixbuf_get_pixels (pixbuf),
image_len,
TRUE,
(GDestroyNotify) g_object_unref,
g_object_ref (pixbuf)));
g_variant_builder_add (&hints_builder, "{sv}", "image-data", image);
}
}
if (icon_name == NULL)
icon_name = g_strdup ("");
if (!g_variant_lookup (notification, "body", "&s", &body))
body = "";
if (!g_variant_lookup (notification, "title", "&s", &title))
title= "";
g_dbus_connection_call (connection,
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"Notify",
g_variant_new ("(susssasa{sv}i)",
"", /* app name */
fdo->notify_id,
icon_name,
title,
body,
&action_builder,
&hints_builder,
-1), /* expire_timeout */
G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
notification_sent, fdo);
}
static void
call_close (GDBusConnection *connection,
guint32 id)
{
g_dbus_connection_call (connection,
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"CloseNotification",
g_variant_new ("(u)", id),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
}
gboolean
fdo_remove_notification (GDBusConnection *connection,
const char *app_id,
const char *id)
{
FdoNotification *n;
n = fdo_find_notification (app_id, id);
if (n)
{
if (n->notify_id > 0)
call_close (connection, n->notify_id);
fdo_notifications = g_slist_remove (fdo_notifications, n);
fdo_notification_free (n);
return TRUE;
}
return FALSE;
}
void
fdo_add_notification (GDBusConnection *connection,
const char *app_id,
const char *id,
GVariant *notification,
ActivateAction activate_action,
gpointer data)
{
FdoNotification *n;
n = fdo_find_notification (app_id, id);
if (n == NULL)
{
n = g_slice_new0 (FdoNotification);
n->app_id = g_strdup (app_id);
n->id = g_strdup (id);
n->notify_id = 0;
n->activate_action = activate_action;
n->activation_token = NULL;
n->data = data;
fdo_notifications = g_slist_prepend (fdo_notifications, n);
}
else
{
/* Only clear default action. All other fields are still valid */
g_clear_pointer (&n->default_action, g_free);
g_clear_pointer (&n->default_action_target, g_variant_unref);
}
g_variant_lookup (notification, "default-action", "s", &n->default_action);
n->default_action_target = g_variant_lookup_value (notification, "default-action-target", NULL);
call_notify (connection, n, notification);
}
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
typedef void (*ActivateAction) (GDBusConnection *connection,
const char *app_id,
const char *id,
const char *name,
GVariant *parameter,
const char *activation_token,
gpointer data);
void fdo_add_notification (GDBusConnection *connection,
const char *app_id,
const char *id,
GVariant *notification,
ActivateAction activate,
gpointer data);
gboolean fdo_remove_notification (GDBusConnection *connection,
const char *app_id,
const char *id);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include <glib/gi18n.h>
#include "xdg-desktop-portal-dbus.h"
#include "filechooser.h"
#include "request.h"
#include "utils.h"
#include "gtkbackports.h"
#include "externalwindow.h"
typedef struct {
XdpImplFileChooser *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
GtkFileChooserAction action;
gboolean multiple;
ExternalWindow *external_parent;
GSList *files;
GtkFileFilter *filter;
int response;
GSList *uris;
gboolean allow_write;
GHashTable *choices;
} FileDialogHandle;
static void
file_dialog_handle_free (gpointer data)
{
FileDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_object_unref (handle->dialog);
g_object_unref (handle->request);
g_slist_free_full (handle->files, g_free);
g_slist_free_full (handle->uris, g_free);
g_hash_table_unref (handle->choices);
g_free (handle);
}
static void
file_dialog_handle_close (FileDialogHandle *handle)
{
gtk_widget_destroy (handle->dialog);
file_dialog_handle_free (handle);
}
static void
add_choices (FileDialogHandle *handle,
GVariantBuilder *builder)
{
GVariantBuilder choices;
GHashTableIter iter;
const char *id;
const char *selected;
g_variant_builder_init (&choices, G_VARIANT_TYPE ("a(ss)"));
g_hash_table_iter_init (&iter, handle->choices);
while (g_hash_table_iter_next (&iter, (gpointer *)&id, (gpointer *)&selected))
g_variant_builder_add (&choices, "(ss)", id, selected);
g_variant_builder_add (builder, "{sv}", "choices", g_variant_builder_end (&choices));
}
static void
add_recent_entry (const char *app_id,
const char *uri)
{
GtkRecentManager *recent;
GtkRecentData data;
/* These fields are ignored by everybody, so it is not worth
* spending effort on filling them out. Just use defaults.
*/
data.display_name = NULL;
data.description = NULL;
data.mime_type = "application/octet-stream";
data.app_name = (char *)app_id;
data.app_exec = "gio open %u";
data.groups = NULL;
data.is_private = FALSE;
recent = gtk_recent_manager_get_default ();
gtk_recent_manager_add_full (recent, uri, &data);
}
static void
send_response (FileDialogHandle *handle)
{
GVariantBuilder uri_builder;
GVariantBuilder opt_builder;
GSList *l;
const char *method_name;
method_name = g_dbus_method_invocation_get_method_name (handle->invocation);
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
if (strcmp (method_name, "SaveFiles") == 0 &&
handle->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
handle->uris)
{
g_autoptr(GFile) base_dir = g_file_new_for_uri (handle->uris->data);
g_slist_free_full (handle->uris, g_free);
handle->uris = NULL;
for (l = handle->files; l; l = l->next)
{
int uniqifier = 0;
const char *file_name = l->data;
g_autoptr(GFile) file = g_file_get_child (base_dir, file_name);
while (g_file_query_exists(file, NULL))
{
g_autofree char *base_name = g_file_get_basename (file);
g_auto(GStrv) parts = NULL;
g_autoptr(GString) unique_name = NULL;
parts = g_strsplit (base_name, ".", 2);
unique_name = g_string_new (parts[0]);
g_string_append_printf (unique_name, "(%i)", ++uniqifier);
if (parts[1] != NULL)
g_string_append (unique_name, parts[1]);
file = g_file_get_child (base_dir, unique_name->str);
}
handle->uris = g_slist_append (handle->uris, g_file_get_uri (file));
}
}
g_variant_builder_init (&uri_builder, G_VARIANT_TYPE_STRING_ARRAY);
for (l = handle->uris; l; l = l->next)
{
add_recent_entry (handle->request->app_id, l->data);
g_variant_builder_add (&uri_builder, "s", l->data);
}
if (handle->filter) {
GVariant *current_filter_variant = gtk_file_filter_to_gvariant (handle->filter);
g_variant_builder_add (&opt_builder, "{sv}", "current_filter", current_filter_variant);
}
g_variant_builder_add (&opt_builder, "{sv}", "uris", g_variant_builder_end (&uri_builder));
g_variant_builder_add (&opt_builder, "{sv}", "writable", g_variant_new_boolean (handle->allow_write));
add_choices (handle, &opt_builder);
if (handle->request->exported)
request_unexport (handle->request);
if (strcmp (method_name, "OpenFile") == 0)
xdp_impl_file_chooser_complete_open_file (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
else if (strcmp (method_name, "SaveFile") == 0)
xdp_impl_file_chooser_complete_save_file (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
else if (strcmp (method_name, "SaveFiles") == 0)
xdp_impl_file_chooser_complete_save_files (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
else
g_assert_not_reached ();
file_dialog_handle_close (handle);
}
static void
file_chooser_response (GtkWidget *widget,
int response,
gpointer user_data)
{
FileDialogHandle *handle = user_data;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
handle->filter = NULL;
handle->uris = NULL;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
handle->filter = NULL;
handle->uris = NULL;
break;
case GTK_RESPONSE_OK:
handle->response = 0;
handle->filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER(widget));
handle->uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (widget));
break;
}
send_response (handle);
}
static void
read_only_toggled (GtkToggleButton *button, gpointer user_data)
{
FileDialogHandle *handle = user_data;
handle->allow_write = !gtk_toggle_button_get_active (button);
}
static void
choice_changed (GtkComboBox *combo,
FileDialogHandle *handle)
{
const char *id;
const char *selected;
id = (const char *)g_object_get_data (G_OBJECT (combo), "choice-id");
selected = gtk_combo_box_get_active_id (combo);
g_hash_table_replace (handle->choices, (gpointer)id, (gpointer)selected);
}
static void
choice_toggled (GtkToggleButton *toggle,
FileDialogHandle *handle)
{
const char *id;
const char *selected;
id = (const char *)g_object_get_data (G_OBJECT (toggle), "choice-id");
selected = gtk_toggle_button_get_active (toggle) ? "true" : "false";
g_hash_table_replace (handle->choices, (gpointer)id, (gpointer)selected);
}
static GtkWidget *
deserialize_choice (GVariant *choice,
FileDialogHandle *handle)
{
GtkWidget *widget;
const char *choice_id;
const char *label;
const char *selected;
GVariant *choices;
int i;
g_variant_get (choice, "(&s&s@a(ss)&s)", &choice_id, &label, &choices, &selected);
if (g_variant_n_children (choices) > 0)
{
GtkWidget *box;
GtkWidget *combo;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_add (GTK_CONTAINER (box), gtk_label_new (label));
combo = gtk_combo_box_text_new ();
g_object_set_data_full (G_OBJECT (combo), "choice-id", g_strdup (choice_id), g_free);
gtk_container_add (GTK_CONTAINER (box), combo);
for (i = 0; i < g_variant_n_children (choices); i++)
{
const char *id;
const char *text;
g_variant_get_child (choices, i, "(&s&s)", &id, &text);
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), id, text);
}
if (strcmp (selected, "") == 0)
g_variant_get_child (choices, 0, "(&s&s)", &selected, NULL);
g_signal_connect (combo, "changed", G_CALLBACK (choice_changed), handle);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo), selected);
widget = box;
}
else
{
GtkWidget *check;
check = gtk_check_button_new_with_label (label);
g_object_set_data_full (G_OBJECT (check), "choice-id", g_strdup (choice_id), g_free);
g_signal_connect (check, "toggled", G_CALLBACK (choice_toggled), handle);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), g_strcmp0 (selected, "true") == 0);
widget = check;
}
gtk_widget_show_all (widget);
return widget;
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
FileDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
if (handle->action == GTK_FILE_CHOOSER_ACTION_OPEN)
xdp_impl_file_chooser_complete_open_file (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
else if (handle->action == GTK_FILE_CHOOSER_ACTION_SAVE)
xdp_impl_file_chooser_complete_save_file (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
else
xdp_impl_file_chooser_complete_save_files (handle->impl,
handle->invocation,
2,
g_variant_builder_end (&opt_builder));
if (handle->request->exported)
request_unexport (handle->request);
file_dialog_handle_close (handle);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static void
update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
{
GtkWidget *preview = GTK_WIDGET (data);
g_autofree char *filename = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
filename = gtk_file_chooser_get_preview_filename (file_chooser);
if (filename)
pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL);
if (pixbuf)
{
g_autoptr(GdkPixbuf) tmp = NULL;
tmp = gdk_pixbuf_apply_embedded_orientation (pixbuf);
g_set_object (&pixbuf, tmp);
}
gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
gtk_file_chooser_set_preview_widget_active (file_chooser, pixbuf != NULL);
}
static gboolean
handle_open (XdpImplFileChooser *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_title,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const gchar *method_name;
const gchar *sender;
GtkFileChooserAction action;
gboolean multiple;
gboolean directory;
gboolean modal;
GdkDisplay *display;
GdkScreen *screen;
GtkWidget *dialog;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
FileDialogHandle *handle;
const char *cancel_label;
const char *accept_label;
GVariantIter *iter;
const char *current_name;
const char *path;
g_autoptr (GVariant) choices = NULL;
g_autoptr (GVariant) current_filter = NULL;
GSList *filters = NULL;
GtkWidget *preview;
method_name = g_dbus_method_invocation_get_method_name (invocation);
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (strcmp (method_name, "SaveFile") == 0)
{
action = GTK_FILE_CHOOSER_ACTION_SAVE;
multiple = FALSE;
}
else if (strcmp (method_name, "SaveFiles") == 0)
{
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
multiple = FALSE;
}
else
{
if (!g_variant_lookup (arg_options, "multiple", "b", &multiple))
multiple = FALSE;
if (!g_variant_lookup (arg_options, "directory", "b", &directory))
directory = FALSE;
action = directory ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : GTK_FILE_CHOOSER_ACTION_OPEN;
}
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
if (!g_variant_lookup (arg_options, "accept_label", "&s", &accept_label))
{
if (strcmp (method_name, "OpenFile") == 0)
accept_label = multiple ? _("_Open") : _("_Select");
else
accept_label = _("_Save");
}
cancel_label = _("_Cancel");
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
dialog = gtk_file_chooser_dialog_new (arg_title, GTK_WINDOW (fake_parent), action,
cancel_label, GTK_RESPONSE_CANCEL,
accept_label, GTK_RESPONSE_OK,
NULL);
gtk_window_set_modal (GTK_WINDOW (dialog), modal);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), multiple);
preview = gtk_image_new ();
g_object_set (preview, "margin", 10, NULL);
gtk_widget_show (preview);
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview);
gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (dialog), FALSE);
gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (dialog), FALSE);
g_signal_connect (dialog, "update-preview", G_CALLBACK (update_preview_cb), preview);
handle = g_new0 (FileDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->action = action;
handle->multiple = multiple;
handle->choices = g_hash_table_new (g_str_hash, g_str_equal);
handle->external_parent = external_parent;
handle->allow_write = TRUE;
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "response", G_CALLBACK (file_chooser_response), handle);
choices = g_variant_lookup_value (arg_options, "choices", G_VARIANT_TYPE ("a(ssa(ss)s)"));
if (choices)
{
int i;
GtkWidget *box;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_widget_show (box);
for (i = 0; i < g_variant_n_children (choices); i++)
{
GVariant *value = g_variant_get_child_value (choices, i);
gtk_container_add (GTK_CONTAINER (box), deserialize_choice (value, handle));
}
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), box);
}
if (g_variant_lookup (arg_options, "filters", "a(sa(us))", &iter))
{
GVariant *variant;
while (g_variant_iter_next (iter, "@(sa(us))", &variant))
{
GtkFileFilter *filter;
filter = gtk_file_filter_new_from_gvariant (variant);
filters = g_slist_append (filters, g_object_ref (filter));
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
g_variant_unref (variant);
}
g_variant_iter_free (iter);
}
if (g_variant_lookup (arg_options, "current_filter", "@(sa(us))", &current_filter))
{
g_autoptr (GtkFileFilter) filter = NULL;
const char *current_filter_name;
filter = g_object_ref_sink (gtk_file_filter_new_from_gvariant (current_filter));
current_filter_name = gtk_file_filter_get_name (filter);
if (!filters)
{
/* We are setting a single, unchangeable filter. */
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
}
else
{
gboolean handled = FALSE;
/* We are trying to select the default filter from the list of
* filters. We want to naively take filter and pass it to
* gtk_file_chooser_set_filter(), but it's not good enough
* because GTK just compares filters by pointer value, so the
* pointer itself has to match. We'll use the heuristic that
* if two filters have the same name, they must be the same
* unless the application is very dumb.
*/
for (GSList *l = filters; l; l = l->next)
{
GtkFileFilter *f = l->data;
const char *name = gtk_file_filter_get_name (f);
if (g_strcmp0 (name, current_filter_name) == 0)
{
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), f);
handled = TRUE;
break;
}
}
if (!handled)
g_warning ("current file filter must be present in filters list when list is nonempty");
}
}
g_slist_free_full (filters, g_object_unref);
if (strcmp (method_name, "OpenFile") == 0)
{
if (g_variant_lookup (arg_options, "current_folder", "^&ay", &path))
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
}
else if (strcmp (method_name, "SaveFile") == 0)
{
if (g_variant_lookup (arg_options, "current_name", "&s", &current_name))
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), current_name);
/* TODO: is this useful ?
* In a sandboxed situation, the current folder and current file
* are likely in the fuse filesystem
*/
if (g_variant_lookup (arg_options, "current_folder", "^&ay", &path))
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
if (g_variant_lookup (arg_options, "current_file", "^&ay", &path))
gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), path);
}
else if (strcmp (method_name, "SaveFiles") == 0)
{
/* TODO: is this useful ?
* In a sandboxed situation, the current folder and current file
* are likely in the fuse filesystem
*/
if (g_variant_lookup (arg_options, "current_folder", "^&ay", &path))
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
if (g_variant_lookup (arg_options, "files", "aay", &iter))
{
char *file = NULL;
while (g_variant_iter_next (iter, "^ay", &file))
handle->files = g_slist_append (handle->files, file);
g_variant_iter_free (iter);
}
}
g_object_unref (fake_parent);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
{
GtkWidget *readonly;
GtkWidget *extra;
extra = gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog));
readonly = gtk_check_button_new_with_label (_("Open files read-only"));
gtk_widget_show (readonly);
g_signal_connect (readonly, "toggled",
G_CALLBACK (read_only_toggled), handle);
if (GTK_IS_CONTAINER (extra))
gtk_container_add (GTK_CONTAINER (extra), readonly);
else
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), readonly);
}
gtk_widget_show (dialog);
gtk_window_present (GTK_WINDOW (dialog));
if (external_parent)
external_window_set_parent_of (external_parent,
gtk_widget_get_window (dialog));
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
gboolean
file_chooser_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_file_chooser_skeleton_new ());
g_signal_connect (helper, "handle-open-file", G_CALLBACK (handle_open), NULL);
g_signal_connect (helper, "handle-save-file", G_CALLBACK (handle_open), NULL);
g_signal_connect (helper, "handle-save-files", G_CALLBACK (handle_open), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean file_chooser_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "gtkbackports.h"
#if !GTK_CHECK_VERSION(3,22,0)
typedef enum {
FILTER_RULE_PATTERN,
FILTER_RULE_MIME_TYPE,
FILTER_RULE_PIXBUF_FORMATS,
FILTER_RULE_CUSTOM
} FilterRuleType;
struct _GtkFileFilter
{
GInitiallyUnowned parent_instance;
gchar *name;
GSList *rules;
GtkFileFilterFlags needed;
};
typedef struct _FilterRule FilterRule;
struct _FilterRule
{
FilterRuleType type;
GtkFileFilterFlags needed;
union {
gchar *pattern;
gchar *mime_type;
GSList *pixbuf_formats;
struct {
GtkFileFilterFunc func;
gpointer data;
GDestroyNotify notify;
} custom;
} u;
};
GVariant *
gtk_file_filter_to_gvariant (GtkFileFilter *filter)
{
GVariantBuilder builder;
GSList *l;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(us)"));
for (l = filter->rules; l; l = l->next)
{
FilterRule *rule = l->data;
switch (rule->type)
{
case FILTER_RULE_PATTERN:
g_variant_builder_add (&builder, "(us)", 0, rule->u.mime_type);
break;
case FILTER_RULE_MIME_TYPE:
g_variant_builder_add (&builder, "(us)", 1, rule->u.mime_type);
break;
case FILTER_RULE_PIXBUF_FORMATS:
{
GSList *f;
for (f = rule->u.pixbuf_formats; f; f = f->next)
{
GdkPixbufFormat *fmt = f->data;
gchar **mime_types;
int i;
mime_types = gdk_pixbuf_format_get_mime_types (fmt);
for (i = 0; mime_types[i]; i++)
g_variant_builder_add (&builder, "(us)", 1, mime_types[i]);
g_strfreev (mime_types);
}
}
break;
case FILTER_RULE_CUSTOM:
default:
break;
}
}
return g_variant_new ("(s@a(us))", filter->name, g_variant_builder_end (&builder));
}
GtkFileFilter *
gtk_file_filter_new_from_gvariant (GVariant *variant)
{
GtkFileFilter *filter;
GVariantIter *iter;
const char *name;
int type;
char *tmp;
filter = gtk_file_filter_new ();
g_variant_get (variant, "(&sa(us))", &name, &iter);
gtk_file_filter_set_name (filter, name);
while (g_variant_iter_next (iter, "(u&s)", &type, &tmp))
{
switch (type)
{
case 0:
gtk_file_filter_add_pattern (filter, tmp);
break;
case 1:
gtk_file_filter_add_mime_type (filter, tmp);
break;
default:
break;
}
}
g_variant_iter_free (iter);
return filter;
}
static void
add_to_variant (const gchar *key,
const gchar *value,
gpointer data)
{
GVariantBuilder *builder = data;
g_variant_builder_add (builder, "{sv}", key, g_variant_new_string (value));
}
GVariant *
gtk_print_settings_to_gvariant (GtkPrintSettings *settings)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
gtk_print_settings_foreach (settings, add_to_variant, &builder);
return g_variant_builder_end (&builder);
}
GtkPrintSettings *
gtk_print_settings_new_from_gvariant (GVariant *variant)
{
GtkPrintSettings *settings;
int i;
g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
settings = gtk_print_settings_new ();
for (i = 0; i < g_variant_n_children (variant); i++)
{
const char *key;
GVariant *v;
g_variant_get_child (variant, i, "{&sv}", &key, &v);
if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
{
const char *value;
g_variant_get (v, "&s", &value);
gtk_print_settings_set (settings, key, value);
}
g_variant_unref (v);
}
return settings;
}
#define MM_PER_INCH 25.4
#define POINTS_PER_INCH 72
gdouble
_gtk_print_convert_from_mm (gdouble len,
GtkUnit unit)
{
switch (unit)
{
case GTK_UNIT_MM:
return len;
case GTK_UNIT_INCH:
return len / MM_PER_INCH;
default:
g_warning ("Unsupported unit");
/* Fall through */
case GTK_UNIT_POINTS:
return len / (MM_PER_INCH / POINTS_PER_INCH);
break;
}
}
GVariant *
gtk_paper_size_to_gvariant (GtkPaperSize *paper_size)
{
const char *name;
const char *ppd_name;
const char *display_name;
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
name = gtk_paper_size_get_name (paper_size);
ppd_name = gtk_paper_size_get_ppd_name (paper_size);
display_name = gtk_paper_size_get_display_name (paper_size);
if (ppd_name != NULL)
g_variant_builder_add (&builder, "{sv}", "PPDName", g_variant_new_string (ppd_name));
else
g_variant_builder_add (&builder, "{sv}", "Name", g_variant_new_string (name));
if (display_name != NULL)
g_variant_builder_add (&builder, "{sv}", "DisplayName", g_variant_new_string (display_name));
g_variant_builder_add (&builder, "{sv}", "Width", g_variant_new_double (gtk_paper_size_get_width (paper_size, GTK_UNIT_MM)));
g_variant_builder_add (&builder, "{sv}", "Height", g_variant_new_double (gtk_paper_size_get_height (paper_size, GTK_UNIT_MM)));
return g_variant_builder_end (&builder);
}
GtkPaperSize *
gtk_paper_size_new_from_gvariant (GVariant *variant)
{
GtkPaperSize *paper_size;
const char *name;
const char *ppd_name;
const char *display_name;
gdouble width, height;
g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
if (!g_variant_lookup (variant, "Width", "d", &width) ||
!g_variant_lookup (variant, "Height", "d", &height))
return NULL;
if (!g_variant_lookup (variant, "Name", "&s", &name))
name = NULL;
if (!g_variant_lookup (variant, "PPDName", "&s", &ppd_name))
ppd_name = NULL;
if (!g_variant_lookup (variant, "DisplayName", "&s", &display_name))
display_name = name;
if (ppd_name != NULL)
paper_size = gtk_paper_size_new_from_ppd (ppd_name,
display_name,
_gtk_print_convert_from_mm (width, GTK_UNIT_POINTS),
_gtk_print_convert_from_mm (height, GTK_UNIT_POINTS));
else if (name != NULL)
paper_size = gtk_paper_size_new_custom (name, display_name,
width, height, GTK_UNIT_MM);
else
paper_size = NULL;
return paper_size;
}
static char *
enum_to_string (GType type,
guint enum_value)
{
GEnumClass *enum_class;
GEnumValue *value;
char *retval = NULL;
enum_class = g_type_class_ref (type);
value = g_enum_get_value (enum_class, enum_value);
if (value)
retval = g_strdup (value->value_nick);
g_type_class_unref (enum_class);
return retval;
}
static guint
string_to_enum (GType type,
const char *enum_string)
{
GEnumClass *enum_class;
const GEnumValue *value;
guint retval = 0;
g_return_val_if_fail (enum_string != NULL, 0);
enum_class = g_type_class_ref (type);
value = g_enum_get_value_by_nick (enum_class, enum_string);
if (value)
retval = value->value;
g_type_class_unref (enum_class);
return retval;
}
GVariant *
gtk_page_setup_to_gvariant (GtkPageSetup *setup)
{
GtkPaperSize *paper_size;
GVariant *variant;
int i;
GVariantBuilder builder;
char *orientation;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
paper_size = gtk_page_setup_get_paper_size (setup);
variant = g_variant_ref_sink (gtk_paper_size_to_gvariant (paper_size));
for (i = 0; i < g_variant_n_children (variant); i++)
g_variant_builder_add_value (&builder, g_variant_get_child_value (variant, i));
g_variant_unref (variant);
g_variant_builder_add (&builder, "{sv}", "MarginTop", g_variant_new_double (gtk_page_setup_get_top_margin (setup, GTK_UNIT_MM)));
g_variant_builder_add (&builder, "{sv}", "MarginBottom", g_variant_new_double (gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_MM)));
g_variant_builder_add (&builder, "{sv}", "MarginLeft", g_variant_new_double (gtk_page_setup_get_left_margin (setup, GTK_UNIT_MM)));
g_variant_builder_add (&builder, "{sv}", "MarginRight", g_variant_new_double (gtk_page_setup_get_right_margin (setup, GTK_UNIT_MM)));
orientation = enum_to_string (GTK_TYPE_PAGE_ORIENTATION,
gtk_page_setup_get_orientation (setup));
g_variant_builder_add (&builder, "{sv}", "Orientation", g_variant_new_take_string (orientation));
return g_variant_builder_end (&builder);
}
GtkPageSetup *
gtk_page_setup_new_from_gvariant (GVariant *variant)
{
GtkPageSetup *setup;
const char *orientation;
gdouble margin;
GtkPaperSize *paper_size;
g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
setup = gtk_page_setup_new ();
paper_size = gtk_paper_size_new_from_gvariant (variant);
if (paper_size)
{
gtk_page_setup_set_paper_size (setup, paper_size);
gtk_paper_size_free (paper_size);
}
if (g_variant_lookup (variant, "MarginTop", "d", &margin))
gtk_page_setup_set_top_margin (setup, margin, GTK_UNIT_MM);
if (g_variant_lookup (variant, "MarginBottom", "d", &margin))
gtk_page_setup_set_bottom_margin (setup, margin, GTK_UNIT_MM);
if (g_variant_lookup (variant, "MarginLeft", "d", &margin))
gtk_page_setup_set_left_margin (setup, margin, GTK_UNIT_MM);
if (g_variant_lookup (variant, "MarginRight", "d", &margin))
gtk_page_setup_set_right_margin (setup, margin, GTK_UNIT_MM);
if (g_variant_lookup (variant, "Orientation", "&s", &orientation))
gtk_page_setup_set_orientation (setup, string_to_enum (GTK_TYPE_PAGE_ORIENTATION,
orientation));
return setup;
}
struct _GtkPrintJobPrivate
{
gchar *title;
GIOChannel *spool_io;
cairo_surface_t *surface;
GtkPrintStatus status;
GtkPrintBackend *backend;
GtkPrinter *printer;
GtkPrintSettings *settings;
GtkPageSetup *page_setup;
GtkPrintPages print_pages;
GtkPageRange *page_ranges;
gint num_page_ranges;
GtkPageSet page_set;
gint num_copies;
gdouble scale;
guint number_up;
GtkNumberUpLayout number_up_layout;
guint printer_set : 1;
guint page_setup_set : 1;
guint settings_set : 1;
guint track_print_status : 1;
guint rotate_to_orientation : 1;
guint collate : 1;
guint reverse : 1;
};
gboolean
gtk_print_job_set_source_fd (GtkPrintJob *job,
int fd,
GError **error)
{
g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
job->priv->spool_io = g_io_channel_unix_new (fd);
if (g_io_channel_set_encoding (job->priv->spool_io, NULL, error) != G_IO_STATUS_NORMAL)
return FALSE;
return TRUE;
}
#endif
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gtk/gtk.h>
#include <gtk/gtkunixprint.h>
#if !GTK_CHECK_VERSION(3,22,0)
GVariant *gtk_file_filter_to_gvariant (GtkFileFilter *filter);
GtkFileFilter *gtk_file_filter_new_from_gvariant (GVariant *variant);
GVariant *gtk_print_settings_to_gvariant (GtkPrintSettings *settings);
GtkPrintSettings *gtk_print_settings_new_from_gvariant (GVariant *variant);
GVariant *gtk_page_setup_to_gvariant (GtkPageSetup *setup);
GtkPageSetup *gtk_page_setup_new_from_gvariant (GVariant *variant);
gboolean gtk_print_job_set_source_fd (GtkPrintJob *job,
int fd,
GError **error);
#endif
#define _GNU_SOURCE 1
#include "config.h"
#include <gtk/gtk.h>
#include <gio/gio.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "session.h"
#include "utils.h"
#include "inhibit.h"
#include "request.h"
enum {
INHIBIT_LOGOUT = 1,
INHIBIT_SWITCH = 2,
INHIBIT_SUSPEND = 4,
INHIBIT_IDLE = 8
};
static GDBusInterfaceSkeleton *inhibit;
static OrgGnomeSessionManager *sessionmanager;
static OrgGnomeScreenSaver *screensaver;
static GDBusProxy *client;
typedef enum {
UNKNOWN = 0,
RUNNING = 1,
QUERY_END = 2,
ENDING = 3
} SessionState;
static SessionState session_state = RUNNING;
static gboolean screensaver_active = FALSE;
static guint query_end_timeout;
static void
uninhibit_done_gnome (GObject *source,
GAsyncResult *result,
gpointer data)
{
g_autoptr(GError) error = NULL;
if (!org_gnome_session_manager_call_uninhibit_finish (sessionmanager, result, &error))
g_warning ("Backend call failed: %s", error->message);
}
static gboolean
handle_close_gnome (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
gpointer data)
{
Request *request = (Request *)object;
guint cookie;
/* If we get a Close call before the Inhibit call returned,
* delay the uninhibit call until we have the cookie.
*/
cookie = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (request), "cookie"));
if (cookie)
org_gnome_session_manager_call_uninhibit (sessionmanager, cookie, NULL, uninhibit_done_gnome, NULL);
else
g_object_set_data (G_OBJECT (request), "closed", GINT_TO_POINTER (1));
if (request->exported)
request_unexport (request);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static void
inhibit_done_gnome (GObject *source,
GAsyncResult *result,
gpointer data)
{
g_autoptr(Request) request = data;
guint cookie = 0;
gboolean closed;
g_autoptr(GError) error = NULL;
if (!org_gnome_session_manager_call_inhibit_finish (sessionmanager, &cookie, result, &error))
g_warning ("Backend call failed: %s", error->message);
closed = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (request), "closed"));
if (closed)
org_gnome_session_manager_call_uninhibit (sessionmanager, cookie, NULL, uninhibit_done_gnome, NULL);
else
g_object_set_data (G_OBJECT (request), "cookie", GUINT_TO_POINTER (cookie));
}
static gboolean
handle_inhibit_gnome (XdpImplInhibit *object,
GDBusMethodInvocation *invocation,
const gchar *arg_handle,
const gchar *arg_app_id,
const gchar *arg_window,
guint arg_flags,
GVariant *arg_options)
{
g_autoptr (Request) request = NULL;
const char *sender;
g_autoptr(GError) error = NULL;
const char *reason;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close_gnome), NULL);
request_export (request, g_dbus_method_invocation_get_connection (invocation));
if (!g_variant_lookup (arg_options, "reason", "&s", &reason))
reason = "";
org_gnome_session_manager_call_inhibit (sessionmanager,
arg_app_id,
0, /* window */
reason,
arg_flags,
NULL,
inhibit_done_gnome,
g_object_ref (request));
xdp_impl_inhibit_complete_inhibit (object, invocation);
return TRUE;
}
static void
send_quit_response (GDBusProxy *client,
gboolean will_quit,
const gchar *reason)
{
g_debug ("Calling EndSessionResponse %d '%s'", will_quit, reason ? reason : "");
g_dbus_proxy_call (client,
"EndSessionResponse",
g_variant_new ("(bs)", will_quit, reason ? reason : ""),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL, NULL, NULL);
}
static void global_emit_state_changed (void);
static void
set_session_state (SessionState state)
{
const char *names[] = {
"Unknown", "Running", "Query-end", "Ending"
};
g_debug ("Session state now: %s", names[state]);
session_state = state;
global_emit_state_changed ();
}
static void global_set_pending_query_end_response (gboolean pending);
static gboolean global_get_pending_query_end_response (void);
static void
stop_waiting_for_query_end_response (gboolean send_response)
{
g_debug ("Stop waiting for QueryEndResponse calls");
if (query_end_timeout != 0)
{
g_source_remove (query_end_timeout);
query_end_timeout = 0;
}
global_set_pending_query_end_response (FALSE);
if (send_response && client)
send_quit_response (client, TRUE, NULL);
}
static gboolean
query_end_response (gpointer data)
{
g_debug ("1 second wait is over");
stop_waiting_for_query_end_response (TRUE);
return G_SOURCE_REMOVE;
}
static void
wait_for_query_end_response (GDBusProxy *proxy)
{
if (query_end_timeout != 0)
return; /* we're already waiting */
g_debug ("Waiting for up to 1 second for QueryEndResponse calls");
query_end_timeout = g_timeout_add (1000, query_end_response, proxy);
global_set_pending_query_end_response (TRUE);
}
static void
maybe_send_quit_response (void)
{
if (query_end_timeout == 0)
return;
if (!client)
return;
if (global_get_pending_query_end_response ())
return;
g_debug ("No more pending QueryEndResponse calls");
stop_waiting_for_query_end_response (TRUE);
}
static void
client_proxy_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
if (g_str_equal (signal_name, "QueryEndSession"))
{
g_debug ("Received QueryEndSession");
wait_for_query_end_response (proxy);
set_session_state (QUERY_END);
maybe_send_quit_response ();
}
else if (g_str_equal (signal_name, "CancelEndSession"))
{
g_debug ("Received CancelEndSession");
stop_waiting_for_query_end_response (FALSE);
set_session_state (RUNNING);
}
else if (g_str_equal (signal_name, "EndSession"))
{
g_debug ("Received EndSession");
stop_waiting_for_query_end_response (FALSE);
set_session_state (ENDING);
send_quit_response (client, TRUE, NULL);
}
else if (g_str_equal (signal_name, "Stop"))
{
g_debug ("Received Stop");
}
}
static OrgFreedesktopScreenSaver *fdo_screensaver;
static void
uninhibit_done_fdo (GObject *source,
GAsyncResult *result,
gpointer data)
{
g_autoptr(GError) error = NULL;
if (!org_freedesktop_screen_saver_call_un_inhibit_finish (fdo_screensaver,
result,
&error))
g_warning ("Backend call failed: %s", error->message);
}
static gboolean
handle_close_fdo (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
gpointer data)
{
Request *request = (Request *)object;
guint cookie;
/* If we get a Close call before the Inhibit call returned,
* delay the uninhibit call until we have the cookie.
*/
cookie = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (request), "cookie"));
if (cookie)
org_freedesktop_screen_saver_call_un_inhibit (fdo_screensaver,
cookie,
NULL,
uninhibit_done_fdo,
NULL);
else
g_object_set_data (G_OBJECT (request), "closed", GINT_TO_POINTER (1));
if (request->exported)
request_unexport (request);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static void
inhibit_done_fdo (GObject *source,
GAsyncResult *result,
gpointer data)
{
g_autoptr(Request) request = data;
guint cookie = 0;
gboolean closed;
g_autoptr(GError) error = NULL;
if (!org_freedesktop_screen_saver_call_inhibit_finish (fdo_screensaver,
&cookie,
result,
&error))
g_warning ("Backend call failed: %s", error->message);
closed = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (request), "closed"));
if (closed)
org_freedesktop_screen_saver_call_un_inhibit (fdo_screensaver,
cookie,
NULL,
uninhibit_done_fdo,
NULL);
else
g_object_set_data (G_OBJECT (request), "cookie", GUINT_TO_POINTER (cookie));
}
static gboolean
handle_inhibit_fdo (XdpImplInhibit *object,
GDBusMethodInvocation *invocation,
const gchar *arg_handle,
const gchar *arg_app_id,
const gchar *arg_window,
guint arg_flags,
GVariant *arg_options)
{
g_autoptr (Request) request = NULL;
const char *sender;
g_autoptr(GError) error = NULL;
const char *reason;
if ((arg_flags & ~INHIBIT_IDLE) != 0)
{
g_dbus_method_invocation_return_error (invocation,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_FAILED,
"Inhibiting other than idle not supported");
return TRUE;
}
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close_fdo), NULL);
request_export (request, g_dbus_method_invocation_get_connection (invocation));
if (!g_variant_lookup (arg_options, "reason", "&s", &reason))
reason = "";
org_freedesktop_screen_saver_call_inhibit (fdo_screensaver,
arg_app_id,
reason,
NULL,
inhibit_done_fdo,
g_object_ref (request));
xdp_impl_inhibit_complete_inhibit (object, invocation);
return TRUE;
}
static GList *active_sessions = NULL;
static void
emit_state_changed (Session *session)
{
GVariantBuilder state;
g_debug ("Emitting StateChanged for session %s", session->id);
g_variant_builder_init (&state, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&state, "{sv}", "screensaver-active", g_variant_new_boolean (screensaver_active));
g_variant_builder_add (&state, "{sv}", "session-state", g_variant_new_uint32 (session_state));
g_signal_emit_by_name (inhibit, "state-changed", session->id, g_variant_builder_end (&state));
}
static void
global_emit_state_changed (void)
{
GList *l;
for (l = active_sessions; l; l = l->next)
emit_state_changed ((Session *)l->data);
}
typedef struct
{
Session parent;
gboolean pending_query_end_response;
} InhibitSession;
typedef struct _InhibitSessionClass
{
SessionClass parent_class;
} InhibitSessionClass;
GType inhibit_session_get_type (void);
G_DEFINE_TYPE (InhibitSession, inhibit_session, session_get_type ())
static void
global_set_pending_query_end_response (gboolean pending)
{
GList *l;
for (l = active_sessions; l; l = l->next)
{
InhibitSession *session = (InhibitSession *)l->data;
session->pending_query_end_response = pending;
}
}
static gboolean
global_get_pending_query_end_response (void)
{
GList *l;
for (l = active_sessions; l; l = l->next)
{
InhibitSession *session = (InhibitSession *)l->data;
if (session->pending_query_end_response)
return TRUE;
}
return FALSE;
}
static void
inhibit_session_close (Session *session)
{
InhibitSession *inhibit_session = (InhibitSession *)session;
g_debug ("Closing inhibit session %s", ((Session *)inhibit_session)->id);
active_sessions = g_list_remove (active_sessions, session);
}
static void
inhibit_session_finalize (GObject *object)
{
G_OBJECT_CLASS (inhibit_session_parent_class)->finalize (object);
}
static void
inhibit_session_init (InhibitSession *inhibit_session)
{
}
static void
inhibit_session_class_init (InhibitSessionClass *klass)
{
GObjectClass *gobject_class;
SessionClass *session_class;
gobject_class = (GObjectClass *)klass;
gobject_class->finalize = inhibit_session_finalize;
session_class = (SessionClass *)klass;
session_class->close = inhibit_session_close;
}
static InhibitSession *
inhibit_session_new (const char *app_id,
const char *session_handle)
{
InhibitSession *inhibit_session;
g_debug ("Creating inhibit session %s", session_handle);
inhibit_session = g_object_new (inhibit_session_get_type (),
"id", session_handle,
NULL);
active_sessions = g_list_prepend (active_sessions, inhibit_session);
return inhibit_session;
}
static gboolean
handle_create_monitor (XdpImplInhibit *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_session_handle,
const char *arg_app_id,
const char *arg_window)
{
g_autoptr(GError) error = NULL;
int response;
Session *session;
session = (Session *)inhibit_session_new (arg_app_id, arg_session_handle);
if (!session_export (session, g_dbus_method_invocation_get_connection (invocation), &error))
{
g_clear_object (&session);
g_warning ("Failed to create inhibit session: %s", error->message);
response = 2;
goto out;
}
response = 0;
out:
xdp_impl_inhibit_complete_create_monitor (object, invocation, response);
if (session)
emit_state_changed (session);
return TRUE;
}
static gboolean
handle_query_end_response (XdpImplInhibit *object,
GDBusMethodInvocation *invocation,
const char *arg_session_handle)
{
InhibitSession *session = (InhibitSession *)lookup_session (arg_session_handle);
g_debug ("Handle QueryEndSessionResponse for session %s", arg_session_handle);
if (session)
{
session->pending_query_end_response = FALSE;
maybe_send_quit_response ();
}
xdp_impl_inhibit_complete_query_end_response (object, invocation);
return TRUE;
}
static void
global_active_changed_cb (GObject *object,
gboolean active)
{
g_debug ("Screensaver %s", active ? "active" : "inactive");
screensaver_active = active;
global_emit_state_changed ();
}
gboolean
inhibit_init (GDBusConnection *bus,
GError **error)
{
g_autofree char *owner = NULL;
g_autofree char *owner2 = NULL;
gboolean active;
inhibit = G_DBUS_INTERFACE_SKELETON (xdp_impl_inhibit_skeleton_new ());
sessionmanager = org_gnome_session_manager_proxy_new_sync (bus,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.gnome.SessionManager",
"/org/gnome/SessionManager",
NULL,
NULL);
owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (sessionmanager));
if (owner)
{
screensaver = org_gnome_screen_saver_proxy_new_sync (bus,
G_DBUS_PROXY_FLAGS_NONE,
"org.gnome.ScreenSaver",
"/org/gnome/ScreenSaver",
NULL,
NULL);
owner2 = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (screensaver));
if (owner2)
{
g_autofree char *client_path = NULL;
g_autofree char *owner3 = NULL;
g_signal_connect (inhibit, "handle-inhibit", G_CALLBACK (handle_inhibit_gnome), NULL);
g_signal_connect (inhibit, "handle-create-monitor", G_CALLBACK (handle_create_monitor), NULL);
g_signal_connect (inhibit, "handle-query-end-response", G_CALLBACK (handle_query_end_response), NULL);
g_signal_connect (screensaver, "active-changed", G_CALLBACK (global_active_changed_cb), NULL);
org_gnome_screen_saver_call_get_active_sync (screensaver, &active, NULL, NULL);
g_object_set_data (G_OBJECT (screensaver), "active", GINT_TO_POINTER (active));
g_debug ("Using org.gnome.SessionManager for inhibit");
g_debug ("Using org.gnome.Screensaver for screensaver state");
if (org_gnome_session_manager_call_register_client_sync (sessionmanager,
"org.freedesktop.portal",
"",
&client_path,
NULL,
NULL))
{
client = g_dbus_proxy_new_sync (bus, 0,
NULL,
"org.gnome.SessionManager",
client_path,
"org.gnome.SessionManager.ClientPrivate",
NULL,
NULL);
owner3 = g_dbus_proxy_get_name_owner (client);
if (owner3)
{
g_signal_connect (client, "g-signal", G_CALLBACK (client_proxy_signal), NULL);
g_debug ("Using org.gnome.SessionManager for session state");
}
}
}
else
{
g_clear_object (&sessionmanager);
g_clear_object (&screensaver);
}
}
else
{
g_clear_object (&sessionmanager);
}
if (!screensaver)
{
g_signal_connect (inhibit, "handle-inhibit", G_CALLBACK (handle_inhibit_fdo), NULL);
g_signal_connect (inhibit, "handle-create-monitor", G_CALLBACK (handle_create_monitor), NULL);
fdo_screensaver = org_freedesktop_screen_saver_proxy_new_sync (bus,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.ScreenSaver",
"/org/freedesktop/ScreenSaver",
NULL,
NULL);
g_signal_connect (fdo_screensaver, "active-changed", G_CALLBACK (global_active_changed_cb), NULL);
org_freedesktop_screen_saver_call_get_active_sync (fdo_screensaver, &active, NULL, NULL);
g_object_set_data (G_OBJECT (fdo_screensaver), "active", GINT_TO_POINTER (active));
g_debug ("Using org.freedesktop.ScreenSaver for inhibit");
g_debug ("Using org.freedesktop.ScreenSaver for screensaver state");
}
if (!g_dbus_interface_skeleton_export (inhibit, bus, "/org/freedesktop/portal/desktop", error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (inhibit)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean inhibit_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2018 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gio/gio.h>
#include "xdg-desktop-portal-dbus.h"
#include "lockdown.h"
#include "utils.h"
static GSettings *lockdown;
static GSettings *location;
static GSettings *privacy;
gboolean
lockdown_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
GSettingsSchemaSource *source;
GSettingsSchema *schema;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_lockdown_skeleton_new ());
lockdown = g_settings_new ("org.gnome.desktop.lockdown");
g_settings_bind (lockdown, "disable-printing", helper, "disable-printing", G_SETTINGS_BIND_DEFAULT);
g_settings_bind (lockdown, "disable-save-to-disk", helper, "disable-save-to-disk", G_SETTINGS_BIND_DEFAULT);
g_settings_bind (lockdown, "disable-application-handlers", helper, "disable-application-handlers", G_SETTINGS_BIND_DEFAULT);
location = g_settings_new ("org.gnome.system.location");
g_settings_bind (location, "enabled", helper, "disable-location", G_SETTINGS_BIND_INVERT_BOOLEAN);
source = g_settings_schema_source_get_default ();
schema = g_settings_schema_source_lookup (source, "org.gnome.desktop.privacy", TRUE);
privacy = g_settings_new ("org.gnome.desktop.privacy");
if (g_settings_schema_has_key (schema, "disable-camera"))
g_settings_bind (privacy, "disable-camera", helper, "disable-camera", G_SETTINGS_BIND_DEFAULT);
if (g_settings_schema_has_key (schema, "disable-microphone"))
g_settings_bind (privacy, "disable-microphone", helper, "disable-microphone", G_SETTINGS_BIND_DEFAULT);
if (g_settings_schema_has_key (schema, "disable-sound-output"))
g_settings_bind (privacy, "disable-sound-output", helper, "disable-sound-output", G_SETTINGS_BIND_DEFAULT);
g_settings_schema_unref (schema);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2018 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean lockdown_init (GDBusConnection *bus, GError **error);
portal_sources = files(
'utils.c',
'request.c',
'session.c',
'filechooser.c',
'notification.c',
'fdonotification.c',
'inhibit.c',
'print.c',
'access.c',
'account.c',
'accountdialog.c',
'email.c',
'gtkbackports.c',
'externalwindow.c',
'dynamic-launcher.c',
)
portal_c_args = [
'-DLOCALEDIR="@0@"'.format(localedir),
]
if get_option('wallpaper').allowed()
portal_deps += dependency('gnome-desktop-3.0')
portal_sources += files(
'wallpaper.c',
'wallpaperpreview.c',
'wallpaperdialog.c',
)
portal_c_args += '-DBUILD_WALLPAPER'
endif
if get_option('settings').allowed()
portal_deps += [
dependency('gsettings-desktop-schemas'),
dependency('fontconfig'),
]
portal_sources += files(
'fc-monitor.c',
'settings.c',
)
portal_c_args += '-DBUILD_SETTINGS'
endif
if get_option('appchooser').allowed()
portal_sources += files(
'appchooser.c',
'appchooserrow.c',
'appchooserdialog.c',
)
portal_c_args += '-DBUILD_APPCHOOSER'
endif
if get_option('lockdown').allowed()
portal_sources += files('lockdown.c')
portal_c_args += '-DBUILD_LOCKDOWN'
endif
if gtkx11_dep.found()
portal_sources += files('externalwindow-x11.c')
endif
if gtkwayland_dep.found()
portal_sources += files('externalwindow-wayland.c')
endif
portal_resources = gnome.compile_resources(
'xdg-desktop-portal-gtk-resources',
'xdg-desktop-portal-gtk.gresource.xml',
c_name: '_xdg_desktop',
source_dir: '.',
)
portal_built_sources = [
portal_resources,
]
portal_built_sources += gnome.gdbus_codegen('xdg-desktop-portal-dbus',
sources: portal_dbus_interfaces,
interface_prefix: 'org.freedesktop.impl.portal.',
namespace: 'XdpImpl',
annotations: [
[ 'org.freedesktop.impl.portal.Print.Print()', 'org.gtk.GDBus.C.UnixFD', 'true' ],
],
)
portal_built_sources += gnome.gdbus_codegen('shell-dbus',
sources: [
fdo_dbus_interfaces,
gnome_dbus_interfaces,
],
)
executable('xdg-desktop-portal-gtk',
sources: [
'xdg-desktop-portal-gtk.c',
portal_sources,
portal_built_sources,
],
dependencies: [
portal_deps,
gtkx11_dep,
gtkwayland_dep,
],
c_args: portal_c_args,
include_directories: [root_inc],
install: true,
install_dir: libexecdir,
)
executable('testappchooser',
sources: [
'testappchooser.c',
'appchooserrow.c',
'appchooserdialog.c',
portal_resources,
],
dependencies: [
portal_deps,
gtkx11_dep,
],
c_args: [
'-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
'-DLOCALEDIR="@0@"'.format(localedir),
],
include_directories: [root_inc],
)
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "notification.h"
#include "fdonotification.h"
#include "request.h"
#include "utils.h"
static char *
app_path_for_id (const gchar *app_id)
{
char *path;
gint i;
path = g_strconcat ("/", app_id, NULL);
for (i = 0; path[i]; i++)
{
if (path[i] == '.')
path[i] = '/';
if (path[i] == '-')
path[i] = '_';
}
return path;
}
static void
activate_action (GDBusConnection *connection,
const char *app_id,
const char *id,
const char *name,
GVariant *parameter,
const char *activation_token,
gpointer data)
{
g_autofree char *object_path = NULL;
GVariantBuilder pdata, parms;
object_path = app_path_for_id (app_id);
g_variant_builder_init (&pdata, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&parms, G_VARIANT_TYPE ("av"));
if (parameter)
g_variant_builder_add (&parms, "v", parameter);
if (activation_token)
{
/* Used by `GTK` < 4.10 */
g_variant_builder_add (&pdata, "{sv}",
"desktop-startup-id", g_variant_new_string (activation_token));
/* Used by `GTK` and `QT` */
g_variant_builder_add (&pdata, "{sv}",
"activation-token", g_variant_new_string (activation_token));
}
if (name && g_str_has_prefix (name, "app."))
{
g_dbus_connection_call (connection,
app_id,
object_path,
"org.freedesktop.Application",
"ActivateAction",
g_variant_new ("(s@av@a{sv})",
name + 4,
g_variant_builder_end (&parms),
g_variant_builder_end (&pdata)),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
}
else
{
g_autoptr(GVariant) ret = NULL;
g_dbus_connection_call (connection,
app_id,
object_path,
"org.freedesktop.Application",
"Activate",
g_variant_new ("(@a{sv})",
g_variant_builder_end (&pdata)),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
g_dbus_connection_emit_signal (connection,
NULL,
"/org/freedesktop/portal/desktop",
"org.freedesktop.impl.portal.Notification",
"ActionInvoked",
g_variant_new ("(sss@av)",
app_id, id, name,
g_variant_builder_end (&parms)),
NULL);
}
}
static gboolean
handle_add_notification (XdpImplNotification *object,
GDBusMethodInvocation *invocation,
#ifdef HAVE_XDP_1_19_1
GUnixFDList *fds G_GNUC_UNUSED,
#endif
const gchar *arg_app_id,
const gchar *arg_id,
GVariant *arg_notification)
{
GDBusConnection *connection;
connection = g_dbus_method_invocation_get_connection (invocation);
fdo_add_notification (connection, arg_app_id, arg_id, arg_notification, activate_action, NULL);
#ifdef HAVE_XDP_1_19_1
xdp_impl_notification_complete_add_notification (object, invocation, NULL);
#else
xdp_impl_notification_complete_add_notification (object, invocation);
#endif
return TRUE;
}
static gboolean
handle_remove_notification (XdpImplNotification *object,
GDBusMethodInvocation *invocation,
const gchar *arg_app_id,
const gchar *arg_id)
{
GDBusConnection *connection;
connection = g_dbus_method_invocation_get_connection (invocation);
fdo_remove_notification (connection, arg_app_id, arg_id);
xdp_impl_notification_complete_remove_notification (object, invocation);
return TRUE;
}
gboolean
notification_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_notification_skeleton_new ());
g_signal_connect (helper, "handle-add-notification", G_CALLBACK (handle_add_notification), NULL);
g_signal_connect (helper, "handle-remove-notification", G_CALLBACK (handle_remove_notification), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean notification_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include <gtk/gtkunixprint.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <gio/gdesktopappinfo.h>
#include "xdg-desktop-portal-dbus.h"
#include "print.h"
#include "request.h"
#include "utils.h"
#include "externalwindow.h"
#include "gtkbackports.h"
typedef struct {
char *app_id;
GtkPageSetup *page_setup;
GtkPrintSettings *settings;
GtkPrinter *printer;
guint timeout_id;
guint32 token;
gboolean preview;
} PrintParams;
static GHashTable *print_params;
static void
print_params_free (gpointer data)
{
PrintParams *params = data;
g_hash_table_remove (print_params, GUINT_TO_POINTER (params->token));
g_free (params->app_id);
g_object_unref (params->page_setup);
g_object_unref (params->settings);
g_object_unref (params->printer);
g_free (params);
}
static void
ensure_print_params (void)
{
if (print_params)
return;
print_params = g_hash_table_new (g_direct_hash, g_direct_equal);
}
static gboolean
print_params_timeout (gpointer data)
{
print_params_free (data);
g_debug ("Removing print params, now %d", g_hash_table_size (print_params));
return G_SOURCE_REMOVE;
}
static PrintParams *
print_params_new (const char *app_id,
gboolean preview,
GtkPageSetup *page_setup,
GtkPrintSettings *settings,
GtkPrinter *printer)
{
PrintParams *params;
guint32 r;
ensure_print_params ();
params = g_new0 (PrintParams, 1);
params->app_id = g_strdup (app_id);
params->page_setup = g_object_ref (page_setup);
params->settings = g_object_ref (settings);
params->printer = g_object_ref (printer);
params->preview = preview;
do {
r = g_random_int ();
} while (r == 0 || g_hash_table_lookup (print_params, GUINT_TO_POINTER (r)) != NULL);
params->token = r;
g_hash_table_insert (print_params, GUINT_TO_POINTER (r), params);
g_debug ("Remembering print params for %s, token %u, now %d",
params->app_id, params->token,
g_hash_table_size (print_params));
params->timeout_id = g_timeout_add_seconds (300, print_params_timeout, params);
return params;
}
static PrintParams *
get_print_params (const char *app_id,
guint32 token)
{
PrintParams *params;
params = (PrintParams *)g_hash_table_lookup (print_params, GUINT_TO_POINTER (token));
if (params == NULL)
return NULL;
if (strcmp (params->app_id, app_id) != 0)
return NULL;
g_source_remove (params->timeout_id);
g_hash_table_remove (print_params, GUINT_TO_POINTER (token));
return params;
}
typedef struct {
XdpImplPrint *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
ExternalWindow *external_parent;
int fd;
int response;
PrintParams *params;
} PrintDialogHandle;
static void
print_dialog_handle_free (gpointer data)
{
PrintDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_object_unref (handle->request);
g_object_unref (handle->dialog);
close (handle->fd);
g_free (handle);
}
static void
print_dialog_handle_close (PrintDialogHandle *handle)
{
gtk_widget_destroy (handle->dialog);
print_dialog_handle_free (handle);
}
static gboolean
can_preview (void)
{
g_autofree char *path = NULL;
path = g_find_program_in_path ("evince-previewer");
if (path)
return TRUE;
g_warning ("evince-previewer not found, disabling print preview");
return FALSE;
}
static GtkPrintCapabilities
print_capabilities_from_options (GVariant *options)
{
g_auto(GStrv) supported_output_file_formats = NULL;
GtkPrintCapabilities capabilities;
capabilities = can_preview () ? GTK_PRINT_CAPABILITY_PREVIEW : 0 |
GTK_PRINT_CAPABILITY_PAGE_SET |
GTK_PRINT_CAPABILITY_COPIES |
GTK_PRINT_CAPABILITY_COLLATE |
GTK_PRINT_CAPABILITY_REVERSE |
GTK_PRINT_CAPABILITY_SCALE |
GTK_PRINT_CAPABILITY_NUMBER_UP;
if (g_variant_lookup (options, "supported_output_file_formats", "^as", &supported_output_file_formats))
{
g_autoptr(GHashTable) formats = NULL;
g_assert (supported_output_file_formats && supported_output_file_formats[0] != NULL);
formats = g_hash_table_new (g_str_hash, g_str_equal);
for (size_t i = 0; supported_output_file_formats[i]; i++)
g_hash_table_add (formats, (gpointer) supported_output_file_formats[i]);
/* This is a limitation of GtkPrintCapability - it doesn't have an enum
* for SVG files.
*/
if (!g_hash_table_contains (formats, "svg"))
{
if (g_hash_table_contains (formats, "pdf"))
capabilities |= GTK_PRINT_CAPABILITY_GENERATE_PDF;
if (g_hash_table_contains (formats, "ps"))
capabilities |= GTK_PRINT_CAPABILITY_GENERATE_PS;
}
}
return capabilities;
}
static gboolean
launch_preview (const char *filename,
const char *title,
GtkPrintSettings *settings,
GtkPageSetup *page_setup,
GError **error)
{
g_autofree char *cmd = NULL;
g_autoptr(GAppInfo) appinfo = NULL;
g_autoptr(GAppLaunchContext) context = NULL;
gboolean retval = FALSE;
g_autoptr(GKeyFile) keyfile = NULL;
g_autofree char *data = NULL;
gsize data_len;
g_autofree char *settings_filename = NULL;
int fd;
fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, error);
if (fd == -1)
goto out;
keyfile = g_key_file_new ();
if (settings)
gtk_print_settings_to_key_file (settings, keyfile, NULL);
if (page_setup)
gtk_page_setup_to_key_file (page_setup, keyfile, NULL);
g_key_file_set_string (keyfile, "Print Job", "title", title);
data = g_key_file_to_data (keyfile, &data_len, NULL);
if (data)
g_file_set_contents (settings_filename, data, data_len, NULL);
cmd = g_strdup_printf ("evince-previewer --unlink-tempfile --print-settings %s %s", settings_filename, filename);
g_debug ("launching %s", cmd);
appinfo = g_app_info_create_from_commandline (cmd,
"Print Preview",
G_APP_INFO_CREATE_NONE,
error);
if (!appinfo)
goto out;
context = (GAppLaunchContext *)gdk_display_get_app_launch_context (gdk_display_get_default ());
retval = g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), error);
out:
if (fd > 0)
close (fd);
return retval;
}
static gboolean
print_file (int fd,
const char *app_id,
gboolean preview,
GtkPrinter *printer,
GtkPrintSettings *settings,
GtkPageSetup *page_setup,
GError **error)
{
g_autoptr (GtkPrintJob) job = NULL;
g_autofree char *title = NULL;
g_autofree char *filename = NULL;
g_autoptr(GUnixInputStream) istream = NULL;
g_autoptr(GUnixOutputStream) ostream = NULL;
int fd2;
g_autofree char *app_desktop_fullname = NULL;
g_autoptr (GDesktopAppInfo) app_info = NULL;
// ensures the app_name won't be NULL even if the app_id.desktop file doesn't exist
g_autofree char *app_name = NULL;
if (!g_str_has_suffix (app_id, ".desktop"))
{
app_desktop_fullname = g_strconcat (app_id, ".desktop", NULL);
}
else
{
app_desktop_fullname = g_strdup (app_id);
}
app_info = g_desktop_app_info_new (app_desktop_fullname);
if (app_info)
{
app_name = g_desktop_app_info_get_locale_string (app_info, "Name");
}
if (app_name == NULL)
app_name = g_strdup (app_id);
title = g_strdup_printf ("Document from %s", app_name);
if (!preview)
job = gtk_print_job_new (title, printer, settings, page_setup);
#if GTK_CHECK_VERSION (3, 22, 0)
if (job && !gtk_print_job_set_source_fd (job, fd, error))
return FALSE;
#endif
istream = (GUnixInputStream *)g_unix_input_stream_new (fd, FALSE);
if ((fd2 = g_file_open_tmp (PACKAGE_NAME "XXXXXX", &filename, error)) == -1)
return FALSE;
ostream = (GUnixOutputStream *)g_unix_output_stream_new (fd2, TRUE);
if (g_output_stream_splice (G_OUTPUT_STREAM (ostream),
G_INPUT_STREAM (istream),
G_OUTPUT_STREAM_SPLICE_NONE,
NULL,
error) == -1)
return FALSE;
if (job)
{
if (!gtk_print_job_set_source_file (job, filename, error))
return FALSE;
gtk_print_job_send (job, NULL, NULL, NULL);
}
else
{
if (!launch_preview (filename, title, settings, page_setup, error))
{
unlink (filename);
return FALSE;
}
}
/* The file will be removed when the GtkPrintJob closes it (once the job is
* complete).
*/
if (!preview)
unlink (filename);
return TRUE;
}
static void
handle_print_response (GtkDialog *dialog,
gint response,
gpointer data)
{
PrintDialogHandle *handle = data;
g_autoptr(GError) error = NULL;
gboolean preview = FALSE;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_APPLY:
preview = TRUE;
/* fall thru */
case GTK_RESPONSE_OK:
{
GtkPrinter *printer;
GtkPrintSettings *settings;
GtkPageSetup *page_setup;
printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (handle->dialog));
settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (handle->dialog));
page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (handle->dialog));
if (!print_file (handle->fd,
handle->request->app_id,
preview,
printer,
settings,
page_setup,
&error))
handle->response = 2;
else
handle->response = 0;
g_object_unref (settings);
}
break;
}
if (handle->request->exported)
request_unexport (handle->request);
if (error)
{
g_dbus_method_invocation_take_error (handle->invocation, error);
}
else
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_print_complete_print (handle->impl,
handle->invocation,
NULL,
handle->response,
g_variant_builder_end (&opt_builder));
}
print_dialog_handle_close (handle);
}
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation,
PrintDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_print_complete_print (handle->impl,
handle->invocation,
NULL,
2,
g_variant_builder_end (&opt_builder));
if (handle->request->exported)
request_unexport (handle->request);
print_dialog_handle_close (handle);
xdp_impl_request_complete_close (object, invocation);
return TRUE;
}
static gboolean
handle_print (XdpImplPrint *object,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_title,
GVariant *arg_fd_in,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
GtkWidget *dialog;
PrintDialogHandle *handle;
guint32 token = 0;
PrintParams *params;
int idx, fd;
gboolean modal;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
g_variant_get (arg_fd_in, "h", &idx);
fd = g_unix_fd_list_get (fd_list, idx, NULL);
g_variant_lookup (arg_options, "token", "u", &token);
params = get_print_params (arg_app_id, token);
if (params)
{
GVariantBuilder opt_builder;
print_file (fd,
params->app_id,
params->preview,
params->printer,
params->settings,
params->page_setup,
NULL);
print_params_free (params);
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
xdp_impl_print_complete_print (object,
invocation,
NULL,
0,
g_variant_builder_end (&opt_builder));
return TRUE;
}
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
dialog = gtk_print_unix_dialog_new (arg_title, NULL);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
gtk_window_set_modal (GTK_WINDOW (dialog), modal);
gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
print_capabilities_from_options (arg_options));
handle = g_new0 (PrintDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->external_parent = external_parent;
handle->fd = fd;
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "response", G_CALLBACK (handle_print_response), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
request_export (request, g_dbus_method_invocation_get_connection (invocation));
gtk_widget_show (dialog);
return TRUE;
}
static void
send_prepare_print_response (PrintDialogHandle *handle)
{
GVariantBuilder opt_builder;
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
if (handle->response == 0)
{
g_variant_builder_add (&opt_builder, "{sv}", "settings", gtk_print_settings_to_gvariant (handle->params->settings));
g_variant_builder_add (&opt_builder, "{sv}", "page-setup", gtk_page_setup_to_gvariant (handle->params->page_setup));
g_variant_builder_add (&opt_builder, "{sv}", "token", g_variant_new_uint32 (handle->params->token));
}
if (handle->request->exported)
request_unexport (handle->request);
xdp_impl_print_complete_prepare_print (handle->impl,
handle->invocation,
handle->response,
g_variant_builder_end (&opt_builder));
print_dialog_handle_close (handle);
}
static void
handle_prepare_print_response (GtkDialog *dialog,
gint response,
gpointer data)
{
PrintDialogHandle *handle = data;
gboolean preview = FALSE;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_APPLY:
preview = TRUE;
/* fall thru */
case GTK_RESPONSE_OK:
{
handle->response = 0;
handle->params = print_params_new (handle->request->app_id,
preview,
gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (handle->dialog)),
gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (handle->dialog)),
gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (handle->dialog)));
}
break;
}
send_prepare_print_response (handle);
}
static gboolean
handle_prepare_print (XdpImplPrint *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_title,
GVariant *arg_settings,
GVariant *arg_page_setup,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
const char *sender;
GtkWidget *dialog;
PrintDialogHandle *handle;
GtkPrintSettings *settings;
GtkPageSetup *page_setup;
gboolean modal;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
settings = gtk_print_settings_new_from_gvariant (arg_settings);
page_setup = gtk_page_setup_new_from_gvariant (arg_page_setup);
if (!g_variant_lookup (arg_options, "modal", "b", &modal))
modal = TRUE;
dialog = gtk_print_unix_dialog_new (arg_title, NULL);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
gtk_window_set_modal (GTK_WINDOW (dialog), modal);
gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
print_capabilities_from_options (arg_options));
gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (dialog), TRUE);
gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog), settings);
gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog), page_setup);
g_object_unref (settings);
g_object_unref (page_setup);
handle = g_new0 (PrintDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
handle->dialog = g_object_ref (dialog);
handle->external_parent = external_parent;
g_signal_connect (request, "handle-close", G_CALLBACK (handle_close), handle);
g_signal_connect (dialog, "response", G_CALLBACK (handle_prepare_print_response), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
gtk_widget_show (dialog);
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
gboolean
print_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_print_skeleton_new ());
g_signal_connect (helper, "handle-print", G_CALLBACK (handle_print), NULL);
g_signal_connect (helper, "handle-prepare-print", G_CALLBACK (handle_prepare_print), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean print_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
* Matthias Clasen <mclasen@redhat.com>
*/
#include "request.h"
#include <string.h>
static void request_skeleton_iface_init (XdpImplRequestIface *iface);
G_DEFINE_TYPE_WITH_CODE (Request, request, XDP_IMPL_TYPE_REQUEST_SKELETON,
G_IMPLEMENT_INTERFACE (XDP_IMPL_TYPE_REQUEST, request_skeleton_iface_init))
static gboolean
handle_close (XdpImplRequest *object,
GDBusMethodInvocation *invocation)
{
Request *request = (Request *)object;
g_autoptr(GError) error = NULL;
if (request->exported)
request_unexport (request);
xdp_impl_request_complete_close (XDP_IMPL_REQUEST (request), invocation);
return TRUE;
}
static void
request_skeleton_iface_init (XdpImplRequestIface *iface)
{
iface->handle_close = handle_close;
}
static void
request_init (Request *request)
{
}
static void
request_finalize (GObject *object)
{
Request *request = (Request *)object;
g_free (request->sender);
g_free (request->app_id);
g_free (request->id);
G_OBJECT_CLASS (request_parent_class)->finalize (object);
}
static void
request_class_init (RequestClass *klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = request_finalize;
}
Request *
request_new (const char *sender,
const char *app_id,
const char *id)
{
Request *request;
request = g_object_new (request_get_type (), NULL);
request->sender = g_strdup (sender);
request->app_id = g_strdup (app_id);
request->id = g_strdup (id);
return request;
}
void
request_export (Request *request,
GDBusConnection *connection)
{
g_autoptr(GError) error = NULL;
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (request),
connection,
request->id,
&error))
{
g_warning ("error exporting request: %s\n", error->message);
g_clear_error (&error);
}
g_object_ref (request);
request->exported = TRUE;
}
void
request_unexport (Request *request)
{
request->exported = FALSE;
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (request));
g_object_unref (request);
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include "xdg-desktop-portal-dbus.h"
typedef struct _Request Request;
typedef struct _RequestClass RequestClass;
struct _Request
{
XdpImplRequestSkeleton parent_instance;
gboolean exported;
char *sender;
char *app_id;
char *id;
};
struct _RequestClass
{
XdpImplRequestSkeletonClass parent_class;
};
GType request_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Request, g_object_unref)
Request *request_new (const char *sender,
const char *app_id,
const char *id);
void request_export (Request *request,
GDBusConnection *connection);
void request_unexport (Request *request);
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "session.h"
enum
{
PROP_0,
PROP_ID,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
static GHashTable *sessions;
static void session_skeleton_iface_init (XdpImplSessionIface *iface);
G_DEFINE_TYPE_WITH_CODE (Session, session, XDP_IMPL_TYPE_SESSION_SKELETON,
G_IMPLEMENT_INTERFACE (XDP_IMPL_TYPE_SESSION,
session_skeleton_iface_init))
#define SESSION_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS ((o), session_get_type (), SessionClass))
Session *
lookup_session (const char *id)
{
return g_hash_table_lookup (sessions, id);
}
gboolean
session_export (Session *session,
GDBusConnection *connection,
GError **error)
{
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (session),
connection,
session->id,
error))
return FALSE;
g_object_ref (session);
session->exported = TRUE;
return TRUE;
}
void
session_unexport (Session *session)
{
session->exported = FALSE;
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
g_object_unref (session);
}
void
session_close (Session *session)
{
if (session->exported)
session_unexport (session);
session->closed = TRUE;
SESSION_GET_CLASS (session)->close (session);
g_object_unref (session);
}
static gboolean
handle_close (XdpImplSession *object,
GDBusMethodInvocation *invocation)
{
Session *session = (Session *)object;
if (!session->closed)
session_close (session);
xdp_impl_session_complete_close (object, invocation);
return TRUE;
}
static void
session_skeleton_iface_init (XdpImplSessionIface *iface)
{
iface->handle_close = handle_close;
}
static void
session_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Session *session = (Session *)object;
switch (prop_id)
{
case PROP_ID:
session->id = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
session_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Session *session = (Session *)object;
switch (prop_id)
{
case PROP_ID:
g_value_set_string (value, session->id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
session_finalize (GObject *object)
{
Session *session = (Session *)object;
g_hash_table_remove (sessions, session->id);
g_free (session->id);
G_OBJECT_CLASS (session_parent_class)->finalize (object);
}
static void
session_constructed (GObject *object)
{
Session *session = (Session *)object;
g_hash_table_insert (sessions, g_strdup (session->id), session);
G_OBJECT_CLASS (session_parent_class)->constructed (object);
}
static void
session_init (Session *session)
{
}
static void
session_class_init (SessionClass *klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = session_constructed;
gobject_class->finalize = session_finalize;
gobject_class->set_property = session_set_property;
gobject_class->get_property = session_get_property;
obj_props[PROP_ID] =
g_param_spec_string ("id", "id", "ID",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
}
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "xdg-desktop-portal-dbus.h"
typedef struct _Session Session;
typedef struct _SessionClass SessionClass;
struct _Session
{
XdpImplSessionSkeleton parent;
gboolean exported;
gboolean closed;
char *id;
};
struct _SessionClass
{
XdpImplSessionSkeletonClass parent_class;
void (*close) (Session *session);
};
GType session_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Session, g_object_unref)
Session *lookup_session (const char *id);
Session *session_new (const char *id);
void session_close (Session *session);
gboolean session_export (Session *session,
GDBusConnection *connection,
GError **error);
void session_unexport (Session *session);
/*
* Copyright © 2018 Igalia S.L.
* Copyright © 2024 GNOME Foundation Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Patrick Griffis <pgriffis@igalia.com>
* Hubert Figuière <hub@figuiere.net>
*/
#include "config.h"
#include <time.h>
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "settings.h"
#include "utils.h"
#include "xdg-desktop-portal-dbus.h"
#include "fc-monitor.h"
static GHashTable *settings;
static FcMonitor *fontconfig_monitor;
static int fontconfig_serial;
static gboolean enable_animations;
static void sync_animations_enabled (XdpImplSettings *impl);
typedef struct {
GSettingsSchema *schema;
GSettings *settings;
} SettingsBundle;
static SettingsBundle *
settings_bundle_new (GSettingsSchema *schema,
GSettings *settings)
{
SettingsBundle *bundle = g_new (SettingsBundle, 1);
bundle->schema = schema;
bundle->settings = settings;
return bundle;
}
static void
settings_bundle_free (SettingsBundle *bundle)
{
g_object_unref (bundle->schema);
g_object_unref (bundle->settings);
g_free (bundle);
}
static gboolean
namespace_matches (const char *namespace,
const char * const *patterns)
{
size_t i;
for (i = 0; patterns[i]; ++i)
{
size_t pattern_len;
const char *pattern = patterns[i];
if (pattern[0] == '\0')
return TRUE;
if (strcmp (namespace, pattern) == 0)
return TRUE;
pattern_len = strlen (pattern);
if (pattern[pattern_len - 1] == '*' && strncmp (namespace, pattern, pattern_len - 1) == 0)
return TRUE;
}
if (i == 0) /* Empty array */
return TRUE;
return FALSE;
}
static GVariant *
get_color_scheme (void)
{
SettingsBundle *bundle = g_hash_table_lookup (settings, "org.gnome.desktop.interface");
int color_scheme;
if (!g_settings_schema_has_key (bundle->schema, "color-scheme"))
return g_variant_new_uint32 (0); /* No preference */
color_scheme = g_settings_get_enum (bundle->settings, "color-scheme");
return g_variant_new_uint32 (color_scheme);
}
static GVariant *
get_contrast_value ()
{
SettingsBundle *bundle = g_hash_table_lookup (settings, "org.gnome.desktop.a11y.interface");
gboolean hc = FALSE;
if (bundle && g_settings_schema_has_key (bundle->schema, "high-contrast"))
hc = g_settings_get_boolean (bundle->settings, "high-contrast");
return g_variant_new_uint32 (hc ? 1 : 0);
}
static gboolean
settings_handle_read_all (XdpImplSettings *object,
GDBusMethodInvocation *invocation,
const char * const *arg_namespaces,
gpointer data)
{
g_autoptr(GVariantBuilder) builder = g_variant_builder_new (G_VARIANT_TYPE ("(a{sa{sv}})"));
GHashTableIter iter;
char *key;
SettingsBundle *value;
g_variant_builder_open (builder, G_VARIANT_TYPE ("a{sa{sv}}"));
g_hash_table_iter_init (&iter, settings);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
g_auto (GStrv) keys = NULL;
GVariantDict dict;
gsize i;
if (!namespace_matches (key, arg_namespaces))
continue;
keys = g_settings_schema_list_keys (value->schema);
g_variant_dict_init (&dict, NULL);
for (i = 0; keys[i]; ++i)
{
if (strcmp (key, "org.gnome.desktop.interface") == 0 &&
strcmp (keys[i], "enable-animations") == 0)
g_variant_dict_insert_value (&dict, keys[i], g_variant_new_boolean (enable_animations));
else
g_variant_dict_insert_value (&dict, keys[i], g_settings_get_value (value->settings, keys[i]));
}
g_variant_builder_add (builder, "{s@a{sv}}", key, g_variant_dict_end (&dict));
}
if (namespace_matches ("org.gnome.fontconfig", arg_namespaces))
{
GVariantDict dict;
g_variant_dict_init (&dict, NULL);
g_variant_dict_insert_value (&dict, "serial", g_variant_new_int32 (fontconfig_serial));
g_variant_builder_add (builder, "{s@a{sv}}", "org.gnome.fontconfig", g_variant_dict_end (&dict));
}
if (namespace_matches ("org.freedesktop.appearance", arg_namespaces))
{
GVariantDict dict;
g_variant_dict_init (&dict, NULL);
g_variant_dict_insert_value (&dict, "color-scheme", get_color_scheme ());
g_variant_dict_insert_value (&dict, "contrast", get_contrast_value ());
g_variant_builder_add (builder, "{s@a{sv}}", "org.freedesktop.appearance", g_variant_dict_end (&dict));
}
g_variant_builder_close (builder);
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (builder));
return TRUE;
}
static gboolean
settings_handle_read (XdpImplSettings *object,
GDBusMethodInvocation *invocation,
const char *arg_namespace,
const char *arg_key,
gpointer data)
{
g_debug ("Read %s %s", arg_namespace, arg_key);
if (strcmp (arg_namespace, "org.gnome.fontconfig") == 0)
{
if (strcmp (arg_key, "serial") == 0)
{
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(v)", g_variant_new_int32 (fontconfig_serial)));
return TRUE;
}
}
else if (strcmp (arg_namespace, "org.freedesktop.appearance") == 0)
{
if (strcmp (arg_key, "color-scheme") == 0)
{
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(v)", get_color_scheme ()));
return TRUE;
}
else if (strcmp (arg_key, "contrast") == 0)
{
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(v)", get_contrast_value ()));
return TRUE;
}
}
else if (strcmp (arg_namespace, "org.gnome.desktop.interface") == 0 &&
strcmp (arg_key, "enable-animations") == 0)
{
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(v)", g_variant_new_boolean (enable_animations)));
return TRUE;
}
else if (g_hash_table_contains (settings, arg_namespace))
{
SettingsBundle *bundle = g_hash_table_lookup (settings, arg_namespace);
if (g_settings_schema_has_key (bundle->schema, arg_key))
{
g_autoptr (GVariant) variant = NULL;
variant = g_settings_get_value (bundle->settings, arg_key);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(v)", variant));
return TRUE;
}
}
g_debug ("Attempted to read unknown namespace/key pair: %s %s", arg_namespace, arg_key);
g_dbus_method_invocation_return_error_literal (invocation, XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_NOT_FOUND,
_("Requested setting not found"));
return TRUE;
}
typedef struct {
XdpImplSettings *self;
const char *namespace;
} ChangedSignalUserData;
static ChangedSignalUserData *
changed_signal_user_data_new (XdpImplSettings *settings,
const char *namespace)
{
ChangedSignalUserData *data = g_new (ChangedSignalUserData, 1);
data->self = settings;
data->namespace = namespace;
return data;
}
static void
changed_signal_user_data_destroy (gpointer data,
GClosure *closure)
{
g_free (data);
}
static void
on_settings_changed (GSettings *settings,
const char *key,
ChangedSignalUserData *user_data)
{
g_autoptr (GVariant) new_value = g_settings_get_value (settings, key);
g_debug ("Emitting changed for %s %s", user_data->namespace, key);
if (strcmp (user_data->namespace, "org.gnome.desktop.interface") == 0 &&
strcmp (key, "enable-animations") == 0)
sync_animations_enabled (user_data->self);
else
xdp_impl_settings_emit_setting_changed (user_data->self,
user_data->namespace, key,
g_variant_new ("v", new_value));
if (strcmp (user_data->namespace, "org.gnome.desktop.interface") == 0 &&
strcmp (key, "color-scheme") == 0)
xdp_impl_settings_emit_setting_changed (user_data->self,
"org.freedesktop.appearance", key,
g_variant_new ("v", get_color_scheme ()));
if (strcmp (user_data->namespace, "org.gnome.desktop.a11y.interface") == 0 &&
strcmp (key, "high-contrast") == 0 &&
g_variant_is_of_type (new_value, G_VARIANT_TYPE_BOOLEAN))
{
gboolean hc = g_variant_get_boolean (new_value);
xdp_impl_settings_emit_setting_changed (user_data->self,
"org.freedesktop.appearance",
"contrast",
g_variant_new ("v", g_variant_new_uint32 (hc ? 1 : 0)));
}
}
static void
init_settings_table (XdpImplSettings *settings,
GHashTable *table)
{
static const char * const schemas[] = {
"org.gnome.desktop.a11y",
"org.gnome.desktop.a11y.interface",
"org.gnome.desktop.calendar",
"org.gnome.desktop.input-sources",
"org.gnome.desktop.interface",
"org.gnome.desktop.peripherals.mouse",
"org.gnome.desktop.privacy",
"org.gnome.desktop.sound",
"org.gnome.desktop.wm.preferences",
"org.gnome.settings-daemon.plugins.xsettings",
};
size_t i;
GSettingsSchemaSource *source = g_settings_schema_source_get_default ();
for (i = 0; i < G_N_ELEMENTS(schemas); ++i)
{
GSettings *setting;
GSettingsSchema *schema;
SettingsBundle *bundle;
const char *schema_name = schemas[i];
schema = g_settings_schema_source_lookup (source, schema_name, TRUE);
if (!schema)
{
g_debug ("%s schema not found", schema_name);
continue;
}
setting = g_settings_new (schema_name);
bundle = settings_bundle_new (schema, setting);
g_signal_connect_data (setting, "changed", G_CALLBACK(on_settings_changed),
changed_signal_user_data_new (settings, schema_name),
changed_signal_user_data_destroy, 0);
g_hash_table_insert (table, (char*)schema_name, bundle);
}
}
static void
fontconfig_changed (FcMonitor *monitor,
XdpImplSettings *impl)
{
const char *namespace = "org.gnome.fontconfig";
const char *key = "serial";
g_debug ("Emitting changed for %s %s", namespace, key);
fontconfig_serial++;
xdp_impl_settings_emit_setting_changed (impl,
namespace, key,
g_variant_new ("v", g_variant_new_int32 (fontconfig_serial)));
}
static void
set_enable_animations (XdpImplSettings *impl,
gboolean new_enable_animations)
{
const char *namespace = "org.gnome.desktop.interface";
const char *key = "enable-animations";
GVariant *enable_animations_variant;
if (enable_animations == new_enable_animations)
return;
enable_animations = new_enable_animations;
enable_animations_variant =
g_variant_new ("v", g_variant_new_boolean (enable_animations));
xdp_impl_settings_emit_setting_changed (impl,
namespace,
key,
enable_animations_variant);
}
static void
sync_animations_enabled (XdpImplSettings *impl)
{
SettingsBundle *bundle = g_hash_table_lookup (settings, "org.gnome.desktop.interface");
gboolean new_enable_animations;
new_enable_animations = g_settings_get_boolean (bundle->settings, "enable-animations");
set_enable_animations (impl, new_enable_animations);
}
gboolean
settings_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_settings_skeleton_new ());
g_signal_connect (helper, "handle-read", G_CALLBACK (settings_handle_read), NULL);
g_signal_connect (helper, "handle-read-all", G_CALLBACK (settings_handle_read_all), NULL);
settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)settings_bundle_free);
init_settings_table (XDP_IMPL_SETTINGS (helper), settings);
fontconfig_monitor = fc_monitor_new ();
g_signal_connect (fontconfig_monitor, "updated", G_CALLBACK (fontconfig_changed), helper);
fc_monitor_start (fontconfig_monitor);
sync_animations_enabled (XDP_IMPL_SETTINGS (helper));
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean settings_init (GDBusConnection *bus, GError **error);
#include <gtk/gtk.h>
#include "appchooserdialog.h"
static void
close_cb (AppChooserDialog *dialog,
gpointer data)
{
GAppInfo *info;
info = app_chooser_dialog_get_info (dialog);
if (info)
g_print ("%s\n", g_app_info_get_id (info));
else
g_print ("canceled\n");
gtk_main_quit ();
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
const char **apps;
int i;
const char *default_id = NULL;
const char *content_type = NULL;
const char *location = NULL;
GOptionEntry entries[] = {
{ "default", 0, 0, G_OPTION_ARG_STRING, &default_id, "The default choice", "ID" },
{ "content-type", 0, 0, G_OPTION_ARG_STRING, &content_type, "The content type", "TYPE" },
{ "location", 0, 0, G_OPTION_ARG_STRING, &location, "The location (file or uri)", "LOCATION" },
{ NULL, }
};
gtk_init_with_args (&argc, &argv, "APP...", entries, NULL, NULL);
apps = g_new (const char *, argc);
for (i = 0; i + 1 < argc; i++)
apps[i] = argv[i + 1];
apps[argc - 1] = NULL;
window = GTK_WIDGET (app_chooser_dialog_new (apps, default_id, content_type, location));
g_signal_connect (window, "close", G_CALLBACK (close_cb), NULL);
gtk_widget_show (window);
gtk_main ();
return 0;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <gio/gio.h>
#include "utils.h"
static const GDBusErrorEntry xdg_desktop_portal_error_entries[] = {
{ XDG_DESKTOP_PORTAL_ERROR_FAILED, "org.freedesktop.portal.Error.Failed" },
{ XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT, "org.freedesktop.portal.Error.InvalidArgument" },
{ XDG_DESKTOP_PORTAL_ERROR_NOT_FOUND, "org.freedesktop.portal.Error.NotFound" },
{ XDG_DESKTOP_PORTAL_ERROR_EXISTS, "org.freedesktop.portal.Error.Exists" },
{ XDG_DESKTOP_PORTAL_ERROR_NOT_ALLOWED, "org.freedesktop.portal.Error.NotAllowed" },
{ XDG_DESKTOP_PORTAL_ERROR_CANCELLED, "org.freedesktop.portal.Error.Cancelled" },
{ XDG_DESKTOP_PORTAL_ERROR_WINDOW_DESTROYED, "org.freedesktop.portal.Error.WindowDestroyed" }
};
GQuark
xdg_desktop_portal_error_quark (void)
{
static volatile gsize quark_volatile = 0;
g_dbus_error_register_error_domain ("xdg-desktop-portal-error-quark",
&quark_volatile,
xdg_desktop_portal_error_entries,
G_N_ELEMENTS (xdg_desktop_portal_error_entries));
return (GQuark) quark_volatile;
}
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gdk/gdk.h>
#define DESKTOP_PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
typedef enum {
XDG_DESKTOP_PORTAL_ERROR_FAILED = 0,
XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT,
XDG_DESKTOP_PORTAL_ERROR_NOT_FOUND,
XDG_DESKTOP_PORTAL_ERROR_EXISTS,
XDG_DESKTOP_PORTAL_ERROR_NOT_ALLOWED,
XDG_DESKTOP_PORTAL_ERROR_CANCELLED,
XDG_DESKTOP_PORTAL_ERROR_WINDOW_DESTROYED
} XdgDesktopPortalErrorEnum;
#define XDG_DESKTOP_PORTAL_ERROR xdg_desktop_portal_error_quark ()
GQuark xdg_desktop_portal_error_quark (void);
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <glib/gstdio.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gio/gdesktopappinfo.h>
#include <gdesktop-enums.h>
#include "xdg-desktop-portal-dbus.h"
#include "shell-dbus.h"
#include "wallpaper.h"
#include "wallpaperdialog.h"
#include "externalwindow.h"
#include "request.h"
#include "utils.h"
#define BACKGROUND_SCHEMA "org.gnome.desktop.background"
typedef struct {
XdpImplWallpaper *impl;
GDBusMethodInvocation *invocation;
Request *request;
GtkWidget *dialog;
ExternalWindow *external_parent;
guint response;
gchar *picture_uri;
} WallpaperDialogHandle;
static void
wallpaper_dialog_handle_free (gpointer data)
{
WallpaperDialogHandle *handle = data;
g_clear_object (&handle->external_parent);
g_clear_object (&handle->request);
g_clear_pointer (&handle->picture_uri, g_free);
if (handle->dialog != NULL)
gtk_widget_destroy (GTK_WIDGET (handle->dialog));
g_clear_object (&handle->dialog);
g_free (handle);
}
static void
send_response (WallpaperDialogHandle *handle)
{
if (handle->request->exported)
request_unexport (handle->request);
xdp_impl_wallpaper_complete_set_wallpaper_uri (handle->impl,
handle->invocation,
handle->response);
wallpaper_dialog_handle_free (handle);
}
static gboolean
set_gsettings (gchar *schema,
gchar *uri)
{
g_autoptr(GSettings) settings = NULL;
settings = g_settings_new (schema);
return (g_settings_set_string (settings, "picture-uri", uri) &&
g_settings_set_enum (settings, "picture-options", G_DESKTOP_BACKGROUND_STYLE_ZOOM));
}
static void
on_file_copy_cb (GObject *source_object,
GAsyncResult *result,
gpointer data)
{
WallpaperDialogHandle *handle = data;
g_autoptr(GFile) destination = NULL;
GFile *picture_file = G_FILE (source_object);
g_autoptr(GError) error = NULL;
g_autofree gchar *uri = NULL;
gchar *contents = NULL;
gsize length = 0;
handle->response = 2;
uri = g_file_get_uri (picture_file);
if (!g_file_load_contents_finish (picture_file, result, &contents, &length, NULL, &error))
{
g_warning ("Failed to copy '%s': %s", uri, error->message);
goto out;
}
destination = g_file_new_for_uri (handle->picture_uri);
if (!g_file_replace_contents (destination,
contents,
length,
NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
NULL, NULL,
&error))
{
g_warning ("Failed to store image as '%s': %s", handle->picture_uri, error->message);
goto out;
}
if (set_gsettings (BACKGROUND_SCHEMA, handle->picture_uri))
handle->response = 0;
else
handle->response = 1;
out:
send_response (handle);
}
static void
set_wallpaper (WallpaperDialogHandle *handle,
const gchar *uri)
{
g_autoptr(GFile) source = NULL;
g_autoptr(GError) error = NULL;
g_autofree gchar *path = NULL;
path = g_build_filename (g_get_user_config_dir (), "background", NULL);
handle->picture_uri = g_filename_to_uri (path, NULL, &error);
if (error)
{
g_warning ("Failed to construct wallpaper uri: %s", error->message);
return;
}
source = g_file_new_for_uri (uri);
g_file_load_contents_async (source,
NULL,
on_file_copy_cb,
handle);
}
static void
handle_wallpaper_dialog_response (WallpaperDialog *dialog,
gint response,
gpointer data)
{
WallpaperDialogHandle *handle = data;
switch (response)
{
default:
g_warning ("Unexpected response: %d", response);
/* Fall through */
case GTK_RESPONSE_DELETE_EVENT:
handle->response = 2;
break;
case GTK_RESPONSE_CANCEL:
handle->response = 1;
break;
case GTK_RESPONSE_APPLY:
handle->response = 0;
set_wallpaper (handle, wallpaper_dialog_get_uri (dialog));
return;
}
send_response (handle);
}
static gboolean
handle_set_wallpaper_uri (XdpImplWallpaper *object,
GDBusMethodInvocation *invocation,
const char *arg_handle,
const char *arg_app_id,
const char *arg_parent_window,
const char *arg_uri,
GVariant *arg_options)
{
g_autoptr(Request) request = NULL;
WallpaperDialogHandle *handle;
const char *sender;
gboolean show_preview = FALSE;
GdkDisplay *display;
GdkScreen *screen;
ExternalWindow *external_parent = NULL;
GtkWidget *fake_parent;
GtkWidget *dialog;
sender = g_dbus_method_invocation_get_sender (invocation);
request = request_new (sender, arg_app_id, arg_handle);
g_variant_lookup (arg_options, "show-preview", "b", &show_preview);
handle = g_new0 (WallpaperDialogHandle, 1);
handle->impl = object;
handle->invocation = invocation;
handle->request = g_object_ref (request);
if (!show_preview)
{
set_wallpaper (handle, arg_uri);
goto out;
}
if (arg_parent_window)
{
external_parent = create_external_window_from_handle (arg_parent_window);
if (!external_parent)
g_warning ("Failed to associate portal window with parent window %s",
arg_parent_window);
}
if (external_parent)
display = external_window_get_display (external_parent);
else
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
fake_parent = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"screen", screen,
NULL);
g_object_ref_sink (fake_parent);
dialog = (GtkWidget *)wallpaper_dialog_new (arg_uri, arg_app_id);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fake_parent));
handle->dialog = g_object_ref (dialog);
g_signal_connect (dialog, "response",
G_CALLBACK (handle_wallpaper_dialog_response), handle);
gtk_widget_realize (dialog);
if (external_parent)
external_window_set_parent_of (external_parent, gtk_widget_get_window (dialog));
gtk_window_present (GTK_WINDOW (dialog));
out:
request_export (request, g_dbus_method_invocation_get_connection (invocation));
return TRUE;
}
gboolean
wallpaper_init (GDBusConnection *bus,
GError **error)
{
GDBusInterfaceSkeleton *helper;
helper = G_DBUS_INTERFACE_SKELETON (xdp_impl_wallpaper_skeleton_new ());
g_signal_connect (helper, "handle-set-wallpaper-uri", G_CALLBACK (handle_set_wallpaper_uri), NULL);
if (!g_dbus_interface_skeleton_export (helper,
bus,
DESKTOP_PORTAL_OBJECT_PATH,
error))
return FALSE;
g_debug ("providing %s", g_dbus_interface_skeleton_get_info (helper)->name);
return TRUE;
}
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Felipe Borges <feborges@redhat.com>
*/
#pragma once
#include <gio/gio.h>
gboolean wallpaper_init (GDBusConnection *bus, GError **error);
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Felipe Borges <feborges@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gio/gio.h>
#include <glib/gi18n.h>
#include "wallpaperdialog.h"
#include "wallpaperpreview.h"
struct _WallpaperDialog {
GtkWindow parent;
GtkWidget *stack;
WallpaperPreview *desktop_preview;
gchar *picture_uri;
};
struct _WallpaperDialogClass {
GtkWindowClass parent_class;
void (* response) (WallpaperDialog *dialog);
};
enum {
RESPONSE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (WallpaperDialog, wallpaper_dialog, GTK_TYPE_WINDOW)
static void
wallpaper_dialog_apply (WallpaperDialog *self)
{
g_signal_emit (self, signals[RESPONSE], 0, GTK_RESPONSE_APPLY);
}
static void
wallpaper_dialog_cancel (WallpaperDialog *self)
{
g_signal_emit (self, signals[RESPONSE], 0, GTK_RESPONSE_CANCEL);
}
static void
wallpaper_dialog_finalize (GObject *object)
{
WallpaperDialog *self = WALLPAPER_DIALOG (object);
g_clear_pointer (&self->picture_uri, g_free);
G_OBJECT_CLASS (wallpaper_dialog_parent_class)->finalize (object);
}
static void
wallpaper_dialog_init (WallpaperDialog *self)
{
volatile GType type G_GNUC_UNUSED;
/* Register types that the builder needs */
type = wallpaper_preview_get_type ();
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
wallpaper_dialog_class_init (WallpaperDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = wallpaper_dialog_finalize;
signals[RESPONSE] = g_signal_new ("response",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, G_TYPE_INT);
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/portal/desktop/gtk/wallpaperdialog.ui");
gtk_widget_class_bind_template_child (widget_class, WallpaperDialog, stack);
gtk_widget_class_bind_template_child (widget_class, WallpaperDialog, desktop_preview);
gtk_widget_class_bind_template_callback (widget_class, wallpaper_dialog_cancel);
gtk_widget_class_bind_template_callback (widget_class, wallpaper_dialog_apply);
}
static void
on_image_loaded_cb (GObject *source_object,
GAsyncResult *result,
gpointer data)
{
WallpaperDialog *self = data;
GFileIOStream *stream = NULL;
GFile *image_file = G_FILE (source_object);
g_autoptr(GFile) tmp = g_file_new_tmp ("XXXXXX", &stream, NULL);
g_autoptr(GError) error = NULL;
gchar *contents = NULL;
gsize length = 0;
g_object_unref (stream);
if (!g_file_load_contents_finish (image_file, result, &contents, &length, NULL, &error))
{
g_warning ("Failed to load image: %s", error->message);
return;
}
if (!g_file_replace_contents (tmp, contents, length, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, NULL, &error))
{
g_warning ("Failed to store image: %s", error->message);
return;
}
self->picture_uri = g_file_get_uri (tmp);
wallpaper_preview_set_image (self->desktop_preview,
self->picture_uri);
}
WallpaperDialog *
wallpaper_dialog_new (const gchar *picture_uri,
const gchar *app_id)
{
WallpaperDialog *self;
g_autoptr(GFile) image_file = g_file_new_for_uri (picture_uri);
self = g_object_new (wallpaper_dialog_get_type (), NULL);
g_file_load_contents_async (image_file,
NULL,
on_image_loaded_cb,
self);
return self;
}
const gchar *
wallpaper_dialog_get_uri (WallpaperDialog *dialog)
{
return dialog->picture_uri;
}
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Felipe Borges <feborges@redhat.com>
*/
#pragma once
#include <gtk/gtk.h>
#define WALLPAPER_TYPE_DIALOG (wallpaper_dialog_get_type ())
#define WALLPAPER_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST (object, WALLPAPER_TYPE_DIALOG, WallpaperDialog))
typedef struct _WallpaperDialog WallpaperDialog;
typedef struct _WallpaperDialogClass WallpaperDialogClass;
GType wallpaper_dialog_get_type (void) G_GNUC_CONST;
WallpaperDialog * wallpaper_dialog_new (const char *picture_uri,
const char *app_id);
const gchar * wallpaper_dialog_get_uri (WallpaperDialog *dialog);
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="xdg-desktop-portal-gtk">
<!-- interface-requires gtk+ 3.22 -->
<template class="WallpaperDialog" parent="GtkWindow">
<property name="type-hint">dialog</property>
<property name="resizable">True</property>
<property name="default-width">500</property>
<property name="default-height">300</property>
<property name="modal">True</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="title" translatable="yes">Set Background</property>
<property name="show-close-button">False</property>
<child>
<object class="GtkButton" id="button_cancel">
<property name="visible">True</property>
<property name="label" translatable="yes">Cancel</property>
<signal name="clicked" handler="wallpaper_dialog_cancel" object="WallpaperDialog" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="set_wallpaper_button">
<property name="visible">True</property>
<property name="can-default">True</property>
<property name="label" translatable="yes">Set</property>
<signal name="clicked" handler="wallpaper_dialog_apply" object="WallpaperDialog" swapped="yes"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="border-width">20</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="expand">True</property>
<child>
<object class="WallpaperPreview" id="desktop_preview">
<property name="visible">True</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Failed to load image file</property>
</object>
</child>
</object>
<packing>
<property name="name">empty-state</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</template>
<object class="GtkSizeGroup">
<property name="mode">both</property>
<widgets>
<widget name="button_cancel"/>
<widget name="set_wallpaper_button"/>
</widgets>
</object>
</interface>
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Felipe Borges <feborges@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-bg.h>
#include "wallpaperpreview.h"
struct _WallpaperPreview {
GtkBox parent;
GtkStack *stack;
GtkWidget *desktop_preview;
GtkWidget *animated_background_icon;
GtkLabel *desktop_clock_label;
GtkWidget *drawing_area;
GnomeDesktopThumbnailFactory *thumbs;
GnomeBG *bg;
GSettings *desktop_settings;
gboolean is_24h_format;
GDateTime *previous_time;
guint clock_time_timeout_id;
};
struct _WallpaperPreviewClass {
GtkBoxClass parent_class;
};
G_DEFINE_TYPE (WallpaperPreview, wallpaper_preview, GTK_TYPE_BOX)
static gboolean
on_preview_draw_cb (GtkWidget *widget,
cairo_t *cr,
WallpaperPreview *self)
{
g_autoptr(GdkPixbuf) pixbuf = NULL;
GtkAllocation allocation;
gtk_widget_get_allocation (GTK_WIDGET (self), &allocation);
pixbuf = gnome_bg_create_thumbnail (self->bg,
self->thumbs,
gdk_screen_get_default (),
allocation.width,
allocation.height);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
return TRUE;
}
static void
update_clock_label (WallpaperPreview *self,
gboolean force)
{
g_autoptr(GDateTime) now = NULL;
g_autofree gchar *label = NULL;
now = g_date_time_new_now_local ();
if (!force && self->previous_time &&
g_date_time_get_hour (now) == g_date_time_get_hour (self->previous_time) &&
g_date_time_get_minute (now) == g_date_time_get_minute (self->previous_time))
{
return;
}
if (self->is_24h_format)
label = g_date_time_format (now, "%R");
else
label = g_date_time_format (now, "%I:%M %p");
gtk_label_set_label (self->desktop_clock_label, label);
g_clear_pointer (&self->previous_time, g_date_time_unref);
self->previous_time = g_steal_pointer (&now);
}
static void
update_clock_format (WallpaperPreview *self)
{
g_autofree gchar *clock_format = NULL;
gboolean is_24h_format;
clock_format = g_settings_get_string (self->desktop_settings, "clock-format");
is_24h_format = g_strcmp0 (clock_format, "24h") == 0;
if (is_24h_format != self->is_24h_format)
{
self->is_24h_format = is_24h_format;
update_clock_label (self, TRUE);
}
}
static gboolean
update_clock_cb (gpointer data)
{
WallpaperPreview *self = WALLPAPER_PREVIEW (data);
update_clock_label (self, FALSE);
return G_SOURCE_CONTINUE;
}
static void
wallpaper_preview_finalize (GObject *object)
{
WallpaperPreview *self = WALLPAPER_PREVIEW (object);
g_clear_object (&self->desktop_settings);
g_clear_object (&self->thumbs);
g_clear_pointer (&self->previous_time, g_date_time_unref);
if (self->clock_time_timeout_id > 0)
{
g_source_remove (self->clock_time_timeout_id);
self->clock_time_timeout_id = 0;
}
G_OBJECT_CLASS (wallpaper_preview_parent_class)->finalize (object);
}
static void
wallpaper_preview_init (WallpaperPreview *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
g_signal_connect_object (self->desktop_settings,
"changed::clock-format",
G_CALLBACK (update_clock_format),
self,
G_CONNECT_SWAPPED);
update_clock_format (self);
self->clock_time_timeout_id = g_timeout_add_seconds (1, update_clock_cb, self);
self->bg = gnome_bg_new ();
gnome_bg_set_placement (self->bg, G_DESKTOP_BACKGROUND_STYLE_ZOOM);
self->thumbs = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
}
static void
wallpaper_preview_map (GtkWidget *widget)
{
static GtkCssProvider *provider;
GTK_WIDGET_CLASS (wallpaper_preview_parent_class)->map (widget);
if (provider == NULL)
{
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/freedesktop/portal/desktop/gtk/wallpaperpreview.css");
gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (widget),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
}
static void
wallpaper_preview_class_init (WallpaperPreviewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = wallpaper_preview_finalize;
widget_class->map = wallpaper_preview_map;
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/portal/desktop/gtk/wallpaperpreview.ui");
gtk_widget_class_bind_template_child (widget_class, WallpaperPreview, stack);
gtk_widget_class_bind_template_child (widget_class, WallpaperPreview, desktop_preview);
gtk_widget_class_bind_template_child (widget_class, WallpaperPreview, animated_background_icon);
gtk_widget_class_bind_template_child (widget_class, WallpaperPreview, drawing_area);
gtk_widget_class_bind_template_child (widget_class, WallpaperPreview, desktop_clock_label);
gtk_widget_class_bind_template_callback (widget_class, on_preview_draw_cb);
}
WallpaperPreview *
wallpaper_preview_new ()
{
return g_object_new (wallpaper_preview_get_type (), NULL);
}
void
wallpaper_preview_set_image (WallpaperPreview *self,
const gchar *image_uri)
{
g_autofree char *path = NULL;
g_autoptr(GFile) image_file = NULL;
image_file = g_file_new_for_uri (image_uri);
path = g_file_get_path (image_file);
gnome_bg_set_filename (self->bg, path);
gtk_widget_set_visible (self->animated_background_icon,
gnome_bg_changes_with_time (self->bg));
gtk_stack_set_visible_child (GTK_STACK (self->stack), self->desktop_preview);
gtk_widget_queue_draw (self->drawing_area);
}
frame.desktop-preview {
min-height: 10px;
padding: 0 4px;
background-color: black;
}
frame.desktop-preview image {
color: white;
}
frame.desktop-preview label {
color: white;
font-weight: bold;
font-size: 6px;
}
frame.lockscreen-preview {
border: solid rgba(0, 0, 0, 0.33);
border-width: 10px 0 0 0;
}
frame.lockscreen-preview label {
color: white;
font-weight: bold;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
font-size: 1.2em;
}
/*
* Copyright © 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Felipe Borges <feborges@redhat.com>
*/
#pragma once
#include <gtk/gtk.h>
#define WALLPAPER_TYPE_PREVIEW (wallpaper_preview_get_type ())
#define WALLPAPER_PREVIEW(object) (G_TYPE_CHECK_INSTANCE_CAST (object, WALLPAPER_TYPE_PREVIEW, WallpaperPreview))
typedef struct _WallpaperPreview WallpaperPreview;
typedef struct _WallpaperPreviewClass WallpaperPreviewClass;
GType wallpaper_preview_get_type (void) G_GNUC_CONST;
void wallpaper_preview_set_image (WallpaperPreview *self,
const gchar *image_uri);
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="xdg-desktop-portal-gtk">
<!-- interface-requires gtk+ 3.22 -->
<template class="WallpaperPreview" parent="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">False</property>
<property name="width-request">384</property>
<property name="height-request">208</property>
<style>
<class name="frame"/>
</style>
<child>
<object class="GtkOverlay">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkDrawingArea" id="drawing_area">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">True</property>
<signal name="draw" handler="on_preview_draw_cb" object="WallpaperPreview" swapped="no"/>
</object>
</child>
<child type="overlay">
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="expand">True</property>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="active">True</property>
<style>
<class name="background"/>
</style>
</object>
</child>
<child>
<object class="GtkFrame" id="desktop_preview">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="shadow-type">none</property>
<property name="valign">start</property>
<style>
<class name="desktop-preview"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Activities</property>
</object>
</child>
<child type="center">
<object class="GtkLabel" id="desktop_clock_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label">01 Jan 00:00</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="spacing">4</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">network-wireless-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">audio-volume-high-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">battery-low-symbolic</property>
<property name="pixel-size">6</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<!-- Wallpaper -->
<child type="overlay">
<object class="GtkImage" id="animated_background_icon">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="margin-end">8</property>
<property name="margin-bottom">8</property>
<property name="pixel-size">16</property>
<property name="icon-name">slideshow-emblem</property>
<style>
<class name="slideshow-icon" />
</style>
</object>
</child>
</object>
</child>
</template>
</interface>
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Matthias Clasen <mclasen@redhat.com>
*/
#define _GNU_SOURCE 1
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixfdlist.h>
#include <glib/gi18n.h>
#include <locale.h>
#include "xdg-desktop-portal-dbus.h"
#include "request.h"
#include "filechooser.h"
#ifdef BUILD_APPCHOOSER
#include "appchooser.h"
#endif
#include "print.h"
#include "dynamic-launcher.h"
#include "notification.h"
#include "inhibit.h"
#include "access.h"
#include "account.h"
#include "email.h"
#ifdef BUILD_LOCKDOWN
#include "lockdown.h"
#endif
#ifdef BUILD_SETTINGS
#include "settings.h"
#endif
#ifdef BUILD_WALLPAPER
#include "wallpaper.h"
#endif
static GMainLoop *loop = NULL;
static GHashTable *outstanding_handles = NULL;
static gboolean opt_verbose;
static gboolean opt_replace;
static gboolean show_version;
static GOptionEntry entries[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL },
{ "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace a running instance", NULL },
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version, "Show program version.", NULL},
{ NULL }
};
static void
message_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
/* Make this look like normal console output */
if (log_level & G_LOG_LEVEL_DEBUG)
printf ("XDP: %s\n", message);
else
printf ("%s: %s\n", g_get_prgname (), message);
}
static void
printerr_handler (const gchar *string)
{
int is_tty = isatty (1);
const char *prefix = "";
const char *suffix = "";
if (is_tty)
{
prefix = "\x1b[31m\x1b[1m"; /* red, bold */
suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */
}
fprintf (stderr, "%serror: %s%s\n", prefix, suffix, string);
}
static void
on_bus_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GError *error = NULL;
if (!file_chooser_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#ifdef BUILD_APPCHOOSER
if (!app_chooser_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#endif
if (!print_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!notification_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!inhibit_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!access_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!account_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!email_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
if (!dynamic_launcher_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#ifdef BUILD_LOCKDOWN
if (!lockdown_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#endif
#ifdef BUILD_SETTINGS
if (!settings_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#endif
#ifdef BUILD_WALLPAPER
if (!wallpaper_init (connection, &error))
{
g_warning ("error: %s\n", error->message);
g_clear_error (&error);
}
#endif
}
static void
on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_debug ("org.freedesktop.impl.portal.desktop.gtk acquired");
}
static void
on_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_main_loop_quit (loop);
}
int
main (int argc, char *argv[])
{
guint owner_id;
g_autoptr(GError) error = NULL;
GDBusConnection *session_bus;
g_autoptr(GOptionContext) context = NULL;
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* Avoid pointless and confusing recursion */
g_unsetenv ("GTK_USE_PORTAL");
gtk_init (&argc, &argv);
context = g_option_context_new ("- portal backends");
g_option_context_set_summary (context,
"A backend implementation for xdg-desktop-portal.");
g_option_context_set_description (context,
"xdg-desktop-portal-gtk provides D-Bus interfaces that\n"
"are used by xdg-desktop-portal to implement portals\n"
"\n"
"Documentation for the available D-Bus interfaces can be found at\n"
"https://flatpak.github.io/xdg-desktop-portal/docs/\n"
"\n"
"Please report issues at https://github.com/flatpak/xdg-desktop-portal-gtk/issues");
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_printerr ("%s: %s", g_get_application_name (), error->message);
g_printerr ("\n");
g_printerr ("Try \"%s --help\" for more information.",
g_get_prgname ());
g_printerr ("\n");
return 1;
}
if (show_version)
{
g_print (PACKAGE_STRING "\n");
return 0;
}
g_set_printerr_handler (printerr_handler);
if (opt_verbose)
g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, message_handler, NULL);
g_set_prgname ("xdg-desktop-portal-gtk");
loop = g_main_loop_new (NULL, FALSE);
outstanding_handles = g_hash_table_new (g_str_hash, g_str_equal);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (session_bus == NULL)
{
g_printerr ("No session bus: %s\n", error->message);
return 2;
}
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.freedesktop.impl.portal.desktop.gtk",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
g_main_loop_run (loop);
g_bus_unown_name (owner_id);
return 0;
}
<?xml version='1.0' encoding='UTF-8'?>
<gresources>
<gresource prefix='/org/freedesktop/portal/desktop/gtk'>
<file>appchooserdialog.ui</file>
<file>appchooserrow.ui</file>
<file>accountdialog.ui</file>
<file>wallpaperdialog.ui</file>
<file>wallpaperpreview.ui</file>
<file>wallpaperpreview.css</file>
</gresource>
</gresources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment