Adding upstream version 48.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
e818d8977d
commit
f9d3f51ece
244 changed files with 107813 additions and 0 deletions
69
.gitlab-ci.yml
Normal file
69
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
include:
|
||||||
|
- project: "GNOME/citemplates"
|
||||||
|
file: "templates/default-rules.yml"
|
||||||
|
- component: gitlab.gnome.org/GNOME/citemplates/gnomeos-basic-ci@master
|
||||||
|
inputs:
|
||||||
|
job-name: "build-gnomeos"
|
||||||
|
- component: gitlab.gnome.org/GNOME/citemplates/gnomeos-basic-ci@master
|
||||||
|
inputs:
|
||||||
|
job-name: "build-gnomeos-no-x11"
|
||||||
|
meson-options: "-Dx11=false"
|
||||||
|
- component: gitlab.gnome.org/GNOME/citemplates/release-service@master
|
||||||
|
inputs:
|
||||||
|
dist-job-name: "build-gnomeos"
|
||||||
|
tarball-artifact-path: "_builddir/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz"
|
||||||
|
|
||||||
|
.build:
|
||||||
|
stage: "build"
|
||||||
|
variables:
|
||||||
|
_DEST: "$CI_PROJECT_DIR/destdir/"
|
||||||
|
script:
|
||||||
|
- meson setup _build $MESON_OPTIONS
|
||||||
|
- meson compile -C _build
|
||||||
|
- meson test -C _build --print-errorlogs --no-stdsplit --no-rebuild
|
||||||
|
- meson dist -C _build --no-tests
|
||||||
|
|
||||||
|
- mkdir -p $_DEST
|
||||||
|
- meson install -C _build --no-rebuild --destdir="$_DEST"
|
||||||
|
after_script:
|
||||||
|
# Cleanup the destdir and thus container volume once we are done
|
||||||
|
- rm -rvf $_DEST
|
||||||
|
artifacts:
|
||||||
|
expire_in: "2 days"
|
||||||
|
when: "always"
|
||||||
|
paths:
|
||||||
|
- "_build/meson-logs/"
|
||||||
|
reports:
|
||||||
|
junit: "_build/meson-logs/testlog.junit.xml"
|
||||||
|
|
||||||
|
build-fedora:
|
||||||
|
extends: ".build"
|
||||||
|
image: "fedora:40"
|
||||||
|
variables:
|
||||||
|
FEDORA_MESON_OPTIONS: "--prefix=/usr -Ddocbook=false -Dman=false"
|
||||||
|
COMMON_DEPENDENCIES: >-
|
||||||
|
gcc
|
||||||
|
git
|
||||||
|
json-glib-devel
|
||||||
|
meson
|
||||||
|
systemd
|
||||||
|
systemd-devel
|
||||||
|
gtk3-devel
|
||||||
|
gnome-desktop3-devel
|
||||||
|
DEPS_X11: >-
|
||||||
|
$COMMON_DEPENDENCIES
|
||||||
|
libX11-devel
|
||||||
|
libSM-devel
|
||||||
|
libICE-devel
|
||||||
|
xorg-x11-xtrans-devel
|
||||||
|
libglvnd-devel
|
||||||
|
libepoxy-devel
|
||||||
|
libXcomposite-devel
|
||||||
|
before_script:
|
||||||
|
- dnf install -y --setopt=install_weak_deps=false $DEPENDENCIES
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- MESON_OPTIONS: "$FEDORA_MESON_OPTIONS"
|
||||||
|
DEPENDENCIES: "$DEPS_X11"
|
||||||
|
- MESON_OPTIONS: "$FEDORA_MESON_OPTIONS -Dx11=false"
|
||||||
|
DEPENDENCIES: "$COMMON_DEPENDENCIES"
|
22
AUTHORS
Normal file
22
AUTHORS
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
new code base authors
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Dan Winship <danw@gnome.org>
|
||||||
|
Lucas Rocha <lucasr@gnome.org>
|
||||||
|
William Jon McCann <jmccann@redhat.com>
|
||||||
|
|
||||||
|
original gnome-session authors
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Tom Tromey <tromey@cygnus.com>
|
||||||
|
Felix Bellaby <felix@pooh.u-net.com>
|
||||||
|
|
||||||
|
smproxy authors
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Ralph Mor, X Consortium
|
||||||
|
|
||||||
|
with modifications from
|
||||||
|
|
||||||
|
Tom Tromey <tromey@cygnus.com>
|
||||||
|
Felix Bellaby <felix@pooh.u-net.com>
|
339
COPYING
Normal file
339
COPYING
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 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.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
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 give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
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 Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
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 Program, 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 Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) 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; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, 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 executable. However, as a
|
||||||
|
special exception, the source code 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.
|
||||||
|
|
||||||
|
If distribution of executable or 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 counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||||
|
|
||||||
|
5. 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 Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program 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 to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. 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 Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program 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.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the 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 Program
|
||||||
|
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 Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, 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
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), 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 Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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, 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.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
50
ChangeLog
Normal file
50
ChangeLog
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
=== ChangeLog discontinued ===
|
||||||
|
|
||||||
|
With the move to git, this module is switching from a ChangeLog file to
|
||||||
|
relying on commit messages to provide change history. Please write commit
|
||||||
|
messages in the format described at http://live.gnome.org/Git/CommitMessages
|
||||||
|
|
||||||
|
Below is a copy of this format:
|
||||||
|
|
||||||
|
=== begin example commit ===
|
||||||
|
tag: Short explanation of the commit
|
||||||
|
|
||||||
|
Longer explanation explaining exactly what's changed, whether any
|
||||||
|
external or private interfaces changed, what bugs were fixed (with bug
|
||||||
|
tracker reference if applicable) and so forth. Be concise but not too brief.
|
||||||
|
=== end example commit ===
|
||||||
|
|
||||||
|
- The commit message is mainly for the other people, so they should be able
|
||||||
|
to understand it now and six months later.
|
||||||
|
|
||||||
|
- Always add a brief description of the commit to the _first_ line of the
|
||||||
|
commit and terminate by two newlines (it will work without the second
|
||||||
|
newline, but that is not nice for the interfaces).
|
||||||
|
|
||||||
|
- First line (the brief description) must only be one sentence and should
|
||||||
|
start with a capital letter unless it starts with a lowercase symbol or
|
||||||
|
identifier. Don't use a trailing period either. Don't exceed 72 characters.
|
||||||
|
|
||||||
|
- You can prefix the first line with one tag, to make it easier to know to
|
||||||
|
which part of the module the commit applies. For example, a commit with
|
||||||
|
"fish: Make it work with newer fortune" in the gnome-panel module clearly
|
||||||
|
applies to the fish applet.
|
||||||
|
|
||||||
|
- The main description (the body) is normal prose and should use normal
|
||||||
|
punctuation and capital letters where appropriate. Normally, for patches
|
||||||
|
sent to a mailing list, the body is copied from there. This main
|
||||||
|
description can be empty if the change is self-explanatory (eg: "Add DOAP
|
||||||
|
file").
|
||||||
|
|
||||||
|
- When committing code on behalf of others use the --author option, e.g. git
|
||||||
|
commit -a --author "Joe Coder <joe@coder.org>".
|
||||||
|
|
||||||
|
- When referring to a bug, you can use this form: bgo#12345. Use bgo for
|
||||||
|
bugzilla.gnome.org, but you can also reference bugs in other bug trackers:
|
||||||
|
rh means bugzilla.redhat.com, bnc means bugzilla.novell.com, lp means
|
||||||
|
launchpad.net, etc. Whenever possible, use the full URL of the bug, though.
|
||||||
|
|
||||||
|
- When a commit closes a bug, the commit message should contain a line like:
|
||||||
|
Closes: http://bugzilla.gnome.org/show_bug.cgi?id=12345
|
||||||
|
or simply:
|
||||||
|
http://bugzilla.gnome.org/show_bug.cgi?id=12345
|
2587
ChangeLog-20020212
Normal file
2587
ChangeLog-20020212
Normal file
File diff suppressed because it is too large
Load diff
1598
ChangeLog-20080310
Normal file
1598
ChangeLog-20080310
Normal file
File diff suppressed because it is too large
Load diff
4082
ChangeLog.pre-git
Normal file
4082
ChangeLog.pre-git
Normal file
File diff suppressed because it is too large
Load diff
24
MAINTAINERS
Normal file
24
MAINTAINERS
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
Currently active maintainers
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Ray Strode
|
||||||
|
E-mail: rstrode@redhat.com
|
||||||
|
Userid: halfline
|
||||||
|
|
||||||
|
William Jon McCann
|
||||||
|
E-mail: mccann@jhu.edu
|
||||||
|
Userid: mccann
|
||||||
|
|
||||||
|
Non-active maintainers, who have a good understanding of the code
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
#Vincent Untz
|
||||||
|
#E-mail: vuntz@gnome.org
|
||||||
|
#Userid: vuntz
|
||||||
|
|
||||||
|
#Lucas Rocha
|
||||||
|
#E-mail: lucasr@gnome.org
|
||||||
|
#Userid: lucasr
|
||||||
|
|
||||||
|
#Mark McLoughlin
|
||||||
|
#E-mail: mark@skynet.ie
|
175
NEWS
Normal file
175
NEWS
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
============
|
||||||
|
Version 48.0
|
||||||
|
============
|
||||||
|
|
||||||
|
The gnome-session script no longer re-runs itself as a subprocess
|
||||||
|
GNOME OS CI was ported to use a CI template
|
||||||
|
Integrated new CI-based release process
|
||||||
|
Fix bugs caused by systemd v257's inhibitor behavior changes
|
||||||
|
Make `gnome-session --version` print to stdout rather than syslog
|
||||||
|
Translation updates
|
||||||
|
README updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 47.0.1
|
||||||
|
==============
|
||||||
|
Add back gnome-session-ctl (oops)
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 47.0
|
||||||
|
============
|
||||||
|
Allow to disable X11 sessions
|
||||||
|
CI updates
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 46.0
|
||||||
|
============
|
||||||
|
|
||||||
|
README updates
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
=============
|
||||||
|
Version 46.rc
|
||||||
|
=============
|
||||||
|
|
||||||
|
Fix for race a shutdown with loginctl terminate-user
|
||||||
|
Updates for Access portal changes
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 46.alpha
|
||||||
|
================
|
||||||
|
|
||||||
|
Make ctrl-c behave better in gnome-session-inhibit
|
||||||
|
Advertise support for headless session
|
||||||
|
Build goo cleanups
|
||||||
|
Copyright header cleanups
|
||||||
|
README cleanups
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 45.0
|
||||||
|
============
|
||||||
|
|
||||||
|
Two crashers fixes
|
||||||
|
Fix inverted boolean in the "null" system backend
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 44.0
|
||||||
|
============
|
||||||
|
|
||||||
|
No updates
|
||||||
|
|
||||||
|
=============
|
||||||
|
Version 44.rc
|
||||||
|
=============
|
||||||
|
|
||||||
|
Code clean ups
|
||||||
|
Better handling when dbus-daemon dies
|
||||||
|
Improved log output
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 43.0
|
||||||
|
============
|
||||||
|
|
||||||
|
Build system improvements
|
||||||
|
GError clean up fix
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 42.0
|
||||||
|
============
|
||||||
|
|
||||||
|
Give better error when failing to get renderer string
|
||||||
|
Fix failure to run sessions for program accounts
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 40.8
|
||||||
|
============
|
||||||
|
|
||||||
|
data: Install GNOME on Wayland session for X11 preferred setups
|
||||||
|
Don't spew as much into log when falling back to non-systemd sessions
|
||||||
|
Work better with certain versions of meson
|
||||||
|
Correct screwed up check for gnome-shell
|
||||||
|
Various cleanups and leak fixes
|
||||||
|
Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 40.1.1
|
||||||
|
==============
|
||||||
|
|
||||||
|
presence: Fix error detection when syncing initial screensaver state
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 40.1
|
||||||
|
============
|
||||||
|
|
||||||
|
presence: Do not auto-start the GNOME Shell screensaver service
|
||||||
|
util: Unset LC_* variables as they may be unset at login time
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 40.0
|
||||||
|
============
|
||||||
|
|
||||||
|
util: Remove undesired variables from activation environment
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 40.beta
|
||||||
|
===============
|
||||||
|
|
||||||
|
gnome-session: GNOME session will now only block sleep for suspend
|
||||||
|
inhibitors and will block shutdown if a logout inhibitor is
|
||||||
|
active.
|
||||||
|
Previously a suspend inhibitor would prevent both sleep and
|
||||||
|
logout. As such, applications may need to be updated and grab
|
||||||
|
both a logout and suspend inhibitor.
|
||||||
|
data: Re-add OnFailure= to .target units
|
||||||
|
util: Disable capturing of subpatterns
|
||||||
|
util: Only accept common space characters
|
||||||
|
Stop dbus-daemon instead of restarting it
|
||||||
|
data: Fix indirect conflict with exit.target via app.slice
|
||||||
|
Translations updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.38.0
|
||||||
|
==============
|
||||||
|
Build goo updates
|
||||||
|
Translations Updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.37.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
util: Unset GNOME_SETUP_DISPLAY at login time
|
||||||
|
main: clear environment on shutdown
|
||||||
|
gnome-session: avoid setting LC_ unless LANG and region disagree
|
||||||
|
data: Add drop-in to configure launched applications
|
||||||
|
autostart-app: Place launched applications into a systemd scope
|
||||||
|
doc: Add description of important systemd units to man page
|
||||||
|
fail-whale-dialog: Make dialog visible in all monitors
|
||||||
|
gnome-session-inhibit: Add --list command
|
||||||
|
gnome-session-ctl: Add systemd service failure checker
|
||||||
|
data: Major changes in systemd configuration
|
||||||
|
Translation Updates: Brazilian Portuguese, Catalan, Chinese (Taiwan),
|
||||||
|
Czech, Friulian, German, Hebrew, Indonesian, Kazakh, Norwegian Bokmål,
|
||||||
|
Polish, Romanian, Slovak, Spanish, Swedish, Turkish, Ukrainian
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.36.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
data: Require UsbProtection component
|
||||||
|
doap: Call this "GNOME Session Manager"
|
||||||
|
Translation Updates: Indonesian, Punjabi
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.35.3
|
||||||
|
==============
|
||||||
|
|
||||||
|
binary: Allow quitting early on SIGTERM/SIGINT
|
||||||
|
binary: Log a critical when our SIGTERM/SIGINT handler fails to log out
|
||||||
|
Translation updates: Chinese (China), Galician
|
66
README.md
Normal file
66
README.md
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# GNOME Session Manager
|
||||||
|
|
||||||
|
The GNOME session manager is in charge of starting the core components of the
|
||||||
|
GNOME desktop, and applications that should be launched at login time. This
|
||||||
|
module is also a natural place for various configuration files that define
|
||||||
|
important settings that are applied to the GNOME desktop, such as selecting
|
||||||
|
which xdg-desktop-portal backends to use.
|
||||||
|
|
||||||
|
You may download updates to the package from: http://download.gnome.org/sources/gnome-session/
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
To discuss `gnome-session`, you should use the
|
||||||
|
[GNOME support forum](https://discourse.gnome.org/c/platform/).
|
||||||
|
|
||||||
|
`gnome-session` development happens on
|
||||||
|
[GNOME's GitLab](http://gitlab.gnome.org/GNOME/gnome-session).
|
||||||
|
You will need to create an account to contribute.
|
||||||
|
|
||||||
|
Bugs should be reported to the
|
||||||
|
[`gnome-session` issue tracker](https://gitlab.gnome.org/GNOME/gnome-session/-/issues/).
|
||||||
|
Please read the
|
||||||
|
[GNOME Handbook's Guidance](https://handbook.gnome.org/issues/reporting.html)
|
||||||
|
on how to prepare a useful bug report.
|
||||||
|
|
||||||
|
Patches can be contributed by
|
||||||
|
[opening a merge request](https://gitlab.gnome.org/GNOME/gnome-session/-/merge_requests).
|
||||||
|
Please read the
|
||||||
|
[GNOME Handbook's Guidance](https://handbook.gnome.org/development.html)
|
||||||
|
on how to prepare a successful merge request.
|
||||||
|
|
||||||
|
## Building and Installing
|
||||||
|
|
||||||
|
Before you can build `gnome-session`, you need the following dependencies:
|
||||||
|
|
||||||
|
- A C compiler
|
||||||
|
- Meson
|
||||||
|
- Ninja
|
||||||
|
- `json-glib`
|
||||||
|
- `systemd`
|
||||||
|
- `gtk3`
|
||||||
|
- `gnome-desktop3`
|
||||||
|
|
||||||
|
If you're building with X11 support, you'll also need:
|
||||||
|
|
||||||
|
- `libX11`
|
||||||
|
- `libSM`
|
||||||
|
- `libICE`
|
||||||
|
- `xtrans`
|
||||||
|
- `libglvnd`
|
||||||
|
- `libepoxy`
|
||||||
|
- `libXcomposite`
|
||||||
|
|
||||||
|
Once you have all the necessary dependencies, you can use Meson to build
|
||||||
|
`gnome-session`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ meson setup _build
|
||||||
|
$ meson compile -C_build
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally, you can use Meson to install `gnome-session` to your system:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo meson install -C_build
|
||||||
|
```
|
5
data/gnome-custom-session.desktop.in.in
Normal file
5
data/gnome-custom-session.desktop.in.in
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Custom
|
||||||
|
Comment=This entry lets you select a saved session
|
||||||
|
Exec=@bindir@/gnome-session-custom-session
|
||||||
|
TryExec=@bindir@/gnome-session-custom-session
|
2
data/gnome-dummy.session.desktop.in.in
Normal file
2
data/gnome-dummy.session.desktop.in.in
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[GNOME Session]
|
||||||
|
Name=GNOME dummy
|
6
data/gnome-launched-override.scope.conf
Normal file
6
data/gnome-launched-override.scope.conf
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[Unit]
|
||||||
|
CollectMode=inactive-or-failed
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Scope]
|
||||||
|
TimeoutStopSec=5s
|
3
data/gnome-portals.conf
Normal file
3
data/gnome-portals.conf
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[preferred]
|
||||||
|
default=gnome;gtk;
|
||||||
|
org.freedesktop.impl.portal.Secret=gnome-keyring;
|
19
data/gnome-session-failed.service.in
Normal file
19
data/gnome-session-failed.service.in
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session Failed lockdown screen (user)
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
CollectMode=inactive-or-failed
|
||||||
|
|
||||||
|
PartOf=gnome-session-failed.target
|
||||||
|
|
||||||
|
# We could do this, but it requires an intermediate target for OnFailure
|
||||||
|
# handling, so gnome-session-failed checks RUNNING_UNDER_GDM itself
|
||||||
|
#Conflicts=gnome-session@gnome-login.target
|
||||||
|
# or in the case of GDM and then not passing --allow-logout
|
||||||
|
#Requisite=gnome-session@gnome-login.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=@libexecdir@/gnome-session-failed --allow-logout
|
||||||
|
# The fail whale doesn't trigger a shutdown itself, so do it here
|
||||||
|
ExecStopPost=-@libexecdir@/gnome-session-ctl --shutdown
|
12
data/gnome-session-failed.target
Normal file
12
data/gnome-session-failed.target
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session Failed
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
|
||||||
|
# We need an initialized session
|
||||||
|
Requisite=gnome-session-initialized.target
|
||||||
|
BindsTo=gnome-session-initialized.target
|
||||||
|
After=gnome-session-initialized.target
|
||||||
|
|
||||||
|
BindsTo=gnome-session-failed.service
|
||||||
|
After=gnome-session-failed.service
|
19
data/gnome-session-initialized.target
Normal file
19
data/gnome-session-initialized.target
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session is initialized
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
DefaultDependencies=no
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
Requires=gnome-session-pre.target
|
||||||
|
After=gnome-session-pre.target
|
||||||
|
|
||||||
|
Requisite=gnome-session.target
|
||||||
|
PartOf=gnome-session.target
|
||||||
|
Before=gnome-session.target
|
||||||
|
|
||||||
|
# Signal gnome-session that we reached the initialized target and
|
||||||
|
# that it may start applications.
|
||||||
|
Requires=gnome-session-signal-init.service
|
||||||
|
Before=gnome-session-signal-init.service
|
12
data/gnome-session-manager.target
Normal file
12
data/gnome-session-manager.target
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session Manager is ready
|
||||||
|
DefaultDependencies=no
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
Requisite=gnome-session-pre.target
|
||||||
|
After=gnome-session-pre.target
|
||||||
|
|
||||||
|
Requisite=gnome-session-initialized.target
|
||||||
|
PartOf=gnome-session-initialized.target
|
||||||
|
Before=gnome-session-initialized.target
|
19
data/gnome-session-manager@.service.in
Normal file
19
data/gnome-session-manager@.service.in
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session Manager (session: %i)
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
CollectMode=inactive-or-failed
|
||||||
|
|
||||||
|
Requisite=gnome-session-pre.target
|
||||||
|
After=gnome-session-pre.target
|
||||||
|
|
||||||
|
Requires=gnome-session-manager.target
|
||||||
|
PartOf=gnome-session-manager.target
|
||||||
|
Before=gnome-session-manager.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
ExecStart=@libexecdir@/gnome-session-binary --systemd-service --session=%i
|
||||||
|
ExecStopPost=-@libexecdir@/gnome-session-ctl --shutdown
|
15
data/gnome-session-monitor.service.in
Normal file
15
data/gnome-session-monitor.service.in
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Monitor Session leader for GNOME Session
|
||||||
|
CollectMode=inactive-or-failed
|
||||||
|
|
||||||
|
# All services started after gnome-session-pre.target need to be torn down
|
||||||
|
# before the session finish can be signalled back to the display manager.
|
||||||
|
PartOf=gnome-session-pre.target
|
||||||
|
Before=gnome-session-pre.target
|
||||||
|
|
||||||
|
# No After, as we want this to start up immediately
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
ExecStart=@libexecdir@/gnome-session-ctl --monitor
|
||||||
|
TimeoutStopSec=5
|
14
data/gnome-session-pre.target
Normal file
14
data/gnome-session-pre.target
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Tasks to be run before GNOME Session starts
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
DefaultDependencies=no
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
Requires=graphical-session-pre.target
|
||||||
|
After=graphical-session-pre.target
|
||||||
|
|
||||||
|
Requisite=gnome-session-initialized.target
|
||||||
|
PartOf=gnome-session-initialized.target
|
||||||
|
Before=gnome-session-initialized.target
|
11
data/gnome-session-restart-dbus.service.in
Normal file
11
data/gnome-session-restart-dbus.service.in
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Restart DBus after GNOME Session shutdown
|
||||||
|
|
||||||
|
# Allow exit.target to start even if this unit is started with replace-irreversibly.
|
||||||
|
# For this to work, we also need to be in the root slice.
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
ExecStart=@libexecdir@/gnome-session-ctl --restart-dbus
|
||||||
|
Slice=-.slice
|
33
data/gnome-session-shutdown.target
Normal file
33
data/gnome-session-shutdown.target
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Shutdown running GNOME Session
|
||||||
|
|
||||||
|
# Allow exit.target to start even if this unit is started with replace-irreversibly.
|
||||||
|
# All (weak) dependencies need to do the same. Services also need to ensure they
|
||||||
|
# are in the root slice by setting Slice=-.slice.
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
Conflicts=graphical-session.target graphical-session-pre.target
|
||||||
|
After=graphical-session.target graphical-session-pre.target
|
||||||
|
|
||||||
|
# Add explicit conflicts/after lines for gnome-session targets, technically
|
||||||
|
# this should not be needed, but is an extra safety measure.
|
||||||
|
Conflicts=gnome-session.target gnome-session-manager.target
|
||||||
|
After=gnome-session.target gnome-session-manager.target
|
||||||
|
|
||||||
|
Conflicts=gnome-session-pre.target gnome-session-initialized.target gnome-session-failed.target
|
||||||
|
After=gnome-session-pre.target gnome-session-initialized.target gnome-session-failed.target
|
||||||
|
|
||||||
|
# We need to make sure this unit is stopped; primarily so that the tree of
|
||||||
|
# units that we created is completely cleaned.
|
||||||
|
# Note that this can also be improved by reversing the conflicts above and
|
||||||
|
# not listing them in the shutdown unit.
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
# We trigger a restart of DBus after reaching the shutdown target this
|
||||||
|
# is a workaround so that DBus services that do not connect to the
|
||||||
|
# display server are shut down after log-out.
|
||||||
|
# This should be removed when the relevant services add a
|
||||||
|
# PartOf=graphical-session.target
|
||||||
|
# Historic bug: https://bugzilla.gnome.org/show_bug.cgi?id=764029
|
||||||
|
Wants=gnome-session-restart-dbus.service
|
||||||
|
Before=gnome-session-restart-dbus.service
|
8
data/gnome-session-signal-init.service.in
Normal file
8
data/gnome-session-signal-init.service.in
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Signal initialization done to GNOME Session Manager
|
||||||
|
|
||||||
|
PartOf=gnome-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=@libexecdir@/gnome-session-ctl --signal-init
|
13
data/gnome-session-wayland.target
Normal file
13
data/gnome-session-wayland.target
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Wayland Session
|
||||||
|
# On wayland all is lost, do a shutdown
|
||||||
|
OnFailure=gnome-session-shutdown.target
|
||||||
|
OnFailureJobMode=replace-irreversibly
|
||||||
|
# Avoid default After/Before rules
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
Before=gnome-session.target
|
||||||
|
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
20
data/gnome-session-wayland@.target
Normal file
20
data/gnome-session-wayland@.target
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Wayland Session (session: %i)
|
||||||
|
DefaultDependencies=no
|
||||||
|
# Start happens explicitly
|
||||||
|
RefuseManualStart=no
|
||||||
|
# Stop happens by starting gnome-session-shutdown.target
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
Conflicts=shutdown.target gnome-session-shutdown.target
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
# As this is the main entry point, pull in the other toplevel gnome-session targets
|
||||||
|
Requires=gnome-session@.target
|
||||||
|
After=gnome-session@.target
|
||||||
|
|
||||||
|
Requires=gnome-session-wayland.target
|
||||||
|
After=gnome-session-wayland.target
|
||||||
|
|
||||||
|
Requires=gnome-session.target
|
||||||
|
After=gnome-session.target
|
8
data/gnome-session-x11-services-ready.target
Normal file
8
data/gnome-session-x11-services-ready.target
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME session X11 services
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
BindsTo=gnome-session-x11-services.target
|
||||||
|
After=gnome-session-x11-services.target
|
||||||
|
|
||||||
|
Before=gnome-session.target
|
11
data/gnome-session-x11-services.target
Normal file
11
data/gnome-session-x11-services.target
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME session X11 services
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
Requisite=gnome-session-initialized.target
|
||||||
|
After=gnome-session-initialized.target
|
||||||
|
PartOf=gnome-session-initialized.target
|
||||||
|
|
||||||
|
Requisite=gnome-session-x11-services-ready.target
|
||||||
|
Before=gnome-session-x11-services-ready.target
|
||||||
|
PartOf=gnome-session-x11-services-ready.target
|
16
data/gnome-session-x11.target
Normal file
16
data/gnome-session-x11.target
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME X11 Session
|
||||||
|
# On X11, try to show the fail screen
|
||||||
|
OnFailure=gnome-session-failed.target
|
||||||
|
OnFailureJobMode=replace
|
||||||
|
# Avoid default After/Before rules
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
Before=gnome-session.target
|
||||||
|
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
# Pull in all X11-specific services the session might depend on
|
||||||
|
Requires=gnome-session-x11-services.target
|
22
data/gnome-session-x11@.target
Normal file
22
data/gnome-session-x11@.target
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME X11 Session (session: %i)
|
||||||
|
OnFailure=gnome-session-failed.target
|
||||||
|
OnFailureJobMode=replace
|
||||||
|
DefaultDependencies=no
|
||||||
|
# Start happens explicitly
|
||||||
|
RefuseManualStart=no
|
||||||
|
# Stop happens by starting gnome-session-shutdown.target
|
||||||
|
#RefuseManualStop=yes
|
||||||
|
|
||||||
|
Conflicts=shutdown.target gnome-session-shutdown.target
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
# As this is the main entry point, pull in the other toplevel gnome-session targets
|
||||||
|
BindsTo=gnome-session@.target
|
||||||
|
After=gnome-session@.target
|
||||||
|
|
||||||
|
BindsTo=gnome-session-x11.target
|
||||||
|
After=gnome-session-x11.target
|
||||||
|
|
||||||
|
BindsTo=gnome-session.target
|
||||||
|
After=gnome-session.target
|
15
data/gnome-session.target
Normal file
15
data/gnome-session.target
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session
|
||||||
|
OnFailure=gnome-session-failed.target
|
||||||
|
OnFailureJobMode=replace
|
||||||
|
DefaultDependencies=no
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
BindsTo=graphical-session.target
|
||||||
|
Before=graphical-session.target
|
||||||
|
|
||||||
|
# gnome-session-monitor.service will quit with the session leader process
|
||||||
|
# gnome-session.target pulls in graphical-session.target
|
||||||
|
BindsTo=gnome-session-monitor.service
|
||||||
|
After=gnome-session-monitor.service
|
16
data/gnome-session@.target
Normal file
16
data/gnome-session@.target
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[Unit]
|
||||||
|
Description=GNOME Session (session: %i)
|
||||||
|
OnFailure=gnome-session-failed.target
|
||||||
|
OnFailureJobMode=replace
|
||||||
|
DefaultDependencies=no
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
Requires=gnome-session-initialized.target
|
||||||
|
After=gnome-session-initialized.target
|
||||||
|
|
||||||
|
Requisite=gnome-session.target
|
||||||
|
PartOf=gnome-session.target
|
||||||
|
Before=gnome-session.target
|
||||||
|
|
||||||
|
Requires=gnome-session-manager@.service
|
9
data/gnome-wayland.desktop.in.in
Normal file
9
data/gnome-wayland.desktop.in.in
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=GNOME on Wayland
|
||||||
|
Comment=This session logs you into GNOME
|
||||||
|
Exec=@bindir@/gnome-session
|
||||||
|
TryExec=@bindir@/gnome-session
|
||||||
|
Type=Application
|
||||||
|
DesktopNames=GNOME
|
||||||
|
X-GDM-SessionRegisters=true
|
||||||
|
X-GDM-CanRunHeadless=true
|
8
data/gnome-xorg.desktop.in.in
Normal file
8
data/gnome-xorg.desktop.in.in
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=GNOME on Xorg
|
||||||
|
Comment=This session logs you into GNOME
|
||||||
|
Exec=@bindir@/gnome-session
|
||||||
|
TryExec=@bindir@/gnome-session
|
||||||
|
Type=Application
|
||||||
|
DesktopNames=GNOME
|
||||||
|
X-GDM-SessionRegisters=true
|
9
data/gnome.desktop.in.in
Normal file
9
data/gnome.desktop.in.in
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=GNOME
|
||||||
|
Comment=This session logs you into GNOME
|
||||||
|
Exec=@bindir@/gnome-session
|
||||||
|
TryExec=@bindir@/gnome-session
|
||||||
|
Type=Application
|
||||||
|
DesktopNames=GNOME
|
||||||
|
X-GDM-SessionRegisters=true
|
||||||
|
X-GDM-CanRunHeadless=true
|
5
data/gnome.session.conf.in
Normal file
5
data/gnome.session.conf.in
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[Unit]
|
||||||
|
# Must be in sync with gnome.session
|
||||||
|
@wants_required_components@
|
||||||
|
|
||||||
|
Requires=@requires_component@.target
|
4
data/gnome.session.desktop.in.in
Normal file
4
data/gnome.session.desktop.in.in
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[GNOME Session]
|
||||||
|
Name=GNOME
|
||||||
|
# Must be in sync with gnome-session@gnome.target.d/gnome.session.conf drop-in
|
||||||
|
RequiredComponents=@required_components@;
|
32
data/hardware-compatibility
Normal file
32
data/hardware-compatibility
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
##
|
||||||
|
## This file contains a list of blacklist/whitelist regular expressions for
|
||||||
|
## renderer strings.
|
||||||
|
##
|
||||||
|
## The regular expressions are case-insensitive POSIX Extended Regular
|
||||||
|
## Expressions. See regex(7) for details.
|
||||||
|
##
|
||||||
|
## Syntax:
|
||||||
|
## - Comment lines start with '#'
|
||||||
|
## - Lines starting with '+' are whitelisting.
|
||||||
|
## - Lines starting with '-' are blacklisting.
|
||||||
|
## - Lines not starting with '#', '+', '-' are ignored.
|
||||||
|
##
|
||||||
|
|
||||||
|
# Intel 830-865
|
||||||
|
-Intel\(R\) 8[[:digit:]]{2,2}[^[:digit:]]
|
||||||
|
|
||||||
|
# Intel IGD
|
||||||
|
-Intel IGD
|
||||||
|
|
||||||
|
# Pre-R300 radeon
|
||||||
|
-Mesa DRI R[12]00[^[:digit:]]
|
||||||
|
-Mesa DRI R[12]00$
|
||||||
|
|
||||||
|
# Old Mesa software GL renderer
|
||||||
|
-software rasterizer
|
||||||
|
|
||||||
|
# Gallium has softpipe; we explicitly enable llvmpipe
|
||||||
|
-softpipe
|
||||||
|
|
||||||
|
# nouveau vieux NV25 doesn't work too well
|
||||||
|
-Mesa DRI nv25
|
194
data/meson.build
Normal file
194
data/meson.build
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
desktop_plain = 'gnome'
|
||||||
|
|
||||||
|
desktops = [
|
||||||
|
desktop_plain,
|
||||||
|
'gnome-wayland',
|
||||||
|
]
|
||||||
|
if have_x11
|
||||||
|
desktops += ['gnome-xorg']
|
||||||
|
endif
|
||||||
|
|
||||||
|
shell_component = {
|
||||||
|
desktop_plain: 'org.gnome.Shell',
|
||||||
|
}
|
||||||
|
|
||||||
|
required_components = {
|
||||||
|
desktop_plain: [
|
||||||
|
'org.gnome.SettingsDaemon.A11ySettings',
|
||||||
|
'org.gnome.SettingsDaemon.Color',
|
||||||
|
'org.gnome.SettingsDaemon.Datetime',
|
||||||
|
'org.gnome.SettingsDaemon.Housekeeping',
|
||||||
|
'org.gnome.SettingsDaemon.Keyboard',
|
||||||
|
'org.gnome.SettingsDaemon.MediaKeys',
|
||||||
|
'org.gnome.SettingsDaemon.Power',
|
||||||
|
'org.gnome.SettingsDaemon.PrintNotifications',
|
||||||
|
'org.gnome.SettingsDaemon.Rfkill',
|
||||||
|
'org.gnome.SettingsDaemon.ScreensaverProxy',
|
||||||
|
'org.gnome.SettingsDaemon.Sharing',
|
||||||
|
'org.gnome.SettingsDaemon.Smartcard',
|
||||||
|
'org.gnome.SettingsDaemon.Sound',
|
||||||
|
'org.gnome.SettingsDaemon.UsbProtection',
|
||||||
|
'org.gnome.SettingsDaemon.Wacom',
|
||||||
|
'org.gnome.SettingsDaemon.XSettings',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
if enable_session_selector
|
||||||
|
desktops += 'gnome-custom-session'
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach name: desktops
|
||||||
|
desktop_conf = configuration_data()
|
||||||
|
desktop_conf.set('bindir', session_bindir)
|
||||||
|
|
||||||
|
desktop = name + '.desktop'
|
||||||
|
|
||||||
|
desktop_in = configure_file(
|
||||||
|
input: desktop + '.in.in',
|
||||||
|
output: desktop + '.in',
|
||||||
|
configuration: desktop_conf
|
||||||
|
)
|
||||||
|
|
||||||
|
if name.endswith('-xorg') and have_x11
|
||||||
|
install_dir = session_datadir / 'xsessions'
|
||||||
|
elif name.endswith('-wayland')
|
||||||
|
install_dir = session_datadir / 'wayland-sessions'
|
||||||
|
else
|
||||||
|
# FIXME: The same target can not be copied into two directories.
|
||||||
|
# There is a workaround in meson_post_install.py until proper
|
||||||
|
# solution arises:
|
||||||
|
# https://github.com/mesonbuild/meson/issues/2416
|
||||||
|
install_dir = session_datadir / 'xsessions'
|
||||||
|
#install_dir = [
|
||||||
|
# join_paths(session_datadir, 'xsessions'),
|
||||||
|
# join_paths(session_datadir, 'wayland-sessions')
|
||||||
|
#]
|
||||||
|
endif
|
||||||
|
|
||||||
|
desktop_target = i18n.merge_file(
|
||||||
|
type: 'desktop',
|
||||||
|
input: desktop_in,
|
||||||
|
output: desktop,
|
||||||
|
po_dir: po_dir,
|
||||||
|
install: true,
|
||||||
|
install_dir: install_dir
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
sessions = [
|
||||||
|
'gnome',
|
||||||
|
'gnome-dummy'
|
||||||
|
]
|
||||||
|
|
||||||
|
foreach session: sessions
|
||||||
|
session_file = session + '.session'
|
||||||
|
desktop_conf = configuration_data()
|
||||||
|
desktop_conf.set('libexecdir', session_libexecdir)
|
||||||
|
desktop_conf.set('required_components', ';'.join(
|
||||||
|
[shell_component.get(session, '')] + required_components.get(session, [])))
|
||||||
|
|
||||||
|
desktop = session_file + '.desktop'
|
||||||
|
|
||||||
|
desktop_in = configure_file(
|
||||||
|
input: desktop + '.in.in',
|
||||||
|
output: desktop + '.in',
|
||||||
|
configuration: desktop_conf
|
||||||
|
)
|
||||||
|
|
||||||
|
i18n.merge_file(
|
||||||
|
type: 'desktop',
|
||||||
|
input: desktop_in,
|
||||||
|
output: session_file,
|
||||||
|
po_dir: po_dir,
|
||||||
|
install: true,
|
||||||
|
install_dir: join_paths(session_pkgdatadir, 'sessions')
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'org.gnome.SessionManager.gschema.xml',
|
||||||
|
install_dir: join_paths(session_datadir, 'glib-2.0', 'schemas'),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_conf = configuration_data()
|
||||||
|
unit_conf.set('libexecdir', session_libexecdir)
|
||||||
|
|
||||||
|
systemd_service = ['gnome-session-manager@.service',
|
||||||
|
'gnome-session-signal-init.service',
|
||||||
|
'gnome-session-restart-dbus.service',
|
||||||
|
'gnome-session-monitor.service',
|
||||||
|
'gnome-session-failed.service']
|
||||||
|
|
||||||
|
foreach service: systemd_service
|
||||||
|
configure_file(
|
||||||
|
input: service + '.in',
|
||||||
|
output: service,
|
||||||
|
install: true,
|
||||||
|
install_dir: systemd_userunitdir,
|
||||||
|
configuration: unit_conf
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
systemd_target = files('gnome-session-wayland@.target',
|
||||||
|
'gnome-session-wayland.target',
|
||||||
|
'gnome-session@.target',
|
||||||
|
'gnome-session.target',
|
||||||
|
'gnome-session-pre.target',
|
||||||
|
'gnome-session-manager.target',
|
||||||
|
'gnome-session-initialized.target',
|
||||||
|
'gnome-session-shutdown.target',
|
||||||
|
'gnome-session-failed.target',
|
||||||
|
)
|
||||||
|
if have_x11
|
||||||
|
systemd_target += [
|
||||||
|
'gnome-session-x11@.target',
|
||||||
|
'gnome-session-x11.target',
|
||||||
|
'gnome-session-x11-services.target',
|
||||||
|
'gnome-session-x11-services-ready.target',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
systemd_target,
|
||||||
|
install_dir: systemd_userunitdir
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'gnome-launched-override.scope.conf',
|
||||||
|
rename: 'override.conf',
|
||||||
|
install_dir : join_paths(systemd_userunitdir, 'gnome-launched-.scope.d')
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach session, req_components: required_components
|
||||||
|
wanted_targets = []
|
||||||
|
foreach component: req_components
|
||||||
|
wanted_targets += 'Wants=@0@.target'.format(component)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
input: session + '.session.conf.in',
|
||||||
|
output: session + '.session.conf',
|
||||||
|
configuration: {
|
||||||
|
'requires_component': shell_component[session],
|
||||||
|
'wants_required_components': '\n'.join(wanted_targets),
|
||||||
|
},
|
||||||
|
install_dir: systemd_userunitdir / 'gnome-session@@0@.target.d'.format(
|
||||||
|
session),
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
data = files('hardware-compatibility')
|
||||||
|
|
||||||
|
if enable_session_selector
|
||||||
|
data += files('session-selector.ui')
|
||||||
|
endif
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
data,
|
||||||
|
install_dir: session_pkgdatadir
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'gnome-portals.conf',
|
||||||
|
install_dir: session_datadir / 'xdg-desktop-portal',
|
||||||
|
)
|
24
data/org.gnome.SessionManager.gschema.xml
Normal file
24
data/org.gnome.SessionManager.gschema.xml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<schemalist gettext-domain="gnome-session-3.0">
|
||||||
|
<schema id="org.gnome.SessionManager" path="/org/gnome/gnome-session/">
|
||||||
|
<key name="auto-save-session" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Save sessions</summary>
|
||||||
|
<description>If enabled, gnome-session will save the session automatically.</description>
|
||||||
|
</key>
|
||||||
|
<key name="auto-save-session-one-shot" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Save this session</summary>
|
||||||
|
<description>When enabled, gnome-session will automatically save the next session at log out even if auto saving is disabled.</description>
|
||||||
|
</key>
|
||||||
|
<key name="logout-prompt" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<summary>Logout prompt</summary>
|
||||||
|
<description>If enabled, gnome-session will prompt the user before ending a session.</description>
|
||||||
|
</key>
|
||||||
|
<key name="show-fallback-warning" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<summary>Show the fallback warning</summary>
|
||||||
|
<description>If enabled, gnome-session will display a warning dialog after login if the session was automatically fallen back.</description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
195
data/session-selector.ui
Normal file
195
data/session-selector.ui
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="2.16"/>
|
||||||
|
<!-- interface-naming-policy project-wide -->
|
||||||
|
<object class="GtkListStore" id="session-store">
|
||||||
|
<columns>
|
||||||
|
<!-- column-name name -->
|
||||||
|
<column type="gchararray"/>
|
||||||
|
</columns>
|
||||||
|
</object>
|
||||||
|
<object class="GtkTreeModelSort" id="sort-model">
|
||||||
|
<property name="model">session-store</property>
|
||||||
|
</object>
|
||||||
|
<object class="GtkWindow" id="main-window">
|
||||||
|
<property name="title" translatable="yes">Custom Session</property>
|
||||||
|
<property name="window_position">center</property>
|
||||||
|
<property name="default_width">500</property>
|
||||||
|
<property name="default_height">310</property>
|
||||||
|
<property name="decorated">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame" id="frame1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label_xalign">0.5</property>
|
||||||
|
<property name="shadow_type">out</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAlignment" id="alignment3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="border_width">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVBox" id="vbox3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkInfoBar" id="info-bar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="message-type">other</property>
|
||||||
|
|
||||||
|
<child internal-child="content_area">
|
||||||
|
<object class="GtkHBox" id="info-bar-content_area">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">0</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="info-label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0.0</property>
|
||||||
|
<property name="yalign">0.5</property>
|
||||||
|
<property name="label" translatable="yes">Please select a custom session to run</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVBox" id="vbox4">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHBox" id="hbox3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hscrollbar_policy">never</property>
|
||||||
|
<property name="vscrollbar_policy">automatic</property>
|
||||||
|
<property name="shadow_type">in</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTreeView" id="session-list">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="headers_visible">False</property>
|
||||||
|
<property name="search_column">0</property>
|
||||||
|
<property name="model">sort-model</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVButtonBox" id="vbuttonbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="layout_style">start</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="new-session">
|
||||||
|
<property name="label" translatable="yes">_New Session</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="remove-session">
|
||||||
|
<property name="label" translatable="yes">_Remove Session</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="rename-session">
|
||||||
|
<property name="label" translatable="yes">Rena_me Session</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHButtonBox" id="hbuttonbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<property name="layout_style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="continue-button">
|
||||||
|
<property name="label" translatable="yes">_Continue</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="has_default">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
6
doc/dbus/config.xsl
Normal file
6
doc/dbus/config.xsl
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||||
|
version="1.0">
|
||||||
|
<xsl:param name="html.stylesheet" select="'docbook.css'"/>
|
||||||
|
</xsl:stylesheet>
|
32
doc/dbus/dbus-introspect-docs.dtd
Normal file
32
doc/dbus/dbus-introspect-docs.dtd
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!-- DTD for D-Bus Introspection Documentation -->
|
||||||
|
|
||||||
|
<!ELEMENT doc (summary?,description?,errors?,permission?,since?,deprecated,seealso?)>
|
||||||
|
|
||||||
|
<!ELEMENT summary (#PCDATA|ref)*>
|
||||||
|
<!ELEMENT description (#PCDATA|para|example)*>
|
||||||
|
<!ELEMENT errors (error)*>
|
||||||
|
<!ELEMENT permission (#PCDATA|ref|para)*>
|
||||||
|
<!ELEMENT since EMPTY>
|
||||||
|
<!ATTLIST since version CDATA #REQUIRED>
|
||||||
|
<!ELEMENT deprecated (#PCDATA|ref)>
|
||||||
|
<!ATTLIST deprecated version CDATA #REQUIRED>
|
||||||
|
<!ATTLIST deprecated instead CDATA #REQUIRED>
|
||||||
|
<!ELEMENT seealso (ref+)>
|
||||||
|
|
||||||
|
<!ELEMENT error (#PCDATA|para)*>
|
||||||
|
<!ATTLIST error name CDATA #REQUIRED>
|
||||||
|
<!ELEMENT para (#PCDATA|example|code|list|ref)*>
|
||||||
|
<!ELEMENT example (#PCDATA|para|code|ref)*>
|
||||||
|
<!ATTLIST language (c|glib|python|shell) #REQUIRED>
|
||||||
|
<!ATTLIST title CDATA #IMPLIED>
|
||||||
|
<!ELEMENT list (item*)>
|
||||||
|
<!ATTLIST list type (bullet|number) #REQUIRED>
|
||||||
|
<!ELEMENT item (term|definition)*>
|
||||||
|
<!ELEMENT term (#PCDATA|ref)*>
|
||||||
|
<!ELEMENT definition (#PCDATA|para)*>
|
||||||
|
|
||||||
|
<!ELEMENT code (#PCDATA)>
|
||||||
|
<!ATTLIST code lang CDATA #IMPLIED>
|
||||||
|
<!ELEMENT ref CDATA>
|
||||||
|
<!ATTLIST ref type (parameter|arg|signal|method|interface) #REQUIRED>
|
||||||
|
<!ATTLIST ref to CDATA #REQUIRED>
|
78
doc/dbus/docbook.css
Normal file
78
doc/dbus/docbook.css
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
body
|
||||||
|
{
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
h1.title
|
||||||
|
{
|
||||||
|
}
|
||||||
|
.permission
|
||||||
|
{
|
||||||
|
color: #ee0000;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.synopsis, .classsynopsis
|
||||||
|
{
|
||||||
|
background: #eeeeee;
|
||||||
|
border: solid 1px #aaaaaa;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
.programlisting
|
||||||
|
{
|
||||||
|
background: #eeeeff;
|
||||||
|
border: solid 1px #aaaaff;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
.variablelist
|
||||||
|
{
|
||||||
|
padding: 4px;
|
||||||
|
margin-left: 3em;
|
||||||
|
}
|
||||||
|
.variablelist td:first-child
|
||||||
|
{
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
td.shortcuts
|
||||||
|
{
|
||||||
|
color: #770000;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
div.refnamediv
|
||||||
|
{
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
div.toc
|
||||||
|
{
|
||||||
|
border: 2em;
|
||||||
|
}
|
||||||
|
a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #FF0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table
|
||||||
|
{
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #777777;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table td, div.table table th
|
||||||
|
{
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #777777;
|
||||||
|
border-width: 1px;
|
||||||
|
padding: 3px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table th
|
||||||
|
{
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
52
doc/dbus/gnome-session.xml.in
Normal file
52
doc/dbus/gnome-session.xml.in
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
|
||||||
|
<!ENTITY dbus-Manager SYSTEM "org.gnome.SessionManager.ref.xml">
|
||||||
|
<!ENTITY dbus-Client SYSTEM "org.gnome.SessionManager.Client.ref.xml">
|
||||||
|
<!ENTITY dbus-ClientPrivate SYSTEM "org.gnome.SessionManager.ClientPrivate.ref.xml">
|
||||||
|
<!ENTITY dbus-Inhibitor SYSTEM "org.gnome.SessionManager.Inhibitor.ref.xml">
|
||||||
|
<!ENTITY dbus-Presence SYSTEM "org.gnome.SessionManager.Presence.ref.xml">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<book id="index">
|
||||||
|
<bookinfo>
|
||||||
|
<title>GNOME Session @VERSION@ Documentation</title>
|
||||||
|
<releaseinfo>Version @VERSION@</releaseinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>William Jon</firstname>
|
||||||
|
<surname>McCann</surname>
|
||||||
|
<affiliation>
|
||||||
|
<address>
|
||||||
|
<email>jmccann@redhat.com</email>
|
||||||
|
</address>
|
||||||
|
</affiliation>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
<part>
|
||||||
|
<title>Reference</title>
|
||||||
|
|
||||||
|
<reference id="dbus-reference">
|
||||||
|
<title>D-Bus API Reference</title>
|
||||||
|
|
||||||
|
<partintro>
|
||||||
|
<para>
|
||||||
|
This API is not yet stable and is likely to change in the future.
|
||||||
|
</para>
|
||||||
|
</partintro>
|
||||||
|
|
||||||
|
&dbus-Manager;
|
||||||
|
&dbus-Client;
|
||||||
|
&dbus-ClientPrivate;
|
||||||
|
&dbus-Inhibitor;
|
||||||
|
&dbus-Presence;
|
||||||
|
|
||||||
|
</reference>
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<index>
|
||||||
|
<title>Index</title>
|
||||||
|
</index>
|
||||||
|
|
||||||
|
</book>
|
48
doc/dbus/meson.build
Normal file
48
doc/dbus/meson.build
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
xsltproc = find_program('xsltproc')
|
||||||
|
|
||||||
|
ifaces_refs = []
|
||||||
|
|
||||||
|
ifaces = [
|
||||||
|
'org.gnome.SessionManager',
|
||||||
|
'org.gnome.SessionManager.Client',
|
||||||
|
'org.gnome.SessionManager.ClientPrivate',
|
||||||
|
'org.gnome.SessionManager.Inhibitor',
|
||||||
|
'org.gnome.SessionManager.Presence'
|
||||||
|
]
|
||||||
|
|
||||||
|
gnome_session_dir = join_paths(meson.project_source_root(), 'gnome-session')
|
||||||
|
spec_to_docbook = files('spec-to-docbook.xsl')
|
||||||
|
|
||||||
|
foreach iface: ifaces
|
||||||
|
iface_ref = iface + '.ref.xml'
|
||||||
|
|
||||||
|
ifaces_refs += custom_target(
|
||||||
|
iface_ref,
|
||||||
|
input: files(join_paths(gnome_session_dir, iface + '.xml')),
|
||||||
|
output: iface_ref,
|
||||||
|
command: [xsltproc, '--output', '@OUTPUT@', spec_to_docbook, '@INPUT@']
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
session_conf = configuration_data()
|
||||||
|
session_conf.set('VERSION', session_version)
|
||||||
|
|
||||||
|
session = meson.project_name()
|
||||||
|
|
||||||
|
xml_in = configure_file(
|
||||||
|
input: session + '.xml.in',
|
||||||
|
output: session + '.xml',
|
||||||
|
configuration: session_conf
|
||||||
|
)
|
||||||
|
|
||||||
|
config_xsl = files('config.xsl')
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
session,
|
||||||
|
input: xml_in,
|
||||||
|
output: session + '.html',
|
||||||
|
command: [find_program('xmlto'), 'xhtml-nochunks', '-o', meson.current_build_dir(), '-m', config_xsl, '@INPUT@'],
|
||||||
|
depends: ifaces_refs,
|
||||||
|
install: true,
|
||||||
|
install_dir: join_paths(session_datadir, 'doc', meson.project_name(), 'dbus')
|
||||||
|
)
|
555
doc/dbus/spec-to-docbook.xsl
Normal file
555
doc/dbus/spec-to-docbook.xsl
Normal file
|
@ -0,0 +1,555 @@
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
|
||||||
|
exclude-result-prefixes="doc">
|
||||||
|
<!--
|
||||||
|
Convert D-Bus Glib xml into DocBook refentries
|
||||||
|
Copyright (C) 2007-2008 William Jon McCann
|
||||||
|
License: GPL
|
||||||
|
-->
|
||||||
|
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
|
||||||
|
|
||||||
|
<xsl:template match="/">
|
||||||
|
|
||||||
|
<xsl:variable name="interface" select="//interface/@name"/>
|
||||||
|
<xsl:variable name="basename">
|
||||||
|
<xsl:call-template name="interface-basename">
|
||||||
|
<xsl:with-param name="str" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
|
||||||
|
<refentry><xsl:attribute name="id"><xsl:value-of select="$interface"/></xsl:attribute>
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle role="top_of_page"><xsl:value-of select="//interface/@name"/></refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname><xsl:value-of select="$interface"/></refname>
|
||||||
|
<refpurpose><xsl:value-of select="$basename"/> interface</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv role="synopsis">
|
||||||
|
<title role="synopsis.title">Methods</title>
|
||||||
|
<synopsis>
|
||||||
|
<xsl:call-template name="methods-synopsis">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</synopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(///signal) > 0">
|
||||||
|
<refsect1 role="signal_proto">
|
||||||
|
<title role="signal_proto.title">Signals</title>
|
||||||
|
<synopsis>
|
||||||
|
<xsl:call-template name="signals-synopsis">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</synopsis>
|
||||||
|
</refsect1>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<refsect1 role="impl_interfaces">
|
||||||
|
<title role="impl_interfaces.title">Implemented Interfaces</title>
|
||||||
|
<para>
|
||||||
|
Objects implementing <xsl:value-of select="$interface"/> also implements
|
||||||
|
org.freedesktop.DBus.Introspectable,
|
||||||
|
org.freedesktop.DBus.Properties
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(///property) > 0">
|
||||||
|
<refsect1 role="properties">
|
||||||
|
<title role="properties.title">Properties</title>
|
||||||
|
<synopsis>
|
||||||
|
<xsl:call-template name="properties-synopsis">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</synopsis>
|
||||||
|
</refsect1>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<refsect1 role="desc">
|
||||||
|
<title role="desc.title">Description</title>
|
||||||
|
<para>
|
||||||
|
<xsl:apply-templates select="//interface/doc:doc"/>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 role="details">
|
||||||
|
<title role="details.title">Details</title>
|
||||||
|
<xsl:call-template name="method-details">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(///signal) > 0">
|
||||||
|
<refsect1 role="signals">
|
||||||
|
<title role="signals.title">Signal Details</title>
|
||||||
|
<xsl:call-template name="signal-details">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</refsect1>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(///property) > 0">
|
||||||
|
<refsect1 role="property_details">
|
||||||
|
<title role="property_details.title">Property Details</title>
|
||||||
|
<xsl:call-template name="property-details">
|
||||||
|
<xsl:with-param name="interface" select="$interface"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</refsect1>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="property-doc">
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:description"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(arg) > 0">
|
||||||
|
<variablelist role="params">
|
||||||
|
<xsl:for-each select="arg">
|
||||||
|
<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
|
||||||
|
<listitem><simpara><xsl:apply-templates select="doc:doc/doc:summary"/></simpara></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</xsl:for-each>
|
||||||
|
</variablelist>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:since"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:deprecated"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:permission"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:seealso"/>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="property-details">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///property">
|
||||||
|
<refsect2>
|
||||||
|
<title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$interface"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property</title>
|
||||||
|
<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$interface"/></secondary></indexterm>
|
||||||
|
<programlisting>'<xsl:value-of select="@name"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="2"/></xsl:call-template>
|
||||||
|
<xsl:call-template name="property-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/></xsl:call-template></programlisting>
|
||||||
|
|
||||||
|
<xsl:call-template name="property-doc"/>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="signal-doc">
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:description"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(arg) > 0">
|
||||||
|
<variablelist role="params">
|
||||||
|
<xsl:for-each select="arg">
|
||||||
|
<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
|
||||||
|
<listitem><simpara><xsl:apply-templates select="doc:doc/doc:summary"/></simpara></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</xsl:for-each>
|
||||||
|
</variablelist>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:since"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:deprecated"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:permission"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:seealso"/>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="signal-details">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///signal">
|
||||||
|
<refsect2>
|
||||||
|
<title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$interface"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal</title>
|
||||||
|
<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$interface"/></secondary></indexterm>
|
||||||
|
<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
|
||||||
|
|
||||||
|
<xsl:call-template name="signal-doc"/>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:code">
|
||||||
|
<programlisting>
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</programlisting>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:tt">
|
||||||
|
<literal>
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</literal>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:i">
|
||||||
|
<emphasis>
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</emphasis>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:b">
|
||||||
|
<emphasis role="bold">
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</emphasis>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:ulink">
|
||||||
|
<ulink>
|
||||||
|
<xsl:attribute name="url"><xsl:value-of select="@url"/></xsl:attribute>
|
||||||
|
<xsl:value-of select="."/>
|
||||||
|
</ulink>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:summary">
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:example">
|
||||||
|
<informalexample>
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</informalexample>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="listitems-do-term">
|
||||||
|
<xsl:param name="str"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="string-length($str) > 0">
|
||||||
|
<emphasis role="bold"><xsl:value-of select="$str"/>: </emphasis>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="do-listitems">
|
||||||
|
<xsl:for-each select="doc:item">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<xsl:call-template name="listitems-do-term"><xsl:with-param name="str" select="doc:term"/></xsl:call-template>
|
||||||
|
<xsl:apply-templates select="doc:definition"/>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:list">
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="contains(@type,'number')">
|
||||||
|
<orderedlist>
|
||||||
|
<xsl:call-template name="do-listitems"/>
|
||||||
|
</orderedlist>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<itemizedlist>
|
||||||
|
<xsl:call-template name="do-listitems"/>
|
||||||
|
</itemizedlist>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:para">
|
||||||
|
<para>
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:description">
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:since">
|
||||||
|
<para role="since">Since <xsl:value-of select="@version"/>
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:deprecated">
|
||||||
|
<xsl:variable name="name" select="../../@name"/>
|
||||||
|
<xsl:variable name="parent">
|
||||||
|
<xsl:call-template name="interface-basename">
|
||||||
|
<xsl:with-param name="str" select="../../../@name"/>/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
|
||||||
|
<xsl:variable name="type" select="name(../..)"/>
|
||||||
|
|
||||||
|
<para role="deprecated">
|
||||||
|
<warning><para><literal><xsl:value-of select="$name"/></literal> is deprecated since version <xsl:value-of select="@version"/> and should not be used in newly-written code. Use
|
||||||
|
|
||||||
|
<xsl:variable name="to">
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="contains($type,'property')">
|
||||||
|
<xsl:value-of select="$parent"/>:<xsl:value-of select="@instead"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'signal')">
|
||||||
|
<xsl:value-of select="$parent"/>::<xsl:value-of select="@instead"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'method')">
|
||||||
|
<xsl:value-of select="$parent"/>.<xsl:value-of select="@instead"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'interface')">
|
||||||
|
<xsl:value-of select="@instead"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="@instead"/>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:variable>
|
||||||
|
|
||||||
|
<xsl:call-template name="create-link">
|
||||||
|
<xsl:with-param name="type" select="$type"/>
|
||||||
|
<xsl:with-param name="to" select="$to"/>
|
||||||
|
<xsl:with-param name="val" select="@instead"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
instead.</para></warning>
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:permission">
|
||||||
|
<para role="permission">
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:errors">
|
||||||
|
<para role="errors">
|
||||||
|
<xsl:apply-templates />
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:seealso">
|
||||||
|
<para>
|
||||||
|
See also:
|
||||||
|
<xsl:apply-templates />
|
||||||
|
|
||||||
|
</para>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="create-link">
|
||||||
|
<xsl:param name="type"/>
|
||||||
|
<xsl:param name="to"/>
|
||||||
|
<xsl:param name="val"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="contains($type,'property')">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'signal')">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'method')">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><function><xsl:value-of select="$val"/></function></link>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="contains($type,'interface')">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><xsl:value-of select="$val"/></link>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="doc:ref">
|
||||||
|
<xsl:call-template name="create-link">
|
||||||
|
<xsl:with-param name="type" select="@type"/>
|
||||||
|
<xsl:with-param name="to" select="@to"/>
|
||||||
|
<xsl:with-param name="val" select="."/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="method-doc">
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:description"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(arg) > 0">
|
||||||
|
<variablelist role="params">
|
||||||
|
<xsl:for-each select="arg">
|
||||||
|
<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
|
||||||
|
<listitem><simpara><xsl:apply-templates select="doc:doc/doc:summary"/></simpara></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</xsl:for-each>
|
||||||
|
</variablelist>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:since"/>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:deprecated"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(doc:doc/doc:errors) > 0">
|
||||||
|
<refsect3>
|
||||||
|
<title>Errors</title>
|
||||||
|
<variablelist role="errors">
|
||||||
|
<xsl:for-each select="doc:doc/doc:errors/doc:error">
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter><xsl:value-of select="@name"/></parameter>:</term>
|
||||||
|
<listitem><simpara><xsl:apply-templates select="."/></simpara></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</xsl:for-each>
|
||||||
|
</variablelist>
|
||||||
|
</refsect3>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="count(doc:doc/doc:permission) > 0">
|
||||||
|
<refsect3>
|
||||||
|
<title>Permissions</title>
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:permission"/>
|
||||||
|
</refsect3>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<xsl:apply-templates select="doc:doc/doc:seealso"/>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="method-details">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///method">
|
||||||
|
<refsect2>
|
||||||
|
<title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$interface"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> ()</title>
|
||||||
|
<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$interface"/></secondary></indexterm>
|
||||||
|
<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="method-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
|
||||||
|
|
||||||
|
<xsl:call-template name="method-doc"/>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="properties-synopsis">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="///property/@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///property">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$interface"/>:<xsl:value-of select="@name"/></xsl:attribute>'<xsl:value-of select="@name"/>'</link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template> <xsl:call-template name="property-args"><xsl:with-param name="indent" select="$longest + 2"/></xsl:call-template>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="signals-synopsis">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="///signal/@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///signal">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$interface"/>::<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///signal"/></xsl:call-template>)
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="methods-synopsis">
|
||||||
|
<xsl:param name="interface"/>
|
||||||
|
<xsl:variable name="longest">
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="///method/@name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:for-each select="///method">
|
||||||
|
<link><xsl:attribute name="linkend"><xsl:value-of select="$interface"/>.<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="method-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///method"/></xsl:call-template>)
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="method-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg"><xsl:value-of select="@direction"/>
|
||||||
|
<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="4 - string-length(@direction)"/></xsl:call-template>'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
|
||||||
|
<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
|
||||||
|
<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="signal-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg">'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
|
||||||
|
<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
|
||||||
|
<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="property-args"><xsl:param name="indent"/>
|
||||||
|
<xsl:value-of select="@access"/><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="9 - string-length(@access) + 1"/></xsl:call-template>'<xsl:value-of select="@type"/>'
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="pad-spaces">
|
||||||
|
<xsl:param name="width"/>
|
||||||
|
<xsl:variable name="spaces" xml:space="preserve"> </xsl:variable>
|
||||||
|
<xsl:value-of select="substring($spaces,1,$width)"/>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="find-longest">
|
||||||
|
<xsl:param name="set"/>
|
||||||
|
<xsl:param name="index" select="1"/>
|
||||||
|
<xsl:param name="longest" select="0"/>
|
||||||
|
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="$index > count($set)">
|
||||||
|
<!--finished looking-->
|
||||||
|
<xsl:value-of select="$longest"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="string-length($set[$index])>$longest">
|
||||||
|
<!--found new longest-->
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="$set"/>
|
||||||
|
<xsl:with-param name="index" select="$index + 1"/>
|
||||||
|
<xsl:with-param name="longest" select="string-length($set[$index])"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<!--this isn't any longer-->
|
||||||
|
<xsl:call-template name="find-longest">
|
||||||
|
<xsl:with-param name="set" select="$set"/>
|
||||||
|
<xsl:with-param name="index" select="$index + 1"/>
|
||||||
|
<xsl:with-param name="longest" select="$longest"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
<xsl:template name="interface-basename">
|
||||||
|
<xsl:param name="str"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="contains($str,'.')">
|
||||||
|
<xsl:call-template name="interface-basename">
|
||||||
|
<xsl:with-param name="str" select="substring-after($str,'.')"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="$str"/>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
</xsl:stylesheet>
|
106
doc/man/gnome-session-inhibit.xml
Normal file
106
doc/man/gnome-session-inhibit.xml
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<refentry id="gnome-session-inhibit" lang="en">
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>gnome-session-inhibit</title>
|
||||||
|
<productname>gnome-session</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>gnome-session-inhibit</refentrytitle>
|
||||||
|
<manvolnum>1</manvolnum>
|
||||||
|
<refmiscinfo class="manual">User Commands</refmiscinfo>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>gnome-session-inhibit</refname>
|
||||||
|
<refpurpose>inhibit gnome-session functionality</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>gnome-session-inhibit</command>
|
||||||
|
<arg choice="opt" rep="repeat">OPTION</arg>
|
||||||
|
<arg choice="opt">COMMAND</arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1><title>Description</title>
|
||||||
|
<para><command>gnome-session-inhibit</command> can inhibit certain
|
||||||
|
gnome-session functionality while executing the given COMMAND. To
|
||||||
|
achieve this, it calls the Inhibit() method of the gnome-session
|
||||||
|
D-Bus API and creates an inhibitor. The inhibitor is automatically
|
||||||
|
removed when gnome-session-inhibit exits.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A typical use case is to prevent the session from going idle (and
|
||||||
|
thus locking the screen) while a movie player is running.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-h</option>, <option>--help</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
print help and exit
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--version</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
print version information and exit
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--app-id</option> ID</term>
|
||||||
|
<listitem><para>
|
||||||
|
The application id to use when calling the gnome-session Inhibit() method.
|
||||||
|
If this option is not specified, "unknown" is used.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--reason</option> REASON</term>
|
||||||
|
<listitem><para>
|
||||||
|
A human-readable reason to pass along when calling the gnome-session
|
||||||
|
Inhibit() method. If this option is not specified, "not specified" is used.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--inhibit</option> ARG</term>
|
||||||
|
<listitem><para>
|
||||||
|
ARG specifies the things to inhibit, as a colon-separated list. The
|
||||||
|
possible values are logout, switch-user, suspend, idle, automount.
|
||||||
|
If this option is used more than once, the values are combined.
|
||||||
|
If this option is not specified, "idle" is assumed.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--inhibit-only</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
Do not launch COMMAND and wait forever instead
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-l</option>, <option>--list</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
list the existing inhibitions and exit
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>See also</title>
|
||||||
|
<para>
|
||||||
|
<citerefentry><refentrytitle>systemd-inhibit</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
34
doc/man/gnome-session-quit.1
Normal file
34
doc/man/gnome-session-quit.1
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
.\"
|
||||||
|
.\" gnome-session-quit manual page.
|
||||||
|
.\" (C) 2000 Miguel de Icaza (miguel@helixcode.com)
|
||||||
|
.\" (C) 2009-2010 Vincent Untz (vuntz@gnome.org)
|
||||||
|
.\"
|
||||||
|
.TH GNOME-SESSION-QUIT 1 "GNOME"
|
||||||
|
.SH NAME
|
||||||
|
gnome-session-quit \- End the current GNOME session
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B gnome-session-quit [\-\-logout|\-\-power-off|\-\-reboot] [\-\-force] [\-\-no-prompt]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fIgnome-session-quit\fP program can be used to end a GNOME session.
|
||||||
|
.SH OPTIONS
|
||||||
|
The following options are supported:
|
||||||
|
.TP
|
||||||
|
.I "--logout"
|
||||||
|
Prompt the user to confirm logout. This is the default behavior.
|
||||||
|
.TP
|
||||||
|
.I "--power-off"
|
||||||
|
Prompt the user to confirm system power off.
|
||||||
|
.TP
|
||||||
|
.I "--reboot"
|
||||||
|
Prompt the user to confirm system reboot.
|
||||||
|
.TP
|
||||||
|
.I "--force"
|
||||||
|
Ignore any inhibitors.
|
||||||
|
.TP
|
||||||
|
.I "--no-prompt"
|
||||||
|
End the session without user interaction. This only works with \fI--logout\fP.
|
||||||
|
.SH BUGS
|
||||||
|
If you find bugs in the \fIgnome-session-quit\fP program, please report
|
||||||
|
these on https://bugzilla.gnome.org.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR gnome-session(1)
|
52
doc/man/gnome-session-selector.xml
Normal file
52
doc/man/gnome-session-selector.xml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<refentry id="gnome-session-selector" lang="en">
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>gnome-session-selector</title>
|
||||||
|
<productname>gnome-session</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>gnome-session-selector</refentrytitle>
|
||||||
|
<manvolnum>1</manvolnum>
|
||||||
|
<refmiscinfo class="manual">User Commands</refmiscinfo>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>gnome-session-selector</refname>
|
||||||
|
<refpurpose>Selects a session to use with gnome-session</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>gnome-session-selector</command>
|
||||||
|
<arg choice="opt">session</arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1><title>Description</title>
|
||||||
|
<para><command>gnome-session-selector</command> can be used from a
|
||||||
|
xsession desktop file to select a session before gnome-session is run.
|
||||||
|
gnome-session reads and stores its session in the
|
||||||
|
<filename><envar>$XDG_DATA_HOME</envar>/gnome-session/saved-session</filename>
|
||||||
|
directory. <command>gnome-session-selector</command> works by replacing
|
||||||
|
the saved-session directory by a symlink to another directory. Since the
|
||||||
|
session name is used as the directory name, it may not contain '/' characters
|
||||||
|
or begin with a '.'.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When a session name is specified, <command>gnome-session-selector</command>
|
||||||
|
will create a symlink to select this session.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When started without arguments, <command>gnome-session-selector</command>
|
||||||
|
will present a dialog that allows to choose one of the existing sessions
|
||||||
|
or create a new one.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>See also</title>
|
||||||
|
<para>
|
||||||
|
<citerefentry><refentrytitle>gnome-session</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
170
doc/man/gnome-session.1
Normal file
170
doc/man/gnome-session.1
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
.\"
|
||||||
|
.\" gnome-session manual page.
|
||||||
|
.\" (C) 2000 Miguel de Icaza (miguel@helixcode.com)
|
||||||
|
.\" (C) 2009-2010 Vincent Untz (vuntz@gnome.org)
|
||||||
|
.\" (C) 2019 Benjamin Berg (bberg@redhat.com)
|
||||||
|
.\" (C) 2020 Sebastian Geiger (sbastig@gmx.net)
|
||||||
|
.\"
|
||||||
|
.TH GNOME-SESSION 1 "May 2020" "GNOME"
|
||||||
|
.SH NAME
|
||||||
|
gnome-session \- Start the GNOME desktop environment
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B gnome-session [\-a|\-\-autostart=DIR] [\-\-session=SESSION] [\-\-failsafe|\-f] [\-\-debug] [\-\-whale]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fIgnome-session\fP program starts up the GNOME desktop
|
||||||
|
environment. This command is typically executed by your login manager
|
||||||
|
(either gdm, xdm, or from your X startup scripts). It will load
|
||||||
|
either your saved session, or it will provide a default session for the
|
||||||
|
user as defined by the system administrator (or the default GNOME
|
||||||
|
installation on your system). Note that \fIgnome-session\fP is a wrapper
|
||||||
|
script for \fIgnome-session-binary\fP.
|
||||||
|
.PP
|
||||||
|
The default session is defined in \fBgnome.session\fP, a .desktop-like
|
||||||
|
file that is looked for in
|
||||||
|
\fB$XDG_CONFIG_HOME/gnome-session/sessions\fP,
|
||||||
|
\fB$XDG_CONFIG_DIRS/gnome-session/sessions\fP and
|
||||||
|
\fB$XDG_DATA_DIRS/gnome-session/sessions\fP.
|
||||||
|
.PP
|
||||||
|
When saving a session, \fIgnome-session\fP saves the currently running
|
||||||
|
applications in the \fB$XDG_CONFIG_HOME/gnome-session/saved-session\fP
|
||||||
|
directory. Saving sessions is only supported with the legacy non-systemd
|
||||||
|
startup method.
|
||||||
|
.PP
|
||||||
|
\fIgnome-session\fP is an X11R6 session manager. It can manage GNOME
|
||||||
|
applications as well as any X11R6 SM compliant application.
|
||||||
|
.SH OPTIONS
|
||||||
|
The following options are supported:
|
||||||
|
.TP
|
||||||
|
.I "--autostart=DIR"
|
||||||
|
The directory \fBDIR\fP to be searched for autostart .desktop files. This option can be used multiple times.
|
||||||
|
When this option is present, then default autostart directories will not be searched.
|
||||||
|
.TP
|
||||||
|
.I "--session=SESSION"
|
||||||
|
Use the applications defined in \fBSESSION.session\fP. If not specified,
|
||||||
|
\fBgnome.session\fP will be used.
|
||||||
|
.TP
|
||||||
|
.I "--failsafe"
|
||||||
|
Run in fail-safe mode. User-specified applications will not be started.
|
||||||
|
.TP
|
||||||
|
.I "--debug"
|
||||||
|
Enable debugging code.
|
||||||
|
.TP
|
||||||
|
.I "--whale"
|
||||||
|
Show the fail whale in a dialog for debugging it.
|
||||||
|
.SH SESSION DEFINITION
|
||||||
|
Sessions are defined in \fB.session\fP files, that are using a .desktop-like
|
||||||
|
format, with the following keys in the \fBGNOME Session\fP group:
|
||||||
|
.TP
|
||||||
|
.I Name
|
||||||
|
Name of the session. This can be localized.
|
||||||
|
.TP
|
||||||
|
.I RequiredComponents
|
||||||
|
List of component identifiers (desktop files) that are required by the session. The required components will always run in the session.
|
||||||
|
.PP
|
||||||
|
Here is an example of a session definition:
|
||||||
|
.PP
|
||||||
|
.in +4n
|
||||||
|
.nf
|
||||||
|
[GNOME Session]
|
||||||
|
Name=GNOME
|
||||||
|
RequiredComponents=gnome-shell;gnome-settings-daemon;
|
||||||
|
.in
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
In \fBsystemd\fP managed sessions the RequiredComponents may be provided by
|
||||||
|
systemd units instead. In this case the corresponding \fB.desktop\fP file needs
|
||||||
|
to contain \fBX-GNOME-HiddenUnderSystemd=true\fP. \fIgnome-session\fP will
|
||||||
|
ignore these components and rely on \fIsystemd\fP to manage them appropriately,
|
||||||
|
see the \fIsystemd\fP for more information on how this works.
|
||||||
|
.PP
|
||||||
|
The \fB.session\fP files are looked for in
|
||||||
|
\fB$XDG_CONFIG_HOME/gnome-session/sessions\fP,
|
||||||
|
\fB$XDG_CONFIG_DIRS/gnome-session/sessions\fP and
|
||||||
|
\fB$XDG_DATA_DIRS/gnome-session/sessions\fP.
|
||||||
|
.SH systemd
|
||||||
|
\fIgnome-session\fP can pass much of the session management over to systemd.
|
||||||
|
In this case, startup components that have \fBX-GNOME-HiddenUnderSystemd=true\fP
|
||||||
|
set in their \fB.desktop\fP file will be ignored by \fIgnome-session\fP. It
|
||||||
|
instead relies on the fact that these components are managed by systemd.
|
||||||
|
.PP
|
||||||
|
.PP
|
||||||
|
\fBsystemd\fP provides the two special targets \fBgraphical-session.target\fP
|
||||||
|
and \fBgraphical-session-pre.target\fP which are fully functional and should be
|
||||||
|
used. \fIgnome-session\fP provides the following main targets:
|
||||||
|
.TP
|
||||||
|
.I "gnome-session.target"
|
||||||
|
Generic unit that will be active throughout the session. Similar to
|
||||||
|
\fBgraphical-session.target\fP.
|
||||||
|
.TP
|
||||||
|
.I "gnome-session-pre.target"
|
||||||
|
Used for tasks that need to be done before session startup. Similar to
|
||||||
|
\fBgraphical-session-pre.target\fP.
|
||||||
|
.TP
|
||||||
|
.I "gnome-session-x11@SESSION.target" "gnome-session-wayland@SESSION.target"
|
||||||
|
Main unit started for X11/wayland based session. \fBSESSION\fP is set according
|
||||||
|
to the session that is passed in \fI--session\fP.
|
||||||
|
.TP
|
||||||
|
.I "gnome-session-x11.target" "gnome-session-wayland.target"
|
||||||
|
Convenience units without the session embedded into the target.
|
||||||
|
.TP
|
||||||
|
.I "gnome-session@SESSION.target"
|
||||||
|
Convenience unit with just the \fBSESSION\fP information embedded.
|
||||||
|
.TP
|
||||||
|
.I "gnome-session-x11-services.target"
|
||||||
|
Special unit started when X11 services are needed. This will be used from GNOME
|
||||||
|
3.36 onwards. Programs will need to use the special \fBGNOME_SETUP_DISPLAY\fP
|
||||||
|
environment variable instead of \fIDISPLAY\fP.
|
||||||
|
.PP
|
||||||
|
Note that care must be taken to set appropriate \fBAfter=\fP rules. It is also
|
||||||
|
strongly recommended to always do this in combination with \fBBindsTo=\fP or
|
||||||
|
\fBPartOf=\fP on one of the core targets (e.g. \fBgraphical-session.target\fP).
|
||||||
|
.PP
|
||||||
|
Units are required to set \fBCollectMode=inactive-or-failed\fP. In addition, it
|
||||||
|
is strongly recommended to set \fBTimeoutStopSec=5\fP so that logout
|
||||||
|
will not be delayed indefinitely in case the process does not stop properly.
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
\fIgnome-session\fP sets several environment variables for the use of
|
||||||
|
its child processes:
|
||||||
|
.PP
|
||||||
|
.B SESSION_MANAGER
|
||||||
|
.IP
|
||||||
|
This variable is used by session-manager aware clients to contact
|
||||||
|
gnome-session.
|
||||||
|
.PP
|
||||||
|
.B DISPLAY
|
||||||
|
.IP
|
||||||
|
This variable is set to the X display being used by
|
||||||
|
\fIgnome-session\fP. Note that if the \fI--display\fP option is used
|
||||||
|
this might be different from the setting of the environment variable
|
||||||
|
when gnome-session is invoked.
|
||||||
|
.PP
|
||||||
|
Behavior of \fIgnome-session\fP ifself can be modified via the following environment variable:
|
||||||
|
.PP
|
||||||
|
.B GNOME_SESSION_AUTOSTART_DIR
|
||||||
|
.IP
|
||||||
|
This variable specifies a list of directories to the searched for autostart
|
||||||
|
files. This variable overrides all directories specified via the
|
||||||
|
\fI--autostart\fP option, as well as all default autostart directories.
|
||||||
|
.SH FILES
|
||||||
|
.PP
|
||||||
|
.B $XDG_CONFIG_HOME/autostart
|
||||||
|
.B $XDG_CONFIG_DIRS/autostart
|
||||||
|
.B /usr/share/gnome/autostart
|
||||||
|
.IP
|
||||||
|
Applications defined via .desktop files in those directories will be started on login.
|
||||||
|
.PP
|
||||||
|
.B $XDG_CONFIG_HOME/gnome-session/sessions
|
||||||
|
.B $XDG_CONFIG_DIRS/gnome-session/sessions
|
||||||
|
.B $XDG_DATA_DIRS/gnome-session/sessions
|
||||||
|
.IP
|
||||||
|
These directories contain the \fB.session\fP files that can be used
|
||||||
|
with the \fI--session\fP option.
|
||||||
|
.PP
|
||||||
|
.B $XDG_CONFIG_HOME/gnome-session/saved-session
|
||||||
|
.IP
|
||||||
|
This directory contains the list of applications of the saved session.
|
||||||
|
.SH BUGS
|
||||||
|
If you find bugs in the \fIgnome-session\fP program, please report
|
||||||
|
these on https://gitlab.gnome.org/GNOME/gnome-session/issues.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR gnome-session-quit(1)
|
44
doc/man/meson.build
Normal file
44
doc/man/meson.build
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
xsltproc = find_program('xsltproc')
|
||||||
|
man1_dir = join_paths(get_option('mandir'), 'man1')
|
||||||
|
|
||||||
|
xsltproc_cmd = [
|
||||||
|
xsltproc,
|
||||||
|
'--output', '@OUTPUT@',
|
||||||
|
'--nonet',
|
||||||
|
'--stringparam', 'man.output.quietly', '1',
|
||||||
|
'--stringparam', 'funcsynopsis.style', 'ansi',
|
||||||
|
'--stringparam', 'man.th.extra1.suppress', '1',
|
||||||
|
'--stringparam', 'man.authors.section.enabled', '0',
|
||||||
|
'--stringparam', 'man.copyright.section.enabled', '0',
|
||||||
|
'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
|
||||||
|
'@INPUT@'
|
||||||
|
]
|
||||||
|
|
||||||
|
mans = ['gnome-session-inhibit']
|
||||||
|
|
||||||
|
if enable_session_selector
|
||||||
|
mans += 'gnome-session-selector'
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach man: mans
|
||||||
|
output = man + '.1'
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
output,
|
||||||
|
input: man + '.xml',
|
||||||
|
output: output,
|
||||||
|
command: xsltproc_cmd,
|
||||||
|
install: true,
|
||||||
|
install_dir: man1_dir
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
man_data = files(
|
||||||
|
'gnome-session.1',
|
||||||
|
'gnome-session-quit.1'
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
man_data,
|
||||||
|
install_dir: man1_dir
|
||||||
|
)
|
7
doc/meson.build
Normal file
7
doc/meson.build
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
if get_option('docbook')
|
||||||
|
subdir('dbus')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('man')
|
||||||
|
subdir('man')
|
||||||
|
endif
|
64
gnome-session.doap
Normal file
64
gnome-session.doap
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||||
|
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||||
|
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||||
|
xmlns="http://usefulinc.com/ns/doap#">
|
||||||
|
|
||||||
|
<name xml:lang="en">GNOME Session Manager</name>
|
||||||
|
<shortdesc xml:lang="en">The GNOME Session Manager</shortdesc>
|
||||||
|
<description>The GNOME Session Manager is in charge of starting the core
|
||||||
|
components of the GNOME desktop, and applications that should be launched at
|
||||||
|
login time.
|
||||||
|
|
||||||
|
GNOME Session also provides the definition of what a standard GNOME session
|
||||||
|
consists of.</description>
|
||||||
|
<homepage rdf:resource="https://wiki.gnome.org/Projects/SessionManagement" />
|
||||||
|
<developer-forum rdf:resource="https://discourse.gnome.org/c/platform/5" />
|
||||||
|
<download-page rdf:resource="https://download.gnome.org/sources/gnome-session/" />
|
||||||
|
<bug-database rdf:resource="https://gitlab.gnome.org/GNOME/gnome-session/issues" />
|
||||||
|
|
||||||
|
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
||||||
|
<programming-language>C</programming-language>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Adrian Vovk</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:adrianvovk@gmail.com" />
|
||||||
|
<gnome:userid>AdrianVovk</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Ray Strode</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:rstrode@redhat.com" />
|
||||||
|
<gnome:userid>halfline</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>William Jon McCann</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:mccann@jhu.edu" />
|
||||||
|
<!-- <gnome:userid>mccann</gnome:userid> -->
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Colin Walters</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
|
||||||
|
<gnome:userid>walters</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Iain Lane</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:iainl@gnome.org" />
|
||||||
|
<gnome:userid>iainl</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Benjamin Berg</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:bberg@gnome.org" />
|
||||||
|
<gnome:userid>bberg</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
</Project>
|
69
gnome-session/README
Normal file
69
gnome-session/README
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
See also http://live.gnome.org/SessionManagement/NewGnomeSession
|
||||||
|
|
||||||
|
Startup
|
||||||
|
-------
|
||||||
|
|
||||||
|
main() creates the GsmSession object representing the session (either
|
||||||
|
failsafe or normal). gsm_session_new() reads the appropriate autostart
|
||||||
|
and session files to create a list of GsmApps to be started.
|
||||||
|
(GsmAppAutostart represents an autostarted app, and GsmAppResumed
|
||||||
|
represents an app resumed from the previous saved session.)
|
||||||
|
|
||||||
|
Startup is divided into 7 phases (GsmManagerPhase):
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_STARTUP covers gnome-session's internal
|
||||||
|
startup, which also includes starting dbus-daemon (if
|
||||||
|
it's not already running). Gnome-session starts up those
|
||||||
|
explicitly because it needs them for its own purposes.
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_EARLY_INITIALIZATION is the first phase of
|
||||||
|
"normal" startup (ie, startup controlled by .desktop files
|
||||||
|
rather than hardcoding). It covers the possible installation of
|
||||||
|
files in $HOME by gnome-initial-setup and must be done before
|
||||||
|
other components such as gnome-keyring use those files.
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_INITIALIZATION covers low-level stuff like
|
||||||
|
gnome-settings-daemon helpers, that need to be
|
||||||
|
running very early (before any windows are displayed).
|
||||||
|
|
||||||
|
Apps in this phase can make use of a D-Bus interface
|
||||||
|
(org.gnome.SessionManager.Setenv) to set environment variables
|
||||||
|
in gnome-session's environment. This can be used for things like
|
||||||
|
$GTK_MODULES, $GNOME_KEYRING_SOCKET, etc
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_WINDOW_MANAGER includes window managers and
|
||||||
|
compositing managers, and anything else that has to be running
|
||||||
|
before any windows are mapped
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_PANEL includes anything that permanently takes
|
||||||
|
up screen real estate (via EWMH struts). This is the first phase
|
||||||
|
where things actually appear on the screen.
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_DESKTOP includes anything that draws directly
|
||||||
|
on the desktop (eg, nautilus).
|
||||||
|
|
||||||
|
* GSM_MANAGER_PHASE_APPLICATION is everything else (normal apps,
|
||||||
|
tray icons, etc)
|
||||||
|
|
||||||
|
For each startup phase, GsmSession launches the appropriate GsmApps.
|
||||||
|
When apps connect to the XSMP or D-Bus servers, GsmClients are created
|
||||||
|
and added to the session. The session tries to map these clients to
|
||||||
|
GsmApps. GsmApps signal when they register (via XSMP or SN) or exit,
|
||||||
|
and GsmSession uses this to decide when the phase is complete.
|
||||||
|
|
||||||
|
FIXME: after starting the session, we need to run the DiscardCommands
|
||||||
|
of resumed apps.
|
||||||
|
|
||||||
|
|
||||||
|
Running/Shutdown
|
||||||
|
----------------
|
||||||
|
|
||||||
|
GSM_MANAGER_PHASE_RUNNING is pretty similar to the old gnome-session;
|
||||||
|
mostly it just tracks XSMP clients, and watches for
|
||||||
|
SmRestartImmediately clients exiting (NOTE: THIS DOESN'T HAPPEN YET).
|
||||||
|
|
||||||
|
GsmClient is in theory not XSMP-specific, but it's very very
|
||||||
|
XSMP-like, and the shutdown procedure is also very XSMP-like. This is
|
||||||
|
just because there's no way to do XSMP shutdown correctly otherwise.
|
||||||
|
However, GsmClientDBus will still be able to present a more sane
|
||||||
|
protocol to its clients than GsmClient presents to it.
|
205
gnome-session/gdm-log.c
Normal file
205
gnome-session/gdm-log.c
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
static gboolean initialized = FALSE;
|
||||||
|
static int syslog_levels = (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
|
||||||
|
|
||||||
|
static void
|
||||||
|
log_level_to_priority_and_prefix (GLogLevelFlags log_level,
|
||||||
|
int *priorityp,
|
||||||
|
const char **prefixp)
|
||||||
|
{
|
||||||
|
int priority;
|
||||||
|
const char *prefix;
|
||||||
|
|
||||||
|
/* Process the message prefix and priority */
|
||||||
|
switch (log_level & G_LOG_LEVEL_MASK) {
|
||||||
|
case G_LOG_FLAG_FATAL:
|
||||||
|
priority = LOG_EMERG;
|
||||||
|
prefix = "FATAL";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_ERROR:
|
||||||
|
priority = LOG_ERR;
|
||||||
|
prefix = "ERROR";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_CRITICAL:
|
||||||
|
priority = LOG_CRIT;
|
||||||
|
prefix = "CRITICAL";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_WARNING:
|
||||||
|
priority = LOG_WARNING;
|
||||||
|
prefix = "WARNING";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_MESSAGE:
|
||||||
|
priority = LOG_NOTICE;
|
||||||
|
prefix = "MESSAGE";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_INFO:
|
||||||
|
priority = LOG_INFO;
|
||||||
|
prefix = "INFO";
|
||||||
|
break;
|
||||||
|
case G_LOG_LEVEL_DEBUG:
|
||||||
|
/* if debug was requested then bump this up to ERROR
|
||||||
|
* to ensure it is seen in a log */
|
||||||
|
if (syslog_levels & G_LOG_LEVEL_DEBUG) {
|
||||||
|
priority = LOG_WARNING;
|
||||||
|
prefix = "DEBUG(+)";
|
||||||
|
} else {
|
||||||
|
priority = LOG_DEBUG;
|
||||||
|
prefix = "DEBUG";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
priority = LOG_DEBUG;
|
||||||
|
prefix = "UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorityp != NULL) {
|
||||||
|
*priorityp = priority;
|
||||||
|
}
|
||||||
|
if (prefixp != NULL) {
|
||||||
|
*prefixp = prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_default_handler (const gchar *log_domain,
|
||||||
|
GLogLevelFlags log_level,
|
||||||
|
const gchar *message,
|
||||||
|
gpointer unused_data)
|
||||||
|
{
|
||||||
|
GString *gstring;
|
||||||
|
int priority;
|
||||||
|
const char *level_prefix;
|
||||||
|
char *string;
|
||||||
|
gboolean do_log;
|
||||||
|
gboolean is_fatal;
|
||||||
|
|
||||||
|
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
|
||||||
|
|
||||||
|
do_log = (log_level & syslog_levels);
|
||||||
|
if (! do_log) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! initialized) {
|
||||||
|
gdm_log_init ();
|
||||||
|
}
|
||||||
|
|
||||||
|
log_level_to_priority_and_prefix (log_level,
|
||||||
|
&priority,
|
||||||
|
&level_prefix);
|
||||||
|
|
||||||
|
gstring = g_string_new (NULL);
|
||||||
|
|
||||||
|
if (log_domain != NULL) {
|
||||||
|
g_string_append (gstring, log_domain);
|
||||||
|
g_string_append_c (gstring, '-');
|
||||||
|
}
|
||||||
|
g_string_append (gstring, level_prefix);
|
||||||
|
|
||||||
|
g_string_append (gstring, ": ");
|
||||||
|
if (message == NULL) {
|
||||||
|
g_string_append (gstring, "(NULL) message");
|
||||||
|
} else {
|
||||||
|
g_string_append (gstring, message);
|
||||||
|
}
|
||||||
|
if (is_fatal) {
|
||||||
|
g_string_append (gstring, "\naborting...\n");
|
||||||
|
} else {
|
||||||
|
g_string_append (gstring, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string = g_string_free (gstring, FALSE);
|
||||||
|
|
||||||
|
syslog (priority, "%s", string);
|
||||||
|
|
||||||
|
g_free (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_toggle_debug (void)
|
||||||
|
{
|
||||||
|
if (syslog_levels & G_LOG_LEVEL_DEBUG) {
|
||||||
|
g_debug ("Debugging disabled");
|
||||||
|
syslog_levels &= ~G_LOG_LEVEL_DEBUG;
|
||||||
|
} else {
|
||||||
|
syslog_levels |= G_LOG_LEVEL_DEBUG;
|
||||||
|
g_debug ("Debugging enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_set_debug (gboolean debug)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
syslog_levels |= G_LOG_LEVEL_DEBUG;
|
||||||
|
g_debug ("Enabling debugging");
|
||||||
|
} else {
|
||||||
|
g_debug ("Disabling debugging");
|
||||||
|
syslog_levels &= ~G_LOG_LEVEL_DEBUG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_init (void)
|
||||||
|
{
|
||||||
|
const char *prg_name;
|
||||||
|
int options;
|
||||||
|
|
||||||
|
g_log_set_default_handler (gdm_log_default_handler, NULL);
|
||||||
|
|
||||||
|
prg_name = g_get_prgname ();
|
||||||
|
|
||||||
|
options = LOG_PID;
|
||||||
|
#ifdef LOG_PERROR
|
||||||
|
options |= LOG_PERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
openlog (prg_name, options, LOG_DAEMON);
|
||||||
|
|
||||||
|
initialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_shutdown (void)
|
||||||
|
{
|
||||||
|
closelog ();
|
||||||
|
initialized = FALSE;
|
||||||
|
}
|
||||||
|
|
50
gnome-session/gdm-log.h
Normal file
50
gnome-session/gdm-log.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_LOG_H
|
||||||
|
#define __GDM_LOG_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gdm_log_default_handler (const gchar *log_domain,
|
||||||
|
GLogLevelFlags log_level,
|
||||||
|
const gchar *message,
|
||||||
|
gpointer unused_data);
|
||||||
|
void gdm_log_set_debug (gboolean debug);
|
||||||
|
void gdm_log_toggle_debug (void);
|
||||||
|
void gdm_log_init (void);
|
||||||
|
void gdm_log_shutdown (void);
|
||||||
|
|
||||||
|
/* compatibility */
|
||||||
|
#define gdm_fail g_critical
|
||||||
|
#define gdm_error g_warning
|
||||||
|
#define gdm_info g_message
|
||||||
|
#define gdm_debug g_debug
|
||||||
|
|
||||||
|
#define gdm_assert g_assert
|
||||||
|
#define gdm_assert_not_reached g_assert_not_reached
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LOG_H */
|
39
gnome-session/gnome-session.in
Executable file
39
gnome-session/gnome-session.in
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ "x$XDG_SESSION_TYPE" = "xwayland" ] &&
|
||||||
|
[ "x$XDG_SESSION_CLASS" != "xgreeter" ] &&
|
||||||
|
[ -n "$SHELL" ] &&
|
||||||
|
grep -q "$SHELL" /etc/shells &&
|
||||||
|
! (echo "$SHELL" | grep -q "false") &&
|
||||||
|
! (echo "$SHELL" | grep -q "nologin"); then
|
||||||
|
if [ "$1" != '-l' ]; then
|
||||||
|
exec bash -c "exec -l '$SHELL' -c 'exec $0 -l $*'"
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
SETTING=$(G_MESSAGES_DEBUG='' gsettings get org.gnome.system.locale region)
|
||||||
|
REGION=${SETTING#\'}
|
||||||
|
REGION=${REGION%\'}
|
||||||
|
|
||||||
|
if [ -n "$REGION" ]; then
|
||||||
|
unset LC_TIME LC_NUMERIC LC_MONETARY LC_MEASUREMENT LC_PAPER
|
||||||
|
|
||||||
|
if [ "$LANG" != "$REGION" ] ; then
|
||||||
|
# LC_CTYPE
|
||||||
|
export LC_NUMERIC=$REGION
|
||||||
|
export LC_TIME=$REGION
|
||||||
|
# LC_COLLATE
|
||||||
|
export LC_MONETARY=$REGION
|
||||||
|
# LC_MESSAGES
|
||||||
|
export LC_PAPER=$REGION
|
||||||
|
# LC_NAME
|
||||||
|
export LC_ADDRESS=$REGION
|
||||||
|
export LC_TELEPHONE=$REGION
|
||||||
|
export LC_MEASUREMENT=$REGION
|
||||||
|
# LC_IDENTIFICATION
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec @libexecdir@/gnome-session-binary "$@"
|
593
gnome-session/gsm-app.c
Normal file
593
gnome-session/gsm-app.c
Normal file
|
@ -0,0 +1,593 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gsm-app.h"
|
||||||
|
#include "org.gnome.SessionManager.App.h"
|
||||||
|
|
||||||
|
/* If a component crashes twice within a minute, we count that as a fatal error */
|
||||||
|
#define _GSM_APP_RESPAWN_RATELIMIT_SECONDS 60
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
char *app_id;
|
||||||
|
int phase;
|
||||||
|
char *startup_id;
|
||||||
|
gboolean registered;
|
||||||
|
GTimeVal last_restart_time;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GsmExportedApp *skeleton;
|
||||||
|
} GsmAppPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EXITED,
|
||||||
|
DIED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint32 app_serial = 1;
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_ID,
|
||||||
|
PROP_STARTUP_ID,
|
||||||
|
PROP_PHASE,
|
||||||
|
PROP_REGISTERED,
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (GsmApp, gsm_app, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_app_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gsm_app_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_app_get_app_id (GsmExportedApp *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmApp *app)
|
||||||
|
{
|
||||||
|
const gchar *id;
|
||||||
|
|
||||||
|
id = GSM_APP_GET_CLASS (app)->impl_get_app_id (app);
|
||||||
|
gsm_exported_app_complete_get_app_id (skeleton, invocation, id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_app_get_startup_id (GsmExportedApp *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
const gchar *id;
|
||||||
|
|
||||||
|
id = g_strdup (priv->startup_id);
|
||||||
|
gsm_exported_app_complete_get_startup_id (skeleton, invocation, id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_app_get_phase (GsmExportedApp *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
gsm_exported_app_complete_get_phase (skeleton, invocation, priv->phase);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_next_app_serial (void)
|
||||||
|
{
|
||||||
|
guint32 serial;
|
||||||
|
|
||||||
|
serial = app_serial++;
|
||||||
|
|
||||||
|
if ((gint32)app_serial < 0) {
|
||||||
|
app_serial = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_app (GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
GError *error;
|
||||||
|
GsmExportedApp *skeleton;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error getting session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton = gsm_exported_app_skeleton_new ();
|
||||||
|
priv->skeleton = skeleton;
|
||||||
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
|
||||||
|
priv->connection, priv->id,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error registering app on session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (skeleton, "handle-get-app-id",
|
||||||
|
G_CALLBACK (gsm_app_get_app_id), app);
|
||||||
|
g_signal_connect (skeleton, "handle-get-phase",
|
||||||
|
G_CALLBACK (gsm_app_get_phase), app);
|
||||||
|
g_signal_connect (skeleton, "handle-get-startup-id",
|
||||||
|
G_CALLBACK (gsm_app_get_startup_id), app);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gsm_app_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GsmApp *app;
|
||||||
|
GsmAppPrivate *priv;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
app = GSM_APP (G_OBJECT_CLASS (gsm_app_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_free (priv->id);
|
||||||
|
priv->id = g_strdup_printf ("/org/gnome/SessionManager/App%u", get_next_app_serial ());
|
||||||
|
|
||||||
|
res = register_app (app);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to register app with session bus");
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_OBJECT (app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_init (GsmApp *app)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_set_phase (GsmApp *app,
|
||||||
|
int phase)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
priv->phase = phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_set_id (GsmApp *app,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
g_free (priv->id);
|
||||||
|
|
||||||
|
priv->id = g_strdup (id);
|
||||||
|
g_object_notify (G_OBJECT (app), "id");
|
||||||
|
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gsm_app_set_startup_id (GsmApp *app,
|
||||||
|
const char *startup_id)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
g_free (priv->startup_id);
|
||||||
|
|
||||||
|
priv->startup_id = g_strdup (startup_id);
|
||||||
|
g_object_notify (G_OBJECT (app), "startup-id");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmApp *app = GSM_APP (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STARTUP_ID:
|
||||||
|
gsm_app_set_startup_id (app, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_ID:
|
||||||
|
gsm_app_set_id (app, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_PHASE:
|
||||||
|
gsm_app_set_phase (app, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_REGISTERED:
|
||||||
|
gsm_app_set_registered (app, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmApp *app = GSM_APP (object);
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STARTUP_ID:
|
||||||
|
g_value_set_string (value, priv->startup_id);
|
||||||
|
break;
|
||||||
|
case PROP_ID:
|
||||||
|
g_value_set_string (value, priv->id);
|
||||||
|
break;
|
||||||
|
case PROP_PHASE:
|
||||||
|
g_value_set_int (value, priv->phase);
|
||||||
|
break;
|
||||||
|
case PROP_REGISTERED:
|
||||||
|
g_value_set_boolean (value, priv->registered);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GsmApp *app = GSM_APP (object);
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_free (priv->startup_id);
|
||||||
|
priv->startup_id = NULL;
|
||||||
|
|
||||||
|
g_free (priv->id);
|
||||||
|
priv->id = NULL;
|
||||||
|
|
||||||
|
if (priv->skeleton != NULL) {
|
||||||
|
g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (priv->skeleton),
|
||||||
|
priv->connection);
|
||||||
|
g_clear_object (&priv->skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&priv->connection);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_app_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_app_class_init (GsmAppClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->set_property = gsm_app_set_property;
|
||||||
|
object_class->get_property = gsm_app_get_property;
|
||||||
|
object_class->dispose = gsm_app_dispose;
|
||||||
|
object_class->constructor = gsm_app_constructor;
|
||||||
|
|
||||||
|
klass->impl_start = NULL;
|
||||||
|
klass->impl_get_app_id = NULL;
|
||||||
|
klass->impl_get_autorestart = NULL;
|
||||||
|
klass->impl_provides = NULL;
|
||||||
|
klass->impl_get_provides = NULL;
|
||||||
|
klass->impl_is_running = NULL;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_PHASE,
|
||||||
|
g_param_spec_int ("phase",
|
||||||
|
"Phase",
|
||||||
|
"Phase",
|
||||||
|
-1,
|
||||||
|
G_MAXINT,
|
||||||
|
-1,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_ID,
|
||||||
|
g_param_spec_string ("id",
|
||||||
|
"ID",
|
||||||
|
"ID",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_STARTUP_ID,
|
||||||
|
g_param_spec_string ("startup-id",
|
||||||
|
"startup ID",
|
||||||
|
"Session management startup ID",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_REGISTERED,
|
||||||
|
g_param_spec_boolean ("registered",
|
||||||
|
"Registered",
|
||||||
|
"Registered",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
signals[EXITED] =
|
||||||
|
g_signal_new ("exited",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmAppClass, exited),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_UCHAR);
|
||||||
|
signals[DIED] =
|
||||||
|
g_signal_new ("died",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmAppClass, died),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_app_peek_id (GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
return priv->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_app_peek_app_id (GsmApp *app)
|
||||||
|
{
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_get_app_id (app);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_app_peek_startup_id (GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
return priv->startup_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_app_peek_phase:
|
||||||
|
* @app: a %GsmApp
|
||||||
|
*
|
||||||
|
* Returns @app's startup phase.
|
||||||
|
*
|
||||||
|
* Return value: @app's startup phase
|
||||||
|
**/
|
||||||
|
GsmManagerPhase
|
||||||
|
gsm_app_peek_phase (GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), GSM_MANAGER_PHASE_APPLICATION);
|
||||||
|
|
||||||
|
return priv->phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_peek_is_disabled (GsmApp *app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_is_disabled) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_is_disabled (app);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_peek_is_conditionally_disabled (GsmApp *app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_is_conditionally_disabled) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_is_conditionally_disabled (app);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_is_running (GsmApp *app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_is_running) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_is_running (app);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_peek_autorestart (GsmApp *app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_get_autorestart) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_get_autorestart (app);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_provides (GsmApp *app, const char *service)
|
||||||
|
{
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_provides) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_provides (app, service);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char **
|
||||||
|
gsm_app_get_provides (GsmApp *app)
|
||||||
|
{
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_get_provides) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_get_provides (app);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_has_autostart_condition (GsmApp *app,
|
||||||
|
const char *condition)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (GSM_APP_GET_CLASS (app)->impl_has_autostart_condition) {
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_has_autostart_condition (app, condition);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_start (GsmApp *app,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_debug ("Starting app: %s", priv->id);
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_start (app, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_restart (GsmApp *app,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
GTimeVal current_time;
|
||||||
|
g_debug ("Re-starting app: %s", priv->id);
|
||||||
|
|
||||||
|
g_get_current_time (¤t_time);
|
||||||
|
if (priv->last_restart_time.tv_sec > 0
|
||||||
|
&& (current_time.tv_sec - priv->last_restart_time.tv_sec) < _GSM_APP_RESPAWN_RATELIMIT_SECONDS) {
|
||||||
|
g_warning ("App '%s' respawning too quickly", gsm_app_peek_app_id (app));
|
||||||
|
g_set_error (error,
|
||||||
|
GSM_APP_ERROR,
|
||||||
|
GSM_APP_ERROR_RESTART_LIMIT,
|
||||||
|
"Component '%s' crashing too quickly",
|
||||||
|
gsm_app_peek_app_id (app));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
priv->last_restart_time = current_time;
|
||||||
|
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_restart (app, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_stop (GsmApp *app,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_stop (app, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_app_exited (GsmApp *app,
|
||||||
|
guchar exit_code)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
g_signal_emit (app, signals[EXITED], 0, exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_app_died (GsmApp *app,
|
||||||
|
int signal)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
g_signal_emit (app, signals[DIED], 0, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_get_registered (GsmApp *app)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
return priv->registered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_app_set_registered (GsmApp *app,
|
||||||
|
gboolean registered)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_APP (app));
|
||||||
|
|
||||||
|
if (priv->registered != registered) {
|
||||||
|
priv->registered = registered;
|
||||||
|
g_object_notify (G_OBJECT (app), "registered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_app_save_to_keyfile (GsmApp *app,
|
||||||
|
GKeyFile *keyfile,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmAppPrivate *priv = gsm_app_get_instance_private (app);
|
||||||
|
|
||||||
|
g_debug ("Saving app: %s", priv->id);
|
||||||
|
return GSM_APP_GET_CLASS (app)->impl_save_to_keyfile (app, keyfile, error);
|
||||||
|
}
|
119
gnome-session/gsm-app.h
Normal file
119
gnome-session/gsm-app.h
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_APP_H__
|
||||||
|
#define __GSM_APP_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "gsm-manager.h"
|
||||||
|
#include "gsm-client.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_APP (gsm_app_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GsmApp, gsm_app, GSM, APP, GObject)
|
||||||
|
|
||||||
|
struct _GsmAppClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (*exited) (GsmApp *app,
|
||||||
|
guchar exit_code);
|
||||||
|
void (*died) (GsmApp *app,
|
||||||
|
int signal);
|
||||||
|
|
||||||
|
/* virtual methods */
|
||||||
|
gboolean (*impl_start) (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_restart) (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_stop) (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_provides) (GsmApp *app,
|
||||||
|
const char *service);
|
||||||
|
char ** (*impl_get_provides) (GsmApp *app);
|
||||||
|
gboolean (*impl_has_autostart_condition) (GsmApp *app,
|
||||||
|
const char *service);
|
||||||
|
gboolean (*impl_is_running) (GsmApp *app);
|
||||||
|
|
||||||
|
gboolean (*impl_get_autorestart) (GsmApp *app);
|
||||||
|
const char *(*impl_get_app_id) (GsmApp *app);
|
||||||
|
gboolean (*impl_is_disabled) (GsmApp *app);
|
||||||
|
gboolean (*impl_is_conditionally_disabled) (GsmApp *app);
|
||||||
|
|
||||||
|
gboolean (*impl_save_to_keyfile) (GsmApp *app,
|
||||||
|
GKeyFile *keyfile,
|
||||||
|
GError **error);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_APP_ERROR_GENERAL = 0,
|
||||||
|
GSM_APP_ERROR_RESTART_LIMIT,
|
||||||
|
GSM_APP_ERROR_START,
|
||||||
|
GSM_APP_ERROR_STOP,
|
||||||
|
GSM_APP_NUM_ERRORS
|
||||||
|
} GsmAppError;
|
||||||
|
|
||||||
|
#define GSM_APP_ERROR gsm_app_error_quark ()
|
||||||
|
|
||||||
|
GQuark gsm_app_error_quark (void);
|
||||||
|
|
||||||
|
gboolean gsm_app_peek_autorestart (GsmApp *app);
|
||||||
|
|
||||||
|
const char *gsm_app_peek_id (GsmApp *app);
|
||||||
|
const char *gsm_app_peek_app_id (GsmApp *app);
|
||||||
|
const char *gsm_app_peek_startup_id (GsmApp *app);
|
||||||
|
GsmManagerPhase gsm_app_peek_phase (GsmApp *app);
|
||||||
|
gboolean gsm_app_peek_is_disabled (GsmApp *app);
|
||||||
|
gboolean gsm_app_peek_is_conditionally_disabled (GsmApp *app);
|
||||||
|
|
||||||
|
gboolean gsm_app_start (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_app_restart (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_app_stop (GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_app_is_running (GsmApp *app);
|
||||||
|
|
||||||
|
void gsm_app_exited (GsmApp *app,
|
||||||
|
guchar exit_code);
|
||||||
|
void gsm_app_died (GsmApp *app,
|
||||||
|
int signal);
|
||||||
|
|
||||||
|
gboolean gsm_app_provides (GsmApp *app,
|
||||||
|
const char *service);
|
||||||
|
char **gsm_app_get_provides (GsmApp *app);
|
||||||
|
gboolean gsm_app_has_autostart_condition (GsmApp *app,
|
||||||
|
const char *condition);
|
||||||
|
gboolean gsm_app_get_registered (GsmApp *app);
|
||||||
|
void gsm_app_set_registered (GsmApp *app,
|
||||||
|
gboolean registered);
|
||||||
|
|
||||||
|
gboolean gsm_app_save_to_keyfile (GsmApp *app,
|
||||||
|
GKeyFile *keyfile,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_APP_H__ */
|
1505
gnome-session/gsm-autostart-app.c
Normal file
1505
gnome-session/gsm-autostart-app.c
Normal file
File diff suppressed because it is too large
Load diff
59
gnome-session/gsm-autostart-app.h
Normal file
59
gnome-session/gsm-autostart-app.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_AUTOSTART_APP_H__
|
||||||
|
#define __GSM_AUTOSTART_APP_H__
|
||||||
|
|
||||||
|
#include "gsm-app.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_AUTOSTART_APP (gsm_autostart_app_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GsmAutostartApp, gsm_autostart_app, GSM, AUTOSTART_APP, GsmApp)
|
||||||
|
|
||||||
|
struct _GsmAutostartAppClass
|
||||||
|
{
|
||||||
|
GsmAppClass parent_class;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (*condition_changed) (GsmApp *app,
|
||||||
|
gboolean condition);
|
||||||
|
};
|
||||||
|
|
||||||
|
GsmApp *gsm_autostart_app_new (const char *desktop_file,
|
||||||
|
gboolean mask_systemd,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsm_autostart_app_add_provides (GsmAutostartApp *aapp,
|
||||||
|
const char *provides);
|
||||||
|
|
||||||
|
#define GSM_AUTOSTART_APP_SYSTEMD_KEY "X-GNOME-HiddenUnderSystemd"
|
||||||
|
#define GSM_AUTOSTART_APP_ENABLED_KEY "X-GNOME-Autostart-enabled"
|
||||||
|
#define GSM_AUTOSTART_APP_PHASE_KEY "X-GNOME-Autostart-Phase"
|
||||||
|
#define GSM_AUTOSTART_APP_PROVIDES_KEY "X-GNOME-Provides"
|
||||||
|
#define GSM_AUTOSTART_APP_STARTUP_ID_KEY "X-GNOME-Autostart-startup-id"
|
||||||
|
#define GSM_AUTOSTART_APP_AUTORESTART_KEY "X-GNOME-AutoRestart"
|
||||||
|
#define GSM_AUTOSTART_APP_DBUS_NAME_KEY "X-GNOME-DBus-Name"
|
||||||
|
#define GSM_AUTOSTART_APP_DBUS_PATH_KEY "X-GNOME-DBus-Path"
|
||||||
|
#define GSM_AUTOSTART_APP_DBUS_ARGS_KEY "X-GNOME-DBus-Start-Arguments"
|
||||||
|
#define GSM_AUTOSTART_APP_DISCARD_KEY "X-GNOME-Autostart-discard-exec"
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_AUTOSTART_APP_H__ */
|
583
gnome-session/gsm-client.c
Normal file
583
gnome-session/gsm-client.c
Normal file
|
@ -0,0 +1,583 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsm-client.h"
|
||||||
|
#include "org.gnome.SessionManager.Client.h"
|
||||||
|
|
||||||
|
static guint32 client_serial = 1;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
char *startup_id;
|
||||||
|
char *app_id;
|
||||||
|
guint status;
|
||||||
|
GsmExportedClient *skeleton;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
} GsmClientPrivate;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PROP_STARTUP_ID = 1,
|
||||||
|
PROP_APP_ID,
|
||||||
|
PROP_STATUS,
|
||||||
|
} GsmClientProperty;
|
||||||
|
|
||||||
|
static GParamSpec *props[PROP_STATUS + 1] = { NULL, };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DISCONNECTED,
|
||||||
|
END_SESSION_RESPONSE,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GsmClient, gsm_client, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define GSM_CLIENT_DBUS_IFACE "org.gnome.SessionManager.Client"
|
||||||
|
|
||||||
|
static const GDBusErrorEntry gsm_client_error_entries[] = {
|
||||||
|
{ GSM_CLIENT_ERROR_GENERAL, GSM_CLIENT_DBUS_IFACE ".GeneralError" },
|
||||||
|
{ GSM_CLIENT_ERROR_NOT_REGISTERED, GSM_CLIENT_DBUS_IFACE ".NotRegistered" }
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_client_error_quark (void)
|
||||||
|
{
|
||||||
|
static volatile gsize quark_volatile = 0;
|
||||||
|
|
||||||
|
g_dbus_error_register_error_domain ("gsm_client_error",
|
||||||
|
&quark_volatile,
|
||||||
|
gsm_client_error_entries,
|
||||||
|
G_N_ELEMENTS (gsm_client_error_entries));
|
||||||
|
return quark_volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_next_client_serial (void)
|
||||||
|
{
|
||||||
|
guint32 serial;
|
||||||
|
|
||||||
|
serial = client_serial++;
|
||||||
|
|
||||||
|
if ((gint32)client_serial < 0) {
|
||||||
|
client_serial = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_get_startup_id (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
gsm_exported_client_complete_get_startup_id (skeleton, invocation, priv->startup_id);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_get_app_id (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
gsm_exported_client_complete_get_app_id (skeleton, invocation, priv->app_id);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_get_restart_style_hint (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
guint hint;
|
||||||
|
|
||||||
|
hint = GSM_CLIENT_GET_CLASS (client)->impl_get_restart_style_hint (client);
|
||||||
|
gsm_exported_client_complete_get_restart_style_hint (skeleton, invocation, hint);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_get_status (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
gsm_exported_client_complete_get_status (skeleton, invocation, priv->status);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_get_unix_process_id (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
guint pid;
|
||||||
|
|
||||||
|
pid = GSM_CLIENT_GET_CLASS (client)->impl_get_unix_process_id (client);
|
||||||
|
gsm_exported_client_complete_get_unix_process_id (skeleton, invocation, pid);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_client_stop_dbus (GsmExportedClient *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmClient *client)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gsm_client_stop (client, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_dbus_method_invocation_take_error (invocation, error);
|
||||||
|
} else {
|
||||||
|
gsm_exported_client_complete_stop (skeleton, invocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_client (GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
GError *error = NULL;
|
||||||
|
GsmExportedClient *skeleton;
|
||||||
|
|
||||||
|
priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
if (priv->connection == NULL) {
|
||||||
|
g_critical ("error getting session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton = gsm_exported_client_skeleton_new ();
|
||||||
|
priv->skeleton = skeleton;
|
||||||
|
g_debug ("exporting client to object path: %s", priv->id);
|
||||||
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
|
||||||
|
priv->connection,
|
||||||
|
priv->id, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error exporting client on session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (skeleton, "handle-get-app-id",
|
||||||
|
G_CALLBACK (gsm_client_get_app_id), client);
|
||||||
|
g_signal_connect (skeleton, "handle-get-restart-style-hint",
|
||||||
|
G_CALLBACK (gsm_client_get_restart_style_hint), client);
|
||||||
|
g_signal_connect (skeleton, "handle-get-startup-id",
|
||||||
|
G_CALLBACK (gsm_client_get_startup_id), client);
|
||||||
|
g_signal_connect (skeleton, "handle-get-status",
|
||||||
|
G_CALLBACK (gsm_client_get_status), client);
|
||||||
|
g_signal_connect (skeleton, "handle-get-unix-process-id",
|
||||||
|
G_CALLBACK (gsm_client_get_unix_process_id), client);
|
||||||
|
g_signal_connect (skeleton, "handle-stop",
|
||||||
|
G_CALLBACK (gsm_client_stop_dbus), client);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gsm_client_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv;
|
||||||
|
GsmClient *client;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
client = GSM_CLIENT (G_OBJECT_CLASS (gsm_client_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_free (priv->id);
|
||||||
|
priv->id = g_strdup_printf ("/org/gnome/SessionManager/Client%u", get_next_client_serial ());
|
||||||
|
|
||||||
|
res = register_client (client);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to register client with session bus");
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_OBJECT (client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_init (GsmClient *client)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmClient *client;
|
||||||
|
GsmClientPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GSM_IS_CLIENT (object));
|
||||||
|
|
||||||
|
client = GSM_CLIENT (object);
|
||||||
|
priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_if_fail (priv != NULL);
|
||||||
|
|
||||||
|
g_free (priv->id);
|
||||||
|
g_free (priv->startup_id);
|
||||||
|
g_free (priv->app_id);
|
||||||
|
|
||||||
|
if (priv->skeleton != NULL) {
|
||||||
|
g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (priv->skeleton),
|
||||||
|
priv->connection);
|
||||||
|
g_clear_object (&priv->skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&priv->connection);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_client_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_client_set_status (GsmClient *client,
|
||||||
|
guint status)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_CLIENT (client));
|
||||||
|
if (priv->status != status) {
|
||||||
|
priv->status = status;
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (client), props[PROP_STATUS]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_set_startup_id (GsmClient *client,
|
||||||
|
const char *startup_id)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_CLIENT (client));
|
||||||
|
|
||||||
|
g_free (priv->startup_id);
|
||||||
|
|
||||||
|
if (startup_id != NULL) {
|
||||||
|
priv->startup_id = g_strdup (startup_id);
|
||||||
|
} else {
|
||||||
|
priv->startup_id = g_strdup ("");
|
||||||
|
}
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (client), props[PROP_STARTUP_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_client_set_app_id (GsmClient *client,
|
||||||
|
const char *app_id)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_if_fail (GSM_IS_CLIENT (client));
|
||||||
|
|
||||||
|
g_free (priv->app_id);
|
||||||
|
|
||||||
|
if (app_id != NULL) {
|
||||||
|
priv->app_id = g_strdup (app_id);
|
||||||
|
} else {
|
||||||
|
priv->app_id = g_strdup ("");
|
||||||
|
}
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (client), props[PROP_APP_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmClient *self;
|
||||||
|
|
||||||
|
self = GSM_CLIENT (object);
|
||||||
|
|
||||||
|
switch ((GsmClientProperty) prop_id) {
|
||||||
|
case PROP_STARTUP_ID:
|
||||||
|
gsm_client_set_startup_id (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_APP_ID:
|
||||||
|
gsm_client_set_app_id (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_STATUS:
|
||||||
|
gsm_client_set_status (self, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmClient *self = GSM_CLIENT (object);
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (self);
|
||||||
|
|
||||||
|
switch ((GsmClientProperty) prop_id) {
|
||||||
|
case PROP_STARTUP_ID:
|
||||||
|
g_value_set_string (value, priv->startup_id);
|
||||||
|
break;
|
||||||
|
case PROP_APP_ID:
|
||||||
|
g_value_set_string (value, priv->app_id);
|
||||||
|
break;
|
||||||
|
case PROP_STATUS:
|
||||||
|
g_value_set_uint (value, priv->status);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
default_stop (GsmClient *client,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||||||
|
|
||||||
|
g_warning ("Stop not implemented");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GsmClient *client;
|
||||||
|
GsmClientPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GSM_IS_CLIENT (object));
|
||||||
|
|
||||||
|
client = GSM_CLIENT (object);
|
||||||
|
priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_debug ("GsmClient: disposing %s", priv->id);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_client_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_client_class_init (GsmClientClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gsm_client_get_property;
|
||||||
|
object_class->set_property = gsm_client_set_property;
|
||||||
|
object_class->constructor = gsm_client_constructor;
|
||||||
|
object_class->finalize = gsm_client_finalize;
|
||||||
|
object_class->dispose = gsm_client_dispose;
|
||||||
|
|
||||||
|
klass->impl_stop = default_stop;
|
||||||
|
|
||||||
|
signals[DISCONNECTED] =
|
||||||
|
g_signal_new ("disconnected",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmClientClass, disconnected),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
signals[END_SESSION_RESPONSE] =
|
||||||
|
g_signal_new ("end-session-response",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmClientClass, end_session_response),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
4, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING);
|
||||||
|
|
||||||
|
props[PROP_STARTUP_ID] =
|
||||||
|
g_param_spec_string ("startup-id",
|
||||||
|
"startup-id",
|
||||||
|
"startup-id",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
props[PROP_APP_ID] =
|
||||||
|
g_param_spec_string ("app-id",
|
||||||
|
"app-id",
|
||||||
|
"app-id",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
props[PROP_STATUS] =
|
||||||
|
g_param_spec_uint ("status",
|
||||||
|
"status",
|
||||||
|
"status",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
GSM_CLIENT_UNREGISTERED,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_client_peek_id (GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return priv->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_client_peek_app_id:
|
||||||
|
* @client: a #GsmClient.
|
||||||
|
*
|
||||||
|
* Note that the application ID might not be known; this happens when for XSMP
|
||||||
|
* clients that we did not start ourselves, for instance.
|
||||||
|
*
|
||||||
|
* Returns: the application ID of the client, or %NULL if no such ID is
|
||||||
|
* known. The string is owned by @client.
|
||||||
|
**/
|
||||||
|
const char *
|
||||||
|
gsm_client_peek_app_id (GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return priv->app_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_client_peek_startup_id (GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return priv->startup_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_client_peek_status (GsmClient *client)
|
||||||
|
{
|
||||||
|
GsmClientPrivate *priv = gsm_client_get_instance_private (client);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), GSM_CLIENT_UNREGISTERED);
|
||||||
|
|
||||||
|
return priv->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_client_peek_restart_style_hint (GsmClient *client)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), GSM_CLIENT_RESTART_NEVER);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_get_restart_style_hint (client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_client_get_app_name:
|
||||||
|
* @client: a #GsmClient.
|
||||||
|
*
|
||||||
|
* Returns: a copy of the application name of the client, or %NULL if no such
|
||||||
|
* name is known.
|
||||||
|
**/
|
||||||
|
char *
|
||||||
|
gsm_client_get_app_name (GsmClient *client)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_get_app_name (client);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_client_cancel_end_session (GsmClient *client,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_cancel_end_session (client, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_client_query_end_session (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_query_end_session (client, flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_client_end_session (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_end_session (client, flags, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_client_stop (GsmClient *client,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_stop (client, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_client_disconnected (GsmClient *client)
|
||||||
|
{
|
||||||
|
g_signal_emit (client, signals[DISCONNECTED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GKeyFile *
|
||||||
|
gsm_client_save (GsmClient *client,
|
||||||
|
GsmApp *app,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return GSM_CLIENT_GET_CLASS (client)->impl_save (client, app, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_client_end_session_response (GsmClient *client,
|
||||||
|
gboolean is_ok,
|
||||||
|
gboolean do_last,
|
||||||
|
gboolean cancel,
|
||||||
|
const char *reason)
|
||||||
|
{
|
||||||
|
g_signal_emit (client, signals[END_SESSION_RESPONSE], 0,
|
||||||
|
is_ok, do_last, cancel, reason);
|
||||||
|
}
|
140
gnome-session/gsm-client.h
Normal file
140
gnome-session/gsm-client.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_CLIENT_H__
|
||||||
|
#define __GSM_CLIENT_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_CLIENT (gsm_client_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GsmClient, gsm_client, GSM, CLIENT, GObject)
|
||||||
|
|
||||||
|
typedef struct _GsmApp GsmApp;
|
||||||
|
typedef struct _GsmClient GsmClient;
|
||||||
|
typedef struct _GsmClientClass GsmClientClass;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_CLIENT_UNREGISTERED = 0,
|
||||||
|
GSM_CLIENT_REGISTERED,
|
||||||
|
GSM_CLIENT_FINISHED,
|
||||||
|
GSM_CLIENT_FAILED
|
||||||
|
} GsmClientStatus;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_CLIENT_RESTART_NEVER = 0,
|
||||||
|
GSM_CLIENT_RESTART_IF_RUNNING,
|
||||||
|
GSM_CLIENT_RESTART_ANYWAY,
|
||||||
|
GSM_CLIENT_RESTART_IMMEDIATELY
|
||||||
|
} GsmClientRestartStyle;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_CLIENT_END_SESSION_FLAG_FORCEFUL = 1 << 0,
|
||||||
|
GSM_CLIENT_END_SESSION_FLAG_SAVE = 1 << 1,
|
||||||
|
GSM_CLIENT_END_SESSION_FLAG_LAST = 1 << 2
|
||||||
|
} GsmClientEndSessionFlag;
|
||||||
|
|
||||||
|
struct _GsmClientClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (*disconnected) (GsmClient *client);
|
||||||
|
void (*end_session_response) (GsmClient *client,
|
||||||
|
gboolean ok,
|
||||||
|
gboolean do_last,
|
||||||
|
gboolean cancel,
|
||||||
|
const char *reason);
|
||||||
|
|
||||||
|
/* virtual methods */
|
||||||
|
char * (*impl_get_app_name) (GsmClient *client);
|
||||||
|
GsmClientRestartStyle (*impl_get_restart_style_hint) (GsmClient *client);
|
||||||
|
guint (*impl_get_unix_process_id) (GsmClient *client);
|
||||||
|
gboolean (*impl_query_end_session) (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_end_session) (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_cancel_end_session) (GsmClient *client,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*impl_stop) (GsmClient *client,
|
||||||
|
GError **error);
|
||||||
|
GKeyFile * (*impl_save) (GsmClient *client,
|
||||||
|
GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_CLIENT_ERROR_GENERAL = 0,
|
||||||
|
GSM_CLIENT_ERROR_NOT_REGISTERED,
|
||||||
|
GSM_CLIENT_NUM_ERRORS
|
||||||
|
} GsmClientError;
|
||||||
|
|
||||||
|
#define GSM_CLIENT_ERROR gsm_client_error_quark ()
|
||||||
|
GQuark gsm_client_error_quark (void);
|
||||||
|
|
||||||
|
const char *gsm_client_peek_id (GsmClient *client);
|
||||||
|
|
||||||
|
|
||||||
|
const char * gsm_client_peek_startup_id (GsmClient *client);
|
||||||
|
const char * gsm_client_peek_app_id (GsmClient *client);
|
||||||
|
guint gsm_client_peek_restart_style_hint (GsmClient *client);
|
||||||
|
guint gsm_client_peek_status (GsmClient *client);
|
||||||
|
|
||||||
|
|
||||||
|
char *gsm_client_get_app_name (GsmClient *client);
|
||||||
|
void gsm_client_set_app_id (GsmClient *client,
|
||||||
|
const char *app_id);
|
||||||
|
void gsm_client_set_status (GsmClient *client,
|
||||||
|
guint status);
|
||||||
|
|
||||||
|
gboolean gsm_client_end_session (GsmClient *client,
|
||||||
|
guint flags,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_client_query_end_session (GsmClient *client,
|
||||||
|
guint flags,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_client_cancel_end_session (GsmClient *client,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsm_client_disconnected (GsmClient *client);
|
||||||
|
|
||||||
|
GKeyFile *gsm_client_save (GsmClient *client,
|
||||||
|
GsmApp *app,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsm_client_stop (GsmClient *client,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
|
||||||
|
void gsm_client_end_session_response (GsmClient *client,
|
||||||
|
gboolean is_ok,
|
||||||
|
gboolean do_last,
|
||||||
|
gboolean cancel,
|
||||||
|
const char *reason);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_CLIENT_H__ */
|
439
gnome-session/gsm-dbus-client.c
Normal file
439
gnome-session/gsm-dbus-client.c
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "org.gnome.SessionManager.ClientPrivate.h"
|
||||||
|
#include "gsm-dbus-client.h"
|
||||||
|
|
||||||
|
#include "gsm-manager.h"
|
||||||
|
#include "gsm-util.h"
|
||||||
|
|
||||||
|
#define SM_DBUS_NAME "org.gnome.SessionManager"
|
||||||
|
#define SM_DBUS_CLIENT_PRIVATE_INTERFACE "org.gnome.SessionManager.ClientPrivate"
|
||||||
|
|
||||||
|
struct _GsmDBusClient
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
char *bus_name;
|
||||||
|
GPid caller_pid;
|
||||||
|
GsmClientRestartStyle restart_style_hint;
|
||||||
|
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GsmExportedClientPrivate *skeleton;
|
||||||
|
guint watch_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PROP_BUS_NAME = 1,
|
||||||
|
} GsmDBusClientProperty;
|
||||||
|
|
||||||
|
static GParamSpec *props[PROP_BUS_NAME + 1] = { NULL, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmDBusClient, gsm_dbus_client, GSM_TYPE_CLIENT)
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
setup_connection (GsmDBusClient *client)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (client->connection == NULL) {
|
||||||
|
client->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GsmDbusClient: Couldn't connect to session bus: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_end_session_response (GsmExportedClientPrivate *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
gboolean is_ok,
|
||||||
|
const char *reason,
|
||||||
|
GsmDBusClient *client)
|
||||||
|
{
|
||||||
|
g_debug ("GsmDBusClient: got EndSessionResponse is-ok:%d reason=%s", is_ok, reason);
|
||||||
|
gsm_client_end_session_response (GSM_CLIENT (client),
|
||||||
|
is_ok, FALSE, FALSE, reason);
|
||||||
|
|
||||||
|
gsm_exported_client_private_complete_end_session_response (skeleton, invocation);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gsm_dbus_client_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GsmDBusClient *client;
|
||||||
|
GError *error = NULL;
|
||||||
|
GsmExportedClientPrivate *skeleton;
|
||||||
|
|
||||||
|
client = GSM_DBUS_CLIENT (G_OBJECT_CLASS (gsm_dbus_client_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
if (! setup_connection (client)) {
|
||||||
|
g_object_unref (client);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton = gsm_exported_client_private_skeleton_new ();
|
||||||
|
client->skeleton = skeleton;
|
||||||
|
g_debug ("exporting dbus client to object path: %s", gsm_client_peek_id (GSM_CLIENT (client)));
|
||||||
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
|
||||||
|
client->connection,
|
||||||
|
gsm_client_peek_id (GSM_CLIENT (client)),
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error exporting client private on session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
g_object_unref (client);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (skeleton, "handle-end-session-response",
|
||||||
|
G_CALLBACK (handle_end_session_response), client);
|
||||||
|
|
||||||
|
return G_OBJECT (client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_init (GsmDBusClient *client)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adapted from PolicyKit */
|
||||||
|
static gboolean
|
||||||
|
get_caller_info (GsmDBusClient *client,
|
||||||
|
const char *sender,
|
||||||
|
uid_t *calling_uid_out,
|
||||||
|
pid_t *calling_pid_out)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusConnection) connection = NULL;
|
||||||
|
GError *error;
|
||||||
|
g_autoptr(GVariant) uid_variant = NULL;
|
||||||
|
g_autoptr(GVariant) pid_variant = NULL;
|
||||||
|
uid_t uid;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (sender == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("error getting session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uid_variant = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"GetConnectionUnixUser",
|
||||||
|
g_variant_new ("(s)", sender),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, NULL, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GetConnectionUnixUser() failed: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_variant = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"GetConnectionUnixProcessID",
|
||||||
|
g_variant_new ("(s)", sender),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, NULL, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GetConnectionUnixProcessID() failed: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (uid_variant, "(u)", &uid);
|
||||||
|
g_variant_get (pid_variant, "(u)", &pid);
|
||||||
|
|
||||||
|
if (calling_uid_out != NULL) {
|
||||||
|
*calling_uid_out = uid;
|
||||||
|
}
|
||||||
|
if (calling_pid_out != NULL) {
|
||||||
|
*calling_pid_out = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("uid = %d", uid);
|
||||||
|
g_debug ("pid = %d", pid);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_client_vanished (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmDBusClient *client = user_data;
|
||||||
|
|
||||||
|
g_bus_unwatch_name (client->watch_id);
|
||||||
|
client->watch_id = 0;
|
||||||
|
|
||||||
|
gsm_client_disconnected (GSM_CLIENT (client));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_set_bus_name (GsmDBusClient *client,
|
||||||
|
const char *bus_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_DBUS_CLIENT (client));
|
||||||
|
|
||||||
|
g_free (client->bus_name);
|
||||||
|
|
||||||
|
client->bus_name = g_strdup (bus_name);
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (client), props[PROP_BUS_NAME]);
|
||||||
|
|
||||||
|
if (!get_caller_info (client, bus_name, NULL, &client->caller_pid)) {
|
||||||
|
client->caller_pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
||||||
|
bus_name,
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
on_client_vanished,
|
||||||
|
client,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_dbus_client_get_bus_name (GsmDBusClient *client)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_DBUS_CLIENT (client), NULL);
|
||||||
|
|
||||||
|
return client->bus_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmDBusClient *self = GSM_DBUS_CLIENT (object);
|
||||||
|
|
||||||
|
switch ((GsmDBusClientProperty) prop_id) {
|
||||||
|
case PROP_BUS_NAME:
|
||||||
|
gsm_dbus_client_set_bus_name (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmDBusClient *self = GSM_DBUS_CLIENT (object);
|
||||||
|
|
||||||
|
switch ((GsmDBusClientProperty) prop_id) {
|
||||||
|
case PROP_BUS_NAME:
|
||||||
|
g_value_set_string (value, self->bus_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmDBusClient *client = (GsmDBusClient *) object;
|
||||||
|
|
||||||
|
g_free (client->bus_name);
|
||||||
|
|
||||||
|
if (client->skeleton != NULL) {
|
||||||
|
g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (client->skeleton),
|
||||||
|
client->connection);
|
||||||
|
g_clear_object (&client->skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&client->connection);
|
||||||
|
|
||||||
|
if (client->watch_id != 0)
|
||||||
|
g_bus_unwatch_name (client->watch_id);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_dbus_client_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GKeyFile *
|
||||||
|
dbus_client_save (GsmClient *client,
|
||||||
|
GsmApp *app,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_debug ("GsmDBusClient: saving client with id %s",
|
||||||
|
gsm_client_peek_id (client));
|
||||||
|
|
||||||
|
/* FIXME: We still don't support client saving for D-Bus
|
||||||
|
* session clients */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
dbus_client_stop (GsmClient *client,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmDBusClient *dbus_client = (GsmDBusClient *) client;
|
||||||
|
gsm_exported_client_private_emit_stop (dbus_client->skeleton);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
dbus_client_get_app_name (GsmClient *client)
|
||||||
|
{
|
||||||
|
/* Always use app-id instead */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GsmClientRestartStyle
|
||||||
|
dbus_client_get_restart_style_hint (GsmClient *client)
|
||||||
|
{
|
||||||
|
return (GSM_DBUS_CLIENT (client)->restart_style_hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
dbus_client_get_unix_process_id (GsmClient *client)
|
||||||
|
{
|
||||||
|
return (GSM_DBUS_CLIENT (client)->caller_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
dbus_client_query_end_session (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmDBusClient *dbus_client = (GsmDBusClient *) client;
|
||||||
|
|
||||||
|
if (dbus_client->bus_name == NULL) {
|
||||||
|
g_set_error (error,
|
||||||
|
GSM_CLIENT_ERROR,
|
||||||
|
GSM_CLIENT_ERROR_NOT_REGISTERED,
|
||||||
|
"Client is not registered");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GsmDBusClient: sending QueryEndSession signal to %s", dbus_client->bus_name);
|
||||||
|
|
||||||
|
gsm_exported_client_private_emit_query_end_session (dbus_client->skeleton, flags);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
dbus_client_end_session (GsmClient *client,
|
||||||
|
GsmClientEndSessionFlag flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmDBusClient *dbus_client = (GsmDBusClient *) client;
|
||||||
|
|
||||||
|
gsm_exported_client_private_emit_end_session (dbus_client->skeleton, flags);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
dbus_client_cancel_end_session (GsmClient *client,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GsmDBusClient *dbus_client = (GsmDBusClient *) client;
|
||||||
|
gsm_exported_client_private_emit_cancel_end_session (dbus_client->skeleton);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_dbus_client_class_init (GsmDBusClientClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GsmClientClass *client_class = GSM_CLIENT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gsm_dbus_client_finalize;
|
||||||
|
object_class->constructor = gsm_dbus_client_constructor;
|
||||||
|
object_class->get_property = gsm_dbus_client_get_property;
|
||||||
|
object_class->set_property = gsm_dbus_client_set_property;
|
||||||
|
|
||||||
|
client_class->impl_save = dbus_client_save;
|
||||||
|
client_class->impl_stop = dbus_client_stop;
|
||||||
|
client_class->impl_query_end_session = dbus_client_query_end_session;
|
||||||
|
client_class->impl_end_session = dbus_client_end_session;
|
||||||
|
client_class->impl_cancel_end_session = dbus_client_cancel_end_session;
|
||||||
|
client_class->impl_get_app_name = dbus_client_get_app_name;
|
||||||
|
client_class->impl_get_restart_style_hint = dbus_client_get_restart_style_hint;
|
||||||
|
client_class->impl_get_unix_process_id = dbus_client_get_unix_process_id;
|
||||||
|
|
||||||
|
props[PROP_BUS_NAME] =
|
||||||
|
g_param_spec_string ("bus-name",
|
||||||
|
"bus-name",
|
||||||
|
"bus-name",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmClient *
|
||||||
|
gsm_dbus_client_new (const char *startup_id,
|
||||||
|
const char *bus_name)
|
||||||
|
{
|
||||||
|
GsmDBusClient *client;
|
||||||
|
|
||||||
|
client = g_object_new (GSM_TYPE_DBUS_CLIENT,
|
||||||
|
"startup-id", startup_id,
|
||||||
|
"bus-name", bus_name,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GSM_CLIENT (client);
|
||||||
|
}
|
35
gnome-session/gsm-dbus-client.h
Normal file
35
gnome-session/gsm-dbus-client.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_DBUS_CLIENT_H__
|
||||||
|
#define __GSM_DBUS_CLIENT_H__
|
||||||
|
|
||||||
|
#include "gsm-client.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_DBUS_CLIENT (gsm_dbus_client_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GsmDBusClient, gsm_dbus_client, GSM, DBUS_CLIENT, GsmClient)
|
||||||
|
|
||||||
|
GsmClient * gsm_dbus_client_new (const char *startup_id,
|
||||||
|
const char *bus_name);
|
||||||
|
const char * gsm_dbus_client_get_bus_name (GsmDBusClient *client);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_DBUS_CLIENT_H__ */
|
461
gnome-session/gsm-fail-whale-dialog.c
Normal file
461
gnome-session/gsm-fail-whale-dialog.c
Normal file
|
@ -0,0 +1,461 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2019 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Colin Walters <walters@verbum.org>
|
||||||
|
* Marco Trevisan <marco@ubuntu.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
#include <gtk/gtkx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gsm-fail-whale-dialog.h"
|
||||||
|
|
||||||
|
#include "gsm-icon-names.h"
|
||||||
|
|
||||||
|
struct _GsmFailWhaleDialog
|
||||||
|
{
|
||||||
|
GtkWindow parent;
|
||||||
|
|
||||||
|
gboolean debug_mode;
|
||||||
|
gboolean allow_logout;
|
||||||
|
gboolean extensions;
|
||||||
|
GdkMonitor *monitor;
|
||||||
|
GdkRectangle geometry;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmFailWhaleDialog, gsm_fail_whale_dialog, GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
|
/* derived from tomboy */
|
||||||
|
static void
|
||||||
|
_window_override_user_time (GsmFailWhaleDialog *window)
|
||||||
|
{
|
||||||
|
guint32 ev_time = gtk_get_current_event_time ();
|
||||||
|
GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
if (!GDK_IS_X11_WINDOW (gdk_window))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ev_time == 0) {
|
||||||
|
gint ev_mask = gtk_widget_get_events (GTK_WIDGET (window));
|
||||||
|
if (!(ev_mask & GDK_PROPERTY_CHANGE_MASK)) {
|
||||||
|
gtk_widget_add_events (GTK_WIDGET (window),
|
||||||
|
GDK_PROPERTY_CHANGE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Last resort for D-BUS or other non-interactive
|
||||||
|
* openings. Causes roundtrip to server. Lame.
|
||||||
|
*/
|
||||||
|
ev_time = gdk_x11_get_server_time (gdk_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_x11_window_set_user_time (gdk_window, ev_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_window_move_resize_window (GsmFailWhaleDialog *window,
|
||||||
|
gboolean move,
|
||||||
|
gboolean resize)
|
||||||
|
{
|
||||||
|
if (window->debug_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_debug ("Move and/or resize window x=%d y=%d w=%d h=%d",
|
||||||
|
window->geometry.x,
|
||||||
|
window->geometry.y,
|
||||||
|
window->geometry.width,
|
||||||
|
window->geometry.height);
|
||||||
|
|
||||||
|
if (resize) {
|
||||||
|
gtk_window_resize (GTK_WINDOW (window),
|
||||||
|
window->geometry.width,
|
||||||
|
window->geometry.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move) {
|
||||||
|
gtk_window_move (GTK_WINDOW (window),
|
||||||
|
window->geometry.x,
|
||||||
|
window->geometry.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_geometry (GsmFailWhaleDialog *fail_dialog)
|
||||||
|
{
|
||||||
|
gdk_monitor_get_geometry (fail_dialog->monitor, &fail_dialog->geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_screen_size_changed (GdkScreen *screen,
|
||||||
|
GsmFailWhaleDialog *fail_dialog)
|
||||||
|
{
|
||||||
|
gtk_widget_queue_resize (GTK_WIDGET (fail_dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->realize) {
|
||||||
|
GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->realize (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
_window_override_user_time (GSM_FAIL_WHALE_DIALOG (widget));
|
||||||
|
update_geometry (GSM_FAIL_WHALE_DIALOG (widget));
|
||||||
|
_window_move_resize_window (GSM_FAIL_WHALE_DIALOG (widget), TRUE, TRUE);
|
||||||
|
|
||||||
|
g_signal_connect (gtk_window_get_screen (GTK_WINDOW (widget)),
|
||||||
|
"size_changed",
|
||||||
|
G_CALLBACK (on_screen_size_changed),
|
||||||
|
widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_unrealize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (widget)),
|
||||||
|
on_screen_size_changed,
|
||||||
|
widget);
|
||||||
|
|
||||||
|
if (GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->unrealize) {
|
||||||
|
GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->unrealize (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_size_request (GtkWidget *widget,
|
||||||
|
GtkRequisition *requisition)
|
||||||
|
{
|
||||||
|
GsmFailWhaleDialog *fail_dialog;
|
||||||
|
GdkRectangle old_geometry;
|
||||||
|
int position_changed = FALSE;
|
||||||
|
int size_changed = FALSE;
|
||||||
|
|
||||||
|
fail_dialog = GSM_FAIL_WHALE_DIALOG (widget);
|
||||||
|
|
||||||
|
old_geometry = fail_dialog->geometry;
|
||||||
|
|
||||||
|
update_geometry (fail_dialog);
|
||||||
|
|
||||||
|
requisition->width = fail_dialog->geometry.width;
|
||||||
|
requisition->height = fail_dialog->geometry.height;
|
||||||
|
|
||||||
|
if (!gtk_widget_get_realized (widget)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_geometry.width != fail_dialog->geometry.width ||
|
||||||
|
old_geometry.height != fail_dialog->geometry.height) {
|
||||||
|
size_changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_geometry.x != fail_dialog->geometry.x ||
|
||||||
|
old_geometry.y != fail_dialog->geometry.y) {
|
||||||
|
position_changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_window_move_resize_window (fail_dialog,
|
||||||
|
position_changed, size_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_get_preferred_width (GtkWidget *widget,
|
||||||
|
gint *minimal_width,
|
||||||
|
gint *natural_width)
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
|
||||||
|
gsm_fail_whale_dialog_size_request (widget, &requisition);
|
||||||
|
|
||||||
|
*minimal_width = *natural_width = requisition.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_get_preferred_width_for_height (GtkWidget *widget,
|
||||||
|
gint for_height,
|
||||||
|
gint *minimal_width,
|
||||||
|
gint *natural_width)
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
|
||||||
|
gsm_fail_whale_dialog_size_request (widget, &requisition);
|
||||||
|
|
||||||
|
*minimal_width = *natural_width = requisition.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_get_preferred_height (GtkWidget *widget,
|
||||||
|
gint *minimal_height,
|
||||||
|
gint *natural_height)
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
|
||||||
|
gsm_fail_whale_dialog_size_request (widget, &requisition);
|
||||||
|
|
||||||
|
*minimal_height = *natural_height = requisition.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_get_preferred_height_for_width (GtkWidget *widget,
|
||||||
|
gint for_width,
|
||||||
|
gint *minimal_height,
|
||||||
|
gint *natural_height)
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
|
||||||
|
gsm_fail_whale_dialog_size_request (widget, &requisition);
|
||||||
|
|
||||||
|
*minimal_height = *natural_height = requisition.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_class_init (GsmFailWhaleDialogClass *klass)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class;
|
||||||
|
|
||||||
|
widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
widget_class->realize = gsm_fail_whale_dialog_realize;
|
||||||
|
widget_class->unrealize = gsm_fail_whale_dialog_unrealize;
|
||||||
|
widget_class->get_preferred_width = gsm_fail_whale_dialog_get_preferred_width;
|
||||||
|
widget_class->get_preferred_height = gsm_fail_whale_dialog_get_preferred_height;
|
||||||
|
widget_class->get_preferred_width_for_height = gsm_fail_whale_dialog_get_preferred_width_for_height;
|
||||||
|
widget_class->get_preferred_height_for_width = gsm_fail_whale_dialog_get_preferred_height_for_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_logout_clicked (GtkWidget *button,
|
||||||
|
GsmFailWhaleDialog *fail_dialog)
|
||||||
|
{
|
||||||
|
if (!fail_dialog->debug_mode) {
|
||||||
|
g_spawn_command_line_async ("gnome-session-quit --force", NULL);
|
||||||
|
}
|
||||||
|
gtk_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_window (GsmFailWhaleDialog *fail_dialog)
|
||||||
|
{
|
||||||
|
GtkWidget *box;
|
||||||
|
GtkWidget *image;
|
||||||
|
GtkWidget *label;
|
||||||
|
GtkWidget *message_label;
|
||||||
|
GtkWidget *button_box;
|
||||||
|
GtkWidget *button;
|
||||||
|
GdkPixbuf *fail_icon;
|
||||||
|
GdkDisplay *display;
|
||||||
|
char *markup;
|
||||||
|
int scale_factor;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
gtk_window_set_title (GTK_WINDOW (fail_dialog), "");
|
||||||
|
gtk_window_set_icon_name (GTK_WINDOW (fail_dialog), GSM_ICON_COMPUTER_FAIL);
|
||||||
|
|
||||||
|
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (fail_dialog), TRUE);
|
||||||
|
gtk_window_set_keep_above (GTK_WINDOW (fail_dialog), TRUE);
|
||||||
|
gtk_window_stick (GTK_WINDOW (fail_dialog));
|
||||||
|
gtk_window_set_position (GTK_WINDOW (fail_dialog), GTK_WIN_POS_CENTER_ALWAYS);
|
||||||
|
|
||||||
|
/* only works if there is a window manager which is unlikely */
|
||||||
|
display = gtk_widget_get_display (GTK_WIDGET (fail_dialog));
|
||||||
|
for (i = 0; i < gdk_display_get_n_monitors (display); i++) {
|
||||||
|
if (gdk_display_get_monitor (display, i) == fail_dialog->monitor) {
|
||||||
|
GdkScreen *screen;
|
||||||
|
|
||||||
|
screen = gtk_widget_get_screen (GTK_WIDGET (fail_dialog));
|
||||||
|
gtk_window_fullscreen_on_monitor (GTK_WINDOW (fail_dialog),
|
||||||
|
screen, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||||
|
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
|
||||||
|
gtk_widget_show (box);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (fail_dialog), box);
|
||||||
|
|
||||||
|
scale_factor = gdk_monitor_get_scale_factor (fail_dialog->monitor);
|
||||||
|
fail_icon = gtk_icon_theme_load_icon_for_scale (gtk_icon_theme_get_default (),
|
||||||
|
GSM_ICON_COMPUTER_FAIL,
|
||||||
|
128,
|
||||||
|
scale_factor,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if (fail_icon != NULL) {
|
||||||
|
image = gtk_image_new_from_pixbuf (fail_icon);
|
||||||
|
gtk_widget_show (image);
|
||||||
|
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
|
||||||
|
g_object_unref (fail_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
markup = g_strdup_printf ("<b><big>%s</big></b>", _("Oh no! Something has gone wrong."));
|
||||||
|
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||||
|
g_free (markup);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
if (!fail_dialog->allow_logout)
|
||||||
|
message_label = gtk_label_new (_("A problem has occurred and the system can’t recover. Please contact a system administrator"));
|
||||||
|
else if (fail_dialog->extensions)
|
||||||
|
message_label = gtk_label_new (_("A problem has occurred and the system can’t recover. All extensions have been disabled as a precaution."));
|
||||||
|
else
|
||||||
|
message_label = gtk_label_new (_("A problem has occurred and the system can’t recover.\nPlease log out and try again."));
|
||||||
|
|
||||||
|
gtk_label_set_justify (GTK_LABEL (message_label), GTK_JUSTIFY_CENTER);
|
||||||
|
gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE);
|
||||||
|
gtk_widget_show (message_label);
|
||||||
|
gtk_box_pack_start (GTK_BOX (box),
|
||||||
|
message_label, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (button_box), 20);
|
||||||
|
gtk_widget_show (button_box);
|
||||||
|
gtk_box_pack_end (GTK_BOX (box),
|
||||||
|
button_box, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
if (fail_dialog->allow_logout) {
|
||||||
|
button = gtk_button_new_with_mnemonic (_("_Log Out"));
|
||||||
|
gtk_widget_show (button);
|
||||||
|
gtk_box_pack_end (GTK_BOX (button_box),
|
||||||
|
button, FALSE, FALSE, 0);
|
||||||
|
g_signal_connect (button, "clicked",
|
||||||
|
G_CALLBACK (on_logout_clicked), fail_dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_fail_whale_dialog_init (GsmFailWhaleDialog *fail_dialog)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean debug_mode = FALSE;
|
||||||
|
static gboolean allow_logout = FALSE;
|
||||||
|
static gboolean extensions = FALSE;
|
||||||
|
static GList *dialogs = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_fail_dialog (GdkMonitor *monitor)
|
||||||
|
{
|
||||||
|
GsmFailWhaleDialog *fail_dialog;
|
||||||
|
|
||||||
|
fail_dialog = g_object_new (GSM_TYPE_FAIL_WHALE_DIALOG, NULL);
|
||||||
|
fail_dialog->debug_mode = debug_mode;
|
||||||
|
fail_dialog->allow_logout = allow_logout;
|
||||||
|
fail_dialog->extensions = extensions;
|
||||||
|
fail_dialog->monitor = monitor;
|
||||||
|
|
||||||
|
setup_window (fail_dialog);
|
||||||
|
|
||||||
|
g_signal_connect (fail_dialog, "destroy",
|
||||||
|
G_CALLBACK (gtk_main_quit), NULL);
|
||||||
|
|
||||||
|
gtk_widget_show (GTK_WIDGET (fail_dialog));
|
||||||
|
|
||||||
|
dialogs = g_list_prepend (dialogs, fail_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_monitor_added (GdkDisplay *display,
|
||||||
|
GdkMonitor *monitor)
|
||||||
|
{
|
||||||
|
create_fail_dialog (monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_monitor_removed (GdkDisplay *display,
|
||||||
|
GdkMonitor *monitor)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = dialogs; l;) {
|
||||||
|
GList *next = l->next;
|
||||||
|
GsmFailWhaleDialog *fail_dialog = l->data;
|
||||||
|
|
||||||
|
if (fail_dialog->monitor == monitor) {
|
||||||
|
dialogs = g_list_delete_link (dialogs, l);
|
||||||
|
gtk_widget_destroy (GTK_WIDGET (fail_dialog));
|
||||||
|
}
|
||||||
|
l = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GOptionEntry entries[] = {
|
||||||
|
{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug_mode, N_("Enable debugging code"), NULL },
|
||||||
|
{ "allow-logout", 0, 0, G_OPTION_ARG_NONE, &allow_logout, N_("Allow logout"), NULL },
|
||||||
|
{ "extensions", 0, 0, G_OPTION_ARG_NONE, &extensions, N_("Show extension warning"), NULL },
|
||||||
|
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
GdkDisplay *display;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
|
||||||
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||||
|
textdomain (GETTEXT_PACKAGE);
|
||||||
|
|
||||||
|
if (!gtk_init_with_args (&argc, &argv, " - fail whale",
|
||||||
|
entries, GETTEXT_PACKAGE,
|
||||||
|
&error)) {
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("%s", error->message);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* display server probably went away. Could be for legitimate reasons, could be for
|
||||||
|
* unexpected reasons. If it went away unexpectantly, that's logged elsewhere, so
|
||||||
|
* let's not add noise by logging here.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force-off allow_logout when running inside GDM, this is needed
|
||||||
|
* because the systemd service always passes --allow-logout
|
||||||
|
*/
|
||||||
|
if (g_strcmp0 (g_getenv ("RUNNING_UNDER_GDM"), "true") == 0)
|
||||||
|
allow_logout = FALSE;
|
||||||
|
|
||||||
|
display = gdk_display_get_default ();
|
||||||
|
for (i = 0; i < gdk_display_get_n_monitors (display); i++) {
|
||||||
|
create_fail_dialog (gdk_display_get_monitor (display, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (display, "monitor-added",
|
||||||
|
G_CALLBACK (on_monitor_added), &dialogs);
|
||||||
|
g_signal_connect (display, "monitor-removed",
|
||||||
|
G_CALLBACK (on_monitor_removed), &dialogs);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
36
gnome-session/gsm-fail-whale-dialog.h
Normal file
36
gnome-session/gsm-fail-whale-dialog.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2019 Canonical Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Colin Walters <walters@verbum.org>
|
||||||
|
* Marco Trevisan <marco@ubuntu.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_FAIL_WHALE_DIALOG_H__
|
||||||
|
#define __GSM_FAIL_WHALE_DIALOG_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_FAIL_WHALE_DIALOG (gsm_fail_whale_dialog_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GsmFailWhaleDialog, gsm_fail_whale_dialog, GSM, FAIL_WHALE_DIALOG, GtkWindow);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_FAIL_WHALE_DIALOG_H__ */
|
66
gnome-session/gsm-fail-whale.c
Normal file
66
gnome-session/gsm-fail-whale.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
* gsm-fail-whale.c
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "gsm-fail-whale.h"
|
||||||
|
#include "gsm-util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_fail_whale_failed (void)
|
||||||
|
{
|
||||||
|
raise (SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_fail_whale_dialog_we_failed (gboolean debug_mode,
|
||||||
|
gboolean allow_logout,
|
||||||
|
GsmShellExtensions *extensions)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gchar *argv[5];
|
||||||
|
static GPid pid = 0;
|
||||||
|
|
||||||
|
if (pid != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
argv[i++] = LIBEXECDIR "/gnome-session-failed";
|
||||||
|
if (debug_mode)
|
||||||
|
argv[i++] = "--debug";
|
||||||
|
if (allow_logout)
|
||||||
|
argv[i++] = "--allow-logout";
|
||||||
|
if (extensions != NULL && gsm_shell_extensions_n_extensions (extensions) > 0)
|
||||||
|
argv[i++] = "--extensions";
|
||||||
|
argv[i++] = NULL;
|
||||||
|
|
||||||
|
if (!g_spawn_async (NULL, argv, (char **) gsm_util_listenv (), G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL)) {
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_child_watch_add (pid,
|
||||||
|
(GChildWatchFunc)on_fail_whale_failed,
|
||||||
|
NULL);
|
||||||
|
}
|
34
gnome-session/gsm-fail-whale.h
Normal file
34
gnome-session/gsm-fail-whale.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* gsm-fail-whale.h
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_FAIL_WHALE_H___
|
||||||
|
#define __GSM_FAIL_WHALE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "gsm-shell-extensions.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gsm_fail_whale_dialog_we_failed (gboolean debug_mode,
|
||||||
|
gboolean allow_logout,
|
||||||
|
GsmShellExtensions *extensions);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_FAIL_WHALE_H__ */
|
||||||
|
|
28
gnome-session/gsm-icon-names.h
Normal file
28
gnome-session/gsm-icon-names.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Novell, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_ICON_NAMES_H__
|
||||||
|
#define __GSM_ICON_NAMES_H__
|
||||||
|
|
||||||
|
#define GSM_ICON_COMPUTER_FAIL "computer-fail-symbolic"
|
||||||
|
#define GSM_ICON_INHIBITOR_DEFAULT "gnome-windows"
|
||||||
|
#define GSM_ICON_LOGOUT "system-log-out"
|
||||||
|
#define GSM_ICON_SHUTDOWN "system-shutdown"
|
||||||
|
#define GSM_ICON_XSMP_DEFAULT "system-run"
|
||||||
|
|
||||||
|
#endif /*__GSM_ICON_NAMES_H__ */
|
36
gnome-session/gsm-inhibitor-flag.h
Normal file
36
gnome-session/gsm-inhibitor-flag.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_INHIBITOR_FLAG_H__
|
||||||
|
#define __GSM_INHIBITOR_FLAG_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0,
|
||||||
|
GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1,
|
||||||
|
GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2,
|
||||||
|
GSM_INHIBITOR_FLAG_IDLE = 1 << 3,
|
||||||
|
GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4
|
||||||
|
} GsmInhibitorFlag;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_INHIBITOR_FLAG_H__ */
|
649
gnome-session/gsm-inhibitor.c
Normal file
649
gnome-session/gsm-inhibitor.c
Normal file
|
@ -0,0 +1,649 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gsm-inhibitor.h"
|
||||||
|
#include "org.gnome.SessionManager.Inhibitor.h"
|
||||||
|
|
||||||
|
#include "gsm-util.h"
|
||||||
|
|
||||||
|
static guint32 inhibitor_serial = 1;
|
||||||
|
|
||||||
|
#define GSM_INHIBITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_INHIBITOR, GsmInhibitorPrivate))
|
||||||
|
|
||||||
|
struct GsmInhibitorPrivate
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
char *bus_name;
|
||||||
|
char *app_id;
|
||||||
|
char *client_id;
|
||||||
|
char *reason;
|
||||||
|
guint flags;
|
||||||
|
guint toplevel_xid;
|
||||||
|
guint cookie;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GsmExportedInhibitor *skeleton;
|
||||||
|
|
||||||
|
guint watch_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_BUS_NAME,
|
||||||
|
PROP_REASON,
|
||||||
|
PROP_APP_ID,
|
||||||
|
PROP_CLIENT_ID,
|
||||||
|
PROP_FLAGS,
|
||||||
|
PROP_TOPLEVEL_XID,
|
||||||
|
PROP_COOKIE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VANISHED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmInhibitor, gsm_inhibitor, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define GSM_INHIBITOR_DBUS_IFACE "org.gnome.SessionManager.Inhibitor"
|
||||||
|
|
||||||
|
static const GDBusErrorEntry gsm_inhibitor_error_entries[] = {
|
||||||
|
{ GSM_INHIBITOR_ERROR_GENERAL, GSM_INHIBITOR_DBUS_IFACE ".GeneralError" },
|
||||||
|
{ GSM_INHIBITOR_ERROR_NOT_SET, GSM_INHIBITOR_DBUS_IFACE ".NotSet" }
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_inhibitor_error_quark (void)
|
||||||
|
{
|
||||||
|
static volatile gsize quark_volatile = 0;
|
||||||
|
|
||||||
|
g_dbus_error_register_error_domain ("gsm_inhibitor_error",
|
||||||
|
&quark_volatile,
|
||||||
|
gsm_inhibitor_error_entries,
|
||||||
|
G_N_ELEMENTS (gsm_inhibitor_error_entries));
|
||||||
|
return quark_volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_inhibitor_get_app_id (GsmExportedInhibitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
const gchar *id;
|
||||||
|
|
||||||
|
if (inhibitor->priv->app_id != NULL) {
|
||||||
|
id = inhibitor->priv->app_id;
|
||||||
|
} else {
|
||||||
|
id = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_exported_inhibitor_complete_get_app_id (skeleton, invocation, id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_inhibitor_get_client_id (GsmExportedInhibitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
/* object paths are not allowed to be NULL or blank */
|
||||||
|
if (IS_STRING_EMPTY (inhibitor->priv->client_id)) {
|
||||||
|
g_dbus_method_invocation_return_error (invocation,
|
||||||
|
GSM_INHIBITOR_ERROR,
|
||||||
|
GSM_INHIBITOR_ERROR_NOT_SET,
|
||||||
|
"Value is not set");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_exported_inhibitor_complete_get_client_id (skeleton, invocation, inhibitor->priv->client_id);
|
||||||
|
g_debug ("GsmInhibitor: getting client-id = '%s'", inhibitor->priv->client_id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_inhibitor_get_reason (GsmExportedInhibitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
const gchar *reason;
|
||||||
|
|
||||||
|
if (inhibitor->priv->reason != NULL) {
|
||||||
|
reason = inhibitor->priv->reason;
|
||||||
|
} else {
|
||||||
|
reason = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_exported_inhibitor_complete_get_reason (skeleton, invocation, reason);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_inhibitor_get_flags (GsmExportedInhibitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
gsm_exported_inhibitor_complete_get_flags (skeleton, invocation, inhibitor->priv->flags);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_inhibitor_get_toplevel_xid (GsmExportedInhibitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
gsm_exported_inhibitor_complete_get_toplevel_xid (skeleton, invocation, inhibitor->priv->toplevel_xid);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_next_inhibitor_serial (void)
|
||||||
|
{
|
||||||
|
guint32 serial;
|
||||||
|
|
||||||
|
serial = inhibitor_serial++;
|
||||||
|
|
||||||
|
if ((gint32)inhibitor_serial < 0) {
|
||||||
|
inhibitor_serial = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_inhibitor (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
GsmExportedInhibitor *skeleton;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
inhibitor->priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error getting session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton = gsm_exported_inhibitor_skeleton_new ();
|
||||||
|
inhibitor->priv->skeleton = skeleton;
|
||||||
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
|
||||||
|
inhibitor->priv->connection,
|
||||||
|
inhibitor->priv->id, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error exporting inhibitor on session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (skeleton, "handle-get-app-id",
|
||||||
|
G_CALLBACK (gsm_inhibitor_get_app_id), inhibitor);
|
||||||
|
g_signal_connect (skeleton, "handle-get-client-id",
|
||||||
|
G_CALLBACK (gsm_inhibitor_get_client_id), inhibitor);
|
||||||
|
g_signal_connect (skeleton, "handle-get-flags",
|
||||||
|
G_CALLBACK (gsm_inhibitor_get_flags), inhibitor);
|
||||||
|
g_signal_connect (skeleton, "handle-get-reason",
|
||||||
|
G_CALLBACK (gsm_inhibitor_get_reason), inhibitor);
|
||||||
|
g_signal_connect (skeleton, "handle-get-toplevel-xid",
|
||||||
|
G_CALLBACK (gsm_inhibitor_get_toplevel_xid), inhibitor);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gsm_inhibitor_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GsmInhibitor *inhibitor;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
inhibitor = GSM_INHIBITOR (G_OBJECT_CLASS (gsm_inhibitor_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->id);
|
||||||
|
inhibitor->priv->id = g_strdup_printf ("/org/gnome/SessionManager/Inhibitor%u", get_next_inhibitor_serial ());
|
||||||
|
res = register_inhibitor (inhibitor);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to register inhibitor with session bus");
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_OBJECT (inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_init (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
inhibitor->priv = GSM_INHIBITOR_GET_PRIVATE (inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_inhibitor_vanished (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmInhibitor *inhibitor = user_data;
|
||||||
|
|
||||||
|
g_bus_unwatch_name (inhibitor->priv->watch_id);
|
||||||
|
inhibitor->priv->watch_id = 0;
|
||||||
|
|
||||||
|
g_signal_emit (inhibitor, signals[VANISHED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_bus_name (GsmInhibitor *inhibitor,
|
||||||
|
const char *bus_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->bus_name);
|
||||||
|
|
||||||
|
if (bus_name != NULL) {
|
||||||
|
inhibitor->priv->bus_name = g_strdup (bus_name);
|
||||||
|
|
||||||
|
inhibitor->priv->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
||||||
|
bus_name,
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
on_inhibitor_vanished,
|
||||||
|
inhibitor,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
inhibitor->priv->bus_name = g_strdup ("");
|
||||||
|
}
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "bus-name");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_app_id (GsmInhibitor *inhibitor,
|
||||||
|
const char *app_id)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->app_id);
|
||||||
|
|
||||||
|
inhibitor->priv->app_id = g_strdup (app_id);
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "app-id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_client_id (GsmInhibitor *inhibitor,
|
||||||
|
const char *client_id)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->client_id);
|
||||||
|
|
||||||
|
g_debug ("GsmInhibitor: setting client-id = %s", client_id);
|
||||||
|
|
||||||
|
if (client_id != NULL) {
|
||||||
|
inhibitor->priv->client_id = g_strdup (client_id);
|
||||||
|
} else {
|
||||||
|
inhibitor->priv->client_id = g_strdup ("");
|
||||||
|
}
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "client-id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_reason (GsmInhibitor *inhibitor,
|
||||||
|
const char *reason)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->reason);
|
||||||
|
|
||||||
|
if (reason != NULL) {
|
||||||
|
inhibitor->priv->reason = g_strdup (reason);
|
||||||
|
} else {
|
||||||
|
inhibitor->priv->reason = g_strdup ("");
|
||||||
|
}
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "reason");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_cookie (GsmInhibitor *inhibitor,
|
||||||
|
guint cookie)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
if (inhibitor->priv->cookie != cookie) {
|
||||||
|
inhibitor->priv->cookie = cookie;
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "cookie");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_flags (GsmInhibitor *inhibitor,
|
||||||
|
guint flags)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
if (inhibitor->priv->flags != flags) {
|
||||||
|
inhibitor->priv->flags = flags;
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "flags");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_toplevel_xid (GsmInhibitor *inhibitor,
|
||||||
|
guint xid)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_INHIBITOR (inhibitor));
|
||||||
|
|
||||||
|
if (inhibitor->priv->toplevel_xid != xid) {
|
||||||
|
inhibitor->priv->toplevel_xid = xid;
|
||||||
|
g_object_notify (G_OBJECT (inhibitor), "toplevel-xid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_inhibitor_peek_bus_name (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), NULL);
|
||||||
|
|
||||||
|
return inhibitor->priv->bus_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_inhibitor_peek_id (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), NULL);
|
||||||
|
|
||||||
|
return inhibitor->priv->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_inhibitor_peek_app_id (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), NULL);
|
||||||
|
|
||||||
|
return inhibitor->priv->app_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_inhibitor_peek_client_id (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), NULL);
|
||||||
|
|
||||||
|
return inhibitor->priv->client_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gsm_inhibitor_peek_reason (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), NULL);
|
||||||
|
|
||||||
|
return inhibitor->priv->reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_inhibitor_peek_flags (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), 0);
|
||||||
|
|
||||||
|
return inhibitor->priv->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_inhibitor_peek_toplevel_xid (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), 0);
|
||||||
|
|
||||||
|
return inhibitor->priv->toplevel_xid;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_inhibitor_peek_cookie (GsmInhibitor *inhibitor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_INHIBITOR (inhibitor), 0);
|
||||||
|
|
||||||
|
return inhibitor->priv->cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmInhibitor *self;
|
||||||
|
|
||||||
|
self = GSM_INHIBITOR (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_BUS_NAME:
|
||||||
|
gsm_inhibitor_set_bus_name (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_APP_ID:
|
||||||
|
gsm_inhibitor_set_app_id (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_CLIENT_ID:
|
||||||
|
gsm_inhibitor_set_client_id (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_REASON:
|
||||||
|
gsm_inhibitor_set_reason (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_FLAGS:
|
||||||
|
gsm_inhibitor_set_flags (self, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
case PROP_COOKIE:
|
||||||
|
gsm_inhibitor_set_cookie (self, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
case PROP_TOPLEVEL_XID:
|
||||||
|
gsm_inhibitor_set_toplevel_xid (self, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmInhibitor *self;
|
||||||
|
|
||||||
|
self = GSM_INHIBITOR (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_BUS_NAME:
|
||||||
|
g_value_set_string (value, self->priv->bus_name);
|
||||||
|
break;
|
||||||
|
case PROP_APP_ID:
|
||||||
|
g_value_set_string (value, self->priv->app_id);
|
||||||
|
break;
|
||||||
|
case PROP_CLIENT_ID:
|
||||||
|
g_value_set_string (value, self->priv->client_id);
|
||||||
|
break;
|
||||||
|
case PROP_REASON:
|
||||||
|
g_value_set_string (value, self->priv->reason);
|
||||||
|
break;
|
||||||
|
case PROP_FLAGS:
|
||||||
|
g_value_set_uint (value, self->priv->flags);
|
||||||
|
break;
|
||||||
|
case PROP_COOKIE:
|
||||||
|
g_value_set_uint (value, self->priv->cookie);
|
||||||
|
break;
|
||||||
|
case PROP_TOPLEVEL_XID:
|
||||||
|
g_value_set_uint (value, self->priv->toplevel_xid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmInhibitor *inhibitor = (GsmInhibitor *) object;
|
||||||
|
|
||||||
|
g_free (inhibitor->priv->id);
|
||||||
|
g_free (inhibitor->priv->bus_name);
|
||||||
|
g_free (inhibitor->priv->app_id);
|
||||||
|
g_free (inhibitor->priv->client_id);
|
||||||
|
g_free (inhibitor->priv->reason);
|
||||||
|
|
||||||
|
if (inhibitor->priv->skeleton != NULL) {
|
||||||
|
g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (inhibitor->priv->skeleton),
|
||||||
|
inhibitor->priv->connection);
|
||||||
|
g_clear_object (&inhibitor->priv->skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhibitor->priv->watch_id != 0) {
|
||||||
|
g_bus_unwatch_name (inhibitor->priv->watch_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&inhibitor->priv->connection);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_inhibitor_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_inhibitor_class_init (GsmInhibitorClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gsm_inhibitor_finalize;
|
||||||
|
object_class->constructor = gsm_inhibitor_constructor;
|
||||||
|
object_class->get_property = gsm_inhibitor_get_property;
|
||||||
|
object_class->set_property = gsm_inhibitor_set_property;
|
||||||
|
|
||||||
|
signals[VANISHED] =
|
||||||
|
g_signal_new ("vanished",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0, NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_BUS_NAME,
|
||||||
|
g_param_spec_string ("bus-name",
|
||||||
|
"bus-name",
|
||||||
|
"bus-name",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_APP_ID,
|
||||||
|
g_param_spec_string ("app-id",
|
||||||
|
"app-id",
|
||||||
|
"app-id",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_CLIENT_ID,
|
||||||
|
g_param_spec_string ("client-id",
|
||||||
|
"client-id",
|
||||||
|
"client-id",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_REASON,
|
||||||
|
g_param_spec_string ("reason",
|
||||||
|
"reason",
|
||||||
|
"reason",
|
||||||
|
"",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_FLAGS,
|
||||||
|
g_param_spec_uint ("flags",
|
||||||
|
"flags",
|
||||||
|
"flags",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_TOPLEVEL_XID,
|
||||||
|
g_param_spec_uint ("toplevel-xid",
|
||||||
|
"toplevel-xid",
|
||||||
|
"toplevel-xid",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_COOKIE,
|
||||||
|
g_param_spec_uint ("cookie",
|
||||||
|
"cookie",
|
||||||
|
"cookie",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GsmInhibitorPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmInhibitor *
|
||||||
|
gsm_inhibitor_new (const char *app_id,
|
||||||
|
guint toplevel_xid,
|
||||||
|
guint flags,
|
||||||
|
const char *reason,
|
||||||
|
const char *bus_name,
|
||||||
|
guint cookie)
|
||||||
|
{
|
||||||
|
GsmInhibitor *inhibitor;
|
||||||
|
|
||||||
|
inhibitor = g_object_new (GSM_TYPE_INHIBITOR,
|
||||||
|
"app-id", app_id,
|
||||||
|
"reason", reason,
|
||||||
|
"bus-name", bus_name,
|
||||||
|
"flags", flags,
|
||||||
|
"toplevel-xid", toplevel_xid,
|
||||||
|
"cookie", cookie,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return inhibitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmInhibitor *
|
||||||
|
gsm_inhibitor_new_for_client (const char *client_id,
|
||||||
|
const char *app_id,
|
||||||
|
guint flags,
|
||||||
|
const char *reason,
|
||||||
|
const char *bus_name,
|
||||||
|
guint cookie)
|
||||||
|
{
|
||||||
|
GsmInhibitor *inhibitor;
|
||||||
|
|
||||||
|
inhibitor = g_object_new (GSM_TYPE_INHIBITOR,
|
||||||
|
"client-id", client_id,
|
||||||
|
"app-id", app_id,
|
||||||
|
"reason", reason,
|
||||||
|
"bus-name", bus_name,
|
||||||
|
"flags", flags,
|
||||||
|
"cookie", cookie,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return inhibitor;
|
||||||
|
}
|
88
gnome-session/gsm-inhibitor.h
Normal file
88
gnome-session/gsm-inhibitor.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_INHIBITOR_H__
|
||||||
|
#define __GSM_INHIBITOR_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "gsm-inhibitor-flag.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_INHIBITOR (gsm_inhibitor_get_type ())
|
||||||
|
#define GSM_INHIBITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_INHIBITOR, GsmInhibitor))
|
||||||
|
#define GSM_INHIBITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_INHIBITOR, GsmInhibitorClass))
|
||||||
|
#define GSM_IS_INHIBITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_INHIBITOR))
|
||||||
|
#define GSM_IS_INHIBITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_INHIBITOR))
|
||||||
|
#define GSM_INHIBITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_INHIBITOR, GsmInhibitorClass))
|
||||||
|
|
||||||
|
typedef struct _GsmInhibitor GsmInhibitor;
|
||||||
|
typedef struct _GsmInhibitorClass GsmInhibitorClass;
|
||||||
|
|
||||||
|
typedef struct GsmInhibitorPrivate GsmInhibitorPrivate;
|
||||||
|
|
||||||
|
struct _GsmInhibitor
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
GsmInhibitorPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmInhibitorClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_INHIBITOR_ERROR_GENERAL = 0,
|
||||||
|
GSM_INHIBITOR_ERROR_NOT_SET,
|
||||||
|
GSM_INHIBITOR_NUM_ERRORS
|
||||||
|
} GsmInhibitorError;
|
||||||
|
|
||||||
|
#define GSM_INHIBITOR_ERROR gsm_inhibitor_error_quark ()
|
||||||
|
GQuark gsm_inhibitor_error_quark (void);
|
||||||
|
|
||||||
|
GType gsm_inhibitor_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GsmInhibitor * gsm_inhibitor_new (const char *app_id,
|
||||||
|
guint toplevel_xid,
|
||||||
|
guint flags,
|
||||||
|
const char *reason,
|
||||||
|
const char *bus_name,
|
||||||
|
guint cookie);
|
||||||
|
GsmInhibitor * gsm_inhibitor_new_for_client (const char *client_id,
|
||||||
|
const char *app_id,
|
||||||
|
guint flags,
|
||||||
|
const char *reason,
|
||||||
|
const char *bus_name,
|
||||||
|
guint cookie);
|
||||||
|
|
||||||
|
const char * gsm_inhibitor_peek_id (GsmInhibitor *inhibitor);
|
||||||
|
const char * gsm_inhibitor_peek_app_id (GsmInhibitor *inhibitor);
|
||||||
|
const char * gsm_inhibitor_peek_client_id (GsmInhibitor *inhibitor);
|
||||||
|
const char * gsm_inhibitor_peek_reason (GsmInhibitor *inhibitor);
|
||||||
|
const char * gsm_inhibitor_peek_bus_name (GsmInhibitor *inhibitor);
|
||||||
|
guint gsm_inhibitor_peek_cookie (GsmInhibitor *inhibitor);
|
||||||
|
guint gsm_inhibitor_peek_flags (GsmInhibitor *inhibitor);
|
||||||
|
guint gsm_inhibitor_peek_toplevel_xid (GsmInhibitor *inhibitor);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_INHIBITOR_H__ */
|
34
gnome-session/gsm-manager-logout-mode.h
Normal file
34
gnome-session/gsm-manager-logout-mode.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.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 __GSM_MANAGER_LOGOUT_MODE_H
|
||||||
|
#define __GSM_MANAGER_LOGOUT_MODE_H
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_MANAGER_LOGOUT_MODE_NORMAL = 0,
|
||||||
|
GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION,
|
||||||
|
GSM_MANAGER_LOGOUT_MODE_FORCE
|
||||||
|
} GsmManagerLogoutMode;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_MANAGER_LOGOUT_MODE_H */
|
3941
gnome-session/gsm-manager.c
Normal file
3941
gnome-session/gsm-manager.c
Normal file
File diff suppressed because it is too large
Load diff
123
gnome-session/gsm-manager.h
Normal file
123
gnome-session/gsm-manager.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.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 __GSM_MANAGER_H
|
||||||
|
#define __GSM_MANAGER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gsm-store.h"
|
||||||
|
#include "gsm-manager-logout-mode.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_MANAGER (gsm_manager_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GsmManager, gsm_manager, GSM, MANAGER, GObject)
|
||||||
|
|
||||||
|
struct _GsmManagerClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* phase_changed) (GsmManager *manager,
|
||||||
|
const char *phase);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* gsm's own startup/initialization phase */
|
||||||
|
GSM_MANAGER_PHASE_STARTUP = 0,
|
||||||
|
/* gnome-initial-setup */
|
||||||
|
GSM_MANAGER_PHASE_EARLY_INITIALIZATION,
|
||||||
|
/* gnome-keyring-daemon */
|
||||||
|
GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER,
|
||||||
|
/* wayland compositor and XWayland */
|
||||||
|
GSM_MANAGER_PHASE_DISPLAY_SERVER,
|
||||||
|
/* xrandr setup, gnome-settings-daemon, etc */
|
||||||
|
GSM_MANAGER_PHASE_INITIALIZATION,
|
||||||
|
/* window/compositing managers */
|
||||||
|
GSM_MANAGER_PHASE_WINDOW_MANAGER,
|
||||||
|
/* apps that will create _NET_WM_WINDOW_TYPE_PANEL windows */
|
||||||
|
GSM_MANAGER_PHASE_PANEL,
|
||||||
|
/* apps that will create _NET_WM_WINDOW_TYPE_DESKTOP windows */
|
||||||
|
GSM_MANAGER_PHASE_DESKTOP,
|
||||||
|
/* everything else */
|
||||||
|
GSM_MANAGER_PHASE_APPLICATION,
|
||||||
|
/* done launching */
|
||||||
|
GSM_MANAGER_PHASE_RUNNING,
|
||||||
|
/* shutting down */
|
||||||
|
GSM_MANAGER_PHASE_QUERY_END_SESSION,
|
||||||
|
GSM_MANAGER_PHASE_END_SESSION,
|
||||||
|
GSM_MANAGER_PHASE_EXIT
|
||||||
|
} GsmManagerPhase;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_MANAGER_ERROR_GENERAL = 0,
|
||||||
|
GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
|
||||||
|
GSM_MANAGER_ERROR_NOT_IN_RUNNING,
|
||||||
|
GSM_MANAGER_ERROR_ALREADY_REGISTERED,
|
||||||
|
GSM_MANAGER_ERROR_NOT_REGISTERED,
|
||||||
|
GSM_MANAGER_ERROR_INVALID_OPTION,
|
||||||
|
GSM_MANAGER_ERROR_LOCKED_DOWN,
|
||||||
|
GSM_MANAGER_NUM_ERRORS
|
||||||
|
} GsmManagerError;
|
||||||
|
|
||||||
|
#define GSM_MANAGER_ERROR gsm_manager_error_quark ()
|
||||||
|
GQuark gsm_manager_error_quark (void);
|
||||||
|
|
||||||
|
GsmManager * gsm_manager_new (GsmStore *client_store,
|
||||||
|
gboolean failsafe,
|
||||||
|
gboolean systemd_managed);
|
||||||
|
GsmManager * gsm_manager_get (void);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean gsm_manager_get_failsafe (GsmManager *manager);
|
||||||
|
gboolean gsm_manager_get_dbus_disconnected (GsmManager *manager);
|
||||||
|
gboolean gsm_manager_get_systemd_managed (GsmManager *manager);
|
||||||
|
|
||||||
|
gboolean gsm_manager_add_autostart_app (GsmManager *manager,
|
||||||
|
const char *path);
|
||||||
|
gboolean gsm_manager_add_required_app (GsmManager *manager,
|
||||||
|
const char *path);
|
||||||
|
gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager,
|
||||||
|
const char *path);
|
||||||
|
gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
|
void gsm_manager_start (GsmManager *manager);
|
||||||
|
|
||||||
|
char * _gsm_manager_get_default_session (GsmManager *manager);
|
||||||
|
|
||||||
|
void _gsm_manager_set_active_session (GsmManager *manager,
|
||||||
|
const char *session_name,
|
||||||
|
gboolean is_fallback);
|
||||||
|
|
||||||
|
void _gsm_manager_set_renderer (GsmManager *manager,
|
||||||
|
const char *renderer);
|
||||||
|
|
||||||
|
gboolean gsm_manager_logout (GsmManager *manager,
|
||||||
|
guint logout_mode,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsm_manager_set_phase (GsmManager *manager,
|
||||||
|
GsmManagerPhase phase);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_MANAGER_H */
|
33
gnome-session/gsm-presence-flag.h
Normal file
33
gnome-session/gsm-presence-flag.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_PRESENCE_FLAG_H__
|
||||||
|
#define __GSM_PRESENCE_FLAG_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_PRESENCE_STATUS_AVAILABLE = 0,
|
||||||
|
GSM_PRESENCE_STATUS_INVISIBLE,
|
||||||
|
GSM_PRESENCE_STATUS_BUSY,
|
||||||
|
GSM_PRESENCE_STATUS_IDLE,
|
||||||
|
} GsmPresenceStatus;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_PRESENCE_FLAG_H__ */
|
542
gnome-session/gsm-presence.c
Normal file
542
gnome-session/gsm-presence.c
Normal file
|
@ -0,0 +1,542 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||||
|
#include <libgnome-desktop/gnome-idle-monitor.h>
|
||||||
|
|
||||||
|
#include "gsm-presence.h"
|
||||||
|
#include "org.gnome.SessionManager.Presence.h"
|
||||||
|
|
||||||
|
#define GSM_PRESENCE_DBUS_IFACE "org.gnome.SessionManager.Presence"
|
||||||
|
#define GSM_PRESENCE_DBUS_PATH "/org/gnome/SessionManager/Presence"
|
||||||
|
|
||||||
|
#define GS_NAME "org.gnome.ScreenSaver"
|
||||||
|
#define GS_PATH "/org/gnome/ScreenSaver"
|
||||||
|
#define GS_INTERFACE "org.gnome.ScreenSaver"
|
||||||
|
|
||||||
|
#define MAX_STATUS_TEXT 140
|
||||||
|
|
||||||
|
#define GSM_PRESENCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_PRESENCE, GsmPresencePrivate))
|
||||||
|
|
||||||
|
struct GsmPresencePrivate
|
||||||
|
{
|
||||||
|
guint status;
|
||||||
|
guint saved_status;
|
||||||
|
char *status_text;
|
||||||
|
gboolean idle_enabled;
|
||||||
|
GnomeIdleMonitor *idle_monitor;
|
||||||
|
guint idle_watch_id;
|
||||||
|
guint idle_timeout;
|
||||||
|
gboolean screensaver_active;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GDBusProxy *screensaver_proxy;
|
||||||
|
|
||||||
|
GsmExportedPresence *skeleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_IDLE_ENABLED,
|
||||||
|
PROP_IDLE_TIMEOUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STATUS_CHANGED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmPresence, gsm_presence, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static const GDBusErrorEntry gsm_presence_error_entries[] = {
|
||||||
|
{ GSM_PRESENCE_ERROR_GENERAL, GSM_PRESENCE_DBUS_IFACE ".GeneralError" }
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_presence_error_quark (void)
|
||||||
|
{
|
||||||
|
static volatile gsize quark_volatile = 0;
|
||||||
|
|
||||||
|
g_dbus_error_register_error_domain ("gsm_presence_error",
|
||||||
|
&quark_volatile,
|
||||||
|
gsm_presence_error_entries,
|
||||||
|
G_N_ELEMENTS (gsm_presence_error_entries));
|
||||||
|
return quark_volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void idle_became_active_cb (GnomeIdleMonitor *idle_monitor,
|
||||||
|
guint id,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_set_status (GsmPresence *presence,
|
||||||
|
guint status)
|
||||||
|
{
|
||||||
|
if (status != presence->priv->status) {
|
||||||
|
presence->priv->status = status;
|
||||||
|
gsm_exported_presence_set_status (presence->priv->skeleton, status);
|
||||||
|
gsm_exported_presence_emit_status_changed (presence->priv->skeleton, presence->priv->status);
|
||||||
|
g_signal_emit (presence, signals[STATUS_CHANGED], 0, presence->priv->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_presence_set_status_text (GsmPresence *presence,
|
||||||
|
const char *status_text,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_PRESENCE (presence), FALSE);
|
||||||
|
|
||||||
|
g_free (presence->priv->status_text);
|
||||||
|
presence->priv->status_text = NULL;
|
||||||
|
|
||||||
|
/* check length */
|
||||||
|
if (status_text != NULL && strlen (status_text) > MAX_STATUS_TEXT) {
|
||||||
|
g_set_error (error,
|
||||||
|
GSM_PRESENCE_ERROR,
|
||||||
|
GSM_PRESENCE_ERROR_GENERAL,
|
||||||
|
"Status text too long");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_text != NULL) {
|
||||||
|
presence->priv->status_text = g_strdup (status_text);
|
||||||
|
} else {
|
||||||
|
presence->priv->status_text = g_strdup ("");
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_exported_presence_set_status_text (presence->priv->skeleton, presence->priv->status_text);
|
||||||
|
gsm_exported_presence_emit_status_text_changed (presence->priv->skeleton, presence->priv->status_text);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_session_idle (GsmPresence *presence,
|
||||||
|
gboolean is_idle)
|
||||||
|
{
|
||||||
|
g_debug ("GsmPresence: setting idle: %d", is_idle);
|
||||||
|
|
||||||
|
if (is_idle) {
|
||||||
|
if (presence->priv->status == GSM_PRESENCE_STATUS_IDLE) {
|
||||||
|
g_debug ("GsmPresence: already idle, ignoring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save current status */
|
||||||
|
presence->priv->saved_status = presence->priv->status;
|
||||||
|
gsm_presence_set_status (presence, GSM_PRESENCE_STATUS_IDLE);
|
||||||
|
|
||||||
|
gnome_idle_monitor_add_user_active_watch (presence->priv->idle_monitor,
|
||||||
|
idle_became_active_cb,
|
||||||
|
presence,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
if (presence->priv->status != GSM_PRESENCE_STATUS_IDLE) {
|
||||||
|
g_debug ("GsmPresence: already not idle, ignoring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore saved status */
|
||||||
|
gsm_presence_set_status (presence, presence->priv->saved_status);
|
||||||
|
g_debug ("GsmPresence: setting non-idle status %d", presence->priv->saved_status);
|
||||||
|
presence->priv->saved_status = GSM_PRESENCE_STATUS_AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
idle_became_idle_cb (GnomeIdleMonitor *idle_monitor,
|
||||||
|
guint id,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmPresence *presence = user_data;
|
||||||
|
set_session_idle (presence, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
idle_became_active_cb (GnomeIdleMonitor *idle_monitor,
|
||||||
|
guint id,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmPresence *presence = user_data;
|
||||||
|
set_session_idle (presence, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_idle_watch (GsmPresence *presence)
|
||||||
|
{
|
||||||
|
if (presence->priv->idle_watch_id > 0) {
|
||||||
|
g_debug ("GsmPresence: removing idle watch (%i)", presence->priv->idle_watch_id);
|
||||||
|
gnome_idle_monitor_remove_watch (presence->priv->idle_monitor,
|
||||||
|
presence->priv->idle_watch_id);
|
||||||
|
presence->priv->idle_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presence->priv->idle_enabled
|
||||||
|
&& presence->priv->idle_timeout > 0) {
|
||||||
|
presence->priv->idle_watch_id = gnome_idle_monitor_add_idle_watch (presence->priv->idle_monitor,
|
||||||
|
presence->priv->idle_timeout,
|
||||||
|
idle_became_idle_cb,
|
||||||
|
presence,
|
||||||
|
NULL);
|
||||||
|
g_debug ("GsmPresence: adding idle watch (%i) for %d secs",
|
||||||
|
presence->priv->idle_watch_id,
|
||||||
|
presence->priv->idle_timeout / 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_screensaver_dbus_signal (GDBusProxy *proxy,
|
||||||
|
gchar *sender_name,
|
||||||
|
gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
GsmPresence *presence)
|
||||||
|
{
|
||||||
|
gboolean is_active;
|
||||||
|
|
||||||
|
if (g_strcmp0 (signal_name, "ActiveChanged") != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (parameters, "(b)", &is_active);
|
||||||
|
|
||||||
|
if (presence->priv->screensaver_active != is_active) {
|
||||||
|
presence->priv->screensaver_active = is_active;
|
||||||
|
set_session_idle (presence, is_active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
screensaver_get_active_cb (GDBusProxy *screensaver_proxy,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GsmPresence *presence)
|
||||||
|
{
|
||||||
|
g_autoptr(GVariant) data = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
gboolean is_active;
|
||||||
|
|
||||||
|
data = g_dbus_proxy_call_finish (screensaver_proxy, res, &error);
|
||||||
|
if (!data) {
|
||||||
|
if (error) {
|
||||||
|
g_warning ("Could not retrieve current screensaver active state: %s",
|
||||||
|
error->message);
|
||||||
|
} else {
|
||||||
|
g_warning ("Could not retrieve current screensaver active state!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (data, "(b)", &is_active);
|
||||||
|
if (presence->priv->screensaver_active != is_active) {
|
||||||
|
presence->priv->screensaver_active = is_active;
|
||||||
|
set_session_idle (presence, is_active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_screensaver_name_owner_changed (GDBusProxy *screensaver_proxy,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GsmPresence *presence)
|
||||||
|
{
|
||||||
|
gchar *name_owner;
|
||||||
|
|
||||||
|
name_owner = g_dbus_proxy_get_name_owner (screensaver_proxy);
|
||||||
|
if (name_owner == NULL) {
|
||||||
|
g_debug ("Detected that screensaver has left the bus");
|
||||||
|
|
||||||
|
presence->priv->screensaver_active = FALSE;
|
||||||
|
set_session_idle (presence, FALSE);
|
||||||
|
} else {
|
||||||
|
g_debug ("Detected that screensaver has aquired the bus");
|
||||||
|
|
||||||
|
g_dbus_proxy_call (presence->priv->screensaver_proxy,
|
||||||
|
"GetActive",
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
1000,
|
||||||
|
NULL,
|
||||||
|
(GAsyncReadyCallback) screensaver_get_active_cb,
|
||||||
|
presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (name_owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_presence_set_status_text_dbus (GsmExportedPresence *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
gchar *status_text,
|
||||||
|
GsmPresence *presence)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (gsm_presence_set_status_text (presence, status_text, &error)) {
|
||||||
|
gsm_exported_presence_complete_set_status_text (skeleton, invocation);
|
||||||
|
} else {
|
||||||
|
g_dbus_method_invocation_take_error (invocation, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_presence_set_status_dbus (GsmExportedPresence *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
guint status,
|
||||||
|
GsmPresence *presence)
|
||||||
|
{
|
||||||
|
gsm_presence_set_status (presence, status);
|
||||||
|
gsm_exported_presence_complete_set_status (skeleton, invocation);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_presence (GsmPresence *presence)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
GsmExportedPresence *skeleton;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
presence->priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error getting session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton = gsm_exported_presence_skeleton_new ();
|
||||||
|
presence->priv->skeleton = skeleton;
|
||||||
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
|
||||||
|
presence->priv->connection,
|
||||||
|
GSM_PRESENCE_DBUS_PATH, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("error registering presence object on session bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (skeleton, "handle-set-status",
|
||||||
|
G_CALLBACK (gsm_presence_set_status_dbus), presence);
|
||||||
|
g_signal_connect (skeleton, "handle-set-status-text",
|
||||||
|
G_CALLBACK (gsm_presence_set_status_text_dbus), presence);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gsm_presence_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GsmPresence *presence;
|
||||||
|
gboolean res;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
presence = GSM_PRESENCE (G_OBJECT_CLASS (gsm_presence_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
res = register_presence (presence);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to register presence with session bus");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This only connects to signals and resolves the current name owner
|
||||||
|
* synchronously. It is important to not auto-start the service!
|
||||||
|
*/
|
||||||
|
presence->priv->screensaver_proxy = g_dbus_proxy_new_sync (presence->priv->connection,
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||||
|
NULL,
|
||||||
|
GS_NAME,
|
||||||
|
GS_PATH,
|
||||||
|
GS_INTERFACE,
|
||||||
|
NULL, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("Unable to create a DBus proxy for GnomeScreensaver: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
} else {
|
||||||
|
g_signal_connect (presence->priv->screensaver_proxy, "notify::g-name-owner",
|
||||||
|
G_CALLBACK (on_screensaver_name_owner_changed), presence);
|
||||||
|
g_signal_connect (presence->priv->screensaver_proxy, "g-signal",
|
||||||
|
G_CALLBACK (on_screensaver_dbus_signal), presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_OBJECT (presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_init (GsmPresence *presence)
|
||||||
|
{
|
||||||
|
presence->priv = GSM_PRESENCE_GET_PRIVATE (presence);
|
||||||
|
|
||||||
|
presence->priv->idle_monitor = gnome_idle_monitor_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_presence_set_idle_enabled (GsmPresence *presence,
|
||||||
|
gboolean enabled)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_PRESENCE (presence));
|
||||||
|
|
||||||
|
if (presence->priv->idle_enabled != enabled) {
|
||||||
|
presence->priv->idle_enabled = enabled;
|
||||||
|
reset_idle_watch (presence);
|
||||||
|
g_object_notify (G_OBJECT (presence), "idle-enabled");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_presence_set_idle_timeout (GsmPresence *presence,
|
||||||
|
guint timeout)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_PRESENCE (presence));
|
||||||
|
|
||||||
|
if (timeout != presence->priv->idle_timeout) {
|
||||||
|
presence->priv->idle_timeout = timeout;
|
||||||
|
reset_idle_watch (presence);
|
||||||
|
g_object_notify (G_OBJECT (presence), "idle-timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmPresence *self;
|
||||||
|
|
||||||
|
self = GSM_PRESENCE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_IDLE_ENABLED:
|
||||||
|
gsm_presence_set_idle_enabled (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_IDLE_TIMEOUT:
|
||||||
|
gsm_presence_set_idle_timeout (self, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmPresence *self;
|
||||||
|
|
||||||
|
self = GSM_PRESENCE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_IDLE_ENABLED:
|
||||||
|
g_value_set_boolean (value, self->priv->idle_enabled);
|
||||||
|
break;
|
||||||
|
case PROP_IDLE_TIMEOUT:
|
||||||
|
g_value_set_uint (value, self->priv->idle_timeout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmPresence *presence = (GsmPresence *) object;
|
||||||
|
|
||||||
|
if (presence->priv->idle_watch_id > 0) {
|
||||||
|
gnome_idle_monitor_remove_watch (presence->priv->idle_monitor,
|
||||||
|
presence->priv->idle_watch_id);
|
||||||
|
presence->priv->idle_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&presence->priv->status_text, g_free);
|
||||||
|
g_clear_object (&presence->priv->idle_monitor);
|
||||||
|
g_clear_object (&presence->priv->screensaver_proxy);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_presence_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_presence_class_init (GsmPresenceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gsm_presence_finalize;
|
||||||
|
object_class->constructor = gsm_presence_constructor;
|
||||||
|
object_class->get_property = gsm_presence_get_property;
|
||||||
|
object_class->set_property = gsm_presence_set_property;
|
||||||
|
|
||||||
|
signals [STATUS_CHANGED] =
|
||||||
|
g_signal_new ("status-changed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmPresenceClass, status_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__UINT,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_UINT);
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_IDLE_ENABLED,
|
||||||
|
g_param_spec_boolean ("idle-enabled",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_IDLE_TIMEOUT,
|
||||||
|
g_param_spec_uint ("idle-timeout",
|
||||||
|
"idle timeout",
|
||||||
|
"idle timeout",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
120000,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GsmPresencePrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmPresence *
|
||||||
|
gsm_presence_new (void)
|
||||||
|
{
|
||||||
|
GsmPresence *presence;
|
||||||
|
|
||||||
|
presence = g_object_new (GSM_TYPE_PRESENCE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return presence;
|
||||||
|
}
|
75
gnome-session/gsm-presence.h
Normal file
75
gnome-session/gsm-presence.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_PRESENCE_H__
|
||||||
|
#define __GSM_PRESENCE_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "gsm-presence-flag.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_PRESENCE (gsm_presence_get_type ())
|
||||||
|
#define GSM_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_PRESENCE, GsmPresence))
|
||||||
|
#define GSM_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_PRESENCE, GsmPresenceClass))
|
||||||
|
#define GSM_IS_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_PRESENCE))
|
||||||
|
#define GSM_IS_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_PRESENCE))
|
||||||
|
#define GSM_PRESENCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_PRESENCE, GsmPresenceClass))
|
||||||
|
|
||||||
|
typedef struct _GsmPresence GsmPresence;
|
||||||
|
typedef struct _GsmPresenceClass GsmPresenceClass;
|
||||||
|
|
||||||
|
typedef struct GsmPresencePrivate GsmPresencePrivate;
|
||||||
|
|
||||||
|
struct _GsmPresence
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
GsmPresencePrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmPresenceClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* status_changed) (GsmPresence *presence,
|
||||||
|
guint status);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_PRESENCE_ERROR_GENERAL = 0,
|
||||||
|
GSM_PRESENCE_NUM_ERRORS
|
||||||
|
} GsmPresenceError;
|
||||||
|
|
||||||
|
#define GSM_PRESENCE_ERROR gsm_presence_error_quark ()
|
||||||
|
GQuark gsm_presence_error_quark (void);
|
||||||
|
|
||||||
|
GType gsm_presence_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GsmPresence * gsm_presence_new (void);
|
||||||
|
|
||||||
|
void gsm_presence_set_idle_enabled (GsmPresence *presence,
|
||||||
|
gboolean enabled);
|
||||||
|
void gsm_presence_set_idle_timeout (GsmPresence *presence,
|
||||||
|
guint n_seconds);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_PRESENCE_H__ */
|
113
gnome-session/gsm-process-helper.c
Normal file
113
gnome-session/gsm-process-helper.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Novell, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include "gsm-process-helper.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gboolean done;
|
||||||
|
GSubprocess *process;
|
||||||
|
gboolean caught_error;
|
||||||
|
GError **error;
|
||||||
|
GMainContext *maincontext;
|
||||||
|
GSource *timeout_source;
|
||||||
|
} GsmProcessHelper;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_child_exited (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GsmProcessHelper *helper = data;
|
||||||
|
|
||||||
|
helper->done = TRUE;
|
||||||
|
|
||||||
|
if (!g_subprocess_wait_check_finish ((GSubprocess*)source, result,
|
||||||
|
helper->caught_error ? NULL : helper->error))
|
||||||
|
helper->caught_error = TRUE;
|
||||||
|
|
||||||
|
g_clear_pointer (&helper->timeout_source, g_source_destroy);
|
||||||
|
|
||||||
|
g_main_context_wakeup (helper->maincontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_child_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
GsmProcessHelper *helper = data;
|
||||||
|
|
||||||
|
g_assert (!helper->done);
|
||||||
|
|
||||||
|
g_subprocess_force_exit (helper->process);
|
||||||
|
|
||||||
|
g_set_error_literal (helper->error,
|
||||||
|
G_IO_CHANNEL_ERROR,
|
||||||
|
G_IO_CHANNEL_ERROR_FAILED,
|
||||||
|
"Timed out");
|
||||||
|
|
||||||
|
helper->timeout_source = NULL;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_process_helper (const char *command_line,
|
||||||
|
unsigned int timeout,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
GsmProcessHelper helper = { 0, };
|
||||||
|
gchar **argv = NULL;
|
||||||
|
GMainContext *subcontext = NULL;
|
||||||
|
|
||||||
|
if (!g_shell_parse_argv (command_line, NULL, &argv, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
helper.error = error;
|
||||||
|
|
||||||
|
subcontext = g_main_context_new ();
|
||||||
|
g_main_context_push_thread_default (subcontext);
|
||||||
|
|
||||||
|
helper.process = g_subprocess_newv ((const char*const*)argv, 0, error);
|
||||||
|
if (!helper.process)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
g_subprocess_wait_async (helper.process, NULL, on_child_exited, &helper);
|
||||||
|
|
||||||
|
helper.timeout_source = g_timeout_source_new (timeout);
|
||||||
|
|
||||||
|
g_source_set_callback (helper.timeout_source, on_child_timeout, &helper, NULL);
|
||||||
|
g_source_attach (helper.timeout_source, subcontext);
|
||||||
|
|
||||||
|
while (!helper.done)
|
||||||
|
g_main_context_iteration (subcontext, TRUE);
|
||||||
|
|
||||||
|
ret = helper.caught_error;
|
||||||
|
out:
|
||||||
|
g_strfreev (argv);
|
||||||
|
if (subcontext) {
|
||||||
|
g_main_context_pop_thread_default (subcontext);
|
||||||
|
g_main_context_unref (subcontext);
|
||||||
|
}
|
||||||
|
g_clear_object (&helper.process);
|
||||||
|
return ret;
|
||||||
|
}
|
32
gnome-session/gsm-process-helper.h
Normal file
32
gnome-session/gsm-process-helper.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Novell, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_PROCESS_HELPER_H
|
||||||
|
#define __GSM_PROCESS_HELPER_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
int gsm_process_helper (const char *command_line,
|
||||||
|
unsigned int timeout,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_PROCESS_HELPER_H */
|
334
gnome-session/gsm-session-fill.c
Normal file
334
gnome-session/gsm-session-fill.c
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006, 2010 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "gsm-session-fill.h"
|
||||||
|
|
||||||
|
#include "gsm-system.h"
|
||||||
|
#include "gsm-manager.h"
|
||||||
|
#include "gsm-process-helper.h"
|
||||||
|
#include "gsm-util.h"
|
||||||
|
|
||||||
|
#define GSM_KEYFILE_SESSION_GROUP "GNOME Session"
|
||||||
|
#define GSM_KEYFILE_RUNNABLE_KEY "IsRunnableHelper"
|
||||||
|
#define GSM_KEYFILE_FALLBACK_KEY "FallbackSession"
|
||||||
|
#define GSM_KEYFILE_REQUIRED_COMPONENTS_KEY "RequiredComponents"
|
||||||
|
|
||||||
|
/* See https://bugzilla.gnome.org/show_bug.cgi?id=641992 for discussion */
|
||||||
|
#define GSM_RUNNABLE_HELPER_TIMEOUT 3000 /* ms */
|
||||||
|
|
||||||
|
typedef void (*GsmFillHandleComponent) (const char *component,
|
||||||
|
const char *app_path,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_required_components (GKeyFile *keyfile,
|
||||||
|
gboolean look_in_saved_session,
|
||||||
|
GsmFillHandleComponent callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
char **required_components;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
g_assert (keyfile != NULL);
|
||||||
|
g_assert (callback != NULL);
|
||||||
|
|
||||||
|
required_components = g_key_file_get_string_list (keyfile,
|
||||||
|
GSM_KEYFILE_SESSION_GROUP,
|
||||||
|
GSM_KEYFILE_REQUIRED_COMPONENTS_KEY,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
if (!required_components)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; required_components[i] != NULL; i++) {
|
||||||
|
char *app_path;
|
||||||
|
|
||||||
|
app_path = gsm_util_find_desktop_file_for_app_name (required_components[i],
|
||||||
|
look_in_saved_session, TRUE);
|
||||||
|
callback (required_components[i], app_path, user_data);
|
||||||
|
g_free (app_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (required_components);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_required_components_helper (const char *component,
|
||||||
|
const char *app_path,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
gboolean *error = user_data;
|
||||||
|
|
||||||
|
if (app_path == NULL) {
|
||||||
|
g_warning ("Unable to find required component '%s'", component);
|
||||||
|
*error = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_required (GKeyFile *keyfile)
|
||||||
|
{
|
||||||
|
gboolean error = FALSE;
|
||||||
|
|
||||||
|
g_debug ("fill: *** Checking required components");
|
||||||
|
|
||||||
|
handle_required_components (keyfile, FALSE,
|
||||||
|
check_required_components_helper, &error);
|
||||||
|
|
||||||
|
g_debug ("fill: *** Done checking required components");
|
||||||
|
|
||||||
|
return !error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_load_saved_session_apps (GsmManager *manager)
|
||||||
|
{
|
||||||
|
GsmSystem *system;
|
||||||
|
gboolean is_login;
|
||||||
|
|
||||||
|
system = gsm_get_system ();
|
||||||
|
is_login = gsm_system_is_login_session (system);
|
||||||
|
g_object_unref (system);
|
||||||
|
|
||||||
|
if (is_login)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gsm_manager_add_autostart_apps_from_dir (manager, gsm_util_get_saved_session_dir ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_required_components_helper (const char *component,
|
||||||
|
const char *app_path,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmManager *manager = user_data;
|
||||||
|
|
||||||
|
if (app_path == NULL)
|
||||||
|
g_warning ("Unable to find required component '%s'", component);
|
||||||
|
else
|
||||||
|
gsm_manager_add_required_app (manager, app_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_standard_apps (GsmManager *manager,
|
||||||
|
GKeyFile *keyfile)
|
||||||
|
{
|
||||||
|
/* Note that saving/restoring sessions is not really possible on systemd, as
|
||||||
|
* XSMP clients cannot be reliably mapped to .desktop files. */
|
||||||
|
g_debug ("fill: *** Adding required components");
|
||||||
|
handle_required_components (keyfile,
|
||||||
|
!gsm_manager_get_failsafe (manager) && !gsm_manager_get_systemd_managed (manager),
|
||||||
|
append_required_components_helper, manager);
|
||||||
|
g_debug ("fill: *** Done adding required components");
|
||||||
|
|
||||||
|
if (!gsm_manager_get_failsafe (manager)) {
|
||||||
|
char **autostart_dirs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
autostart_dirs = gsm_util_get_autostart_dirs ();
|
||||||
|
|
||||||
|
if (!gsm_manager_get_systemd_managed (manager))
|
||||||
|
maybe_load_saved_session_apps (manager);
|
||||||
|
|
||||||
|
for (i = 0; autostart_dirs[i]; i++) {
|
||||||
|
gsm_manager_add_autostart_apps_from_dir (manager,
|
||||||
|
autostart_dirs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (autostart_dirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GKeyFile *
|
||||||
|
get_session_keyfile_if_valid (const char *path)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
gsize len;
|
||||||
|
char **list;
|
||||||
|
|
||||||
|
g_debug ("fill: *** Looking if %s is a valid session file", path);
|
||||||
|
|
||||||
|
keyfile = g_key_file_new ();
|
||||||
|
|
||||||
|
if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) {
|
||||||
|
g_debug ("Cannot use session '%s': non-existing or invalid file.", path);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_key_file_has_group (keyfile, GSM_KEYFILE_SESSION_GROUP)) {
|
||||||
|
g_warning ("Cannot use session '%s': no '%s' group.", path, GSM_KEYFILE_SESSION_GROUP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = g_key_file_get_string_list (keyfile,
|
||||||
|
GSM_KEYFILE_SESSION_GROUP,
|
||||||
|
GSM_KEYFILE_REQUIRED_COMPONENTS_KEY,
|
||||||
|
&len, NULL);
|
||||||
|
if (list)
|
||||||
|
g_strfreev (list);
|
||||||
|
if (len == 0)
|
||||||
|
g_warning ("Session '%s': no component in the session.", path);
|
||||||
|
|
||||||
|
return keyfile;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_key_file_free (keyfile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_valid_session_keyfile:
|
||||||
|
* @session: name of session
|
||||||
|
*
|
||||||
|
* We look for the session file in XDG_CONFIG_HOME, XDG_CONFIG_DIRS and
|
||||||
|
* XDG_DATA_DIRS. This enables users and sysadmins to override a specific
|
||||||
|
* session that is shipped in XDG_DATA_DIRS.
|
||||||
|
*/
|
||||||
|
static GKeyFile *
|
||||||
|
find_valid_session_keyfile (const char *session)
|
||||||
|
{
|
||||||
|
GPtrArray *dirs;
|
||||||
|
const char * const *system_config_dirs;
|
||||||
|
const char * const *system_data_dirs;
|
||||||
|
int i;
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
char *basename;
|
||||||
|
|
||||||
|
dirs = g_ptr_array_new ();
|
||||||
|
|
||||||
|
g_ptr_array_add (dirs, (gpointer) g_get_user_config_dir ());
|
||||||
|
|
||||||
|
system_config_dirs = g_get_system_config_dirs ();
|
||||||
|
for (i = 0; system_config_dirs[i]; i++)
|
||||||
|
g_ptr_array_add (dirs, (gpointer) system_config_dirs[i]);
|
||||||
|
|
||||||
|
system_data_dirs = g_get_system_data_dirs ();
|
||||||
|
for (i = 0; system_data_dirs[i]; i++)
|
||||||
|
g_ptr_array_add (dirs, (gpointer) system_data_dirs[i]);
|
||||||
|
|
||||||
|
keyfile = NULL;
|
||||||
|
basename = g_strdup_printf ("%s.session", session);
|
||||||
|
|
||||||
|
for (i = 0; i < dirs->len; i++) {
|
||||||
|
g_autofree gchar *path = g_build_filename (dirs->pdata[i], "gnome-session", "sessions", basename, NULL);
|
||||||
|
keyfile = get_session_keyfile_if_valid (path);
|
||||||
|
if (keyfile != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirs)
|
||||||
|
g_ptr_array_free (dirs, TRUE);
|
||||||
|
if (basename)
|
||||||
|
g_free (basename);
|
||||||
|
|
||||||
|
return keyfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GKeyFile *
|
||||||
|
get_session_keyfile (const char *session,
|
||||||
|
char **actual_session,
|
||||||
|
gboolean *is_fallback)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
gboolean session_runnable;
|
||||||
|
char *value;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
*actual_session = NULL;
|
||||||
|
|
||||||
|
g_debug ("fill: *** Getting session '%s'", session);
|
||||||
|
|
||||||
|
keyfile = find_valid_session_keyfile (session);
|
||||||
|
|
||||||
|
if (!keyfile)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
session_runnable = TRUE;
|
||||||
|
|
||||||
|
value = g_key_file_get_string (keyfile,
|
||||||
|
GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_RUNNABLE_KEY,
|
||||||
|
NULL);
|
||||||
|
if (!IS_STRING_EMPTY (value)) {
|
||||||
|
g_debug ("fill: *** Launching helper '%s' to know if session is runnable", value);
|
||||||
|
session_runnable = gsm_process_helper (value, GSM_RUNNABLE_HELPER_TIMEOUT, &error);
|
||||||
|
if (!session_runnable) {
|
||||||
|
g_warning ("Session '%s' runnable check failed: %s", session,
|
||||||
|
error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free (value);
|
||||||
|
|
||||||
|
if (session_runnable) {
|
||||||
|
session_runnable = check_required (keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session_runnable) {
|
||||||
|
*actual_session = g_strdup (session);
|
||||||
|
if (is_fallback)
|
||||||
|
*is_fallback = FALSE;
|
||||||
|
return keyfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("fill: *** Session is not runnable");
|
||||||
|
|
||||||
|
/* We can't run this session, so try to use the fallback */
|
||||||
|
value = g_key_file_get_string (keyfile,
|
||||||
|
GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_FALLBACK_KEY,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_key_file_free (keyfile);
|
||||||
|
keyfile = NULL;
|
||||||
|
|
||||||
|
if (!IS_STRING_EMPTY (value)) {
|
||||||
|
if (is_fallback)
|
||||||
|
*is_fallback = TRUE;
|
||||||
|
keyfile = get_session_keyfile (value, actual_session, NULL);
|
||||||
|
}
|
||||||
|
g_free (value);
|
||||||
|
|
||||||
|
return keyfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_session_fill (GsmManager *manager,
|
||||||
|
const char *session)
|
||||||
|
{
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
gboolean is_fallback;
|
||||||
|
char *actual_session;
|
||||||
|
|
||||||
|
keyfile = get_session_keyfile (session, &actual_session, &is_fallback);
|
||||||
|
|
||||||
|
if (!keyfile)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
_gsm_manager_set_active_session (manager, actual_session, is_fallback);
|
||||||
|
|
||||||
|
g_free (actual_session);
|
||||||
|
|
||||||
|
load_standard_apps (manager, keyfile);
|
||||||
|
|
||||||
|
g_key_file_free (keyfile);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
32
gnome-session/gsm-session-fill.h
Normal file
32
gnome-session/gsm-session-fill.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006, 2010 Novell, Inc.
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_SESSION_FILL_H
|
||||||
|
#define __GSM_SESSION_FILL_H
|
||||||
|
|
||||||
|
#include "gsm-manager.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
gboolean gsm_session_fill (GsmManager *manager,
|
||||||
|
const char *session);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SESSION_FILL_H */
|
293
gnome-session/gsm-session-save.c
Normal file
293
gnome-session/gsm-session-save.c
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
* gsm-session-save.c
|
||||||
|
* Copyright (C) 2008 Lucas Rocha.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsm-app.h"
|
||||||
|
#include "gsm-util.h"
|
||||||
|
#include "gsm-autostart-app.h"
|
||||||
|
#include "gsm-client.h"
|
||||||
|
|
||||||
|
#include "gsm-session-save.h"
|
||||||
|
|
||||||
|
#define GSM_MANAGER_SCHEMA "org.gnome.SessionManager"
|
||||||
|
#define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot"
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean gsm_session_clear_saved_session (const char *directory,
|
||||||
|
GHashTable *discard_hash);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *dir;
|
||||||
|
GHashTable *discard_hash;
|
||||||
|
GsmStore *app_store;
|
||||||
|
GError **error;
|
||||||
|
} SessionSaveData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_app_has_app_id (const char *id,
|
||||||
|
GsmApp *app,
|
||||||
|
const char *app_id_a)
|
||||||
|
{
|
||||||
|
const char *app_id_b;
|
||||||
|
|
||||||
|
app_id_b = gsm_app_peek_app_id (app);
|
||||||
|
return g_strcmp0 (app_id_a, app_id_b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
save_one_client (char *id,
|
||||||
|
GObject *object,
|
||||||
|
SessionSaveData *data)
|
||||||
|
{
|
||||||
|
GsmClient *client;
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
GsmApp *app = NULL;
|
||||||
|
const char *app_id;
|
||||||
|
char *path = NULL;
|
||||||
|
char *filename = NULL;
|
||||||
|
char *contents = NULL;
|
||||||
|
gsize length = 0;
|
||||||
|
char *discard_exec;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
client = GSM_CLIENT (object);
|
||||||
|
|
||||||
|
app_id = gsm_client_peek_app_id (client);
|
||||||
|
if (!IS_STRING_EMPTY (app_id)) {
|
||||||
|
if (g_str_has_suffix (app_id, ".desktop"))
|
||||||
|
filename = g_strdup (app_id);
|
||||||
|
else
|
||||||
|
filename = g_strdup_printf ("%s.desktop", app_id);
|
||||||
|
|
||||||
|
path = g_build_filename (data->dir, filename, NULL);
|
||||||
|
|
||||||
|
app = (GsmApp *)gsm_store_find (data->app_store,
|
||||||
|
(GsmStoreFunc)_app_has_app_id,
|
||||||
|
(char *)app_id);
|
||||||
|
}
|
||||||
|
keyfile = gsm_client_save (client, app, &local_error);
|
||||||
|
|
||||||
|
if (keyfile == NULL || local_error) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = g_key_file_to_data (keyfile, &length, &local_error);
|
||||||
|
|
||||||
|
if (local_error) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path || g_file_test (path, G_FILE_TEST_EXISTS)) {
|
||||||
|
if (filename)
|
||||||
|
g_free (filename);
|
||||||
|
if (path)
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
filename = g_strdup_printf ("%s.desktop",
|
||||||
|
gsm_client_peek_startup_id (client));
|
||||||
|
path = g_build_filename (data->dir, filename, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_file_set_contents (path,
|
||||||
|
contents,
|
||||||
|
length,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
|
if (local_error) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
discard_exec = g_key_file_get_string (keyfile,
|
||||||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||||||
|
GSM_AUTOSTART_APP_DISCARD_KEY,
|
||||||
|
NULL);
|
||||||
|
if (discard_exec) {
|
||||||
|
g_hash_table_insert (data->discard_hash,
|
||||||
|
discard_exec, discard_exec);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GsmSessionSave: saved client %s to %s", id, filename);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (keyfile != NULL) {
|
||||||
|
g_key_file_free (keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (contents);
|
||||||
|
g_free (filename);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
/* in case of any error, stop saving session */
|
||||||
|
if (local_error) {
|
||||||
|
g_propagate_error (data->error, g_steal_pointer (&local_error));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_session_save (GsmStore *client_store,
|
||||||
|
GsmStore *app_store,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSettings *settings;
|
||||||
|
const char *save_dir;
|
||||||
|
SessionSaveData data;
|
||||||
|
|
||||||
|
g_debug ("GsmSessionSave: Saving session");
|
||||||
|
|
||||||
|
/* Clear one shot key autosave in the event its set (so that it's actually
|
||||||
|
* one shot only)
|
||||||
|
*/
|
||||||
|
settings = g_settings_new (GSM_MANAGER_SCHEMA);
|
||||||
|
g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE);
|
||||||
|
g_object_unref (settings);
|
||||||
|
|
||||||
|
save_dir = gsm_util_get_saved_session_dir ();
|
||||||
|
if (save_dir == NULL) {
|
||||||
|
g_warning ("GsmSessionSave: cannot create saved session directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.dir = save_dir;
|
||||||
|
data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, NULL);
|
||||||
|
data.app_store = app_store;
|
||||||
|
|
||||||
|
/* remove old saved session */
|
||||||
|
gsm_session_clear_saved_session (save_dir, data.discard_hash);
|
||||||
|
data.error = error;
|
||||||
|
|
||||||
|
gsm_store_foreach (client_store,
|
||||||
|
(GsmStoreFunc) save_one_client,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
g_hash_table_destroy (data.discard_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_session_clear_one_client (const char *filename,
|
||||||
|
GHashTable *discard_hash)
|
||||||
|
{
|
||||||
|
gboolean result = TRUE;
|
||||||
|
GKeyFile *key_file;
|
||||||
|
char *discard_exec = NULL;
|
||||||
|
char **envp;
|
||||||
|
|
||||||
|
g_debug ("GsmSessionSave: removing '%s' from saved session", filename);
|
||||||
|
|
||||||
|
envp = (char **) gsm_util_listenv ();
|
||||||
|
key_file = g_key_file_new ();
|
||||||
|
if (g_key_file_load_from_file (key_file, filename,
|
||||||
|
G_KEY_FILE_NONE, NULL)) {
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
discard_exec = g_key_file_get_string (key_file,
|
||||||
|
G_KEY_FILE_DESKTOP_GROUP,
|
||||||
|
GSM_AUTOSTART_APP_DISCARD_KEY,
|
||||||
|
NULL);
|
||||||
|
if (!discard_exec)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (discard_hash && g_hash_table_lookup (discard_hash, discard_exec))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!g_shell_parse_argv (discard_exec, &argc, &argv, NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
result = g_spawn_async (NULL, argv, envp, G_SPAWN_SEARCH_PATH,
|
||||||
|
NULL, NULL, NULL, NULL) && result;
|
||||||
|
|
||||||
|
g_strfreev (argv);
|
||||||
|
} else {
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (key_file)
|
||||||
|
g_key_file_free (key_file);
|
||||||
|
if (discard_exec)
|
||||||
|
g_free (discard_exec);
|
||||||
|
|
||||||
|
result = (g_unlink (filename) == 0) && result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_session_clear_saved_session (const char *directory,
|
||||||
|
GHashTable *discard_hash)
|
||||||
|
{
|
||||||
|
GDir *dir;
|
||||||
|
const char *filename;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
g_debug ("GsmSessionSave: clearing currently saved session at %s",
|
||||||
|
directory);
|
||||||
|
|
||||||
|
if (directory == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
dir = g_dir_open (directory, 0, &error);
|
||||||
|
if (error) {
|
||||||
|
g_warning ("GsmSessionSave: error loading saved session directory: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((filename = g_dir_read_name (dir))) {
|
||||||
|
char *path = g_build_filename (directory,
|
||||||
|
filename, NULL);
|
||||||
|
|
||||||
|
result = gsm_session_clear_one_client (path, discard_hash)
|
||||||
|
&& result;
|
||||||
|
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close (dir);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_session_save_clear (void)
|
||||||
|
{
|
||||||
|
const char *save_dir;
|
||||||
|
|
||||||
|
g_debug ("GsmSessionSave: Clearing saved session");
|
||||||
|
|
||||||
|
save_dir = gsm_util_get_saved_session_dir ();
|
||||||
|
if (save_dir == NULL) {
|
||||||
|
g_warning ("GsmSessionSave: cannot create saved session directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsm_session_clear_saved_session (save_dir, NULL);
|
||||||
|
}
|
34
gnome-session/gsm-session-save.h
Normal file
34
gnome-session/gsm-session-save.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* gsm-session-save.h
|
||||||
|
* Copyright (C) 2008 Lucas Rocha.
|
||||||
|
*
|
||||||
|
* 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 __GSM_SESSION_SAVE_H__
|
||||||
|
#define __GSM_SESSION_SAVE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "gsm-store.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gsm_session_save (GsmStore *client_store,
|
||||||
|
GsmStore *app_store,
|
||||||
|
GError **error);
|
||||||
|
void gsm_session_save_clear (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SESSION_SAVE_H__ */
|
199
gnome-session/gsm-shell-extensions.c
Normal file
199
gnome-session/gsm-shell-extensions.c
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc
|
||||||
|
*
|
||||||
|
* 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, 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <json-glib/json-glib.h>
|
||||||
|
|
||||||
|
#include "gsm-shell-extensions.h"
|
||||||
|
|
||||||
|
#define SHELL_SCHEMA "org.gnome.shell"
|
||||||
|
#define DISABLE_EXTENSIONS_KEY "disable-user-extensions"
|
||||||
|
|
||||||
|
#define SHELL_EXTENSIONS_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsPrivate))
|
||||||
|
|
||||||
|
struct _GsmShellExtensionsPrivate
|
||||||
|
{
|
||||||
|
GSettings *settings;
|
||||||
|
guint num_extensions;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmShellExtensions, gsm_shell_extensions, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_shell_extensions_finalize:
|
||||||
|
* @object: (in): A #GsmShellExtensions.
|
||||||
|
*
|
||||||
|
* Finalizer for a #GsmShellExtensions instance. Frees any resources held by
|
||||||
|
* the instance.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gsm_shell_extensions_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmShellExtensions *extensions = GSM_SHELL_EXTENSIONS (object);
|
||||||
|
GsmShellExtensionsPrivate *priv = extensions->priv;
|
||||||
|
|
||||||
|
g_clear_object (&priv->settings);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_shell_extensions_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_shell_extensions_class_init:
|
||||||
|
* @klass: (in): A #GsmShellExtensionsClass.
|
||||||
|
*
|
||||||
|
* Initializes the #GsmShellExtensionsClass and prepares the vtable.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gsm_shell_extensions_class_init (GsmShellExtensionsClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (klass);
|
||||||
|
object_class->finalize = gsm_shell_extensions_finalize;
|
||||||
|
g_type_class_add_private (object_class, sizeof (GsmShellExtensionsPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_extensions_scan_dir (GsmShellExtensions *self,
|
||||||
|
GFile *dir)
|
||||||
|
{
|
||||||
|
GFileEnumerator *enumerator;
|
||||||
|
GFileInfo *info;
|
||||||
|
JsonParser *metadata_parser;
|
||||||
|
|
||||||
|
metadata_parser = json_parser_new ();
|
||||||
|
|
||||||
|
enumerator = g_file_enumerate_children (dir,
|
||||||
|
"standard::*",
|
||||||
|
G_FILE_QUERY_INFO_NONE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (enumerator == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
|
||||||
|
{
|
||||||
|
gchar *metadata_filename;
|
||||||
|
const gchar *metadata_uuid;
|
||||||
|
gchar *dir_uuid;
|
||||||
|
JsonObject *metadata_root;
|
||||||
|
|
||||||
|
dir_uuid = (char *) g_file_info_get_name (info);
|
||||||
|
|
||||||
|
metadata_filename = g_build_filename (g_file_get_path (dir),
|
||||||
|
dir_uuid,
|
||||||
|
"metadata.json",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!json_parser_load_from_file (metadata_parser, metadata_filename, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_free (metadata_filename);
|
||||||
|
|
||||||
|
metadata_root = json_node_get_object (json_parser_get_root (metadata_parser));
|
||||||
|
|
||||||
|
metadata_uuid = json_object_get_string_member (metadata_root, "uuid");
|
||||||
|
if (!g_str_equal (metadata_uuid, dir_uuid))
|
||||||
|
{
|
||||||
|
g_warning ("Extension with dirname '%s' does not match metadata's UUID of '%s'. Skipping.",
|
||||||
|
dir_uuid, metadata_uuid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->num_extensions++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_extensions_scan (GsmShellExtensions *self)
|
||||||
|
{
|
||||||
|
gchar *dirname;
|
||||||
|
GFile *dir;
|
||||||
|
const gchar * const * system_data_dirs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* User data dir first. */
|
||||||
|
dirname = g_build_filename (g_get_user_data_dir (), "gnome-shell", "extensions", NULL);
|
||||||
|
dir = g_file_new_for_path (dirname);
|
||||||
|
g_free (dirname);
|
||||||
|
|
||||||
|
gsm_shell_extensions_scan_dir (self, dir);
|
||||||
|
g_object_unref (dir);
|
||||||
|
|
||||||
|
system_data_dirs = g_get_system_data_dirs ();
|
||||||
|
for (i = 0; system_data_dirs[i]; i++)
|
||||||
|
{
|
||||||
|
dirname = g_build_filename (system_data_dirs[i], "gnome-shell", "extensions", NULL);
|
||||||
|
dir = g_file_new_for_path (dirname);
|
||||||
|
g_free (dirname);
|
||||||
|
|
||||||
|
gsm_shell_extensions_scan_dir (self, dir);
|
||||||
|
g_object_unref (dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_shell_extensions_init:
|
||||||
|
* @self: (in): A #GsmShellExtensions.
|
||||||
|
*
|
||||||
|
* Initializes the newly created #GsmShellExtensions instance.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gsm_shell_extensions_init (GsmShellExtensions *self)
|
||||||
|
{
|
||||||
|
GSettingsSchemaSource *source;
|
||||||
|
GSettingsSchema *schema;
|
||||||
|
|
||||||
|
self->priv = SHELL_EXTENSIONS_PRIVATE (self);
|
||||||
|
|
||||||
|
source = g_settings_schema_source_get_default ();
|
||||||
|
schema = g_settings_schema_source_lookup (source, SHELL_SCHEMA, TRUE);
|
||||||
|
|
||||||
|
if (schema != NULL)
|
||||||
|
{
|
||||||
|
self->priv->settings = g_settings_new_full (schema, NULL, NULL);
|
||||||
|
g_settings_schema_unref (schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv->settings != NULL)
|
||||||
|
gsm_shell_extensions_scan (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_shell_extensions_disable_all (GsmShellExtensions *self)
|
||||||
|
{
|
||||||
|
return g_settings_set_boolean (self->priv->settings,
|
||||||
|
DISABLE_EXTENSIONS_KEY,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_shell_extensions_n_extensions (GsmShellExtensions *self)
|
||||||
|
{
|
||||||
|
if (self->priv->settings == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return self->priv->num_extensions;
|
||||||
|
}
|
61
gnome-session/gsm-shell-extensions.h
Normal file
61
gnome-session/gsm-shell-extensions.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc
|
||||||
|
*
|
||||||
|
* 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, 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_SHELL_EXTENSIONS_H
|
||||||
|
#define __GSM_SHELL_EXTENSIONS_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_SHELL_EXTENSIONS (gsm_shell_extensions_get_type ())
|
||||||
|
#define GSM_SHELL_EXTENSIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensions))
|
||||||
|
#define GSM_SHELL_EXTENSIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsClass))
|
||||||
|
#define GSM_IS_SHELL_EXTENSIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SHELL_EXTENSIONS))
|
||||||
|
#define GSM_IS_SHELL_EXTENSIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SHELL_EXTENSIONS))
|
||||||
|
#define GSM_SHELL_EXTENSIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_SHELL_EXTENSIONS, GsmShellExtensionsClass))
|
||||||
|
|
||||||
|
typedef struct _GsmShellExtensions GsmShellExtensions;
|
||||||
|
typedef struct _GsmShellExtensionsClass GsmShellExtensionsClass;
|
||||||
|
typedef struct _GsmShellExtensionsPrivate GsmShellExtensionsPrivate;
|
||||||
|
|
||||||
|
struct _GsmShellExtensions
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
GsmShellExtensionsPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmShellExtensionsClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gsm_shell_extensions_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
gboolean gsm_shell_extensions_disable_all (GsmShellExtensions *self);
|
||||||
|
|
||||||
|
guint gsm_shell_extensions_n_extensions (GsmShellExtensions *self);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SHELL_EXTENSIONS_H */
|
507
gnome-session/gsm-shell.c
Normal file
507
gnome-session/gsm-shell.c
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc
|
||||||
|
*
|
||||||
|
* 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, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsm-inhibitor.h"
|
||||||
|
#include "gsm-shell.h"
|
||||||
|
|
||||||
|
#define SHELL_NAME "org.gnome.Shell"
|
||||||
|
#define SHELL_PATH "/org/gnome/Shell"
|
||||||
|
#define SHELL_INTERFACE "org.gnome.Shell"
|
||||||
|
|
||||||
|
#define SHELL_END_SESSION_DIALOG_PATH "/org/gnome/SessionManager/EndSessionDialog"
|
||||||
|
#define SHELL_END_SESSION_DIALOG_INTERFACE "org.gnome.SessionManager.EndSessionDialog"
|
||||||
|
|
||||||
|
#define AUTOMATIC_ACTION_TIMEOUT 60
|
||||||
|
|
||||||
|
#define GSM_SHELL_GET_PRIVATE(o) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SHELL, GsmShellPrivate))
|
||||||
|
|
||||||
|
struct _GsmShellPrivate
|
||||||
|
{
|
||||||
|
GDBusProxy *end_session_dialog_proxy;
|
||||||
|
GsmStore *inhibitors;
|
||||||
|
|
||||||
|
guint32 is_running : 1;
|
||||||
|
|
||||||
|
gboolean dialog_is_open;
|
||||||
|
GsmShellEndSessionDialogType end_session_dialog_type;
|
||||||
|
|
||||||
|
guint update_idle_id;
|
||||||
|
guint watch_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_IS_RUNNING
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
END_SESSION_DIALOG_OPENED = 0,
|
||||||
|
END_SESSION_DIALOG_OPEN_FAILED,
|
||||||
|
END_SESSION_DIALOG_CLOSED,
|
||||||
|
END_SESSION_DIALOG_CANCELED,
|
||||||
|
END_SESSION_DIALOG_CONFIRMED_LOGOUT,
|
||||||
|
END_SESSION_DIALOG_CONFIRMED_SHUTDOWN,
|
||||||
|
END_SESSION_DIALOG_CONFIRMED_REBOOT,
|
||||||
|
NUMBER_OF_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[NUMBER_OF_SIGNALS] = { 0 };
|
||||||
|
|
||||||
|
static void gsm_shell_class_init (GsmShellClass *klass);
|
||||||
|
static void gsm_shell_init (GsmShell *ck);
|
||||||
|
static void gsm_shell_finalize (GObject *object);
|
||||||
|
|
||||||
|
static void queue_end_session_dialog_update (GsmShell *shell);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmShell, gsm_shell, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmShell *shell = GSM_SHELL (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_IS_RUNNING:
|
||||||
|
g_value_set_boolean (value,
|
||||||
|
shell->priv->is_running);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
|
||||||
|
prop_id,
|
||||||
|
pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_class_init (GsmShellClass *shell_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GParamSpec *param_spec;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (shell_class);
|
||||||
|
|
||||||
|
object_class->finalize = gsm_shell_finalize;
|
||||||
|
object_class->get_property = gsm_shell_get_property;
|
||||||
|
|
||||||
|
param_spec = g_param_spec_boolean ("is-running",
|
||||||
|
"Is running",
|
||||||
|
"Whether GNOME Shell is running in the session",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READABLE);
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_IS_RUNNING,
|
||||||
|
param_spec);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_OPENED] =
|
||||||
|
g_signal_new ("end-session-dialog-opened",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_opened),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_OPEN_FAILED] =
|
||||||
|
g_signal_new ("end-session-dialog-open-failed",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_open_failed),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_CLOSED] =
|
||||||
|
g_signal_new ("end-session-dialog-closed",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_closed),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_CANCELED] =
|
||||||
|
g_signal_new ("end-session-dialog-canceled",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_canceled),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_CONFIRMED_LOGOUT] =
|
||||||
|
g_signal_new ("end-session-dialog-confirmed-logout",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_confirmed_logout),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_CONFIRMED_SHUTDOWN] =
|
||||||
|
g_signal_new ("end-session-dialog-confirmed-shutdown",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_confirmed_shutdown),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals [END_SESSION_DIALOG_CONFIRMED_REBOOT] =
|
||||||
|
g_signal_new ("end-session-dialog-confirmed-reboot",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_confirmed_reboot),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
g_type_class_add_private (shell_class, sizeof (GsmShellPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_shell_name_vanished (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmShell *shell = user_data;
|
||||||
|
shell->priv->is_running = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_shell_name_appeared (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
const gchar *name_owner,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmShell *shell = user_data;
|
||||||
|
shell->priv->is_running = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_ensure_connection (GsmShell *shell)
|
||||||
|
{
|
||||||
|
if (shell->priv->watch_id != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell->priv->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
||||||
|
SHELL_NAME,
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
|
on_shell_name_appeared,
|
||||||
|
on_shell_name_vanished,
|
||||||
|
shell, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_init (GsmShell *shell)
|
||||||
|
{
|
||||||
|
shell->priv = GSM_SHELL_GET_PRIVATE (shell);
|
||||||
|
|
||||||
|
gsm_shell_ensure_connection (shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_shell_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmShell *shell;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
shell = GSM_SHELL (object);
|
||||||
|
|
||||||
|
parent_class = G_OBJECT_CLASS (gsm_shell_parent_class);
|
||||||
|
|
||||||
|
g_object_unref (shell->priv->inhibitors);
|
||||||
|
|
||||||
|
if (shell->priv->watch_id != 0) {
|
||||||
|
g_bus_unwatch_name (shell->priv->watch_id);
|
||||||
|
shell->priv->watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmShell *
|
||||||
|
gsm_shell_new (void)
|
||||||
|
{
|
||||||
|
GsmShell *shell;
|
||||||
|
|
||||||
|
shell = g_object_new (GSM_TYPE_SHELL, NULL);
|
||||||
|
|
||||||
|
return shell;
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmShell *
|
||||||
|
gsm_get_shell (void)
|
||||||
|
{
|
||||||
|
static GsmShell *shell = NULL;
|
||||||
|
|
||||||
|
if (shell == NULL) {
|
||||||
|
shell = gsm_shell_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_object_ref (shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_shell_is_running (GsmShell *shell)
|
||||||
|
{
|
||||||
|
gsm_shell_ensure_connection (shell);
|
||||||
|
|
||||||
|
return shell->priv->is_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
add_inhibitor_to_array (const char *id,
|
||||||
|
GsmInhibitor *inhibitor,
|
||||||
|
GVariantBuilder *builder)
|
||||||
|
{
|
||||||
|
g_variant_builder_add (builder, "o", gsm_inhibitor_peek_id (inhibitor));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
get_array_from_store (GsmStore *inhibitors)
|
||||||
|
{
|
||||||
|
GVariantBuilder builder;
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
|
||||||
|
gsm_store_foreach (inhibitors,
|
||||||
|
(GsmStoreFunc) add_inhibitor_to_array,
|
||||||
|
&builder);
|
||||||
|
|
||||||
|
return g_variant_builder_end (&builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_open_finished (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GsmShell *shell = user_data;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
if (shell->priv->update_idle_id != 0) {
|
||||||
|
g_source_remove (shell->priv->update_idle_id);
|
||||||
|
shell->priv->update_idle_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell->priv->dialog_is_open = FALSE;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Unable to open shell end session dialog: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_OPEN_FAILED], 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_OPENED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_end_session_dialog_dbus_signal (GDBusProxy *proxy,
|
||||||
|
gchar *sender_name,
|
||||||
|
gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
GsmShell *shell)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
int index;
|
||||||
|
} signal_map[] = {
|
||||||
|
{ "Closed", END_SESSION_DIALOG_CLOSED },
|
||||||
|
{ "Canceled", END_SESSION_DIALOG_CANCELED },
|
||||||
|
{ "ConfirmedLogout", END_SESSION_DIALOG_CONFIRMED_LOGOUT },
|
||||||
|
{ "ConfirmedReboot", END_SESSION_DIALOG_CONFIRMED_REBOOT },
|
||||||
|
{ "ConfirmedShutdown", END_SESSION_DIALOG_CONFIRMED_SHUTDOWN },
|
||||||
|
{ NULL, -1 }
|
||||||
|
};
|
||||||
|
int signal_index = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; signal_map[i].name != NULL; i++) {
|
||||||
|
if (g_strcmp0 (signal_map[i].name, signal_name) == 0) {
|
||||||
|
signal_index = signal_map[i].index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal_index == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shell->priv->dialog_is_open = FALSE;
|
||||||
|
|
||||||
|
if (shell->priv->update_idle_id != 0) {
|
||||||
|
g_source_remove (shell->priv->update_idle_id);
|
||||||
|
shell->priv->update_idle_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (shell->priv->inhibitors,
|
||||||
|
G_CALLBACK (queue_end_session_dialog_update),
|
||||||
|
shell);
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (shell), signals[signal_index], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_end_session_dialog_name_owner_changed (GDBusProxy *proxy,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GsmShell *shell)
|
||||||
|
{
|
||||||
|
gchar *name_owner;
|
||||||
|
|
||||||
|
name_owner = g_dbus_proxy_get_name_owner (proxy);
|
||||||
|
if (name_owner == NULL) {
|
||||||
|
g_clear_object (&shell->priv->end_session_dialog_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (name_owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_need_end_session_dialog_update (GsmShell *shell)
|
||||||
|
{
|
||||||
|
/* No longer need an update */
|
||||||
|
if (shell->priv->update_idle_id == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
shell->priv->update_idle_id = 0;
|
||||||
|
|
||||||
|
gsm_shell_open_end_session_dialog (shell,
|
||||||
|
shell->priv->end_session_dialog_type,
|
||||||
|
shell->priv->inhibitors);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
queue_end_session_dialog_update (GsmShell *shell)
|
||||||
|
{
|
||||||
|
if (shell->priv->update_idle_id != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shell->priv->update_idle_id = g_idle_add ((GSourceFunc) on_need_end_session_dialog_update,
|
||||||
|
shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_shell_open_end_session_dialog (GsmShell *shell,
|
||||||
|
GsmShellEndSessionDialogType type,
|
||||||
|
GsmStore *inhibitors)
|
||||||
|
{
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
|
||||||
|
if (shell->priv->dialog_is_open) {
|
||||||
|
g_return_val_if_fail (shell->priv->end_session_dialog_type == type,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shell->priv->end_session_dialog_proxy == NULL) {
|
||||||
|
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
SHELL_NAME,
|
||||||
|
SHELL_END_SESSION_DIALOG_PATH,
|
||||||
|
SHELL_END_SESSION_DIALOG_INTERFACE,
|
||||||
|
NULL, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_critical ("Could not connect to the shell: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell->priv->end_session_dialog_proxy = proxy;
|
||||||
|
|
||||||
|
g_signal_connect (proxy, "notify::g-name-owner",
|
||||||
|
G_CALLBACK (on_end_session_dialog_name_owner_changed),
|
||||||
|
shell);
|
||||||
|
g_signal_connect (proxy, "g-signal",
|
||||||
|
G_CALLBACK (on_end_session_dialog_dbus_signal),
|
||||||
|
shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_proxy_call (shell->priv->end_session_dialog_proxy,
|
||||||
|
"Open",
|
||||||
|
g_variant_new ("(uuu@ao)",
|
||||||
|
type,
|
||||||
|
0,
|
||||||
|
AUTOMATIC_ACTION_TIMEOUT,
|
||||||
|
get_array_from_store (inhibitors)),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
G_MAXINT, NULL,
|
||||||
|
on_open_finished, shell);
|
||||||
|
|
||||||
|
g_object_ref (inhibitors);
|
||||||
|
|
||||||
|
if (shell->priv->inhibitors != NULL) {
|
||||||
|
g_signal_handlers_disconnect_by_func (shell->priv->inhibitors,
|
||||||
|
G_CALLBACK (queue_end_session_dialog_update),
|
||||||
|
shell);
|
||||||
|
g_object_unref (shell->priv->inhibitors);
|
||||||
|
}
|
||||||
|
|
||||||
|
shell->priv->inhibitors = inhibitors;
|
||||||
|
|
||||||
|
g_signal_connect_swapped (inhibitors, "added",
|
||||||
|
G_CALLBACK (queue_end_session_dialog_update),
|
||||||
|
shell);
|
||||||
|
|
||||||
|
g_signal_connect_swapped (inhibitors, "removed",
|
||||||
|
G_CALLBACK (queue_end_session_dialog_update),
|
||||||
|
shell);
|
||||||
|
|
||||||
|
shell->priv->dialog_is_open = TRUE;
|
||||||
|
shell->priv->end_session_dialog_type = type;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_shell_close_end_session_dialog (GsmShell *shell)
|
||||||
|
{
|
||||||
|
if (!shell->priv->end_session_dialog_proxy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shell->priv->dialog_is_open = FALSE;
|
||||||
|
|
||||||
|
g_dbus_proxy_call (shell->priv->end_session_dialog_proxy,
|
||||||
|
"Close",
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, NULL, NULL, NULL);
|
||||||
|
}
|
87
gnome-session/gsm-shell.h
Normal file
87
gnome-session/gsm-shell.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_SHELL_H__
|
||||||
|
#define __GSM_SHELL_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gsm-store.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_SHELL (gsm_shell_get_type ())
|
||||||
|
#define GSM_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SHELL, GsmShell))
|
||||||
|
#define GSM_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SHELL, GsmShellClass))
|
||||||
|
#define GSM_IS_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SHELL))
|
||||||
|
#define GSM_IS_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SHELL))
|
||||||
|
#define GSM_SHELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_SHELL, GsmShellClass))
|
||||||
|
#define GSM_SHELL_ERROR (gsm_shell_error_quark ())
|
||||||
|
|
||||||
|
typedef struct _GsmShell GsmShell;
|
||||||
|
typedef struct _GsmShellClass GsmShellClass;
|
||||||
|
typedef struct _GsmShellPrivate GsmShellPrivate;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT = 0,
|
||||||
|
GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN,
|
||||||
|
GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART,
|
||||||
|
} GsmShellEndSessionDialogType;
|
||||||
|
|
||||||
|
struct _GsmShell
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GsmShellPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmShellClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* end_session_dialog_opened) (GsmShell *shell);
|
||||||
|
void (* end_session_dialog_open_failed) (GsmShell *shell);
|
||||||
|
void (* end_session_dialog_closed) (GsmShell *shell);
|
||||||
|
void (* end_session_dialog_canceled) (GsmShell *shell);
|
||||||
|
|
||||||
|
void (* end_session_dialog_confirmed_logout) (GsmShell *shell);
|
||||||
|
void (* end_session_dialog_confirmed_shutdown) (GsmShell *shell);
|
||||||
|
void (* end_session_dialog_confirmed_reboot) (GsmShell *shell);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gsm_shell_get_type (void);
|
||||||
|
|
||||||
|
GsmShell *gsm_shell_new (void);
|
||||||
|
|
||||||
|
GsmShell *gsm_get_shell (void);
|
||||||
|
gboolean gsm_shell_is_running (GsmShell *shell);
|
||||||
|
|
||||||
|
gboolean gsm_shell_open_end_session_dialog (GsmShell *shell,
|
||||||
|
GsmShellEndSessionDialogType type,
|
||||||
|
GsmStore *inhibitors);
|
||||||
|
void gsm_shell_close_end_session_dialog (GsmShell *shell);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SHELL_H__ */
|
408
gnome-session/gsm-store.c
Normal file
408
gnome-session/gsm-store.c
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gsm-store.h"
|
||||||
|
|
||||||
|
#define GSM_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_STORE, GsmStorePrivate))
|
||||||
|
|
||||||
|
struct GsmStorePrivate
|
||||||
|
{
|
||||||
|
GHashTable *objects;
|
||||||
|
gboolean locked;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADDED,
|
||||||
|
REMOVED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_LOCKED
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
static void gsm_store_class_init (GsmStoreClass *klass);
|
||||||
|
static void gsm_store_init (GsmStore *store);
|
||||||
|
static void gsm_store_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GsmStore, gsm_store, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_store_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gsm_store_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_store_size (GsmStore *store)
|
||||||
|
{
|
||||||
|
return g_hash_table_size (store->priv->objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_store_remove (GsmStore *store,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
GObject *found;
|
||||||
|
gboolean removed;
|
||||||
|
char *id_copy;
|
||||||
|
|
||||||
|
g_return_val_if_fail (store != NULL, FALSE);
|
||||||
|
|
||||||
|
found = g_hash_table_lookup (store->priv->objects, id);
|
||||||
|
if (found == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
id_copy = g_strdup (id);
|
||||||
|
|
||||||
|
g_object_ref (found);
|
||||||
|
|
||||||
|
removed = g_hash_table_remove (store->priv->objects, id_copy);
|
||||||
|
g_assert (removed);
|
||||||
|
|
||||||
|
g_signal_emit (store, signals [REMOVED], 0, id_copy);
|
||||||
|
|
||||||
|
g_object_unref (found);
|
||||||
|
g_free (id_copy);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_store_foreach (GsmStore *store,
|
||||||
|
GsmStoreFunc func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_return_if_fail (store != NULL);
|
||||||
|
g_return_if_fail (func != NULL);
|
||||||
|
|
||||||
|
g_hash_table_find (store->priv->objects,
|
||||||
|
(GHRFunc)func,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GObject *
|
||||||
|
gsm_store_find (GsmStore *store,
|
||||||
|
GsmStoreFunc predicate,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
g_return_val_if_fail (store != NULL, NULL);
|
||||||
|
g_return_val_if_fail (predicate != NULL, NULL);
|
||||||
|
|
||||||
|
object = g_hash_table_find (store->priv->objects,
|
||||||
|
(GHRFunc)predicate,
|
||||||
|
user_data);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
GObject *
|
||||||
|
gsm_store_lookup (GsmStore *store,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
g_return_val_if_fail (store != NULL, NULL);
|
||||||
|
g_return_val_if_fail (id != NULL, NULL);
|
||||||
|
|
||||||
|
object = g_hash_table_lookup (store->priv->objects, id);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GsmStoreFunc func;
|
||||||
|
gpointer user_data;
|
||||||
|
GsmStore *store;
|
||||||
|
GList *removed;
|
||||||
|
} WrapperData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
foreach_remove_wrapper (const char *id,
|
||||||
|
GObject *object,
|
||||||
|
WrapperData *data)
|
||||||
|
{
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
res = (data->func) (id, object, data->user_data);
|
||||||
|
if (res) {
|
||||||
|
data->removed = g_list_prepend (data->removed, g_strdup (id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gsm_store_foreach_remove (GsmStore *store,
|
||||||
|
GsmStoreFunc func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
guint ret;
|
||||||
|
WrapperData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (store != NULL, 0);
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
data.store = store;
|
||||||
|
data.user_data = user_data;
|
||||||
|
data.func = func;
|
||||||
|
data.removed = NULL;
|
||||||
|
|
||||||
|
ret = g_hash_table_foreach_remove (store->priv->objects,
|
||||||
|
(GHRFunc)foreach_remove_wrapper,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
while (data.removed != NULL) {
|
||||||
|
char *id;
|
||||||
|
id = data.removed->data;
|
||||||
|
g_debug ("GsmStore: emitting removed for %s", id);
|
||||||
|
g_signal_emit (store, signals [REMOVED], 0, id);
|
||||||
|
g_free (data.removed->data);
|
||||||
|
data.removed->data = NULL;
|
||||||
|
data.removed = g_list_delete_link (data.removed, data.removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_remove_all (const char *id,
|
||||||
|
GObject *object,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_store_clear (GsmStore *store)
|
||||||
|
{
|
||||||
|
g_return_if_fail (store != NULL);
|
||||||
|
|
||||||
|
g_debug ("GsmStore: Clearing object store");
|
||||||
|
|
||||||
|
gsm_store_foreach_remove (store,
|
||||||
|
_remove_all,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_store_add (GsmStore *store,
|
||||||
|
const char *id,
|
||||||
|
GObject *object)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (store != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (id != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (object != NULL, FALSE);
|
||||||
|
|
||||||
|
/* If we're locked, we don't accept any new session
|
||||||
|
objects. */
|
||||||
|
if (store->priv->locked) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GsmStore: Adding object id %s to store", id);
|
||||||
|
|
||||||
|
g_hash_table_insert (store->priv->objects,
|
||||||
|
g_strdup (id),
|
||||||
|
g_object_ref (object));
|
||||||
|
|
||||||
|
g_signal_emit (store, signals [ADDED], 0, id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_store_set_locked (GsmStore *store,
|
||||||
|
gboolean locked)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSM_IS_STORE (store));
|
||||||
|
|
||||||
|
store->priv->locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_store_get_locked (GsmStore *store)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSM_IS_STORE (store), FALSE);
|
||||||
|
|
||||||
|
return store->priv->locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmStore *self;
|
||||||
|
|
||||||
|
self = GSM_STORE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_LOCKED:
|
||||||
|
gsm_store_set_locked (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GsmStore *self;
|
||||||
|
|
||||||
|
self = GSM_STORE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_LOCKED:
|
||||||
|
g_value_set_boolean (value, self->priv->locked);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GsmStore *store;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GSM_IS_STORE (object));
|
||||||
|
|
||||||
|
store = GSM_STORE (object);
|
||||||
|
|
||||||
|
gsm_store_clear (store);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_store_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_class_init (GsmStoreClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gsm_store_get_property;
|
||||||
|
object_class->set_property = gsm_store_set_property;
|
||||||
|
object_class->finalize = gsm_store_finalize;
|
||||||
|
object_class->dispose = gsm_store_dispose;
|
||||||
|
|
||||||
|
signals [ADDED] =
|
||||||
|
g_signal_new ("added",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmStoreClass, added),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_STRING);
|
||||||
|
signals [REMOVED] =
|
||||||
|
g_signal_new ("removed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmStoreClass, removed),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_STRING);
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_LOCKED,
|
||||||
|
g_param_spec_boolean ("locked",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GsmStorePrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_destroy_object (GObject *object)
|
||||||
|
{
|
||||||
|
g_debug ("GsmStore: Unreffing object: %p", object);
|
||||||
|
g_object_unref (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_init (GsmStore *store)
|
||||||
|
{
|
||||||
|
|
||||||
|
store->priv = GSM_STORE_GET_PRIVATE (store);
|
||||||
|
|
||||||
|
store->priv->objects = g_hash_table_new_full (g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
(GDestroyNotify) _destroy_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_store_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GsmStore *store;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GSM_IS_STORE (object));
|
||||||
|
|
||||||
|
store = GSM_STORE (object);
|
||||||
|
|
||||||
|
g_return_if_fail (store->priv != NULL);
|
||||||
|
|
||||||
|
g_hash_table_destroy (store->priv->objects);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsm_store_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmStore *
|
||||||
|
gsm_store_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GSM_TYPE_STORE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GSM_STORE (object);
|
||||||
|
}
|
96
gnome-session/gsm-store.h
Normal file
96
gnome-session/gsm-store.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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 __GSM_STORE_H
|
||||||
|
#define __GSM_STORE_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_STORE (gsm_store_get_type ())
|
||||||
|
#define GSM_STORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSM_TYPE_STORE, GsmStore))
|
||||||
|
#define GSM_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSM_TYPE_STORE, GsmStoreClass))
|
||||||
|
#define GSM_IS_STORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSM_TYPE_STORE))
|
||||||
|
#define GSM_IS_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSM_TYPE_STORE))
|
||||||
|
#define GSM_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSM_TYPE_STORE, GsmStoreClass))
|
||||||
|
|
||||||
|
typedef struct GsmStorePrivate GsmStorePrivate;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
GsmStorePrivate *priv;
|
||||||
|
} GsmStore;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* added) (GsmStore *store,
|
||||||
|
const char *id);
|
||||||
|
void (* removed) (GsmStore *store,
|
||||||
|
const char *id);
|
||||||
|
} GsmStoreClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GSM_STORE_ERROR_GENERAL
|
||||||
|
} GsmStoreError;
|
||||||
|
|
||||||
|
#define GSM_STORE_ERROR gsm_store_error_quark ()
|
||||||
|
|
||||||
|
typedef gboolean (*GsmStoreFunc) (const char *id,
|
||||||
|
GObject *object,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GQuark gsm_store_error_quark (void);
|
||||||
|
GType gsm_store_get_type (void);
|
||||||
|
|
||||||
|
GsmStore * gsm_store_new (void);
|
||||||
|
|
||||||
|
gboolean gsm_store_get_locked (GsmStore *store);
|
||||||
|
void gsm_store_set_locked (GsmStore *store,
|
||||||
|
gboolean locked);
|
||||||
|
|
||||||
|
guint gsm_store_size (GsmStore *store);
|
||||||
|
gboolean gsm_store_add (GsmStore *store,
|
||||||
|
const char *id,
|
||||||
|
GObject *object);
|
||||||
|
void gsm_store_clear (GsmStore *store);
|
||||||
|
gboolean gsm_store_remove (GsmStore *store,
|
||||||
|
const char *id);
|
||||||
|
|
||||||
|
void gsm_store_foreach (GsmStore *store,
|
||||||
|
GsmStoreFunc func,
|
||||||
|
gpointer user_data);
|
||||||
|
guint gsm_store_foreach_remove (GsmStore *store,
|
||||||
|
GsmStoreFunc func,
|
||||||
|
gpointer user_data);
|
||||||
|
GObject * gsm_store_find (GsmStore *store,
|
||||||
|
GsmStoreFunc predicate,
|
||||||
|
gpointer user_data);
|
||||||
|
GObject * gsm_store_lookup (GsmStore *store,
|
||||||
|
const char *id);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_STORE_H */
|
276
gnome-session/gsm-system.c
Normal file
276
gnome-session/gsm-system.c
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include "gsm-system.h"
|
||||||
|
|
||||||
|
#include "gsm-systemd.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REQUEST_COMPLETED,
|
||||||
|
SHUTDOWN_PREPARED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_ACTIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_INTERFACE (GsmSystem, gsm_system, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_system_default_init (GsmSystemInterface *iface)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
signals [REQUEST_COMPLETED] =
|
||||||
|
g_signal_new ("request-completed",
|
||||||
|
GSM_TYPE_SYSTEM,
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmSystemInterface, request_completed),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_POINTER);
|
||||||
|
signals[SHUTDOWN_PREPARED] =
|
||||||
|
g_signal_new ("shutdown-prepared",
|
||||||
|
GSM_TYPE_SYSTEM,
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GsmSystemInterface, shutdown_prepared),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_BOOLEAN);
|
||||||
|
pspec = g_param_spec_boolean ("active",
|
||||||
|
"Active",
|
||||||
|
"Whether or not session is active",
|
||||||
|
TRUE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
||||||
|
g_object_interface_install_property (iface, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GObject GsmSystemNull;
|
||||||
|
typedef GObjectClass GsmSystemNullClass;
|
||||||
|
|
||||||
|
static void do_nothing (void) { }
|
||||||
|
static gboolean return_true (void) { return TRUE; }
|
||||||
|
static gboolean return_false (void) { return FALSE; }
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_system_null_init_iface (GsmSystemInterface *iface)
|
||||||
|
{
|
||||||
|
iface->can_switch_user = (void *) return_false;
|
||||||
|
iface->can_stop = (void *) return_false;
|
||||||
|
iface->can_restart = (void *) return_false;
|
||||||
|
iface->can_restart_to_firmware_setup = (void *) return_false;
|
||||||
|
iface->set_restart_to_firmware_setup = (void *) do_nothing;
|
||||||
|
iface->can_suspend = (void *) return_false;
|
||||||
|
iface->can_hibernate = (void *) return_false;
|
||||||
|
iface->attempt_stop = (void *) do_nothing;
|
||||||
|
iface->attempt_restart = (void *) do_nothing;
|
||||||
|
iface->suspend = (void *) do_nothing;
|
||||||
|
iface->hibernate = (void *) do_nothing;
|
||||||
|
iface->set_session_idle = (void *) do_nothing;
|
||||||
|
iface->is_login_session = (void *) return_true;
|
||||||
|
iface->set_inhibitors = (void *) do_nothing;
|
||||||
|
iface->prepare_shutdown = (void *) do_nothing;
|
||||||
|
iface->complete_shutdown = (void *) do_nothing;
|
||||||
|
iface->is_last_session_for_user = (void *) return_false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_system_null_init (GsmSystemNull *gsn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_system_null_get_property (GObject *object, guint prop_id,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
g_value_set_boolean (value, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsm_system_null_class_init (GsmSystemNullClass *class)
|
||||||
|
{
|
||||||
|
class->get_property = gsm_system_null_get_property;
|
||||||
|
class->set_property = (void *) do_nothing;
|
||||||
|
|
||||||
|
g_object_class_override_property (class, 1, "active");
|
||||||
|
}
|
||||||
|
|
||||||
|
static GType gsm_system_null_get_type (void);
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GsmSystemNull, gsm_system_null, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (GSM_TYPE_SYSTEM, gsm_system_null_init_iface))
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gsm_system_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark error_quark = 0;
|
||||||
|
|
||||||
|
if (error_quark == 0) {
|
||||||
|
error_quark = g_quark_from_static_string ("gsm-system-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_quark;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_switch_user (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_switch_user (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_stop (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_stop (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_restart (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_restart (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_restart_to_firmware_setup (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_restart_to_firmware_setup (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_set_restart_to_firmware_setup (GsmSystem *system,
|
||||||
|
gboolean enable)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->set_restart_to_firmware_setup (system, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_suspend (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_suspend (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_can_hibernate (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->can_hibernate (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_attempt_stop (GsmSystem *system)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->attempt_stop (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_attempt_restart (GsmSystem *system)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->attempt_restart (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_suspend (GsmSystem *system)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->suspend (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_hibernate (GsmSystem *system)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->hibernate (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_set_session_idle (GsmSystem *system,
|
||||||
|
gboolean is_idle)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->set_session_idle (system, is_idle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_set_inhibitors (GsmSystem *system,
|
||||||
|
GsmInhibitorFlag flags)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->set_inhibitors (system, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_is_login_session (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->is_login_session (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_system_is_last_session_for_user (GsmSystem *system)
|
||||||
|
{
|
||||||
|
return GSM_SYSTEM_GET_IFACE (system)->is_last_session_for_user (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_system_is_active:
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the current session is in the foreground
|
||||||
|
* Since: 3.8
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gsm_system_is_active (GsmSystem *system)
|
||||||
|
{
|
||||||
|
gboolean is_active;
|
||||||
|
g_object_get ((GObject*)system, "active", &is_active, NULL);
|
||||||
|
return is_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_prepare_shutdown (GsmSystem *system,
|
||||||
|
gboolean restart)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->prepare_shutdown (system, restart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_system_complete_shutdown (GsmSystem *system)
|
||||||
|
{
|
||||||
|
GSM_SYSTEM_GET_IFACE (system)->complete_shutdown (system);
|
||||||
|
}
|
||||||
|
|
||||||
|
GsmSystem *
|
||||||
|
gsm_get_system (void)
|
||||||
|
{
|
||||||
|
static GsmSystem *system = NULL;
|
||||||
|
|
||||||
|
if (system == NULL) {
|
||||||
|
system = GSM_SYSTEM (gsm_systemd_new ());
|
||||||
|
if (system != NULL) {
|
||||||
|
g_debug ("Using systemd for session tracking");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system == NULL) {
|
||||||
|
system = g_object_new (gsm_system_null_get_type (), NULL);
|
||||||
|
g_warning ("Using null backend for session tracking");
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_object_ref (system);
|
||||||
|
}
|
130
gnome-session/gsm-system.h
Normal file
130
gnome-session/gsm-system.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Jon McCann <jmccann@redhat.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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jon McCann <jmccann@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_SYSTEM_H__
|
||||||
|
#define __GSM_SYSTEM_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gsm-inhibitor.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_SYSTEM (gsm_system_get_type ())
|
||||||
|
#define GSM_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SYSTEM, GsmSystem))
|
||||||
|
#define GSM_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SYSTEM, GsmSystemInterface))
|
||||||
|
#define GSM_IS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SYSTEM))
|
||||||
|
#define GSM_SYSTEM_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GSM_TYPE_SYSTEM, GsmSystemInterface))
|
||||||
|
#define GSM_SYSTEM_ERROR (gsm_system_error_quark ())
|
||||||
|
|
||||||
|
typedef struct _GsmSystem GsmSystem;
|
||||||
|
typedef struct _GsmSystemInterface GsmSystemInterface;
|
||||||
|
typedef enum _GsmSystemError GsmSystemError;
|
||||||
|
|
||||||
|
struct _GsmSystemInterface
|
||||||
|
{
|
||||||
|
GTypeInterface base_interface;
|
||||||
|
|
||||||
|
void (* request_completed) (GsmSystem *system,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void (* shutdown_prepared) (GsmSystem *system,
|
||||||
|
gboolean success);
|
||||||
|
|
||||||
|
gboolean (* can_switch_user) (GsmSystem *system);
|
||||||
|
gboolean (* can_stop) (GsmSystem *system);
|
||||||
|
gboolean (* can_restart) (GsmSystem *system);
|
||||||
|
gboolean (* can_restart_to_firmware_setup) (GsmSystem *system);
|
||||||
|
void (* set_restart_to_firmware_setup) (GsmSystem *system,
|
||||||
|
gboolean enable);
|
||||||
|
gboolean (* can_suspend) (GsmSystem *system);
|
||||||
|
gboolean (* can_hibernate) (GsmSystem *system);
|
||||||
|
void (* attempt_stop) (GsmSystem *system);
|
||||||
|
void (* attempt_restart) (GsmSystem *system);
|
||||||
|
void (* suspend) (GsmSystem *system);
|
||||||
|
void (* hibernate) (GsmSystem *system);
|
||||||
|
void (* set_session_idle) (GsmSystem *system,
|
||||||
|
gboolean is_idle);
|
||||||
|
gboolean (* is_login_session) (GsmSystem *system);
|
||||||
|
void (* set_inhibitors) (GsmSystem *system,
|
||||||
|
GsmInhibitorFlag flags);
|
||||||
|
void (* prepare_shutdown) (GsmSystem *system,
|
||||||
|
gboolean restart);
|
||||||
|
void (* complete_shutdown)(GsmSystem *system);
|
||||||
|
gboolean (* is_last_session_for_user) (GsmSystem *system);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _GsmSystemError {
|
||||||
|
GSM_SYSTEM_ERROR_RESTARTING = 0,
|
||||||
|
GSM_SYSTEM_ERROR_STOPPING
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gsm_system_get_type (void);
|
||||||
|
|
||||||
|
GQuark gsm_system_error_quark (void);
|
||||||
|
|
||||||
|
GsmSystem *gsm_get_system (void);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_switch_user (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_stop (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_restart (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_restart_to_firmware_setup (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_set_restart_to_firmware_setup (GsmSystem *system,
|
||||||
|
gboolean enable);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_suspend (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_can_hibernate (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_attempt_stop (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_attempt_restart (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_suspend (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_hibernate (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_set_session_idle (GsmSystem *system,
|
||||||
|
gboolean is_idle);
|
||||||
|
|
||||||
|
gboolean gsm_system_is_login_session (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_is_last_session_for_user (GsmSystem *system);
|
||||||
|
|
||||||
|
gboolean gsm_system_is_active (GsmSystem *system);
|
||||||
|
|
||||||
|
void gsm_system_set_inhibitors (GsmSystem *system,
|
||||||
|
GsmInhibitorFlag flags);
|
||||||
|
|
||||||
|
void gsm_system_prepare_shutdown (GsmSystem *system,
|
||||||
|
gboolean restart);
|
||||||
|
void gsm_system_complete_shutdown (GsmSystem *system);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SYSTEM_H__ */
|
1197
gnome-session/gsm-systemd.c
Normal file
1197
gnome-session/gsm-systemd.c
Normal file
File diff suppressed because it is too large
Load diff
59
gnome-session/gsm-systemd.h
Normal file
59
gnome-session/gsm-systemd.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Matthias Clasen <mclasen@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_SYSTEMD_H__
|
||||||
|
#define __GSM_SYSTEMD_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_SYSTEMD (gsm_systemd_get_type ())
|
||||||
|
#define GSM_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SYSTEMD, GsmSystemd))
|
||||||
|
#define GSM_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SYSTEMD, GsmSystemdClass))
|
||||||
|
#define GSM_IS_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SYSTEMD))
|
||||||
|
#define GSM_IS_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SYSTEMD))
|
||||||
|
#define GSM_SYSTEMD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_SYSTEMD, GsmSystemdClass))
|
||||||
|
|
||||||
|
typedef struct _GsmSystemd GsmSystemd;
|
||||||
|
typedef struct _GsmSystemdClass GsmSystemdClass;
|
||||||
|
typedef struct _GsmSystemdPrivate GsmSystemdPrivate;
|
||||||
|
|
||||||
|
struct _GsmSystemd
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GsmSystemdPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmSystemdClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gsm_systemd_get_type (void);
|
||||||
|
|
||||||
|
GsmSystemd *gsm_systemd_new (void) G_GNUC_MALLOC;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_SYSTEMD_H__ */
|
929
gnome-session/gsm-util.c
Normal file
929
gnome-session/gsm-util.c
Normal file
|
@ -0,0 +1,929 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
* gsm-util.c
|
||||||
|
* Copyright (C) 2008 Lucas Rocha.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsm-util.h"
|
||||||
|
|
||||||
|
static gchar *_saved_session_dir = NULL;
|
||||||
|
static gchar **child_environment;
|
||||||
|
|
||||||
|
/* These are variables that will not be passed on to subprocesses
|
||||||
|
* (either directly, via systemd or DBus).
|
||||||
|
* Some of these are blacklisted as they might end up in the wrong session
|
||||||
|
* (e.g. XDG_VTNR), others because they simply must never be passed on
|
||||||
|
* (NOTIFY_SOCKET).
|
||||||
|
*/
|
||||||
|
static const char * const variable_blacklist[] = {
|
||||||
|
"NOTIFY_SOCKET",
|
||||||
|
"XDG_SEAT",
|
||||||
|
"XDG_SESSION_ID",
|
||||||
|
"XDG_VTNR",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The following is copied from GDMs spawn_session function.
|
||||||
|
*
|
||||||
|
* Environment variables listed here will be copied into the user's service
|
||||||
|
* environments if they are set in gnome-session's environment. If they are
|
||||||
|
* not set in gnome-session's environment, they will be removed from the
|
||||||
|
* service environments. This is to protect against environment variables
|
||||||
|
* leaking from previous sessions (e.g. when switching from classic to
|
||||||
|
* default GNOME $GNOME_SHELL_SESSION_MODE will become unset).
|
||||||
|
*/
|
||||||
|
static const char * const variable_unsetlist[] = {
|
||||||
|
"DISPLAY",
|
||||||
|
"XAUTHORITY",
|
||||||
|
"WAYLAND_DISPLAY",
|
||||||
|
"WAYLAND_SOCKET",
|
||||||
|
"GNOME_SHELL_SESSION_MODE",
|
||||||
|
"GNOME_SETUP_DISPLAY",
|
||||||
|
|
||||||
|
/* None of the LC_* variables should survive a logout/login */
|
||||||
|
"LC_CTYPE",
|
||||||
|
"LC_NUMERIC",
|
||||||
|
"LC_TIME",
|
||||||
|
"LC_COLLATE",
|
||||||
|
"LC_MONETARY",
|
||||||
|
"LC_MESSAGES",
|
||||||
|
"LC_PAPER",
|
||||||
|
"LC_NAME",
|
||||||
|
"LC_ADDRESS",
|
||||||
|
"LC_TELEPHONE",
|
||||||
|
"LC_MEASUREMENT",
|
||||||
|
"LC_IDENTIFICATION",
|
||||||
|
"LC_ALL",
|
||||||
|
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
char *
|
||||||
|
gsm_util_find_desktop_file_for_app_name (const char *name,
|
||||||
|
gboolean look_in_saved_session,
|
||||||
|
gboolean autostart_first)
|
||||||
|
{
|
||||||
|
char *app_path;
|
||||||
|
char **app_dirs;
|
||||||
|
GKeyFile *key_file;
|
||||||
|
char *desktop_file;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
app_path = NULL;
|
||||||
|
|
||||||
|
app_dirs = gsm_util_get_desktop_dirs (look_in_saved_session, autostart_first);
|
||||||
|
|
||||||
|
key_file = g_key_file_new ();
|
||||||
|
|
||||||
|
desktop_file = g_strdup_printf ("%s.desktop", name);
|
||||||
|
|
||||||
|
g_debug ("GsmUtil: Looking for file '%s'", desktop_file);
|
||||||
|
|
||||||
|
for (i = 0; app_dirs[i] != NULL; i++) {
|
||||||
|
g_debug ("GsmUtil: Looking in '%s'", app_dirs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_key_file_load_from_dirs (key_file,
|
||||||
|
desktop_file,
|
||||||
|
(const char **) app_dirs,
|
||||||
|
&app_path,
|
||||||
|
G_KEY_FILE_NONE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (app_path != NULL) {
|
||||||
|
g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for gnome vendor prefix */
|
||||||
|
if (app_path == NULL) {
|
||||||
|
g_free (desktop_file);
|
||||||
|
desktop_file = g_strdup_printf ("gnome-%s.desktop", name);
|
||||||
|
|
||||||
|
g_key_file_load_from_dirs (key_file,
|
||||||
|
desktop_file,
|
||||||
|
(const char **) app_dirs,
|
||||||
|
&app_path,
|
||||||
|
G_KEY_FILE_NONE,
|
||||||
|
NULL);
|
||||||
|
if (app_path != NULL) {
|
||||||
|
g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (desktop_file);
|
||||||
|
g_key_file_free (key_file);
|
||||||
|
|
||||||
|
g_strfreev (app_dirs);
|
||||||
|
|
||||||
|
return app_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ensure_dir_exists (const char *dir)
|
||||||
|
{
|
||||||
|
if (g_mkdir_with_parents (dir, 0700) == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
g_warning ("GsmSessionSave: Failed to create directory %s: %s", dir, strerror (errno));
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
gsm_util_get_empty_tmp_session_dir (void)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
gboolean exists;
|
||||||
|
|
||||||
|
tmp = g_build_filename (g_get_user_config_dir (),
|
||||||
|
"gnome-session",
|
||||||
|
"saved-session.new",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
exists = ensure_dir_exists (tmp);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!exists)) {
|
||||||
|
g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp);
|
||||||
|
g_free (tmp);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
/* make sure it's empty */
|
||||||
|
GDir *dir;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
dir = g_dir_open (tmp, 0, NULL);
|
||||||
|
if (dir) {
|
||||||
|
while ((filename = g_dir_read_name (dir))) {
|
||||||
|
char *path = g_build_filename (tmp, filename,
|
||||||
|
NULL);
|
||||||
|
g_unlink (path);
|
||||||
|
}
|
||||||
|
g_dir_close (dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *
|
||||||
|
gsm_util_get_saved_session_dir (void)
|
||||||
|
{
|
||||||
|
if (_saved_session_dir == NULL) {
|
||||||
|
gboolean exists;
|
||||||
|
|
||||||
|
_saved_session_dir =
|
||||||
|
g_build_filename (g_get_user_config_dir (),
|
||||||
|
"gnome-session",
|
||||||
|
"saved-session",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
exists = ensure_dir_exists (_saved_session_dir);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!exists)) {
|
||||||
|
static gboolean printed_warning = FALSE;
|
||||||
|
|
||||||
|
if (!printed_warning) {
|
||||||
|
g_warning ("GsmSessionSave: could not create directory for saved session: %s", _saved_session_dir);
|
||||||
|
printed_warning = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_saved_session_dir = NULL;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _saved_session_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char ** autostart_dirs;
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_util_set_autostart_dirs (char ** dirs)
|
||||||
|
{
|
||||||
|
autostart_dirs = g_strdupv (dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **
|
||||||
|
gsm_util_get_standard_autostart_dirs (void)
|
||||||
|
{
|
||||||
|
GPtrArray *dirs;
|
||||||
|
const char * const *system_config_dirs;
|
||||||
|
const char * const *system_data_dirs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dirs = g_ptr_array_new ();
|
||||||
|
|
||||||
|
g_ptr_array_add (dirs,
|
||||||
|
g_build_filename (g_get_user_config_dir (),
|
||||||
|
"autostart", NULL));
|
||||||
|
|
||||||
|
system_data_dirs = g_get_system_data_dirs ();
|
||||||
|
for (i = 0; system_data_dirs[i]; i++) {
|
||||||
|
g_ptr_array_add (dirs,
|
||||||
|
g_build_filename (system_data_dirs[i],
|
||||||
|
"gnome", "autostart", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
system_config_dirs = g_get_system_config_dirs ();
|
||||||
|
for (i = 0; system_config_dirs[i]; i++) {
|
||||||
|
g_ptr_array_add (dirs,
|
||||||
|
g_build_filename (system_config_dirs[i],
|
||||||
|
"autostart", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (dirs, NULL);
|
||||||
|
|
||||||
|
return (char **) g_ptr_array_free (dirs, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char **
|
||||||
|
gsm_util_get_autostart_dirs ()
|
||||||
|
{
|
||||||
|
if (autostart_dirs) {
|
||||||
|
return g_strdupv ((char **)autostart_dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gsm_util_get_standard_autostart_dirs ();
|
||||||
|
}
|
||||||
|
|
||||||
|
char **
|
||||||
|
gsm_util_get_app_dirs ()
|
||||||
|
{
|
||||||
|
GPtrArray *dirs;
|
||||||
|
const char * const *system_data_dirs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dirs = g_ptr_array_new ();
|
||||||
|
|
||||||
|
g_ptr_array_add (dirs,
|
||||||
|
g_build_filename (g_get_user_data_dir (),
|
||||||
|
"applications",
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
system_data_dirs = g_get_system_data_dirs ();
|
||||||
|
for (i = 0; system_data_dirs[i]; i++) {
|
||||||
|
g_ptr_array_add (dirs,
|
||||||
|
g_build_filename (system_data_dirs[i],
|
||||||
|
"applications",
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (dirs, NULL);
|
||||||
|
|
||||||
|
return (char **) g_ptr_array_free (dirs, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char **
|
||||||
|
gsm_util_get_desktop_dirs (gboolean include_saved_session,
|
||||||
|
gboolean autostart_first)
|
||||||
|
{
|
||||||
|
char **apps;
|
||||||
|
char **autostart;
|
||||||
|
char **standard_autostart;
|
||||||
|
char **result;
|
||||||
|
int size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
apps = gsm_util_get_app_dirs ();
|
||||||
|
autostart = gsm_util_get_autostart_dirs ();
|
||||||
|
|
||||||
|
/* Still, check the standard autostart dirs for things like fulfilling session reqs,
|
||||||
|
* if using a non-standard autostart dir for autostarting */
|
||||||
|
if (autostart_dirs != NULL)
|
||||||
|
standard_autostart = gsm_util_get_standard_autostart_dirs ();
|
||||||
|
else
|
||||||
|
standard_autostart = NULL;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
for (i = 0; apps[i] != NULL; i++) { size++; }
|
||||||
|
for (i = 0; autostart[i] != NULL; i++) { size++; }
|
||||||
|
if (standard_autostart != NULL)
|
||||||
|
for (i = 0; standard_autostart[i] != NULL; i++) { size++; }
|
||||||
|
if (include_saved_session)
|
||||||
|
size += 1;
|
||||||
|
|
||||||
|
result = g_new (char *, size + 1); /* including last NULL */
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
if (autostart_first) {
|
||||||
|
if (include_saved_session)
|
||||||
|
result[size++] = g_strdup (gsm_util_get_saved_session_dir ());
|
||||||
|
|
||||||
|
for (i = 0; autostart[i] != NULL; i++, size++) {
|
||||||
|
result[size] = autostart[i];
|
||||||
|
}
|
||||||
|
if (standard_autostart != NULL) {
|
||||||
|
for (i = 0; standard_autostart[i] != NULL; i++, size++) {
|
||||||
|
result[size] = standard_autostart[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; apps[i] != NULL; i++, size++) {
|
||||||
|
result[size] = apps[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; apps[i] != NULL; i++, size++) {
|
||||||
|
result[size] = apps[i];
|
||||||
|
}
|
||||||
|
if (standard_autostart != NULL) {
|
||||||
|
for (i = 0; standard_autostart[i] != NULL; i++, size++) {
|
||||||
|
result[size] = standard_autostart[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; autostart[i] != NULL; i++, size++) {
|
||||||
|
result[size] = autostart[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include_saved_session)
|
||||||
|
result[size++] = g_strdup (gsm_util_get_saved_session_dir ());
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (apps);
|
||||||
|
g_free (autostart);
|
||||||
|
g_free (standard_autostart);
|
||||||
|
|
||||||
|
result[size] = NULL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_text_is_blank (const char *str)
|
||||||
|
{
|
||||||
|
if (str == NULL) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*str) {
|
||||||
|
if (!isspace(*str)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_util_init_error:
|
||||||
|
* @fatal: whether or not the error is fatal to the login session
|
||||||
|
* @format: printf-style error message format
|
||||||
|
* @...: error message args
|
||||||
|
*
|
||||||
|
* Displays the error message to the user. If @fatal is %TRUE, gsm
|
||||||
|
* will exit after displaying the message.
|
||||||
|
*
|
||||||
|
* This should be called for major errors that occur before the
|
||||||
|
* session is up and running. (Notably, it positions the dialog box
|
||||||
|
* itself, since no window manager will be running yet.)
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gsm_util_init_error (gboolean fatal,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
char *msg;
|
||||||
|
va_list args;
|
||||||
|
gchar *argv[13];
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
msg = g_strdup_vprintf (format, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
argv[0] = "zenity";
|
||||||
|
argv[1] = "--error";
|
||||||
|
argv[2] = "--class";
|
||||||
|
argv[3] = "mutter-dialog";
|
||||||
|
argv[4] = "--title";
|
||||||
|
argv[5] = "\"\"";
|
||||||
|
argv[6] = "--text";
|
||||||
|
argv[7] = msg;
|
||||||
|
argv[8] = "--icon-name";
|
||||||
|
argv[9] = "face-sad-symbolic";
|
||||||
|
argv[10] = "--ok-label";
|
||||||
|
argv[11] = _("_Log out");
|
||||||
|
argv[12] = NULL;
|
||||||
|
|
||||||
|
g_spawn_sync (NULL, argv, child_environment, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
g_free (msg);
|
||||||
|
|
||||||
|
if (fatal) {
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsm_util_generate_startup_id:
|
||||||
|
*
|
||||||
|
* Generates a new SM client ID.
|
||||||
|
*
|
||||||
|
* Return value: an SM client ID.
|
||||||
|
**/
|
||||||
|
char *
|
||||||
|
gsm_util_generate_startup_id (void)
|
||||||
|
{
|
||||||
|
static int sequence = -1;
|
||||||
|
static guint rand1 = 0;
|
||||||
|
static guint rand2 = 0;
|
||||||
|
static pid_t pid = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
/* The XSMP spec defines the ID as:
|
||||||
|
*
|
||||||
|
* Version: "1"
|
||||||
|
* Address type and address:
|
||||||
|
* "1" + an IPv4 address as 8 hex digits
|
||||||
|
* "2" + a DECNET address as 12 hex digits
|
||||||
|
* "6" + an IPv6 address as 32 hex digits
|
||||||
|
* Time stamp: milliseconds since UNIX epoch as 13 decimal digits
|
||||||
|
* Process-ID type and process-ID:
|
||||||
|
* "1" + POSIX PID as 10 decimal digits
|
||||||
|
* Sequence number as 4 decimal digits
|
||||||
|
*
|
||||||
|
* XSMP client IDs are supposed to be globally unique: if
|
||||||
|
* SmsGenerateClientID() is unable to determine a network
|
||||||
|
* address for the machine, it gives up and returns %NULL.
|
||||||
|
* GNOME and KDE have traditionally used a fourth address
|
||||||
|
* format in this case:
|
||||||
|
* "0" + 16 random hex digits
|
||||||
|
*
|
||||||
|
* We don't even bother trying SmsGenerateClientID(), since the
|
||||||
|
* user's IP address is probably "192.168.1.*" anyway, so a random
|
||||||
|
* number is actually more likely to be globally unique.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!rand1) {
|
||||||
|
rand1 = g_random_int ();
|
||||||
|
rand2 = g_random_int ();
|
||||||
|
pid = getpid ();
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence = (sequence + 1) % 10000;
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
return g_strdup_printf ("10%.04x%.04x%.10lu%.3u%.10lu%.4d",
|
||||||
|
rand1,
|
||||||
|
rand2,
|
||||||
|
(unsigned long) tv.tv_sec,
|
||||||
|
(unsigned) tv.tv_usec,
|
||||||
|
(unsigned long) pid,
|
||||||
|
sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_util_update_activation_environment (const char *variable,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GDBusConnection *connection;
|
||||||
|
gboolean environment_updated;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GVariant *reply;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
environment_updated = FALSE;
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
g_variant_builder_add (&builder, "{ss}", variable, value);
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"UpdateActivationEnvironment",
|
||||||
|
g_variant_new ("(@a{ss})",
|
||||||
|
g_variant_builder_end (&builder)),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
} else {
|
||||||
|
environment_updated = TRUE;
|
||||||
|
g_variant_unref (reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&connection);
|
||||||
|
|
||||||
|
return environment_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_export_activation_environment (GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
GDBusConnection *connection;
|
||||||
|
gboolean environment_updated = FALSE;
|
||||||
|
char **entry_names;
|
||||||
|
int i = 0;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GRegex *name_regex, *value_regex;
|
||||||
|
GVariant *reply;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_regex = g_regex_new ("^[a-zA-Z_][a-zA-Z0-9_]*$", G_REGEX_OPTIMIZE, 0, error);
|
||||||
|
|
||||||
|
if (name_regex == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_regex = g_regex_new ("^(?:[ \t\n]|[^[:cntrl:]])*$", G_REGEX_OPTIMIZE, 0, error);
|
||||||
|
|
||||||
|
if (value_regex == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child_environment == NULL) {
|
||||||
|
child_environment = g_listenv ();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
for (entry_names = g_listenv (); entry_names[i] != NULL; i++) {
|
||||||
|
const char *entry_name = entry_names[i];
|
||||||
|
const char *entry_value = g_getenv (entry_name);
|
||||||
|
|
||||||
|
if (g_strv_contains (variable_blacklist, entry_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!g_utf8_validate (entry_name, -1, NULL) ||
|
||||||
|
!g_regex_match (name_regex, entry_name, 0, NULL) ||
|
||||||
|
!g_utf8_validate (entry_value, -1, NULL) ||
|
||||||
|
!g_regex_match (value_regex, entry_value, 0, NULL)) {
|
||||||
|
|
||||||
|
g_message ("Environment variable is unsafe to export to dbus: %s", entry_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_environment = g_environ_setenv (child_environment,
|
||||||
|
entry_name, entry_value,
|
||||||
|
TRUE);
|
||||||
|
g_variant_builder_add (&builder, "{ss}", entry_name, entry_value);
|
||||||
|
}
|
||||||
|
g_regex_unref (name_regex);
|
||||||
|
g_regex_unref (value_regex);
|
||||||
|
|
||||||
|
g_strfreev (entry_names);
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"UpdateActivationEnvironment",
|
||||||
|
g_variant_new ("(@a{ss})",
|
||||||
|
g_variant_builder_end (&builder)),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
} else {
|
||||||
|
environment_updated = TRUE;
|
||||||
|
g_variant_unref (reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&connection);
|
||||||
|
|
||||||
|
return environment_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_export_user_environment (GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
GDBusConnection *connection;
|
||||||
|
gboolean environment_updated = FALSE;
|
||||||
|
char **entries;
|
||||||
|
int i = 0;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GRegex *regex;
|
||||||
|
GVariant *reply;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
regex = g_regex_new ("^[a-zA-Z_][a-zA-Z0-9_]*=(?:[ \t\n]|[^[:cntrl:]])*$", G_REGEX_OPTIMIZE, 0, error);
|
||||||
|
|
||||||
|
if (regex == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = g_get_environ ();
|
||||||
|
|
||||||
|
for (i = 0; variable_blacklist[i] != NULL; i++)
|
||||||
|
entries = g_environ_unsetenv (entries, variable_blacklist[i]);
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(asas)"));
|
||||||
|
|
||||||
|
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
for (i = 0; variable_unsetlist[i] != NULL; i++)
|
||||||
|
g_variant_builder_add (&builder, "s", variable_unsetlist[i]);
|
||||||
|
for (i = 0; variable_blacklist[i] != NULL; i++)
|
||||||
|
g_variant_builder_add (&builder, "s", variable_blacklist[i]);
|
||||||
|
g_variant_builder_close (&builder);
|
||||||
|
|
||||||
|
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
for (i = 0; entries[i] != NULL; i++) {
|
||||||
|
const char *entry = entries[i];
|
||||||
|
|
||||||
|
if (!g_utf8_validate (entry, -1, NULL) ||
|
||||||
|
!g_regex_match (regex, entry, 0, NULL)) {
|
||||||
|
|
||||||
|
g_message ("Environment entry is unsafe to upload into user environment: %s", entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&builder, "s", entry);
|
||||||
|
}
|
||||||
|
g_variant_builder_close (&builder);
|
||||||
|
g_regex_unref (regex);
|
||||||
|
|
||||||
|
g_strfreev (entries);
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"UnsetAndSetEnvironment",
|
||||||
|
g_variant_builder_end (&builder),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
} else {
|
||||||
|
environment_updated = TRUE;
|
||||||
|
g_variant_unref (reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&connection);
|
||||||
|
|
||||||
|
return environment_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsm_util_update_user_environment (const char *variable,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GDBusConnection *connection;
|
||||||
|
gboolean environment_updated;
|
||||||
|
char *entry;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GVariant *reply;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
environment_updated = FALSE;
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
entry = g_strdup_printf ("%s=%s", variable, value);
|
||||||
|
g_variant_builder_add (&builder, "s", entry);
|
||||||
|
g_free (entry);
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"SetEnvironment",
|
||||||
|
g_variant_new ("(@as)",
|
||||||
|
g_variant_builder_end (&builder)),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
} else {
|
||||||
|
environment_updated = TRUE;
|
||||||
|
g_variant_unref (reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&connection);
|
||||||
|
|
||||||
|
return environment_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_systemd_unit_is_active (const char *unit,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusProxy) proxy = NULL;
|
||||||
|
g_autoptr(GVariant) result = NULL;
|
||||||
|
g_autofree gchar *object_path = NULL;
|
||||||
|
g_autofree gchar *active_state = NULL;
|
||||||
|
g_autoptr(GDBusProxy) unit_proxy = NULL;
|
||||||
|
|
||||||
|
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
|
||||||
|
if (proxy == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = g_dbus_proxy_call_sync (proxy,
|
||||||
|
"GetUnit",
|
||||||
|
g_variant_new ("(s)", unit),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
if (error && *error) {
|
||||||
|
g_autofree char *remote_error = g_dbus_error_get_remote_error (*error);
|
||||||
|
|
||||||
|
if (g_strcmp0 (remote_error, "org.freedesktop.systemd1.NoSuchUnit") == 0) {
|
||||||
|
g_clear_error (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (result, "(o)", &object_path);
|
||||||
|
g_clear_pointer (&result, g_variant_unref);
|
||||||
|
|
||||||
|
unit_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.systemd1.Unit",
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
|
||||||
|
if (unit_proxy == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = g_dbus_proxy_get_cached_property (unit_proxy, "ActiveState");
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, "Error getting ActiveState property");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (result, "s", &active_state);
|
||||||
|
|
||||||
|
return g_str_equal (active_state, "active");
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_start_systemd_unit (const char *unit,
|
||||||
|
const char *mode,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusConnection) connection = NULL;
|
||||||
|
g_autoptr(GVariant) reply = NULL;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"StartUnit",
|
||||||
|
g_variant_new ("(ss)",
|
||||||
|
unit, mode),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsm_util_systemd_reset_failed (GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusConnection) connection = NULL;
|
||||||
|
g_autoptr(GVariant) reply = NULL;
|
||||||
|
GError *bus_error = NULL;
|
||||||
|
|
||||||
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
||||||
|
|
||||||
|
if (connection == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"ResetFailed",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
-1, NULL, &bus_error);
|
||||||
|
|
||||||
|
if (bus_error != NULL) {
|
||||||
|
g_propagate_error (error, bus_error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsm_util_setenv (const char *variable,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (child_environment == NULL)
|
||||||
|
child_environment = g_listenv ();
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
child_environment = g_environ_unsetenv (child_environment, variable);
|
||||||
|
else
|
||||||
|
child_environment = g_environ_setenv (child_environment, variable, value, TRUE);
|
||||||
|
|
||||||
|
/* If this fails it isn't fatal, it means some things like session
|
||||||
|
* management and keyring won't work in activated clients.
|
||||||
|
*/
|
||||||
|
if (!gsm_util_update_activation_environment (variable, value, &error)) {
|
||||||
|
g_warning ("Could not make bus activated clients aware of %s=%s environment variable: %s", variable, value, error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this fails, the system user session won't get the updated environment
|
||||||
|
*/
|
||||||
|
if (!gsm_util_update_user_environment (variable, value, &error)) {
|
||||||
|
g_debug ("Could not make systemd aware of %s=%s environment variable: %s", variable, value, error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * const *
|
||||||
|
gsm_util_listenv (void)
|
||||||
|
{
|
||||||
|
return (const char * const *) child_environment;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * const *
|
||||||
|
gsm_util_get_variable_blacklist (void)
|
||||||
|
{
|
||||||
|
return variable_blacklist;
|
||||||
|
}
|
69
gnome-session/gsm-util.h
Normal file
69
gnome-session/gsm-util.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* gsm-util.h
|
||||||
|
* Copyright (C) 2008 Lucas Rocha.
|
||||||
|
*
|
||||||
|
* 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 __GSM_UTIL_H__
|
||||||
|
#define __GSM_UTIL_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define IS_STRING_EMPTY(x) ((x)==NULL||(x)[0]=='\0')
|
||||||
|
|
||||||
|
char * gsm_util_find_desktop_file_for_app_name (const char *app_name,
|
||||||
|
gboolean look_in_saved_session,
|
||||||
|
gboolean autostart_first);
|
||||||
|
|
||||||
|
gchar *gsm_util_get_empty_tmp_session_dir (void);
|
||||||
|
|
||||||
|
const char *gsm_util_get_saved_session_dir (void);
|
||||||
|
|
||||||
|
gchar** gsm_util_get_app_dirs (void);
|
||||||
|
|
||||||
|
gchar** gsm_util_get_autostart_dirs (void);
|
||||||
|
void gsm_util_set_autostart_dirs (char **dirs);
|
||||||
|
|
||||||
|
gchar ** gsm_util_get_desktop_dirs (gboolean include_saved_session,
|
||||||
|
gboolean autostart_first);
|
||||||
|
|
||||||
|
gboolean gsm_util_text_is_blank (const char *str);
|
||||||
|
|
||||||
|
void gsm_util_init_error (gboolean fatal,
|
||||||
|
const char *format, ...) G_GNUC_PRINTF (2, 3);
|
||||||
|
|
||||||
|
char * gsm_util_generate_startup_id (void);
|
||||||
|
|
||||||
|
void gsm_util_setenv (const char *variable,
|
||||||
|
const char *value);
|
||||||
|
const char * const * gsm_util_listenv (void);
|
||||||
|
const char * const * gsm_util_get_variable_blacklist(void);
|
||||||
|
|
||||||
|
gboolean gsm_util_export_activation_environment (GError **error);
|
||||||
|
gboolean gsm_util_export_user_environment (GError **error);
|
||||||
|
gboolean gsm_util_systemd_unit_is_active (const char *unit,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_util_start_systemd_unit (const char *unit,
|
||||||
|
const char *mode,
|
||||||
|
GError **error);
|
||||||
|
gboolean gsm_util_systemd_reset_failed (GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
void gsm_quit (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_UTIL_H__ */
|
1359
gnome-session/gsm-xsmp-client.c
Normal file
1359
gnome-session/gsm-xsmp-client.c
Normal file
File diff suppressed because it is too large
Load diff
89
gnome-session/gsm-xsmp-client.h
Normal file
89
gnome-session/gsm-xsmp-client.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Novell, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GSM_XSMP_CLIENT_H__
|
||||||
|
#define __GSM_XSMP_CLIENT_H__
|
||||||
|
|
||||||
|
#include "gsm-client.h"
|
||||||
|
|
||||||
|
#include <X11/SM/SMlib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GSM_TYPE_XSMP_CLIENT (gsm_xsmp_client_get_type ())
|
||||||
|
#define GSM_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClient))
|
||||||
|
#define GSM_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass))
|
||||||
|
#define GSM_IS_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_XSMP_CLIENT))
|
||||||
|
#define GSM_IS_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_XSMP_CLIENT))
|
||||||
|
#define GSM_XSMP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass))
|
||||||
|
|
||||||
|
typedef struct _GsmXSMPClient GsmXSMPClient;
|
||||||
|
typedef struct _GsmXSMPClientClass GsmXSMPClientClass;
|
||||||
|
|
||||||
|
typedef struct GsmXSMPClientPrivate GsmXSMPClientPrivate;
|
||||||
|
|
||||||
|
struct _GsmXSMPClient
|
||||||
|
{
|
||||||
|
GsmClient parent;
|
||||||
|
GsmXSMPClientPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GsmXSMPClientClass
|
||||||
|
{
|
||||||
|
GsmClientClass parent_class;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
gboolean (*register_request) (GsmXSMPClient *client,
|
||||||
|
char **client_id);
|
||||||
|
void (*register_confirmed) (GsmXSMPClient *client,
|
||||||
|
const char *client_id);
|
||||||
|
gboolean (*logout_request) (GsmXSMPClient *client,
|
||||||
|
gboolean prompt);
|
||||||
|
|
||||||
|
|
||||||
|
void (*saved_state) (GsmXSMPClient *client);
|
||||||
|
|
||||||
|
void (*request_phase2) (GsmXSMPClient *client);
|
||||||
|
|
||||||
|
void (*request_interaction) (GsmXSMPClient *client);
|
||||||
|
void (*interaction_done) (GsmXSMPClient *client,
|
||||||
|
gboolean cancel_shutdown);
|
||||||
|
|
||||||
|
void (*save_yourself_done) (GsmXSMPClient *client);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gsm_xsmp_client_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GsmClient *gsm_xsmp_client_new (IceConn ice_conn);
|
||||||
|
|
||||||
|
void gsm_xsmp_client_connect (GsmXSMPClient *client,
|
||||||
|
SmsConn conn,
|
||||||
|
unsigned long *mask_ret,
|
||||||
|
SmsCallbacks *callbacks_ret);
|
||||||
|
|
||||||
|
void gsm_xsmp_client_save_state (GsmXSMPClient *client);
|
||||||
|
void gsm_xsmp_client_save_yourself (GsmXSMPClient *client,
|
||||||
|
gboolean save_state);
|
||||||
|
void gsm_xsmp_client_save_yourself_phase2 (GsmXSMPClient *client);
|
||||||
|
void gsm_xsmp_client_interact (GsmXSMPClient *client);
|
||||||
|
void gsm_xsmp_client_shutdown_cancelled (GsmXSMPClient *client);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_XSMP_CLIENT_H__ */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue