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