./ 0000755 0000041 0000041 00000000000 13264221041 011236 5 ustar www-data www-data ./man/ 0000755 0000041 0000041 00000000000 13264221014 012011 5 ustar www-data www-data ./man/unity-settings-daemon.xml 0000644 0000041 0000041 00000014035 13264221014 017005 0 ustar www-data www-data
unity-settings-daemon
Unity
Maintainer
Bastien
Nocera
hadess@hadess.net
unity-settings-daemon
1
User Commands
unity-settings-daemon
Unity settings daemon
unity-settings-daemon OPTION
Description
unity-settings-daemon provides many
session-wide services and functions that require a
long-running process.
Among the services implemented by unity-settings-daemon
are an XSettings manager, which provides theming, font
and other settings to GTK+ applications, and a clipboard
manager, which preserves clipboard contents when an
application exits.
Many user interface elements of
unity and
unity-control-center rely on
unity-settings-daemon for their functionality.
The internal architecture of unity-settings-daemon
consists of a number of plugins, which provide functionality
such as printer notifications, software update monitoring,
background changing, etc. For debugging purposes, these
plugins can be individually disabled by changing the
gsettings key org.gnome.settings-daemon.plugins.plugin-name.active, where
plugin-name is
the name of the plugin. To see a list of all plugins,
use the command
gsettings list-children org.gnome.settings-daemon.plugins
unity-settings-daemon takes the name
org.gnome.SettingsDaemon on the session bus to ensure
that only one instance is running. Some plugins export
objects under this name to make their functionality
available to other applications. The interfaces of
these objects should generally be considered private
and unstable.
unity-settings-daemon is a required component of
the Unity desktop, i.e. it is listed in the
RequiredComponents field of
/usr/share/gnome-session/sessions/gnome.session.
It is started in the initialization phase of the session,
and gnome-session will restart it
if it crashes.
Options
,
Prints a short help
text and exits.
Enables debugging code.
Exits after a timeout (30 seconds) for debugging.
Files
/usr/share/gnome-session/sessions/ubuntu.session
Unity session definition file where unity-settings-daemon is listed as a required component.
/etc/xdg/autostart/unity-settings-daemon.desktop
Autostart file for unity-settings-daemon, where its autostart phase is set.
See Also
unity1,
unity-control-center1,
gnome-session1
./man/Makefile.am 0000644 0000041 0000041 00000001037 13264221014 014046 0 ustar www-data www-data XSLTPROC_FLAGS = \
--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
.xml.1:
$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
man_MANS = \
unity-settings-daemon.1
xml_files = $(man_MANS:.1=.xml)
EXTRA_DIST = $(xml_files)
DISTCLEANFILES = $(man_MANS)
./NEWS 0000644 0000041 0000041 00000301462 13264221014 011743 0 ustar www-data www-data ===============
Version 3.8.6.1
===============
- New release for build failures
=============
Version 3.8.6
=============
Housekeeping:
- Optimise for "do nothing" when cleaning thumbnails
Keyboard:
- Don't set the XKB group switching option when not needed
Mouse:
- Fix critical warnings with touchpad settings
Wacom:
- Make OSD work again with newer librsvg
Power:
- Stop X from turning our screen off
XRandR:
- Prevent guint32 overflow
=============
Version 3.8.5
=============
Housekeeping:
- Fixed a bug that would prevent files in the Trash from being purged
Mouse:
- Enable edge scrolling if two-finger scroll is unavailable
Power:
- Fix a crash when hibernating on low power
Printers:
- Translate printer warnings
- Code cleanup
- Do more things asynchronously
- Poll remote CUPS servers for notifications
Screensaver:
- Support KDE variant of interface
- Fix a crash
Updates:
- Fix a crash
=============
Version 3.8.4
=============
- Fix possible crasher on startup
- Fix battery warning notifications not going away after
plugging the laptop
- Make gnome-shell's monitoring of user-added applications
faster by creating the directory for them
- Fix possible crash in XRandR with overlapping screens
=============
Version 3.8.3
=============
Media-keys:
- Fix potential crash if gnome-shell crashes while coming up
- Show shell search for search button
Keyboard:
- Remove the input source switcher helper
- Introduce a SetInputSource DBus method
Updates:
- Fix potential crash
=============
Version 3.8.2
=============
Media-keys:
- Don't show a label for "analog-output" ports
Color:
- Remove warning for some laptop docks
- Don't try to parse temporary files we generate
Power:
- Fix brightness not being restored on resume on some systems
- Make "Turn off screen when inactive" switch work
=============
Version 3.8.1
=============
Power:
- Don't change the active state when running in a VM
- Fix compilation on non-Linux platforms
Cursor:
- Fix possible crashes on older versions of X.org
Media-keys:
- Fix race condition with gnome-shell on startup
- Fix broken startup notifications
- Fix possible crash when changing the volume
- Fix crash when the shell vanishes and reappears
Keyboard:
- Cancel outstanding D-Bus operations when stopping
- Enforce the XKB group when changing layouts
- Make sure to add the XKB US layout in GDM on empty configurations
Mouse:
- Enable two-finger scrolling by default
Printers:
- Fix deprecation compile-time warnings
=============
Version 3.8.0
=============
Color:
- Set the default profile locale to be en_US, not EN_us
Power:
- Fix state problems if gnome-shell crashes or is killed within
the screensaver
Cursor:
- Fix crash with X.org prior to 1.14, requires a matching gnome-desktop
release as well
- Updated translations
==============
Version 3.7.92
==============
Media keys:
- Remove obsolete check for XInput2
- Use the shell's D-Bus interface to show OSDs
- Fix warnings on startup trying to call gnome-shell
Keyboard:
- Fix extra layouts being forgotten on GDM's second launch
- Fix dead keys and similar features being broken in legacy applications
- Avoid delay switch to IBus input source the first time around
Font:
- Remove reference to font schema
Updates:
- Fix possible crashers on exit
- Updated translations
==============
Version 3.7.91
==============
Media keys:
- Key grabbing is now done in gnome-shell, which fixes problems
with keybindings not working in certain conditions
Sound:
- Fix possible crashes when starting in a clean home directory
Cursor:
- Disable code to make it popup the On-Screen Keyboard on touchscreens
==============
Version 3.7.90
==============
- Set locale and IBus envvars on startup for our children
- Remove background plugin, as background handling is now
done in gnome-shell
A11y settings:
- Import GIO instead of GTK+/GDK
- Do enable toolkit accessibility, even if we don't need it,
for the benefit of third-party/legacy toolkits and apps
Media keys:
- Add other bindings to the whitelist
Cursor:
- Enable the on-screen keyboard when touch is used
Keyboard:
- Adapt to gnome-xkb-info API change
Power:
- Make blanking timeouts match
- Show notifications when about to suspend from idle
- Wake up the display when about to logout
- Adapt to new GnomeIdleMonitor API
- Don't change the brightness on inactive sessions
Remote Display:
- Disable animations on Xvnc as well
- Re-enable animations if Vino is gone
Sound:
- Avoid polling non-existent directories
Updates:
- Fix crasher when firmware updates is disabled
XSettings:
- propagate the remember-recent-files GSetting to XSettings
Wacom:
- Bump req for GDK_FULLSCREEN_ON_ALL_MONITORS
===============
Version 3.7.5.1
===============
Fix keyboard shortcut handling with XI 2.3
=============
Version 3.7.5
=============
A11Y Keyboard:
- Disable everything on exit if no settings changed
- Remove GTK+ fallback dialogues
Color:
- Set the correct metadata on the auto-created EDID profile
- Switching to a new account shouldn't warn
Daemon:
- Also apply LC_PAPER
Media Keys:
- Use D-Bus API to lock the screen
- Use F20 for the temporary mic mute key
Power:
- Add way to disable the backlight helper
- Avoid dead-locking with gnome-shell on startup
- Avoid possible crash when shutting down quickly or at startup
- Drop explicit screen locking on suspend
- Fix incorrect backlight level on restore
- Handle dim idle the same way as other idles
- Lots of test additions
- Wake up the display when unplugging the AC too
Remote DIsplay:
- Detect SPICE sessions as well
- Monitor Vino's Connected status
Screenshot:
- Save to GtkRecentManager on success
- Lots of test additions.
Updates:
- Allow the shell time to initialize before checking for offline update failures
Wacom:
- Use regular fullscreen window for OSD
And updated translations
=============
Version 3.7.4
=============
Updates:
- Support notification filtering
Media-keys:
- Save screenshots without using gnome-screenshot
- Updated design for the on-screen OSD
- Show output device when changing the volume
- Add OSD support for the "Battery" key on certain laptops
- Add support for the microphone mute key on certain keyboards
- Move sound initialisation out of the critical startup path
Color:
- Addition to implement new mockups in gnome-control-center
Housekeeping:
- Fix purging not working
Keyboard:
- Don't migrate ibus xkb engines
Power:
- Add test suite
- Fix Power settings panel not picking up the updated brightness
- Fix dimming of the screen not working, and don't dim when inhibited
- Fix timeouts being longer than configured in some cases
- Aggressively blank the screen when the shield is down
- Update idle configuration when plugging or unplugging the mains
- Really turn off the screen on suspend for MacBook laptops
- Allow overriding VM detection with the gnome.is_vm=[01] kernel command-line parameter
Wacom:
- Fix problems resetting touch buttons on 64-bit systems
- Allow switching modes while OSD is active
XRandR:
- use default-monitors-setup for autoconfiguration even after boot
=============
Version 3.7.3
=============
- Add implementation for Freedesktop.org ScreenSaver inhibition API
- Disable animations on slow links (VNC for example)
- Remove fallback mode handling code
- Disable the smartcard plugin for now
Daemon:
- Many plugins ordering bug fixes
- Use gnome-session properties instead of libsystemd-login
- Allow whitelisting plugins, to make it easier for gdm to catch up
- Install all the schemas, even the ones for which the plugins aren't
installed
- Add a way to replace the daemon
- exit gracefully if the session name is already taken
Power:
- Remove unused settings keys
- Do not attempt to suspend, dim or blank if running inside a VM
- Port to GnomeIdleMonitor from gnome-desktop
- Adjust sleep timer to blank timer in some cases
- Check if action is available before taking action
- Hide critical battery warning when power is plugged
- Fix possible race with gnome-shell on startup
Sound:
- Fix sound plugin never working properly
Media-keys:
- Use the shared libgnome-volume-control code
- Support launching gnome-calculator instead of gcalctool
- Add default shortcuts for the magnifier
- Add repeat to the brightness keys
Keyboard:
- Fix build without IBus
- Fix potential infinite loop due to num-lock handling
- Don't print warnings when calls are cancelled
- Handle keyboard shortcuts with Caps Lock for switching inputs
Mouse:
- Fix natural horizontal scroll
XRandR:
- Add new follow-lid behavior and tie gsd-power lid-close to XRandR
- Avoid crasher if XRandR calls fail on startup
- Fix the "rotate" button not working
- Swap axes for some (non-Wacom) tablets as well
Wacom:
- Avoid infinite recursion with a non-Wacom display
- Fix handling of Cintiq 24HD mode-switch buttons
- Mode switch LED fixes for some tablets
- Add OSD help window (see gnome-control-center for how to launch it)
Cursor:
- Only show the cursor when the mouse gets used
Housekeeping:
- Implement automatic purging of trash, along with a D-Bus interface for it
Print-notifications:
- Don't show strange notifications when printing
Updates:
- Fix warning on startup with PackageKit < 0.8.1
=============
Version 3.7.1
=============
Daemon:
- Provide a singleton SessionManager proxy object
- Ensure session registration happens before other idles
- Use logind for suspending and rebooting the system
- Require logind for session tracking
Input:
- Clarify hotplug command exit value handling
- Add trackball detection
Keyboard:
- Add default ibus engine for Indic locales
- Don't apply global settings for every keyboard
Mouse:
- Re-enable touchpad when mouse isn't present
Power:
- Fix "no devices" error path in gsd-backlight-helper
- Add a watchdog to keep X's builtin screen saver disabled
- Fix a number of possible crashers
Wacom:
- Add support for touchstrips and touchrings without a modeswitch
XSettings:
- Optimise xsettings changes
=============
Version 3.6.1
=============
Keyboard:
- Allow grabbing the Menu key
- Apply XKB variants and options for each IBus engine
- Don't setup legacy toolkits if IBus is missing
- Add default setup for some particular languages
- Convert old libgnomekbd and IBus configurations
- Add support for more modifiers only combinations
- Fix input switching eating the modifiers keys in some cases
Mouse:
- Fix "Locate Pointer" eating the Ctrl key
- Fix "Locate Pointer" animation showing when the Ctrl key has been used
Updates:
- Never show the user a message about cancelled transactions
Wacom:
- Fix LEDs switching for some tablet models
Housekeeping:
- Fix possible crashers on exit
Color:
- Fix possible crashers on exit
=============
Version 3.6.0
=============
Keyboard:
- Create sources from the X layouts if the configuration is empty
- Always do that in GDM, so system-wide layouts work
- Add modifiers-only shortcuts to switch input sources
==============
Version 3.5.92
==============
Keyboard:
- Don't block getting the IBus global engine
- Don't touch the XKB layout if no input sources were configured
- Fix gtk+ IM module getting set to IBus for XKB sources
Media keys:
- Make "toggle brightness" work
Color:
- Don't warn about non-existent DMI file
Power:
- Fix some instances where an external screen would turn off
Wacom:
- Require wacom 0.6 to fix bugs with some tablets
==============
Version 3.5.91
==============
Mouse:
- Fix natural-scroll not working until switched off and on again
Keyboard:
- Don't handle IBus for fallback, it will use the same UI it always did
- Hook IBus support for legacy applications
Power:
- Do not attempt to change the brightness of an output that was disabled
- Fix idle blank and sleep timeout
==============
Version 3.5.90
==============
Power:
- Fix D-Bus path of the screensaver
Mouse:
- Add support for natural scroll for touchpads
Keyboard:
- Apply XKB options
Wacom:
- Implement the "switch monitor" combination
And updated translations
=============
Version 3.5.6
=============
Build:
- Add optional man page
- List plugin schemas as children of the main schema
Updates:
- Remove unused code
- Avoid compilation warnings due to PackageKit API changes
Mouse:
- If one device was ignored, we would ignore all the devices
Smartcard:
- Don't try to use smartcard drivers that didn't load
Keyboard:
- Require ibus 1.4.99 for ibus support
Wacom:
- Avoid a warning at login
=============
Version 3.5.5
=============
* Add test applications for a number of plugins
Color:
- Fix notification-related memory leaks
Keyboard:
- Add support for switching to IBus input methods
Wacom:
- Fix crasher related to screen tablets
- Do not rotate "pad" devices
- Apply display rotation to device that's mapped to it
- Make shortcuts that require Shift work as expected
- Re-apply calibration and aspect-ratio when the screen changes
but don't apply it to touch devices
Housekeeping:
- Fix notification-related memory leaks
Updates:
- Remove unused settings
- Remove a number of unused notifications
- Don't ever live-update packages in the session
- Fix a number of memory leaks
- Prevent crash if a device that requires a firmware is removed before the
firmware search completes
=============
Version 3.5.4
=============
Wacom:
- Fix crasher related to screen matching (Olivier Fourdan)
Printers:
- Don't block the session with unreachable printers
=============
Version 3.5.3
=============
Keyboard A11y:
- Don't crash when changing large print in fallback mode
- Link to an existing help page
Housekeeping:
- Support new XDG thumbnail directory locations
Keyboard:
- Don't crash if LANG is empty
Media-keys:
- Make keyboard shortcuts work again
- Use systemd to shutdown or suspend if available
Mouse:
- Only inhibits mouse clicks and scrolls with syndaemon
Power:
- End the lid-close safety timer when the lid gets opened
- Update fallback status icon on icon state change
- Don't leak notifications
- Avoid duplicate translations
- Use systemd to shutdown or suspend if available
- Don't enable backlight helper if GUdev is not available
Updates:
- Adapt to new upstream property name
- Add a notification for offline updates
Wacom:
- Update display mapping on monitor changes
- Flag unknown devices created from fallback
- Add keep aspect ratio option
- Use GnomeRROutput instead of GnomeRROutputInfo
- Match built-in monitor
XRandr:
- Explicitly set clone state variable when generating monitor configs
=============
Version 3.5.2
=============
- Remove ability to D-Bus activate (Ray Strode)
Media-keys:
- Get proper gnome-keyring environment (Bastien Nocera)
- Simplify the OSD code (Bastien)
- Add keybindings to switch input sources (Rui Matos)
Mouse:
- Fix applying settings to newly added touchpads (Owen Taylor)
- Reduce default touchpad deactivation to 1s (Nicolas Dufresne)
Housekeeping:
- Split out 'ingnore unix mount' code (Bastien)
Keyboard:
- Always apply xmodmap (Sergey V. Udaltsov)
- Lots of cleanups (Bastien)
- Apply XKB layouts ourselfs and stop relying on libgnomekbd (Rui Matos)
Power:
- Disconnect from upower signals when needed (Richard Hughes)
- Add org.gnome.settings-daemon.plugins.power.lid-close-suspend-with-extrnal-monitors
key to allow forcing suspend on lid close (Paolo Bonzini)
Print:
- Fix setting of default media size (Marek Kasik)
- Don't create an unused proxy object (Matthias Clasen)
- Speed up initialization (Matthias)
Updates:
- Automatically download updates rather than installing them (Richard)
Wacom:
- Disable wacom support on s390 (Dan Horák)
- Disable wacom support on non-linux (Antoine Jacoutot)
- Don't put touchscreens in relative mode (Timo Aaltonen)
- Make tablet configuration per-machine (Bastien)
Color:
- Be quiet about unloadable profiles (Richard)
Translations:
- Catalan
- Crimean Tatar
- Dutch
- Galician
- German
- Hebrew
- Italian
- Kannada
- Norwegian bokmål
- Slovenian
- Swedish
=============
Version 3.4.0
=============
Wacom:
- Check if the "last-stylus" property has been set (Olivier Fourdan)
Translations:
- Simplified Chinese (zh_CN) (YunQiang Su)
- Hindi (Chandan Kumar)
- Belarusian (Ihar Hrachyshka)
- Brazilian Portuguese (Jonh Wendell)
- French (Bruno Brouard)
- Hebrew (Yaron Shahrabani)
- Lithuanian (Žygimantas Beručka)
- Portuguese (Duarte Loreto)
- Telugu (Sasi Bhushan)
- Traditional Chinese (Chao-Hsiung Liao)
- Vietnamese (Nguyễn Thái Ngọc Duy)
- Ukranian (Daniel Korostil)
==============
Version 3.3.92
==============
Color:
- Apply the color profile even if the device has an invalid EDID (Richard Hughes)
- Create a color device even if the device has an invalid EDID (Richard Hughes)
- Don't use the username in the profile ID, it's optional and not-required (Richard Hughes)
Common:
- Add hint on how to set the script path (Bastien Nocera)
- Fix library linkage on Mageia (Jani Välimaa)
- Support explicitly setting G_MESSAGES_DEBUG (Martin Pitt)
Media Keys:
- Avoid hard-coded shortcuts not working (Bastien Nocera)
- Call Shutdown for the logout action (Bastien Nocera)
Mouse:
- Stop syndaemon when settings-daemon dies (Martin Pitt)
Power:
- Do not emit DBus interface change signals when doing the idle dim (Richard Hughes)
- Don't print a message when no backlights are detected (Richard Hughes)
- Failing to clear DPMS timeouts should not be fatal (Alexandre Rostovtsev)
- Fix broken abs_to_percentage() logic (Cosimo Cecchi)
- Lazily connect to gnome-screensaver (Martin Pitt)
- Lock the screensaver if the lid is closed and lock is enabled (Richard Hughes)
- Make the idle dim time 90 seconds to match OSX (Richard Hughes)
Print Notifications:
- Add test tool (Lars Uebernickel)
- Don't unref floating GVariant (Marek Kasik)
Wacom:
- Add README about configuration storage (Bastien Nocera)
XRandR:
- Fix the rotate display button not working (Sjoerd Simons)
- List external display only before internal only (Bastien Nocera)
XSettings:
- Add README.xsettings about overrides (Ryan Lortie)
- Add test-xsettings program (Ryan Lortie)
- Add xsettings_setting_get() accessor (Ryan Lortie)
- Add XSETTINGS_VARIANT_TYPE_COLOR macro (Ryan Lortie)
- Always call xsettings_setting_set() (Ryan Lortie)
- Don't return XSettingsResult codes (Ryan Lortie)
- Introduce 'tiers' of XSettings (Ryan Lortie)
- Load overrides on startup (Ryan Lortie)
- Remove global 'settings' list (Ryan Lortie)
- Switch manager to GLib memory functions (Ryan Lortie)
- Switch to GVariant for value storage (Ryan Lortie)
- Use GHashTable in the xsettings manager (Ryan Lortie)
- Wire overrides into GSettings (Ryan Lortie)
Translations:
- Belarusian (Ihar Hrachyshka, Kasia Bondarava)
- British English (Bruce Cowan)
- Bulgarian (Alexander Shopov)
- Catalan (Joan Duran)
- Catalan (Valencian) (Carles Ferrando)
- Czech (Adam Matoušek, Marek Černocký)
- Finnish (Timo Jyrinki)
- Galician (Fran Diéguez)
- Gujarati (Sweta Kothari)
- Hungarian (Gabor Kelemen)
- Korean (Changwoo Ryu)
- Latvian (Anita Reitere)
- Norwegian bokmål (Kjartan Maraas)
- Russian (Yuri Myasoedov)
- Serbian (Мирослав Николић)
- Slovenian (Matej Urbančič)
- Traditional Chinese (Cheng-Chia Tseng)
- Vietnamese (Nguyễn Thái Ngọc Duy)
- Punjabi (A S Alam)
- Ukranian (Daniel Korostil)
==============
Version 3.3.91
==============
Color:
- Fix warning with non-present devices
- Make displays without EDID data use the correct device ID
- Create the correct device ID for EDIDs with no text data
- Fix EDID checksum generation
Power:
- Emit a Changed() signal when the backlight changes
- Don't overflow when pressing the keyboard brightness button
Media-keys:
- Make Alt+Print appear as Alt+Print not Alt+SysRq
Wacom:
- Add support for mode switch buttons, touchrings, touchstrips,
and light up the LEDs appropriately
- Add support for current tool ID from Wacom driver
- Fix possible crasher setting pressure curve or display area
- Force touchpads to use relative mode and ignore mode changes
- Fix double-event generation
- Fix installation problems with libexecdir == libdir
- Make monitor == -1 reset the display configuration
================
Version 3.3.90.1
================
Build:
- Fix build with --enable-systemd
==============
Version 3.3.90
==============
Build:
- Remove last requirement for dbus-glib
- Remove use of deprecated g_thread_init()
- Fix linking with -Bsymbolic
Wacom:
- Add tablet button listing and settings
- Add display mapping
Keyboard:
- Fix blinking num-lock in some circumstances
Color:
- Set _ICC_PROFILE correctly when there is no primary device specified
Power:
- Fix possible crasher in backlight helper on error
=============
Version 3.3.5
=============
Build:
- Remove unused date & time mechanism. gnome-control-center
uses a different API, provided by systemd on some systems.
A11y keyboard:
- Reduce the number of settings updates on startup
Power:
- Require a newer upower
- Optionally use systemd to shutdown when power is low
- Use GDBusProxy-compatible PropertiesChanged signal
- Fix "
" appearing in notification popups
Wacom:
- Add a way to get/set the screen associated with a tablet
- Don't crash when using a generic tablet
- Add support for the puck and touch device types
- Add support for enumerating tablet buttons
Printers:
- Also notify for unknown error reasons
- Unify printer name usage
Color:
- Set the brightness of the display if it was saved as
metadata in the color profile
Media keys, XSettings, Updates:
- Fix possible crashes on exit
Housekeeping, Wacom, XSettings:
- Fix memory leaks
Media keys:
- Add screenshot keyboard shortcuts
Keyboard:
- Don't save num-lock state when caps-lock changes
Automounter:
- Optionally use systemd to check for active seat
=============
Version 3.3.4
=============
Build:
- Fix distribution of a pre-processed desktop file
Daemon:
- Fix --debug not working
- Remove gnome_settings_session_get_screen() and
gnome_settings_session_get_upower_client(), as
the underlying functions return singletons
Color:
- Fix some screen setups not being color corrected
XRandR:
- Better handling of docking stations and plugging of
external monitors (for suspend, and turning off monitors
to work as designed)
Wacom:
- Fix loading of the plugin
- Fix GSettings read/write for per-tablet/per-styli configs
- Export more tablet and stylus metadata
===============
Version 3.3.3.1
===============
Wacom:
- Fix referenced module name (Frederic Peters)
=============
Version 3.3.3
=============
Build:
- Require GTK+ 3.3.4 (for key accel parsing)
- Require XI2 (for wacom support)
Common:
- Remove unused X key event code (Bastien)
Wacom:
- Lots of infrastructure buildup that I can't really
summarize here (Bastien Nocera)
- Rename plugin to avoid name clash with libwacom (Bastien)
- Use libwacom to get tablet metadata (Bastien)
- Implement per-device and per-stylus settings (Bastien)
Power:
- Add the vendor name to the battery recall
warning (Dominique Leuenberger) (#664418)
- Add automatic dimming of keyboard backlight (Alex Murray)
Print:
- Prevent crashes when cups sends malformed
D-Bus signals (Lars Uebernickel) (#665689)
XSettings:
- Set GtkShellShowsAppMenu xsetting when the shell is running (Colin Walters)
Translations:
Hebrew
Norwegian bokmål
Romanian
Spanish
=============
Version 3.3.2
=============
Common:
- Remove left-over debug (Bastien Nocera) (#660073)
- Fix handling of (Bastien Nocera)
- Update required gnome-desktop version (Bastien Nocera)
- Return opcode when detecting XInput2 (Bastien Nocera)
- Add helper to get the input device node (Bastien Nocera)
- Use XInput2 to capture and match keys (Bastien Nocera)
- Use GTK+ functions instead of own impl (Bastien Nocera) (#663343)
- Fix small memleak (Bastien Nocera)
- Allow to grab 'Print' without modifiers (Florian Müllner) (#663623)
- Require gsettings-desktop-schemas 3.3.0 (Bastien Nocera)
A11y keyboard:
- Port to GSettings (Bastien Nocera) (#631502)
Automount:
- Call bind_textdomain_codeset() (Bastien Nocera)
Color:
- Do not load all the color devices twice at startup (Richard Hughes)
- Don't assign the same device more than once at startup (Richard Hughes)
- Fix a crash if ~/.local is deleted at runtime (Richard Hughes) (#660664)
- Simplify gcm_profile_store_mkdir_with_parents() (Bastien Nocera)
- Cancel any in-progress directory searching on plugin unload (Richard Hughes)
- Do not check for directory presence sync (Richard Hughes)
- Fix critical warning if the user disables the internal LCD screen (Richard Hughes)
- Reset the gamma tables when the screen configuration changes (Richard Hughes) (#660164)
- Unbreak loading profiles at startup (Cosimo Cecchi) (#660790)
- Do not prefix the EDID profile title with 'Default' (Richard Hughes)
- Set model and vendor to 'unknown' if not specified or unavailable (Richard Hughes)
Daemon:
- Create a reference to a GnomePnpIds object to speed up loading (Richard Hughes)
Datetime:
- Fix build requirements (Bastien Nocera)
Media keys:
- Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya)
- Don't assert if the user sets the 'button-power' action to 'shutdown' (Richard Hughes)
- Don't assert if the user sets the 'button-power' action to 'nothing' (Richard Hughes)
- Only ever send signals to specific apps (Bastien Nocera)
- Document the MediaPlayerKeyPressed signal (Bastien Nocera)
- Add some D-Bus API documentation (Bastien Nocera)
- Fix OSD touchpad icon names (Bastien Nocera) (#661179)
- Fix suspend button not locking the screen (Bastien Nocera) (#660267)
- Fix the suspend key not working (Bastien Nocera) (#660267)
- Remove unused allowed-keys entry (Bastien Nocera)
- Cache the volume change event sound (Bastien Nocera)
- Update for GVC API (Bastien Nocera)
- Print warning for real errors (Bastien Nocera)
- Apply volume on the device the key came from (Bastien Nocera) (#340720)
- Add custom shortcut type (Bastien Nocera)
- Implement GConf keyboard shortcuts (Bastien Nocera) (#625228)
- Redraw volume OSD when not composited (Marien Zwart) (#660990)
- Update for gsd-keygrab API change (Bastien Nocera) (#663343)
- Move some metacity shortcuts into g-s-d (Florian Müllner) (#663623)
- Port custom keybindings to GSettings (Florian Müllner) (#631502)
Power:
- Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya)
- Do not revert to the pre-idle brightness if idle dimming is disabled (Richard Hughes) (#660434)
- Remove some unused schema for enabling the sleep-inactive actions (Richard Hughes) (#660395)
- Clarify what a value of 0 is for sleep-inactive-x-timeout (Richard Hughes)
- Do not sleep-on-idle by default (Richard Hughes)
- Simplify hiding/showing the status icon (Bastien Nocera)
- Ensure the DPMS state is 'on' at startup (Richard Hughes) (#660482)
- Close low-battery notification when plugged in (Florian Müllner) (#660942)
- Remove the window filter when the plugin is unloaded (Richard Hughes)
- Don't crash when setting the dim timeout when using NX (Richard Hughes) (#661000)
- Call XSyncInitialize() in case GTK+ wasn't compiled with XSync support (Richard Hughes)
- Emit 'Changed' signal to all listeners (Gary Ching-Pang Lin)
- Fix "undefined symbol: WEXITSTATUS" error (Richard Hughes) (#662020)
- Make non-urgent notifications transient (Florian Müllner) (#662711)
Printers:
- Fix build on systems without LC_PAPER (Bastien Nocera) (#660626)
- Call setlocale() (Bastien Nocera) (#660632)
- Exit gsd-printer when session ends (Marek Kasik) (#660158)
- Correct signature when calling PrinterAddOptionDefault (Marek Kasik)
- Don't show "Not connected?" when not needed (Marek Kasik)
- Unown name on the system bus when session goes idle (Marek Kasik) (#660158)
- Set requesting-user-name when getting job info (Marek Kasik)
- Show printer-state-reasons only when printing my jobs (Marek Kasik)
- Don't allow "/" in printer name (Marek Kasik) (#661774)
- Make notifications resident (Marek Kasik)
- Fix a leak (Marek Kasik)
Smartcard:
- Remove unnecessary translations (Bastien Nocera)
Xrandr:
- Use a GCancellable for g_bus_get calls so that they can be cancelled (Rodrigo Moya)
Xsettings:
- Remove workaround to deal with g-s-d not exiting correctly (Rodrigo Moya)
- Plug mem leaks (Christian Persch) (#663239)
Wacom:
- Fix possible crasher (Bastien Nocera) (#661170)
- Set cursor devices to be in relative mode by default (Jason Gerecke) (#662977)
- Add classes to manage settings and properties (Bastien Nocera)
Translations:
- ast (Xandru Armesto)
- de (Mario Blättermann)
- eo (Kristjan SCHMIDT)
- es (Daniel Mustieles, Jorge González)
- gl (Fran Dieguez)
- lt (Algimantas Margevičius)
- nb (Kjartan Maraas)
- nl (Redmar, Wouter Bolsterlee)
- or (Manoj Kumar Giri)
- sl (Matej Urbančič)
- sv (Daniel Nylander)
- te (krishnababu k)
- uk (Daniel Korostil)
- vi (Nguyễn Thái Ngọc Duy)
=============
Version 3.2.0
=============
Power:
- Correctly put the screen and computer to sleep when idle (Richard Hughes) (#659066)
Translations:
- ca (Joan Duran, Gil Forcada)
- ca@valencia (Carles Ferrando)
- da (Flemming Christensen)
- eu (Inaki Larranaga Murgoitio)
- hu (Gabor Kelemen)
- ja (OKANO Takayoshi)
- ko (Changwoo Ryu)
- or (Manoj Kumar Giri)
- ru (Alexandre Prokoudine, Yuri Myasoedov)
==============
Version 3.1.92
==============
A11Y keyboard:
- Show the a11y dialogue on right-click (Bastien Nocera) (#564171)
Color:
- Be less chatty when creating duplicate profiles (Richard Hughes)
- Do not segfault when doing fast-user-switching into a new account (Richard Hughes) (#736846)
- Use a username suffix on the profile ID (Richard Hughes) (#736846)
- Do not show a warning when switching to a new user account (Richard Hughes)
- Use the correct profiles when fast user switching (Richard Hughes)
- Fix linking (Matthias Clasen) (#659086)
Common:
- Add helper to list disabled devices (Bastien Nocera)
- Clean up X11 library dependencies (Bastien Nocera) (#657178)
- Bump colord dependency (Rodrigo Moya)
Datetime:
- Allow chrony to be used on Fedora (Tomas Bzatek) (#655119)
- Add NTP support for SUSE variants (Vincent Untz) (#654970)
GConf:
- Plug some memory leaks (Rodrigo Moya)
- Disconnect callbacks when cleaning up (Rodrigo Moya)
Keyboard:
- Remember and apply NumLock status (Bastien Nocera) (#631989)
Media keys:
- Don't show a level when muted (Bastien Nocera) (#644537)
- Fix keyboard brightness (Alex Murray) (#658689)
- Use the same "Music" mime-type as g-c-c (Bastien Nocera)
- There's no Beagle anymore (Bastien Nocera)
- Use gtk_show_uri() to launch nautilus (Bastien Nocera)
- Clean up app launching (Bastien Nocera) (#141379)
- Clean up upower req (Bastien Nocera)
- Remove unused empty LIBS linkage (Bastien Nocera)
- Fix compile-time warning (Bastien Nocera)
- Move keyboard brightness icon here (Bastien Nocera)
- Remove OSD icons (Bastien Nocera)
Mouse:
- Add more debug for "touchpad disabled" (Bastien Nocera)
- Try harder to re-enable devices (Bastien Nocera) (#656397)
Power:
- Make ABS_TO_PERCENTAGE warn on invalid input (Bastien Nocera) (#657364)
- Correctly check for helper exit status (Bastien Nocera)
- Avoid warnings without backlights (Bastien Nocera)
- Do not connect to signals if we failed to connect (Richard Hughes)
- Don't crash if we try to calculate the idle state before connected to gnome-session (Richard Hughes) (#657917)
- Be less chatty when optional hardware is not attached (Richard Hughes) (#658613)
- Fix a critical warning when getting the session inhibit state (Richard Hughes)
- Do not handle the idle state transaction when the session is not active (Richard Hughes) (#658568)
- Don't fall through the switch statement when shutting down (Richard Hughes) (#659202)
- Do not leak the icon when getting device status (Richard Hughes) (#659213)
- Protect against a potential SIGFE (Richard Hughes) (#659205)
- Do not emit multiple 'Changed' signals when recalculating (Richard Hughes) (#659204)
- Do not use G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES when we want to read properties (Richard Hughes) (#659066)
- Fix compilation without libcanberra-gtk (Bastien Nocera)
Printers:
- Use the best PPD for new printer (Marek Kasik) (#658544)
- Style fixes (Bastien Nocera)
Updates:
- Ignore virtual mountpoints when looking for external media (Richard Hughes) (#658282)
- Use the correct icons in the notifications (Richard Hughes)
Translations:
- de (Mario Blättermann)
- en_GB (Bruce Cowan)
- es (Jorge González, Daniel Mustieles)
- fi (Timo Jyrinki)
- fr (Bruno Brouard)
- he (Yaron Shahrabani)
- it (Luca Ferretti)
- ja (Jiro Matsuzawa)
- lt (Aurimas Černius)
- lv (Rudolfs Mazurs)
- pl (Piotr Drąg)
- pt (Duarte Loreto)
- sl (Matej Urbančič)
- sr (Мирослав Николић)
==============
Version 3.1.91
==============
Common:
- Don't list XINPUT_LIBS twice, move X11_LIBS from LDFLAGS to LIBADD (Stefan Sauer)
Color:
- Ensure the 'Recalibration required' notification has a custom app name (Richard Hughes)
- Fix a critical warning on startup (Richard Hughes)
- Do not notify to recalibrate on every startup (Richard Hughes)
Daemon:
- Fix possible double-free outside gnome-session (Bastien Nocera)
Gconf:
- Double check stuff we add to the hash table (Rodrigo Moya) (#658055)
Housekeeping:
- NULL-terminate the ignore-paths array (Bastien Nocera) (#657849)
Power:
- Do not exit gnome-settings-daemon if upower fails to load (Richard Hughes)
- Fix impossible to hit error paths (Bastien Nocera) (#657364)
- Fix BRIGHTESS_STEP_AMOUNT calculation macro (Kamal Mostafa)
- Do most of the work in _start () (Bastien Nocera) (#657924)
- Never idle-dim the display to a higher brightness level (Richard Hughes) (#658144)
Printers:
- Remove redundant code (Marek Kasik)
Xsettings:
- Handle rgba-order key (Bastien Nocera) (#657525)
- Don't poke at an empty hashtable (Bastien Nocera) (#657464)
- Fix a stray brace (Owen Taylor)
Translations:
- be (Ihar Hrachyshka)
- cz (Marek Černocký)
- pt_BR (Og B. Maciel)
- ta (Dr.T.Vasudevan)
==============
Version 3.1.90
==============
A11Y-keyboard:
- Use GIO's DBus API instead of dbus-glib's (Rodrigo Moya)
Color:
- Don't use uninitialized GErrors (Matthias Clasen)
- Do not set an age for display and printer profiles (Richard Hughes)
- Remove the ability to disable notifications (Richard Hughes)
- Do not search user-icc directories if they do not exist (Richard Hughes) (#657484)
Daemon:
- Add Unity to OnlyShowIn value for autostart desktop file (Michael Terry) (#654919)
Media keys:
- Don't go up to 11 (Bastien Nocera) (#649411)
Mouse:
- Be more careful to avoid segfaults (Matthias Clasen) (#657462)
Power:
- Ensure the critical battery beep is stopped when the AC is inserted (Richard Hughes)
- Ensure we lock the screen before suspending on lid close (Richard Hughes) (#655924)
- Add mention of bug 652183 (Bastien Nocera)
Smartcard:
- Use GIO's DBus API instead of dbus-glib's (Rodrigo Moya)
Updates:
- Do not log a warning if the firmware-missing file does not exist (Richard Hughes)
- Do not log a warning at startup if getting the upgrade list is not supported (Richard Hughes) (#657483)
Translations:
- bg (Alexander Shopov)
- id (Andika Triwidada)
- pa (A S Alam)
- ta (Dr.T.Vasudevan)
- zh_CN (Aron Xu)
=============
Version 3.1.5
=============
A11y-keyboard:
- Enable plugin by default (Rodrigo Moya) (#656287)
Automount:
- Link against the private profiler library (Cosimo Cecchi)
- Add some missing includes (Cosimo Cecchi)
- Don't ship the .in file, just the .in.in one (Bastien Nocera)
- Silence two trivial -Wformat-security warnings (Richard Hughes)
Color:
- Do not show multiple warnings if colord is not available at runtime (Richard Hughes)
- Fix a potential crash when unloading the color plugin (Richard Hughes)
- Fix a potential crash if creating the per-user ICC directory fails (Richard Hughes)
- Make lcms2 a hard dependency (Richard Hughes)
Housekeeping:
- Use new g_format_size() instead of g_format_size_for_display() (Javier Jardón)
Media keys:
- Don't preserve the path after filling (Cosimo Cecchi)
- Remove the half pixel offset from the progressbar fill (Cosimo Cecchi)
- Always round the render coordinates for media icons (Cosimo Cecchi)
Power:
- Add the idle actions (Richard Hughes)
- Show a status icon when in fallback mode (Richard Hughes)
- Respect the idle-dim-ac and idle-dim-battery configuration keys (Richard Hughes)
- Add a backlight helper, as xbacklight isn't always present (Richard Hughes)
- Fall back to the backlight helper if xbacklight is not available (Richard Hughes)
- Fix a potential crash when unloading the power plugin (Richard Hughes)
- Ensure we return the new percentage when changing the brightness (Richard Hughes)
Updates:
- Do not use deprecated PackageKit #defines (Richard Hughes)
Wacom:
- Invert TPCButton setting (Peter Hutterer) (#656372)
Translations:
- es (Daniel Mustieles)
- fa (Arash Mousavi)
- gl (Fran Dieguez)
- he (Yaron Shahrabani)
- ru (Yuri Kozlov)
- sl (Andrej Žnidaršič)
- sv (Daniel Nylander)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
=============
Version 3.1.4
=============
A11y-keyboard:
- Do proper cleanup when the plugin is stopped (Rodrigo Moya)
Automount:
- Turn the automount plugin in a separate binary (Cosimo Cecchi) (#653521)
- Fix distcheck of .desktop.in.in file (Rodrigo Moya)
Common:
- Fix grabbing of multimedia keys (Chris Coulson)
Daemon:
- Set locale environment on gnome-session as early as possible (Rodrigo Moya) (#654182)
- Plug memory leak (Rodrigo Moya)
Datetime:
- Use friendlier wording for date & time policykit prompt (Michael Terry) (#645951)
Media keys:
- Add button handling code from gnome-power-manager (Richard Hughes)
Power:
- Add power plugin to replace g-p-m (Richard Hughes)
Translations:
- be (Ihar Hrachyshka)
- cz (Marek Černocký)
- de (Mario Blättermann)
- es (Daniel Mustieles, Jorge González, Sebi Kul, Francisco Molinero)
- gl (Fran Dieguez)
- he (Yaron Shahrabani)
- lt (Aurimas Černius)
- lv (Rudolfs Mazurs)
- nb (Kjartan Maraas)
- pa (A S Alam)
- tr (Muhammet Kara)
=============
Version 3.1.3
=============
Common:
- Use defines instead of variables for ranges (Bastien Nocera)
- Fix function keys not being grabbed (Bastien Nocera) (#649222)
- Allow the "Pause" key to be used (Bastien Nocera) (#653524)
Clipboard:
- Fix incremental sending from the clipboard manager (Cosimo Cecchi) (#652609)
Color:
- Fix a potential buffer-overflow when converting to wide text (Richard Hughes)
Keyboard:
- Use the same kbd layout menu labels as Gnome Shell (Jeremy Bicha) (#652836)
- Add missing "Settings" to the string (Bastien Nocera)
- Fix menu items actions (Bastien Nocera)
Media keys:
- Use constant for icon size in OSD (Bastien Nocera)
- Remove progress bar borders (Bastien Nocera) (#652321)
Mouse:
- Check device is a touchpad before enabling/disabling it (Rodrigo Moya)
Translations:
- be (Ihar Hrachyshka)
- es (Jorge González)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- nb (Kjartan Maraas)
- sl (Matej Urbančič)
- sr (Мирослав Николић)
=============
Version 3.1.2
=============
Common:
- Don't try to convert show-keyboard-leds-indicator in gnome-settings-daemon.convert
(Chris Coulson)
- Add touchscreen detection (Bastien Nocera)
- Add X property setting helper (Bastien Nocera)
- Add code to detect accelerometers (Bastien Nocera)
- Add better error reporting for egg key parsing (Bastien Nocera)
- Add code to allow disabling input devices (Bastien Nocera)
Color:
- Add new color plugin (Richard Hughes)
Cursor:
- Hide cursor on tablets with only a touchscreen (Bastien Nocera) (#650604)
- Show the cursor again on exit (Bastien Nocera)
- Fix XFixes version checking (Bastien Nocera)
- Ignore PS/2 mice as well (Bastien Nocera)
- Fix checking for extension pointer (Bastien Nocera)
Datetime:
- Fix ntp logic on Debian to include ntpdate as well as ntpd (Michael Terry) (#644821)
GConf:
- Add missing schema for org.gnome.settings-daemon.plugins.gconf (Rodrigo Moya) (#652200)
Keybindings:
- Complete update to egg key parsing change (Florian Müllner)
Media keys:
- Only start D-Bus when _start() is called (Bastien Nocera)
- Simplify touchpad OSD (Bastien Nocera)
- Hardcode the "toggle touchpad" button (Bastien Nocera)
- Remove old-style OSD (Bastien Nocera)
- Always use the primary monitor for display (Bastien Nocera) (#650159)
- Make sound changes quiet with Alt (Bastien Nocera) (#651704)
Mouse:
- Use new disable/enable device code (Bastien Nocera)
Orientation:
- Add orientation plugin (Bastien Nocera)
Updates:
- Fix a string that is hard to translate (Richard Hughes) (#645749)
Wacom:
- Enable wacom touch key by default (Peter Hutterer)
- Use property settings helper in common/ (Bastien Nocera)
- Typedef the Wacom device types (Bastien Nocera)
Xrandr:
- Switch touchscreen rotation as wel (Bastien Nocera)
- Fix small memory leak on shutdown (Bastien Nocera)
- Remove the functionality to call gcm-apply when outputs change (Richard Hughes)
- Remove rotation handling for wacom tablets (Bastien Nocera)
Translations:
- bg (Alexander Shopov)
- ca@valencia (Carles Ferrando)
- cz (Marek Černocký)
- de (Mario Blättermann)
- es (Jorge González, Daniel Mustieles)
- fa (Arash Mousavi)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- nb (Kjartan Maraas)
- pl (Piotr Drąg)
- sl (Matej Urbančič)
=============
Version 3.1.1
=============
Common:
- Add input-helper test application (Bastien Nocera)
- Fix syndaemon never getting started (Edward Sheldrake) (#648885)
- Add meaningful app names to notifications from plugins (Matthias Clasen) (#648911)
Datetime:
- Simplify NTP handling for distros (Bastien Nocera)
- Fix setting NTP on Fedora 15 (Bastien Nocera)
Media keys:
- Show a popup when no media player is running (Bastien Nocera)
- Use symbolic icon for Eject action (Bastien Nocera) (#649523)
Mouse:
- Clean up error handling (Bastien Nocera)
- Don't crash if mouse has no FeedbackStates (Bastien Nocera) (#649539)
Updates:
- Fix the interface name (Richard Hughes)
- Deal with absence of gnome-session gracefully (Matthias Clasen)
Xrandr:
- Never use a notification for errors (Bastien Nocera) (#648303)
Translations:
- es (Daniel Mustieles)
- he (Yaron Shahrabani)
- ug (Abduxukur Abdurixit)
=============
Version 3.0.3
=============
Common:
- Use defines instead of variables for ranges (Bastien Nocera)
- Fix function keys not being grabbed (Bastien Nocera) (#649222)
- Allow the "Pause" key to be used (Bastien Nocera) (#653524)
- Fix grabbing of multimedia keys (Rodrigo Moya)
Wacom:
- Enable wacom touch key by default (Peter Hutterer) (#651020)
Translations:
- bg (Alexander Shopov)
- ca (Gil Forcada)
- ca@valencia (Carles Ferrando)
- cz (Marek Černocký)
- de (Mario Blättermann)
- es (Daniel Mustieles)
- gl (Fran Diéguez)
- pl (Piotr Drąg)
- sl (Matej Urbančič)
- sr (Мирослав Николић)
- sv (Daniel Nylander)
=============
Version 3.0.2
=============
Common:
- Fix syndaemon never getting started (Edward Sheldrake) (#648885)
- Fix example input device script (Bastien Nocera)
- Don't try to convert show-keyboard-leds-indicator in gnome-settings-daemon.convert (Chris Coulson)
Date & Time:
- Fix setting NTP on Fedora 15 (Bastien Nocera) (#648556)
Media keys:
- Use symbolic icon for Eject action (Bastien Nocera) (#649523)
Mouse:
- Don't pass NULL to device_is_touchpad (Matthias Clasen) (#649214)
- Clean up error handling (Bastien Nocera)
- Don't crash if mouse has no FeedbackStates (Bastien Nocera) (#649539)
XRandr:
- Never use a notification for errors (Bastien Nocera) (#648303)
Translations:
- fa (Arash Mousavi)
- ug (Abduxukur Abdurixit)
=============
Version 3.0.1
=============
Updates: Fix firmware auto-installation
Media-keys: Fix possible crash when sound device is removed
Updated translations
===============
Version 3.0.0.1
===============
Keyboard: Fix crash showing the keyboard layout in fallback mode
Updated translations
=============
Version 3.0.0
=============
Common:
- Change default inactive sleep on battery to suspend (William Jon McCann)
Keyboard:
- Clarify actual units used for repeat rate (Bastien Nocera) (#646241)
Printers:
- Cancel CUPS' subscription policy (Marek Kasik)
- Make CUPS' subscriptions expirable (Marek Kasik)
- Remove old subscriptions (Marek Kasik)
XSettings:
- Try a few times to start the xsettings manager (Rodrigo Moya) (#634988)
Translations:
- bn (Jamil Ahmed)
- ca (Jordi Serratosa)
- cz (Marek Černocký)
- da (Ask H. Larsen)
- de (Christian Kirbach, Wolfgang Stöggl)
- en_GB (Bruce Cowan)
- eu (Iñaki Larrañaga Murgoitio)
- he (Yaron Shahrabani)
- hi (Rajesh Ranjan)
- hu (Gabor Kelemen)
- id (Dirgita)
- ja (Takayuki KUSANO)
- ko (Changwoo Ryu)
- lv (Rudolfs Mazurs)
- ml (Ani Peter)
- nl (Wouter Bolsterlee, Hannie Dumoleyn)
- pl (Piotr Drąg)
- pt_BR (Djavan Fagundes)
- ru (Yuri Myasoedov)
- sr (Miroslav Nikolić)
- sv (Daniel Nylander)
- ta (Dr.T.Vasudevan)
- ug (Abduxukur Abdurixit)
- vi (Nguyễn Thái Ngọc Duy)
- zh_CN (Aron Xu)
===============
Version 2.91.93
===============
Power:
- Don't suspend the computer when idle by default
- Add back "interactive" option
Date & Time:
- Check for the correct PolicyKit action
Accessibility settings:
- Enable plugin by default, so that screen readers and
on-screen keyboards work out-of-the-box
And loads of translations
===============
Version 2.91.92
===============
Common:
- Update priority of a few plugins (Bastien Nocera)
- gdk_display_get_device_manager() retval handling (Bastien Nocera) (#685020)
- Improve CUPS detection (Saleem Abdulrasool) (#644063)
- Make sure G_LOG_DOMAIN is set to the plugin name for each plugin (Richard Hughes)
- Make sure we mop up stray idle handlers (Bastien Nocera)
- Simplify input helper (Bastien Nocera)
- Launch a custom script on input devices (Peter Hutterer) (#635486)
Daemon:
- Fix possible crasher on exit (Bastien Nocera) (#639347)
Media keys:
- Update gvc copy/paste from control-center (Bastien Nocera)
- Make volume go up to 11 (Bastien Nocera) (#631030)
- Simplify volume keys handling (Sjoerd Simons) (#640963)
Mouse:
- Fix possible memory leak (Bastien Nocera)
- Implement touchpad motion settings (Bastien Nocera) (#642474)
- Fix shape handling in locate-pointer (Gerd Kohlberger) (#645092)
- Handle touchpad handedness changing (Bastien Nocera)
- Don't apply any settings if XInput isn't present (Bastien Nocera)
- Separate device dependent calls (Bastien Nocera)
- Remove duplicated calls on start (Bastien Nocera)
- Remove unused supports_xinput_devices() call (Bastien Nocera)
- Make sure syndaemon is killed when touchpad disappears (Bastien Nocera)
- Hook up input device customisation script (Bastien Nocera)
- Fix double-free when handling one-button touchpad (Bastien Nocera)
- Fix crash in GHashTable usage (Bastien Nocera)
Power:
- Set the default display off time to be same as session idle time (William Jon McCann)
Updates:
- g_get_real_time() returns microseconds, not seconds since the epoch (Richard Hughes)
- Ensure te user gets the updates notification if it's never been shown (Richard Hughes)
- Ensure the user gets notified of normal updates at the correct interval (Richard Hughes)
Translations:
- ar (Khaled Hosny)
- de (Mario Blättermann)
- el (Γιώργος Στεφανάνης)
- et (Mattias Põldaru)
- fr (Cyril Arnaud, Gérard Baylard, Alain Lojewski and Claude Paroz)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- hu (Gabor Kelemen)
- lt (Gintautas Miliauskas)
- lv (Rudolfs Mazurs)
- pl (Piotr Drąg)
- ro (Lucian Adrian Grijincu)
- sl (Matej Urbančič, Andrej Žnidaršič)
- sr (Miroslav Nikolić)
- sv (Daniel Nylander)
===============
Version 2.91.91
===============
Automount:
- Fix crash when unlocking the screen saver
- Don't queue volumes when session is inactive
Housekeeping:
- Use nautilus's D-Bus API to empty the trash
Media keys:
- Add magnifier in/out keybindings
- Fix larger text/smaller text keybindings
Mouse:
- Make locate pointer feature work with GTK+ 3
Printers:
- Use new CUPS D-Bus API
Updates:
- Use auto-download updates when possible
XSettings:
- Also accept .gtk-module for GTK+ modules
- Don't set Xft.lcdfilter, it's broken
- Use "text-scaling-factor" key instead of DPI
===============
Version 2.91.90
===============
A11Y Settings:
- Add new plugin (Bastien Nocera)
Automount:
- Look if the session is active before automounting new volumes (Cosimo Cecchi)
- Disable automounting while screen is locked (Martin Pitt, Cosimo Cecchi)
Background:
- Stop pending fades if new ones initiated (Ray Strode)
Date & Time:
- Add Debian support to NTP service activation (Milan Bouchet-Valat) (#641598)
- Fix gsd_datetime_check_tz_name() never working (Bastien Nocera) (#674999)
Keyboard:
- Update for new libgnomekbd API (Sergey V. Udaltsov)
- Match shell behaviour for visibility (Bastien Nocera)
- Explicitly calling gtk_widget_show_all for kbd layout (Sergey V. Udaltsov)
Media keys:
- Fix crash when keybindings change (Bastien Nocera)
- Add more Universal Access keybindings (Bastien Nocera) (#641279)
Mouse:
- Use event driven mode for syndaemon (Pauli Nieminen) (#639623)
- Use syndaemon -K to ignore Ctrl+C and other combos (Peter Hutterer) (#639487)
Print notification:
- Go back to using name in notifications (William Jon McCann)
- Check that cups is recent enough (Marek Kasik)
Updates:
- Add an updates plugin to integrate with PackageKit (Richard Hughes)
XSettings:
- Fix memleak, using wrong unref function (Bastien Nocera)
Translations:
- ar (Khaled Hosny)
- es (Daniel Mustieles, Jorge González)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- it (Luca Ferretti)
- ko (Changwoo Ryu)
- nb (Kjartan Maraas)
- pa (A S Alam)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
==============
Version 2.91.9
==============
XSettings:
- Initialize gtk-modules setting (Dan Winship)
- Support GTK/AutoMnemonics setting (Matthias Clasen)
Date & Time:
- Use a single polkit action for this (Thomas Wood)
Media keys:
- Prevent volume underflow (Sjoerd Simons, Bastien Nocera)
- Use symbolic icons for OSD (Matthias Clasen, Bastien Nocera)
Keybindings:
- Rename Accessibility keybindings to 'Universal Access' (William Jon McCann)
- Mark Accessibility keybindings as system (William Jon McCann)
Keyboard:
- Don't create kbd indicators in the shell (Sergey V. Udaltsov)
- Remove $GDM_KEYBOARD_LAYOUT handling (Bastien Nocera)
- Fix control-center invocation (Yanko Kaneti)
Housekeeping:
- Fix an untranslatable string (Cosimo Cecchi)
Print notification:
- New plugin for print notifications (Marek Kasik)
- Appearance and wording tweaks (William Jon McCann)
- Translations:
Arabic
Estonian
Galician
Hebrew
Italian
Japanese
Norwegian bokmål
Simplified Chinese
Spanish
==============
Version 2.91.8
==============
- Connect to the right GnomeRRScreen signal
==============
Version 2.91.7
==============
- Adapt to new gnome-desktop API (Giovanni Campagna)
- Remove unused macros (Federico Mena Quintero)
- Translations:
- de (Paul Seyfert)
- es (Jorge González)
- et (Ivar Smolin, Mattias Põldaru)
- gl (Fran Diéguez)
- nb (Torstein Adolf Winterseth)
- pa (A S Alam )
- sv (Daniel Nylander)
- vi (Nguyễn Thái, Nguyen Vu Hung)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
================
Version 2.91.6.2
================
- Fix a crasher with GTK+ 2.91.7 (Cosimo Cecchi)
================
Version 2.91.6.1
================
- Suppress warnings due to gdk_error_trap_pop (Cosimo Cecchi)
- Fix build with GTK+ 2.91.7 (Cosimo Cecchi)
==============
Version 2.91.6
==============
- Port to GtkStyleContext (Bastien Nocera)
- Suspend by default on battery power (Colin Walters)
- Timezone and NTP improvements (Bastien Nocera)
- Port to GtkAppChooserButton (Cosimo Cecchi)
- Port background code to GDBus (Dan Williams)
- Support multiple smartcard drivers (Ray Strode)
- Background plugin misc fixes (Tomas Bzatek, Owen W. Taylor)
================
Version 2.91.5.1
================
- Handle rename of org.gnome.media-handling (Owen W. Taylor)
==============
Version 2.91.5
==============
- Add automount plugin (Tomas Bzatek)
- Don't pass NULL strings to g_variant_new() (Bastien Nocera)
- Properly handle gnome-session EndSession signals (Cosimo Cecchi)
==============
Version 2.91.4
==============
- Add Wacom configuration plugin (Peter Hutterer)
- Add support for the XF86TouchpadOn/Off keys (Bastien Nocera)
- Move some gnome-power-manager settings, so it can
be used in the control center (Richard Hughes)
- Only ever call g_bus_own_name() once for the main D-Bus name (BN)
- Register with gnome-session to avoid timeouts, and transition
problems on login (BN)
- Fix possible warnings or crashers when _stop() is called without
_start() having been completed (William Jon McCann)
==============
Version 2.91.3
==============
- Remove xrdb plugin (Bastien Nocera)
- Remove outdated GConf schemas (BN)
- Handle a11y toggle shortcut keys in media-keys (BN)
- Make volume down work when muted (BN)
- Export the "cursor-blink-timeout" XSetting
- Add test-system-timezone test program
- Fix possible crasher in media-keys (William Jon McCann)
- Make media-keys not crash when there are no listeners (BN)
- Use a notification for the low space waring in housekeeping (WJMcC)
- Make libnotify a hard-dependency (BN)
- Add a real test application for housekeeping (BN)
- Port daemon and xrandr plugin to GDBus (BN)
- Fix possible warnings in keyboard plugin (BN)
- Fix logout key shortcut not asking for a confirmation (BN)
- Don't warn about low space when over 1GB is free (BN)
================
Version 2.91.2.1
================
- Require a newer gnome-desktop with GSettings support for the background plugin
(Tomas Bzatek)
==============
Version 2.91.2
==============
- Migration to GSettings (Bastien Nocera, Rodrigo Moya, Gerd Kohlberger,
Carlos García Campos)
- Use MIME types for URL handlers (Rodrigo Moya)
- Fix the GSD_API_VERSION definition in configure.ac (Matthias Clasen)
- Update PolicyKit minimum requirement (Bastien Nocera)
- Remove typing break plugin (Bastien Nocera)
- Update the required version of gnome-desktop3/GTK3 (Bastien Nocera)
- Require libnotify 0.6.0 (William Jon McCann)
- KEY_SCROLL_METHOD is an enum not an int (Alban Browaeys) (#631963)
- Don't use gdk_drawable_get_screen (Alban Browaeys) (#631931)
- Fix version substitution in pkg-config file (Bastien Nocera) (#631866)
- Remove status icon for monitors (Bastien Nocera) (#631995)
- Make XInput a hard requirement (Bastien Nocera)
- Use canberra-gtk for GTK3 (Bastien Nocera)
- More network filesystems not to monitor (Josselin Mouette) (#606421)
- Fix loading plugins information (Bastien Nocera) (#631933)
- For media key, use the default application for audio/ogg (Rodrigo Moya)
- Set priority for plugins based on settings (Bastien Nocera)
- Never daemonise the "daemon" (Bastien Nocera)
- Use Gdk to get events about input devices being added (Bastien Nocera)
- Cleanup macro magic in plugin.h (Paolo Borelli) (#591798)
- Update gnome-media cut'n'paste code (Bastien Nocera) (#612024)
- Add gnome-settings-daemon man page (Joshua Cummings) (#588716)
- Remove horrible xmodmap fallback code (Bastien Nocera) (#150542)
- Remove outdated plugin (Bastien Nocera)
- Use g_timeout_add_seconds (Bastien Nocera) (#582703)
- Keyboard plugin improvements (Sergey V. Udaltsov)
- Don't choke if there are old plugins laying around (William Jon McCann)
- Check for touchpad before running syndaemon (Hernando Torque) (#632122)
- Add icon to the "Keep settings" dialogue (Bastien Nocera) (#579021)
- Add support for the enable-animation setting (Bastien Nocera) (#630535)
- Export Xft.lcdfilter for OO.o's benefit (Chris Coleman) (#631924)
- Remove XFree86 4.3.0 check (Bastien Nocera) (#632569)
- Make fontconfig a hard dependency (Bastien Nocera)
- Add GConf<->GSettings bridge plugin (Rodrigo Moya)
- Show a touchpad-disabled if no touchpad (Bastien Nocera)
- Make the "log out" key really do that (Bastien Nocera)
- If the stored configuration fails at startup, use the fallback configurations
(Gary Lin)
- Add ability to hard-code media keys (Bastien Nocera) (#623223)
- Use $(sysconfigdir) for .ad files, since they are settings (Rodrigo Moya)
- Enable maintainer mode (Rodrigo Moya)
- Don't display the gnome-settings-daemon autostart in the startup applications
list (Rodrigo Moya)
- Add settings key for disabling boot time configuration (Martin Pitt, Rodrigo
Moya) (#631388)
- Don't access free'd memory if a volume is unmounted whilst the dialog is
running (Rodrigo Moya)
- Port to GDBus (Bastien Nocera)
- Add support for more multimedia keys (Bastien Nocera)
- Handle video out keys in media-keys (Ray Strode) (#623223)
- Use virtual modifier for the Windows key (Ray Strode)
- Simplify the default XRandR behaviour (Bastien Nocera) (#634092)
- Add middle-button-enabled key (Bastien Nocera) (#633863)
- Prepare for the demise of size_request (Matthias Clasen) (#633320)
- Translations:
- ca (Carles Ferrando)
- de (Mario Blättermann)
- es (Jorge González)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- ja (Takayuki KUSANO)
- ko (Changwoo Ryu)
- nb (Kjartan Maraas)
- pa (A S Alam )
==============
Version 2.91.0
==============
- Give a name to the keyboard status icon (Matthias Clasen) (#610319)
- Fix include directory to match API version (Bastien Nocera)
- Add daemon path to pkg-config files (Bastien Nocera)
- Don't switch mouse buttons for XTest devices (Bastien Nocera) (#627084)
- Remove GtkObject usage (Matthias Clasen) (#630678)
- Use gtk3 draw event instead of expose-event (William Jon McCann) (#630975)
- Use gdk-pixbuf header (William Jon McCann) (#630975)
- Don't use GdkColormap (William Jon McCann)
- Use cairo regions to set input shape (William Jon McCann)
- Adapt to GnomeBG API changes (William Jon McCann)
- Use an empty region to ignore events (William Jon McCann)
- Don't destroy the cairo context in draw handler (William Jon McCann)
- Adapt to libgnomekbd API changes (Sergey V. Udaltsov)
- Translations:
- ar (Khaled Hosny)
- bg (Damyan Ivanov)
- ca (Joan Duran)
- cz (Petr Kovar)
- gl (Fran Diéguez)
===============
Version 2.90.1
===============
- Apply keyboard a11y settings for newly plugged keyboards
- Loads of compilation fixes for GTK3
- Fix crasher when certain items are copied to the clipboard
- Silent build by default
Display:
- Don't try to activate display configurations where all the outputs are off
- Don't cycle through custom display configurations on XF86Display button press
- Add logging infrastructure
================
Version 2.31.5.1
================
- Include fixes from 2.31.4.2
- Translations:
- nb (Kjartan Maraas)
==============
Version 2.31.5
==============
- Depend on gnome-desktop-3.0 (Rodrigo Moya)
- Translations:
- es (Jorge González)
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
- sl (Matej Urbančič)
================
Version 2.31.4.2
================
- Fix the binary name in the datetime DBus .service file (Thomas Wood)
- Translations:
- gl (Fran Diéguez)
- he (Yaron Shahrabani)
================
Version 2.31.4.1
================
- Fix the datetime DBus .service file (Thomas Wood)
==============
Version 2.31.4
==============
- Fix build for --disable-smartcard-support (Ray Strode) (#617748)
- Use gtk+-3.0 (Rodrigo Moya)
- Fix launching the display configuration tool (Matthias Clasen)
- Move clock service from gnome-panel (Rodrigo Moya, Thomas Wood)
- Define plugindir in .pc file (Rodrigo Moya)
- Translations:
- et (Ivar Smolin)
- lv (Rudols Mazurs)
- nb (Kjartan Maraas)
==============
Version 2.31.3
==============
- Fixed icon names, prefixed with kbd- (Sergey Udaltsov)
- Use "show layout" dialog from libgnomekbd (Sergey Udaltsov)
- Translations:
- et (Ivar Smolin)
- he (Yaron Shahrabani)
- sl (Matej Urbančič)
==============
Version 2.31.2
==============
- Fix installation of the xrandr helper binary (Jens Granseur) (#617782)
- Always dist smartcard.gnome-settings-plugin (Ray Strode) (#617748)
- Adjust XF86Display timestamps if they are out of order with RANDR
timestamps (Chase Douglas) (#610482)
- Don't install template files into the icon theme (Matthias Clasen)
- Fix loading OSD icons when there's no SVG version (Bastien Nocera) (#618023)
- Only check for baobob if we're about to show a dialog (Ross Burton)
- Translations:
- de (Mario Blättermann)
- en@shaw (Thomas Thurman)
- es (Jorge González)
- gl (Fran Diéguez)
- or (Manoj Kumar Giri)
==============
Version 2.31.1
==============
- Create the directory for the system's RANDR configuration (Federico Mena Quintero)
- Add the logic needed for the "Make Default" button in gnome-display-properties
(Federico Mena Quintero)
- Use $sysconfdir for /etc installation (Rodrigo Moya)
- Replace deprecated GTK_WIDGET_STATE (Andre Klapper)
- Compile with -DGSEAL_ENABLE (Andre Klapper) (#612588)
- Use Layouts instead of Groups (Sergey Udaltsov) (#553108)
- Add smartcard plugin (Ray Strode)
- Software LED indicators (Sergey Udaltsov) (#616380)
- Use LED icons instead of files (Sergey Udaltsov)
- Translations:
- de (Mario Blättermann)
- en_GB (Philip Withnall)
- es (Jorge Gonzalez)
- gl (Francisco Diéguez)
- mr (Sandeep Shedmake)
- sk (Pavol Šimo)
- sl (Matej Urbančič)
- te (krishnababu k)
==============
Version 2.30.1
==============
- Fix keyboard indicator displaying (Martin Pitt) (#613666)
- Default to system settings for handling multiple keyboard layouts (Martin Pitt)
- Introduce gconf key that allows hiding the indicator (Sergey Udaltsov) (#612240)
(#613666)
- Translations:
- ca (Jordi Serratosa)
- ca@valencia (Carles Ferrando)
- crh (Reşat SABIQ)
- et (Ivar Smolin)
- kn (Shankar Prasad)
- sl (Pavol Šimo)
- th (Theppitak Karoonboonyanan)
==============
Version 2.30.0
==============
- Protect XInput code by ifdefs if XInput isn't available (Daniel Macks) (#611670)
- Don't play a sound when the volume doesn't change (Bastien Nocera) (#610001)
- Fix linking with pedantic linkers (Bastien Nocera) (#610244)
- Remove unused do_sleep_action function (Bastien Nocera)
- Apply all keyboard settings to new keyboards (Bastien Nocera) (#610245)
- Ensure the window is realized before we invalidate it (Richard Hughes) (#604918)
- Replace "eject" spawn with GIO code (Bastien Nocera) (#580779)
- Don't spawn xrdb (Martin Pitt) (#586276)
- Add translator hint (Jens Granseuer) (#613647)
- Disable font plugin by default (Bastien Nocera) (#613604)
- Translations:
- bn (Jamil Ahmed)
- da (Ask H. Larsen)
- et (Ivar Smolin)
- eu (Inaki Larranaga Murgoitio)
- he (Nikos Bakaoukas)
- hu (Gabor Kelemen)
- ko (Changwoo Ryu)
- lt (Gintautas Miliauskas)
- nl (Hannie Dumoleyn, Reinout van Schouwen)
- nn (Torstein Adolf Winterseth)
- pa (A S Alam)
- pt (Duarte Loreto)
- ro (Adi Roiban)
- sl (Pavol Šimo)
- sr (Miloš Popović)
- uk (Maxim V. Dziumanenko)
===============
Version 2.29.92
===============
- Translations:
- bg (Alexander Shopov)
- ca (Joan Duran)
- en_GB (Bruce Cowan)
- fi (Timo Jyrinki)
- hu (Gabor Kelemen)
- it (Luca Ferretti)
- nb (Kjartan Maraas)
- pt_BR (Antonio Fernandes C. Neto)
- sv (Daniel Nylander)
===============
Version 2.29.91
===============
- Fn-F8 should disable/enable touch points (Peter Hutterer) (#594831)
- Always set the position of outputs, even if they are already turned on
(Federico Mena Quintero)
- Apply keyboard settings to newly plugged in devices (Federico Mena Quintero)
(#610245)
- Translations:
- de (Jochen Skulj, Mario Blättermann)
- es (Jorge González)
- gl (Fran Diéguez)
- ro (Lucian Adrian Grijincu)
- sl (Matej Urbančič)
- ta (vasudeven)
- ru (Leonid Kanter)
- zh_CN (Ray Wang)
- zh_HK & zh_TW (Chao-Hsiung Liao)
===============
Version 2.29.90
===============
- Add gthread-2.0 to required modules for the daemon (Jens Granseuer) (#608217)
- Centralize the use of gnome_rr_config_apply_with_time (Federico Mena Quintero)
- Translations:
- et (Ivar Smolin)
- sl (Matej Urbančič)
==============
Version 2.29.6
==============
- Don't allow left-handed setting for single-button touchpads (Peter Hutterer)
- Don't die on X servers without XKB (Matthias Clasen) (#604651)
- Translations:
- bg (Alexander Shopov)
- bn (Jamil Ahmed)
- es (Jorge González)
- nb (Kjartan Maraas)
- ta (vasudeven)
==============
Version 2.29.5
==============
- Fix variant handling in $GDM_KEYBOARD_LAYOUT (Martin Pitt) (#596897)
- Tighten check for XInput (Jens Granseuer)
- Fix bluriness in level bar, and popup (Bastien Nocera) (#567249)
- Remove unused variable (Bastien Nocera) (#599904)
- Honour libexecdir when spawning gsd-locate-pointer (Jens Granseuer) (#599209)
- Allow left-handed setting for touchpads (Peter Hutterer)
- Use a rounded instead of curved rectangle (William Jon McCann)
- Improve the media keys overlay design (William Jon McCann) (#596136)
- Add brightness to the media-keys popup (Bastien Nocera) (#599677)
- Fix for GSEAL goal (Bastien Nocera) (#599861)
- Avoid volumes going over 100% (Bastien Nocera) (#600770)
- Make OSD display more generic (Bastien Nocera) (#600951)
- Support loading -rtl and -ltr variants of icons (Bastien Nocera) (#600984)
- Relicense gsd-media-keys-window.[ch] to LGPL (Bastien Nocera) (#600986)
- Hide the status icon before unreffing it (Matthias Clasen) (#601696)
- Make eject behave better on OpenBSD (Jasper Lievisse Adriaanse) (#598573)
- Export libexecdir in .pc file (DJ Lucas) (#596388)
- Run gnome-color-manager apply program when the outputs change
(Richard Hughes)
- Factor out function to get keycodes from keysym names (Federico Mena Quintero)
- Handle the XF86RotateWindows hotkey by rotating a laptop's display
(Federico Mena Quintero)
- Respond to monitor configuration changes when in charge (Matthias Clasen)
(#601203)
- Filter invalid layouts before looking for the index of one passed by gdm
(Vincent Untz) (#585868)
- Add linsysfs to list of virtual filesystems (Coleman Kane) (#604396)
- Remove sleep keybindings (Bastien Nocera) (#170175)
- Start an on-screen-display window (OSD) (Federico Mena Quintero)
- Split the composited and non-composited code for the expose-event handler
(Federico Mena Quintero)
- Use a hand-drawn frame instead of a GtkBuilder frame (Federico Mena Quintero)
- Using GkbdStatus for the automatic notification icon (Sergey V. Udaltsov)
- Implement popup menu for the notification icon (Sergey V. Udaltsov)
- Add extra API required by GsdMediaKeysWindow (Federico Mena Quintero)
- Add timed exit option (William Jon McCann)
- Fixes for new libxklavier (Sergey V. Udaltsov)
- Translations:
- ast (Xandru Armesto Fernandez)
- en@shaw (Thomas Thurman)
- es (Jorge González)
- et (Mattias Põldaru, Ivar Smolin)
- ja (Takayuki KUSANO)
- nb (Kjartan Maraas)
- nds (Nils-Christoph Fiedler)
- ru (Leonid Kanter)
- sl (Matej Urbančič)
- sv (Daniel Nylander)
- uk (Maxim V. Dziumanenko)
- vi (Nguyễn Thái Ngọc Duy)
- zh_CN (Aron Xu)
==============
Version 2.28.1
==============
- Try harder to use the keyboard layout passed by gdm (Vincent Untz)
- Translations:
- ca (Joan Duran)
- el (Kostas Papadimas)
- or (Manoj Kumar Giri)
- pl (Tomasz Dominikowski)
- ru (Andrey Grigoriev, Alexandre Prokoudine)
- sl (Matej Urbančič)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
==============
Version 2.28.0
==============
- Fix incomplete function declaration (Vincent Untz)
- Don't install the dummy plugin whilst keeping the Makefile.am
almost intact for copy/paste (Bastien Nocera) (#578538)
- Fix Touchpad left-handed issues (Bastien Nocera) (#594617)
- Add sound effect to volume key handling (Bastien Nocera) (#404683)
- Remove useless custom eject icon (Bastien Nocera)
- Validate xsettings GConf keys read from the configuration (Jens Granseuer)
(#594821)
- Fix compiler warnings (Jens Granseuer)
- Translations:
- as (Amitakhya Phukan)
- cz (Petr Kovar)
- da (Ask H. Larsen)
- de (Mario Blättermann)
- en_GB (Bruce Cowan)
- hi (Rajesh Ranjan)
- hu (Gabor Kelemen)
- it (Luca Ferretti)
- ja (Takayuki KUSANO)
- kn (Shankar Prasad)
- mai (Rajesh Ranjan)
- ml (Ani)
- mr (Sandeep Shedmake)
- or (Manoj Kumar Giri)
- pa (A S Alam )
- pl (Piotr Drąg)
- ro (Adi Roiban, Dumitru Mișu Moldovan)
- sr (Miloš Popović)
- te (krishnababu k)
- uk (Maxim V. Dziumanenko)
===============
Version 2.27.92
===============
- Make 'Locate Pointer a separate process (Matthias Clasen) (#524499)
- Skip button mappings only for core devices (Peter Hutterer)
- Translations:
- ar (Khaled Hosny)
- bn (Jamil Ahmed)
- bn_IN (Runa Bhattacharjee)
- ca (Gil Forcada)
- ca@valencia (Carles Ferrando)
- et (Ivar Smolin)
- eu (Inaki Larranaga Murgoitio)
- gu (Sweta Kothari)
- he (Yaron Shahrabani)
- kn (Shankar Prasad)
- lt (Gintautas Miliauskas)
- nb (Kjartan Maraas)
- pt (Duarte Loreto)
- te (krishnababu k)
- tr (Baris Cicek)
===============
Version 2.27.91
===============
- Update gnome-volume-control code (Bastien Nocera)
- Update cut'n'paste from gnome-media (Bastien Nocera)
- Update volume control code for new API (Bastien Nocera)
- Translations:
- bg (Alexander Shopov)
- fi (Tommi Vainikainen)
- ga (Seán de Búrca)
- ko (Changwoo Ryu)
- pt_BR (Henrique P. Machado)
===============
Version 2.27.90
===============
- Update gnome-volume-control from gnome-media (Bastien Nocera) (#589825)
- Fix crash in gvc_mixer_stream_is_running() (Chris Coulson) (#590073)
- Add '-k' option to syndaemon call for 'Disable touchpad while typing'
(C de-Avillez) (#590588)
- Low disk space warning bug-fixes (Chris Coulson) (#591153)
- Translations:
- br (Denis Arnaud)
- es (Jorge González)
- et (Ivar Smolin, Priit Laes and Mattias Põldaru)
- fr (Nicolas Repentin and Claude Paroz)
- gl (Antón Méixome)
- nb (Kjartan Maraas)
- or (Manoj Kumar Giri)
- sv (Daniel Nylander)
- ta (drtvasudevan)
- zh_CN (Ray Wang)
==============
Version 2.27.5
==============
- Only use applicable configurations for switching with the XF86Display hotkey
(Federico Mena Quintero)
- Only use applicable configurations when auto-configuring outputs during hotplug
(Federico Mena Quintero)
- Really lay out displays from left to right when using the XF86Display hotkey
(Federico Mena Quintero)
- For the XF86Display hotkey, preserve the cycle order when sanitizing the
configurations (Federico Mena Quintero)
- Remove last libglade dependency (Felix Riemann)
- Improved low disk space warning (Chris Coulson) (#573980)
- Fix compiler warnings (Jens Granseuer)
- Translations:
- es (Jorge González)
- et (Ivar Smolin)
- fr (Claude Paroz)
- he (Yaron Sharabani)
- sv (Daniel Nylander)
- ta (drtvasudevan)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
==============
Version 2.27.4
==============
- Remove screensaver plugin, it's autostarted now (Matthias Clasen)
- Don't take too long in RANDR D-Bus method implementation (Federico Mena
Quintero)
- Add support for Synaptics touchpads (Matthias Clasen)
- Don't spawn more than one syncdaemon (Matthias Clasen)
- Depend on gnome-desktop >= 2.26.3 (Rodrigo Moya)
- Update gnome-volume-control code from master (Bastien Nocera)
- Fix order of arguments to strstr (Federico Mena Quintero)
- Depend on libxklavier 4.0 (Sergey V. Udaltsov)
- Remove libglade dependency from media-keys and keyboard plugins (Felix Riemann)
- Translations:
- he (Yaron Shahrabani)
- hu (Gabor Kelemen)
- in_BN (Runa Bhattacharjee)
- uk (Maxim V. Dziumanenko)
==============
Version 2.27.3
==============
- Make the RANDR tray icon's per-monitor labels explicitly black (Federico Mena
Quintero) (#556050)
- Include config.h so that the notifications code in housekeeping plugin can
actually be built (Jens Granseuer) (#584217)
- Use "screen reader" instead of "screenreader" in schema (Gabor Kelemen) (#572911)
- Lots of RANDR fixes and improvements (Federico Mena Quintero)
- Nicer handling of broken XKB configuration in gconf (Sergey Udaltsov) (#585259)
- Make 'locate pointer' deal with wm/cm changes (Matthias Clasen) (#585209)
- Be more careful when comparing two key structs (Matthias Clasen) (#580616)
- Translations:
- da (Ask H. Larsen)
- es (Jorge Gonzalez)
- et (Ivar Smolin)
- nb (Kjartan Maraas)
- sv (Daniel Nylander)
- ta (drtvasudevan)
==============
Version 2.27.1
==============
- Use ngettext for the reset dialog (Jens Granseuer) (#575409)
- Replace deprecated gtk_status_icon_set_tooltip (Thomas H.P. Andersen) (#578480)
- Updated translations:
- ca (Jordi Mas i Hernandez)
- es (Jorge Gonzalez)
- nb (Kjartan Maraas)
- sl (Matej Urban)
- zh_CN (Deng Xiyue)
==============
Version 2.26.1
==============
- Fix crash when closing the lid on some laptops (Jens Granseuer) (#576875)
- Fix crash when closing a11y notification bubble (Jens Granseuer) (#576535)
(use of libnotify >= 0.4.5 highly recommended)
- Fix problems with saving/restoring screen setup (Federico Mena Quintero)
- Make the screen resolution confirmation dialog always appear in front of
the settings window (Federico Mena Quintero) (#576006)
- Increase confirmation timeout to 30 seconds to give slower devices (like
projectors) time to adjust
- Avoid some GConf roundtrips (Jens Granseuer) (#578539, #578542)
- Build fixes (Jens Granseuer, yselkowitz@users.sourceforge.net)
- Updated translations:
- ar (Khaled Hosny)
- as (Amitakhya Phukan)
- kn (Shankar Prasad)
- nb (Kjartan Maraas)
- sr (Miloš Popović)
- sr@latin (Miloš Popović)
==============
Version 2.26.0
==============
- Make build work with -Wl,-z,defs (Christopher Taylor) (#574452)
- Updated translations:
- as (Amitakhya Phukan)
- ca (Gil Forcada)
- cs (Petr Kovar)
- da (Kenneth Nielsen)
- de (Mario Blättermann)
- el (Kostas Papadimas)
- eu (Inaki Larranaga Murgoitio)
- gl (Ignacio Casal Quinteiro)
- gu (Ankitkumar Patel)
- he (Yair Hershkovitz)
- hi (Rajesh Ranjan)
- it (Luca Ferretti)
- ja (Takeshi AIHANA)
- lt (Gintautas Miliauskas)
- ml (Ani Peter)
- mr (Sandeep Shedmake)
- or (Manoj Kumar Giri)
- ro (Mișu Moldovan)
- ru (Nickolay V. Shmyrev)
- ta (I. Felix)
- te (Krishnababu K)
===============
Version 2.25.92
===============
- don't print warnings for disabled custom shortcuts (Jens Granseuer)
- revert screen resolution change if the user closes the confirmation window
using the close icon or by pressing escape (Jens Granseuer) (#571492)
- add missing keys for a11y shortcut keys to GConf schemas (Jens Granseuer)
(#572807)
- install gnome-settings-daemon-plugin.h for custom plugin developement
(Jens Granseuer) (#573610)
- Updated translations:
- bg (Alexander Shopov)
- en_GB (Philip Withnall)
- es (Jorge Gonzalez)
- fi (Ilkka Tuohela)
- fr (Claude Paroz)
- gu (Sweta Kothari)
- hu (Gabor Kelemen)
- ko (Changwoo Ryu)
- nl (Wouter Bolsterlee)
- pl (Tomasz Dominikowski)
- pt (Duarte Loreto)
- pt_BR (Krix Apolinário, Vladimir Melo)
- sv (Daniel Nylander)
- th (Theppitak Karoonboonyanan)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
===============
Version 2.25.91
===============
- Have gnome-session restart g-s-d if it crashes (Matthias Clasen)
- Add --without-libnotify to disable notifications (Nirbheek Chauchan)
- Avoid warnings due to notifications on nonexisting status icons
(Matthias Clasen)
- Fix crash with invalid keyboard shortcuts (Jens Granseuer)
- fix label for "Don't show this message again" checkbox (Luca Ferretti) (#517821)
- HIG fix for button labels (Luca Ferretti) (#571819)
- Don't use legacy icons for keyboard and mouse (Luca Ferretti) (#571823)
- Fix alignment of the composited media window (Leo Iannacone) (#567249)
- Updated translations:
- ast (Mikel González)
- ca (Gil Forcada)
- da (Kenneth Nielsen)
- es (Jorge Gonzalez)
- eu (Iñaki Larrañaga Murgoitio)
- ja (Takeshi AIHANA)
- nl (Wouter Bolsterlee)
- pl (Tomasz Dominikowski)
- ro (Jani Monoses)
- sv (Daniel Nylander)
- vi (Clytie Siddall)
===============
Version 2.25.90
===============
- Initialize thread system (Frederic Peters) (#565515)
- Better support for Eject and Sleep actions on BSD (Jasper Lievisse Adriaanse)
(#565472)
- Spawn screensaver after a 30 second timeout instead of when idle so that it
doesn't compete with other processes when the session starts (Jens Granseuer)
(#564059)
- Add low diskspace notification (Vincent Untz) (#557647)
- Support hotkeys for a11y tools (Matthias Clasen) (#565310)
- Quiet xrdb when there are duplicate rules in the .ad files (Bastien Nocera)
(#566610)
- Add debugging output when de/registering media players (Jens Granseuer)
(#564433)
- Add a new sound plugin that tells PulseAudio to drop its sample cache when
the sound theme changes (Lennart Poettering) (#545386)
- Don't pop up an error message when there's no randr configuration file
(Federico Mena Quintero)
- Ungrab keys when key-related plugins are disabled (Jens Granseuer) (#567867)
- Use PulseAudio directly to change the volume (Bastien Nocera) (#567177)
- Don't draw_background immediately when nautilus is disabled, GnomeBG will
send a signal (Ray Strode)
- Add crossfade transition when switching backgrounds (Ray Strode) (#552857)
- Use XF86Explorer to launch the file manager (Bastien Nocera)
- Fix possible crash when pressing Fn-F7 (Andres Freund) (#568713)
- Delay drawing the background until SessionRunning (Ray Stode)
- Ask for confirmation with a timeout after changing the randr configuration
(Federico Mena Quintero) (#545115)
- Require gnome-desktop 2.25.6 (Jen Granseuer)
- Plug leaks
- Build fixes
- Updated translations:
- es (Jorge González)
- et (Mattias Põldaru)
- he (Yuval Tanny)
- hu (Gabor Kelemen)
- it (Luca Ferretti)
- ko (Changwoo Ryu)
- nb (Kjartan Maraas)
- pt_BR (Krix Apolinário)
- sv (Daniel Nylander)
- zh_CN (甘露(Gan Lu))
==============
Version 2.25.3
==============
- Add support for fn-f7 type keys (Søren Sandmann)
- Use D-Bus instead of an X client mesage in the xrandr plugin, so
the front-end can get error messages as well (Federico Mena Quintero)
- Fix crash when the X server doesn't have the XInput extension (Jens Granseuer) (#562977)
- Don't call umask (Behdad Esfahbod) (#563543)
- Shut the daemon down properly when the SIGTERM signal is received or the
D-Bus bus goes away (Ray Strode)
- Restore AccessX bits to original values on exit, fixes sticky keys
coming on when gnome-settings-daemon has exited (Ray Strode)
- Use only top-level glib and gtk+ headers (Pedro Fragoso) (#563796)
==============
Version 2.25.2
==============
- No need to trap XkbQueryExtension and friends errors (Jens Granseuer) (#559346)
- Add some performance annotations around libxklavier calls (Behdad Esfahbod)
- Start managers in idle callbacks (Behdad Esfahbod) (#559482, #559564)
- Only initialize fontconfig when starting up (Behdad Esfahbod) (#559550)
- Remove unnecessary X error traps (Jens Granseuer) (#559562)
- Init a11y status icon only when needed (Behdad Esfahbod) (#559558)
- Reshufle plugin priorities a bit (Behdad Esfhabod)
- Delay constructing the GnomeBg object until we need it (Behdad Esfahbod)
(#559639)
- Listen for DeviceEnabled instead of DeviceAdded to be sure the mouse has
been initialized (William Grant) (#559827)
- Add debugging output for volume_step (Jens Granseuer)
- Fork before gtk_init (Behdad Esfahbod) (#559695)
- Lockdown in the keybinding plugin (Matthias Clasen) (#553434)
- Trap X errors so we don't crash on X servers that don't support DevicePresence
(Jens Granseuer) (#560618)
- Fix handling of time = GDK_CURRENT_TIME (Jens Granseuer) (#559797)
- Add bundle_loader linker flag to fix compilation on MacOS X (dmack@netspace.org)
(#522673)
- Grab all keycodes that match the respective keysim (Mario Limonciello) (#561275)
- Fix --no-daemon (Behdad Esfahbod)
- Depend on libxklavier 3.8 (Sergey Udaltsov)
- Fix checks for various X libraries (Jens Granseuer)
- Fix check for xklavier device discovery (Jens Granseuer)
==============
Version 2.25.1
==============
- Ignore the 'activate' signal for deselected items so that the rotation
setting doesn't reset when the systray menu is opened (Eric Piel)
(#554951)
- Don't make togglekeys_enable depend on global AccessX state (Jens
Granseuer) (#555009)
- Fix picking up of the GDM layout (Matthias Clasen) (#554525 and
#555873)
- Use printf safely (Christian Persch) (#555553)
- Show the shutdown dialog when the power button is pressed (Matthias
Clasen) (#556307)
- Support the Gtk/ButtonImages XSetting (Matthias Clasen) (#556797)
- Clean-up volume initialization (Jens Granseuer) (#552383)
- Make the composited volume images more clear (Bogdan Butnaru)
(#557307)
- Spawn screensaver process in idle callback (Rodrigo Moya)
- Remove sound plugin (Jens Granseuer) (#557806)
- Replace gnome_help_display_desktop with gtk_show_uri (Jens Granseuer)
(#557808)
- Listen for X device changes and reconfigure the mouse if necessary
(William Grant) (#549267)
- Remove AM_MAINTAINER_MODE (Jens Granseuer) (#558503)
- Disable xrdb plugin by default (Behdad Esfahbod) (#557807)
- Improve performance logging annotations (Behdad Esfahbod) (#559162)
- Cleanup font module (Behdad Esfahbod) (#559163)
- Don't trap errors around grab_key (Behdad Esfahbod) (#559164)
- Don't run 'mousetweaks -s' at startup (Behdad Esfahbod) (#559165)
- Start fontconfig monitors, mouse and clipboard managers in idle
callbacks (Behdad Esfahbod) (#559166)
- Preload gconf dirs when feasible (Behdad Esfahbod) (#559167)
- Wait for initialization processes to be done before spawning other
processes (Behdad Esfahbod) (#559168)
- Don't close stderr to not lose warnings (Behdad Esfahbod)
- Use a pipe to communicate between children and parent process instead
of a signal (Behdad Esfahbod)
- Updated translations:
- et (Priit Laes)
- mk (Jovan Naumovski)
- pt_BR (Leonardo Ferreira Fontenelle)
- sk (Marcel Telka)
==============
Version 2.24.0
==============
- Fix the fix for read-only home directories (Simon Zheng) (#530975)
- Make the volume popup not crash when invoking it on any screen but
the first when using a compositing manager (Jens Granseuer)
(#551677)
- Add GPLv2 copyright notice explicitly so that newer versions of
autotools don't declare us GPLv3 (Jens Granseuer) (#551956)
- Specify GTK modules to load in a GConf directory instead of the
single /desktop/gnome/gtk-modules key (Jens Granseuer) (#539840)
- Also allow linking the module state to other boolean keys by using
a string value that is the name of the key to use (Jens Granseuer)
- Made the housekeeping plugin less aggressive by default (Michael J.
Chudobiak) (#552680)
- Updated translations:
- af (Friedel Wolff)
- ar (Khaled Hosny)
- bn_IN (Runa Bhattacharjee)
- ca (Gil Forcada)
- da (Kenneth Nielsen)
- el (Kostas Papadimas)
- et (Priit Laes)
- he (Yair Hershkovitz)
- hu (Gabor Kelemen)
- it (Luca Ferretti)
- kn (Shankar Prasad)
- lt (Gintautas Miliauskas)
- ml (Praveen Arimbrathodiyil)
- mr (Sandeep Shedmake)
- pl (Wadim Dziedzic)
- pt_BR (Leonardo Ferreira Fontenelle)
- ro (Mişu Moldovan)
- ta (Tirumurthi Vasudevan)
- zh_CN (Funda Wang)
===============
Version 2.23.92
===============
- Try harder to use the keyboard layout passed by GDM (Matthias Clasen)
(#551062)
- Updated translations:
- bg (Alexander Shopov)
- de (Hendrik Richter)
- en_GB (Philip Withnall)
- ga (Seán de Búrca)
- ko (Changwoo Ryu)
- nl (Reinout van Schouwen)
- pt (Duarte Loreto)
- sv (Daniel Nylander)
===============
Version 2.23.91
===============
- Removed translatable property on stock gtk-close (Claude Paroz)
- Fix a constness warning (Jens Granseuer)
- Fix a crash due to an incorrect signal handler definition (William Jon
McCann)
- Use a scale factor instead of a fixed DPI (William Jon McCann)
- Use g_warning instead of g_error when setup fails so we don't abort
(Jens Granseuer) (#549483)
- Updated translations:
- cs (Petr Kovar)
- eu (Inaki Larranaga Murgoitio)
- fi (Ilkka Tuohela)
- fr (Claude Paroz)
- ja (Takeshi AIHANA)
- nb (Kjartan Maraas)
- pt_BR (Leonardo Ferreira Fontenelle)
- th (Theppitak Karoonboonyanan)
- vi (Nguyễn Thái Ngọc Duy)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
===============
Version 2.23.90
===============
- PulseAudio check to not ouput "no" twice (Jens Granseuer)
- Add status icon when a11y hotkeys are enabled, and display Universal
Access preferences when it is clicked (William Jon McCann) (#526070)
- Simplify libnotify check, fix fontconfig result output (Jens Granseuer)
- Put the Glade file where all the others are (jens Granseuer)
- Remove some unnecessary boilerplate (Jens Granseuer)
- Use g_file_monitor instead of g_file_monitor_file/_directory (Jens
Granseuer) (#546372)
- Remove warning that isn't (Jens Granseuer)
- Fixed crash in randr startup (Jens Granseuer)
- Fail xrandr initialization if we couldn't start xrandr (Matthias Clasen)
(#546446)
- Try harder to clean up xrandr in _stop so we can enable/disable the plugin
on the fly (Jens Granseuer)
- For LIBSOUNDS, check for libgnomeui, not just libgnome (Federico Mena Quintero)
- Add sexy labels when setting up dual monitors (Federico Mena Quintero)
- Add a separator to the menu before "Configure display settings" (Federico Mena
Quintero)
- Use GDK to get DPI (William Jon McCann)
- Updated translations:
- ar (Djihed Afifi)
- es (Jorge Gonzalez)
- et (Priit Laes)
- fi (Ilkka Tuohela)
- gl (Ignacio Casal Quinteiro)
- ja (Takeshi AIHANA)
- he (Yair Hershkovitz)
- ml (Praveen Arimbrathodiyil)
- nb (Kjartan Maraas)
- pt (Duarte Loreto)
- pt_BR (Leonardo Ferreira Fontenelle)
- th (Theppitak Karoonboonyanan)
==============
Version 2.23.6
==============
- Remove libgnomeui dependency (James Sharpe) (#544347)
- Bump glib dependency to 2.15 (Wouter Bolsterlee) (#544737)
- Use standard icon names for the OSD (Matthias Clasen) (#544733)
- Make the display notification icon configurable (Søren Sandmann)
- Resolve NumLock dynamically (Jens Granseuer) (#165343)
- Updated translations:
- ar (Djihed Afifi)
- es (Jorge Gonzalez)
- gl (Ignacio Casal Quinteiro)
- nb (Kjartan Maraas)
- pt_BR (Leonardo Ferreira Fontenelle)
==============
Version 2.23.5
==============
- New settings for event sounds (Lennart Poettering) (#539786)
- Fix include path for building against uninstalled package.
(Damien Carbery) (#543289)
- Remove 'daemon' from the warning message (Gerd Kohlberger) (#543095)
- Make more shortcuts with shift work (Jens Granseuer) (#542275)
- Update RandR code to use new gnome-desktop API (Soren Sandmann)
- Fix accelerator check (Jens Granseuer) (#538699)
- Detect and enable PulseAudio (Colin Walters) (#533198)
==============
Version 2.23.4
==============
- Check for fontconfig instead of xft2 (Behdad Esfahbod)
- Send a Fontconfig/Timestamp xsettings notification whenever fontconfig
configurations change (Behdad Esfahbod) (#490374)
- Properly match keybindings that need Shift for resolving the keysym
(Jens Granseuer, Bastien Nocera) (#536581)
- If available use the esd_serverdir variable to locate the esd daemon
so it can be started even if it's not in the PATH (Jens Granseuer, Brian
Cameron) (#531868)
- Updated translations:
- ar (Djihed Afifi)
- th (Theppitak Karoonboonyanan)
==============
Version 2.23.3
==============
- Execute the correct action when there are multiple keyboard shortcuts with
the same keycode but different keysyms (Bastien Nocera) (#530356)
- Fix wallpaper handling for people running a session without nautilus
(Matthias Clasen) (#531487)
- Try to keep the keyboard layout from gdm (Matthias Clasen) (#531589)
- Don't die when the user's home directory is read-only (Brian Cameron)
(#530975)
- Fix artifacts from the locate pointer animation in non-composited mode
(Carlos Garnacho) (#531861)
- Pass clicks to the media popup window through to the underlying window
(Carlos Garnacho) (#531862)
- Use new gnome-desktop background API and get rid of libbackground (William
Jon McCann)
- Don't eat keypresses for multimedia key events in the mouse plugin (Bastien
Nocera)
- Shutdown when receiving the "SessionOver" signal from gnome-session (Lucas
Rocha, Jens Granseuer) (#522017)
- Fix memory leaks in the font plugin (Jens Granseuer)
- Move the locate pointer animation with the mouse cursor (Gerd Kohlberger)
(#531665)
- Fix build without GStreamer (Jens Granseuer) (#536177)
- Updated translation:
- ar (Djihed Afifi)
- bg (Yavor Doganov)
- es (Jorge Gonzalez)
- gl (Ignacio Casal Quinteiro)
- nb (Kjartan Maraas)
- th (Theppitak Karoonboonyanan)
- vi (Clytie Siddall)
================
Version 2.23.1.1
================
- Install .desktop for gnome-settings-daemon in a standard autostart directory
(Lucas Rocha)
- Updated translations:
- nb (Kjartan Maraas)
==============
Version 2.23.1
==============
- Sound server startup based on GConf setting, even when esd is disabled
(Alexey Shabalin) (#523743)
- Added a new "housekeeping" plugin to set limits on the size and age of the
thumbnail cache (Michael J. Chudobiak) (#523159)
- Fix mismatched modifier maping between egg and GTK (Jens Granseuer)
- Replace some custom functionality with stock GTK (Jens Granseuer)
- Mark string for translation (Jens Granseuer)
- Use G_DEFINE_TYPE instead of open-coding (Jens Granseuer)
- Change data types to match glib, avoid using time_t (Jens Granseuer)
- Add mapping for Gtk/Modules xsetting using GConf (Jens Granseuer) (#507386)
- Set GConf keys back to false if mousetweaks is not installed (Gerd Kohlberger)
(#525042)
- Don't try to add grabas with invalid modifiers (Jens Granseuer)
- Remove trailing newlines from messages since g_warning already takes care
of those (Jens Granseuer)
- Fix various leaks (Jens Granseuer)
- Fix TYPE macro and remove unimplemented prototype (Lorne Applebaum)
- Add a special volume subclass for better support of IBM Thinkpad hardware
volume buttons (Lorne Applebaum) (#524425)
- Initialize inited_ok or behaviour is undefined when xkb setup fails (Jens
Granseuer)
- Continued attempt at making XKB setup and error handling a bit less arcane
and crufty (Jens Granseuer)
- Only use the built-in default for volume_step if we get an error from GConf,
not just when the value is 0 which might be what the user wants (Jens
Granseuer)
- Adds a "threshold" property to the AcmeVolume class that denotes the minimum
percentage required to actually affect the volume (Jens Granseuer)
- Don't install any listeners or callbacks when XKB is not available (Jens
Granseuer)
- Remove excessive key grab logging (Jens Granseuer)
- Make plugins deactivation work (Jens Granseuer)
- Properly null-terminate g_build_filename (Jens Granseuer)
- Turn into a daemon by default and make --no-daemon work (Jens Granseuer)
- DBus API has been stable for a while; don't define DBUS_API_SUBJECT_TO_CHANGE
anymore (Jens Granseuer)
- Drop GConf backup for xkb (Sergey Udaltsov)
- Extract some functionality used by several plugins into a separate shared
helper library (Jens Granseuer) (#525426)
- Reset GConf keys when we can't launch the daemon (Jens Granseuer)
- Updated translations:
- bn_IN (Runa Bhattacharjee)
- es (Jorge Gonzalez)
- et (Priit Laes)
- nn (Eskild Hustvedt)
- sk (Marcel Telka)
- te (Sunil Mohan Adapa)
==============
Version 2.22.1
==============
- Fix segfault when shutting down the typing break monitor (Jens Granseuer)
(#521786)
- Set window type hint on the volume popup (Jens Granseuer) (#522232)
- Remove unused properties from actions GUI (Jens Granseuer)
- Reset opacity when removing the timeout (Jens Granseuer) (#522499)
- Fix handling of child process (William Jon McCann)
- Add a tool to test media keys (William Jon McCann)
- Add some profiling code (William Jon McCann)
- Fix compiler warnings (William Jon McCann)
- Fix leaks (William Jon McCann) (#524183)
- Add more stuff to the configuration summary (William Jon McCann)
- Don't eat key events (Jens Granseuer) (#523676)
- Apply keyboard settings on startup (Jens Granseuer) (#525440)
- Make "Home" keybinding work again (Jens Granseuer)
- Updated translations:
- bn_IN (Runa Bhattacharjee)
- et (Priit Laes)
- nn (Eskild Hustvedt)
- sk (Marcel Telka)
- te (Sunil Mohan Adapa)
- vi (Nguyễn Thái Ngọc Duy)
==============
Version 2.22.0
==============
- Actually link against libXi when building with XInput support (Jens Granseuer)
(#519488)
- Disable debug by default (William Jon McCann)
- Don't pass GError's if we're not going to use them (Jens Graseuer)
- Remove obsolete settings for the removed default editor plugin (Jens Granseuer)
- Updated translations:
- da (Kenneth Nielsen)
- el (Kostas Papadimas)
- en_GB (Philip Withnall)
- es (Jorge Gonzalez)
- et (Priit Laes)
- hu (Gabor Kelemen)
- it (Luca Ferretti)
- lt (Gintautas Miliauskas)
- mk (Arangel Angov)
- nb (Kjartan Maraas)
- nl (Vincent van Adrighem)
- ru (Leonid Kanter)
- uk (Maxim Dziumanenko)
- zh_HK (Chao-Hsiung Liao)
- zh_TW (Chao-Hsiung Liao)
===============
Version 2.21.92
===============
- Only print debug messages if --debug is used
- Only load plugins when requested not at every start
- Fixed #515340, Add a way to prioritise plugin load (William Jon McCann)
- Fixed #515341, Signal when plugins finish loading (William Jon McCann)
- Fixed #517259, Escape hostname for use in gconf key (Vincent Untz)
- Fixed #517418, gnome-display-properties resolution change will not be used after logout or reboot (Jens Granseuer)
- Fixed #518075, Sound plugin should start pulseaudio itself (Bastien Nocera)
Translations:
- Updated fr: Claude Paroz
- Updated de: Hendrik Brandt
- Updated nl: Vincent van Adrighem
- Updated be@latin: Ihar Hrachyshka
- Updated pt_BR: Jonh Wendell
- Updated pt: Duarte Loreto
- Updated ca: Gil Forcada
- Updated *: Matthias Clasen
- Updated oc: Yannig Marchegay
- Updated sv: Daniel Nylander
- Updated ja: Takeshi AIHANA
- Updated cs: Petr Kovar
- Updated ar: Djihed Afifi
- Updated it: Luca Ferretti
- Updated es: Jorge Gonzalez
- Updated th: Theppitak Karoonboonyanan
- Updated eu: Inaki Larranaga Murgoitio
- Updated fi: bug #518255, Ilkka Tuohela
- Updated gl: Ignacio Casal Quinteiro
- Updated nb: Kjartan Maraas
- Updated pl: Artur Flinta
===============
Version 2.21.91
===============
- Use a flat directory instead of a hierarchy to install plugins
into (Christian Persch) (#513246)
- Don't scan the plugins directory recursively (Christian Persch)
(#513246)
- Install the settings plugin to a versioned directory to fix install
with libdir == libexecdir (Christan Persch) (#504203)
- Review short and long descriptions for GConf keys (Luca Ferretti)
(#514047)
- Don't crash when running the screensaver fails (Jens Granseuer)
(#514385)
- Rename src folder to gnome-settings-daemon (Damien Carberry, Jens
Granseuer) (#511820)
- Add uninstalled.pc file for building against an uninstalled copy of
g-s-d (Damien Carberry, Jens Granseuer) (#511820)
- Add separate checks for libbackground and use external copy (Jens
Granseuer)
- Use gnome_settings_daemon for the GConf path (Jens Granseuer) (#514411)
- Release the Glade XML ASAP and keep track of the 2 widgets we need
(Jens Granseuer)
- Make sure we return a GError if initialization fails (Jens Granseuer)
(#514926)
- Load the XKB settings initially (Matthias Clasen) (#511771)
- Fix leaks (Jens Granseuer)
- Unref the GConfClient only after done with it (Jens Granseuer)
- Check for xinput (Sebastien Bacher) (#514942)
- Fix copy'n'paste error (Jens Granseuer) (#515426)
- Declare variables at the beginning of a block to make older compilers
happy (Jens Granseuer)
- Add back support for defining plugin start order (Jens Granseuer)
- Assign return value from g_slist_sort to the plugins list variable
(Wouter Bolsterlee) (#515340)
- Replace gnome_vfs usage with GIO (Rodrigo Moya) (#513990)
=================
Version 2.21.90.2
=================
- Use correct binary path in DBus service file (Rodrigo Moya)
- Updated translations:
- sv (Daniel Nylander)
=================
Version 2.21.90.1
=================
- Use plain $libexecdir for g-s-d binary (Rodrigo Moya)
===============
Version 2.21.90
===============
- Add a more appealing animation for locate pointer feature if composite
is available (Carlos Garnacho)
- Quote function names in AC_DEFUN to fix autoconf warnings (Jens Granseuer)
- Fix build with builddir != srcdir (Christian Persch) (#509142)
- Use g_ascii_dtostr instead of setlocale (Christian Persch) (#505470)
- Read check for XFT2 that got loast in the g-s-d split (Jens Granseuer)
(#510925)
- Fix typo in typing break key (Jens Granseuer) (#510429)
- Define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-bg.h (Jens
Granseuer)
- No longer define DBUS_API_SUBJECT_TO_CHANGE (Jens Granseuer)
- Initialize GnomeProgram to avoid critical warnings from libgnome (Wouter
Bolsterlee) (#509770)
- Hopefully allow $(libdir) to be the same directory as $(libexecdir) by
installing the gnome-settings-daemon binary into a subdirectory of
$(libexecdir) (Wouter Bolsterlee) (#504203)
- Don't use weird autofoo stuff to install gnome-settings-daemon into another
directory (Wouter Bolsterlee) (#504203)
- Suppress verbose GConf schema installation output (Wouter Bolsterlee)
================
Version 2.21.5.2
================
- Use libtool for building static libs also (Rodrigo Moya)
- Automake fixes for allowing long file names (Rodrigo Moya)
- Updated translations:
- nb (Kjartan Maraas)
================
Version 2.21.5.1
================
- Added translations from gnome-control-center module (Rodrigo Moya)
(#509651)
===============
Version 2.21.5
===============
- Support animated backgrounds (Soren Sandmann)
- Init gnome-vfs and use correct name in desktop file (William Jon McCann)
- Use new setting from libgnome to make toolbar icon size setting work
(William Jon McCann)
- Add Gtk/IMModule XSetting (Akira TAGOH) (#504182)
- Reverted patch for SUPER key modifier (Rodrigo Moya)
- Support mousetweaks (Gerd Kohlberger) (#503547)
- Only consider /desktop/gnome/accessibility/keyboard/enable as option
for enabling keyboard a11y features from the keyboard, not as global
switch to turn all a11y features on/off (Denis Washington)
===============
Version 2.21.4
===============
Initial development release of new gnome-settings-daemon design.
./acinclude.m4 0000644 0000041 0000041 00000007260 13264221014 013434 0 ustar www-data www-data dnl EXTRA_COMPILE_WARNINGS
dnl Turn on many useful compiler warnings
dnl For now, only works on GCC
AC_DEFUN([EXTRA_COMPILE_WARNINGS],[
dnl ******************************
dnl More compiler warnings
dnl ******************************
AC_ARG_ENABLE(compile-warnings,
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
[Turn on compiler warnings]),,
[enable_compile_warnings="m4_default([$1],[yes])"])
warnCFLAGS=
if test "x$GCC" != xyes; then
enable_compile_warnings=no
fi
warning_flags=
realsave_CFLAGS="$CFLAGS"
case "$enable_compile_warnings" in
no)
warning_flags=
;;
minimum)
warning_flags="-Wall"
;;
yes)
warning_flags="-Wall -Wmissing-prototypes"
;;
maximum|error)
warning_flags="-Wall -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
CFLAGS="$warning_flags $CFLAGS"
for option in -Wno-sign-compare; do
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $option"
AC_MSG_CHECKING([whether gcc understands $option])
AC_TRY_COMPILE([], [],
has_option=yes,
has_option=no,)
CFLAGS="$SAVE_CFLAGS"
AC_MSG_RESULT($has_option)
if test $has_option = yes; then
warning_flags="$warning_flags $option"
fi
unset has_option
unset SAVE_CFLAGS
done
unset option
if test "$enable_compile_warnings" = "error" ; then
warning_flags="$warning_flags -Werror"
fi
;;
*)
AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings)
;;
esac
CFLAGS="$realsave_CFLAGS"
AC_MSG_CHECKING(what warning flags to pass to the C compiler)
AC_MSG_RESULT($warning_flags)
AC_ARG_ENABLE(iso-c,
AC_HELP_STRING([--enable-iso-c],
[Try to warn if code is not ISO C ]),,
[enable_iso_c=no])
AC_MSG_CHECKING(what language compliance flags to pass to the C compiler)
complCFLAGS=
if test "x$enable_iso_c" != "xno"; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-ansi[\ \ ]*) ;;
*) complCFLAGS="$complCFLAGS -ansi" ;;
esac
case " $CFLAGS " in
*[\ \ ]-pedantic[\ \ ]*) ;;
*) complCFLAGS="$complCFLAGS -pedantic" ;;
esac
fi
fi
AC_MSG_RESULT($complCFLAGS)
WARN_CFLAGS="$warning_flags $complCFLAGS"
AC_SUBST(WARN_CFLAGS)
])
dnl as-ac-expand.m4 0.2.0 -*- autoconf -*-
dnl autostars m4 macro for expanding directories using configure's prefix
dnl (C) 2003, 2004, 2005 Thomas Vander Stichele
dnl Copying and distribution of this file, with or without modification,
dnl are permitted in any medium without royalty provided the copyright
dnl notice and this notice are preserved.
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
dnl example:
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
AC_DEFUN([AS_AC_EXPAND],
[
EXP_VAR=[$1]
FROM_VAR=[$2]
dnl first expand prefix and exec_prefix if necessary
prefix_save=$prefix
exec_prefix_save=$exec_prefix
dnl if no prefix given, then use /usr/local, the default prefix
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
fi
dnl if no exec_prefix given, then use prefix
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
dnl loop until it doesn't change anymore
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done
dnl clean up
full_var=$new_full_var
AC_SUBST([$1], "$full_var")
dnl restore prefix and exec_prefix
prefix=$prefix_save
exec_prefix=$exec_prefix_save
])
./configure.ac 0000644 0000041 0000041 00000045577 13264221014 013546 0 ustar www-data www-data AC_PREREQ([2.60])
AC_INIT([unity-settings-daemon],
[1.0])
AC_CONFIG_SRCDIR([gnome-settings-daemon/gnome-settings-manager.c])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.9 tar-ustar dist-xz no-dist-gzip check-news])
AM_MAINTAINER_MODE([enable])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
m4_define([gsd_api_version_major],[1])
m4_define([gsd_api_version_minor],[0])
m4_define([gsd_api_version],[gsd_api_version_major.gsd_api_version_minor])
GSD_API_VERSION="gsd_api_version"
AC_SUBST(GSD_API_VERSION)
AC_STDC_HEADERS
AC_PROG_CXX
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
AC_HEADER_STDC
AC_SUBST(VERSION)
AC_CONFIG_HEADERS([config.h])
IT_PROG_INTLTOOL([0.37.1])
GETTEXT_PACKAGE=unity-settings-daemon
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Name of default gettext domain])
AM_GLIB_GNU_GETTEXT
GSD_INTLTOOL_PLUGIN_RULE='%.gnome-settings-plugin: %.gnome-settings-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
AC_SUBST([GSD_INTLTOOL_PLUGIN_RULE])
dnl ---------------------------------------------------------------------------
dnl - Dependencies
dnl ---------------------------------------------------------------------------
GLIB_REQUIRED_VERSION=2.35.3
GIO_REQUIRED_VERSION=${GLIB_REQUIRED_VERSION}
GTK_REQUIRED_VERSION=3.7.8
GCONF_REQUIRED_VERSION=2.6.1
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
LIBNOTIFY_REQUIRED_VERSION=0.7.3
UPOWER_GLIB_REQUIRED_VERSION=0.9.1
PA_REQUIRED_VERSION=2.0
LIBWACOM_REQUIRED_VERSION=0.7
LIBRSVG_REQUIRED_VERSION=2.36.2
UPOWER_REQUIRED_VERSION=0.9.11
IBUS_REQUIRED_VERSION=1.4.99
GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION=3.7.2.1
XRANDR_REQUIRED_VERSION=1.3
XEXT_REQUIRED_VERSION=1.1
EXTRA_COMPILE_WARNINGS(yes)
PKG_CHECK_MODULES(SETTINGS_DAEMON,
gtk+-3.0 >= $GTK_REQUIRED_VERSION
gio-2.0 >= $GIO_REQUIRED_VERSION
gmodule-2.0
gthread-2.0
gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION
)
PKG_CHECK_MODULES(SETTINGS_PLUGIN,
gtk+-3.0 >= $GTK_REQUIRED_VERSION
gio-2.0 >= $GIO_REQUIRED_VERSION
libnotify >= $LIBNOTIFY_REQUIRED_VERSION
gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION
x11
)
GSD_PLUGIN_LDFLAGS="-export_dynamic -module -avoid-version -no-undefined"
AC_SUBST([GSD_PLUGIN_LDFLAGS])
AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
dnl ================================================================
dnl GSettings stuff
dnl ================================================================
GLIB_GSETTINGS
dnl ---------------------------------------------------------------------------
dnl - Check for gnome-desktop
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
dnl ---------------------------------------------------------------------------
dnl - Check for LCMS2
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(LCMS, lcms2 >= 2.2, have_new_lcms=yes, have_new_lcms=no)
if test x$have_new_lcms = xyes; then
AC_DEFINE(HAVE_NEW_LCMS,1,[Got new lcms2])
else
PKG_CHECK_MODULES(LCMS, lcms2)
fi
dnl ---------------------------------------------------------------------------
dnl - Check for libnotify
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED_VERSION,
[have_libnotify=yes], have_libnotify=no)
if test "x$have_libnotify" = xno ; then
AC_MSG_ERROR([libnotify is required to build unity-settings-daemon])
fi
AC_SUBST(LIBNOTIFY_CFLAGS)
AC_SUBST(LIBNOTIFY_LIBS)
dnl ---------------------------------------------------------------------------
dnl - GUdev integration (default enabled)
dnl ---------------------------------------------------------------------------
GUDEV_PKG=""
AC_ARG_ENABLE(gudev, AS_HELP_STRING([--disable-gudev],[Disable GUdev support (not optional on Linux platforms)]), enable_gudev=$enableval)
if test x$enable_gudev != xno; then
PKG_CHECK_MODULES(GUDEV, gudev-1.0, have_gudev="yes", have_gudev="no")
if test "x$have_gudev" = "xyes"; then
AC_DEFINE(HAVE_GUDEV, 1, [define if GUdev is available])
GUDEV_PKG="gudev-1.0"
else
if test x$enable_gudev = xyes; then
AC_MSG_ERROR([GUdev enabled but not found])
fi
fi
else
have_gudev=no
fi
AM_CONDITIONAL(HAVE_GUDEV, test x$have_gudev = xyes)
dnl ---------------------------------------------------------------------------
dnl - common
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(COMMON, x11 kbproto xi)
dnl ---------------------------------------------------------------------------
dnl - libunity-settings-daemon
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(LIBUNITY_SETTINGS_DAEMON, gtk+-3.0 >= $GTK_REQUIRED_VERSION xrandr >= $XRANDR_REQUIRED_VERSION xext >= $XEXT_REQUIRED_VERSION)
PKG_CHECK_MODULES(CHECK_GL_TEXTURE_SIZE, gl x11)
dnl ---------------------------------------------------------------------------
dnl - automount
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(AUTOMOUNT, x11 kbproto)
dnl ---------------------------------------------------------------------------
dnl - XTest
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(XTEST, x11 xtst)
AC_SUBST(XTEST_CFLAGS)
AC_SUBST(XTEST_LIBS)
dnl ---------------------------------------------------------------------------
dnl - background
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(BACKGROUND, x11 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
dnl ---------------------------------------------------------------------------
dnl - mouse
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(MOUSE, x11 xi)
dnl ---------------------------------------------------------------------------
dnl - cursor
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(CURSOR, xfixes gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
dnl ---------------------------------------------------------------------------
dnl - xsettings
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(XSETTINGS, fontconfig)
dnl ---------------------------------------------------------------------------
dnl - Keyboard plugin stuff
dnl ---------------------------------------------------------------------------
AC_ARG_ENABLE(ibus,
AS_HELP_STRING([--disable-ibus],
[Disable IBus support]),
enable_ibus=$enableval,
enable_ibus=yes)
if test "x$enable_ibus" = "xyes" ; then
IBUS_MODULE="ibus-1.0 >= $IBUS_REQUIRED_VERSION"
AC_DEFINE(HAVE_IBUS, 1, [Defined if IBus support is enabled])
else
IBUS_MODULE=
fi
AM_CONDITIONAL(HAVE_IBUS, test "x$enable_ibus" == "xyes")
AC_ARG_ENABLE(fcitx,
AS_HELP_STRING([--disable-fcitx],
[Disable Fcitx support]),
enable_fcitx=$enableval,
enable_fcitx=yes)
if test "x$enable_fcitx" = "xyes" ; then
FCITX_MODULE="fcitx-config fcitx-gclient"
AC_DEFINE(HAVE_FCITX, 1, [Defined if Fcitx support is enabled])
AC_CHECK_PROG(HAVE_GPERF, gperf, yes)
if test "x$HAVE_GPERF" != "xyes" ; then
AC_MSG_ERROR([gperf needed for Fcitx support])
fi
else
FCITX_MODULE=
fi
AM_CONDITIONAL(HAVE_FCITX, test "x$enable_fcitx" == "xyes")
PKG_CHECK_MODULES(KEYBOARD, accountsservice xkbfile xkeyboard-config $IBUS_MODULE $FCITX_MODULE gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
XKB_BASE=$($PKG_CONFIG --variable xkb_base xkeyboard-config)
AC_SUBST(XKB_BASE)
dnl ---------------------------------------------------------------------------
dnl - Housekeeping plugin stuff
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(GIOUNIX, [gio-unix-2.0])
dnl ---------------------------------------------------------------------------
dnl - media-keys plugin stuff
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify alsa $FCITX_MODULE])
PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
AM_CONDITIONAL(HAVE_INTROSPECTION, false)
dnl ---------------------------------------------------------------------------
dnl - xrandr plugin stuff
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(XRANDR, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION])
dnl ---------------------------------------------------------------------------
dnl - orientation plugin stuff
dnl ---------------------------------------------------------------------------
if test x$have_gudev != xno; then
PKG_CHECK_MODULES(ORIENTATION, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION gudev-1.0])
fi
dnl ---------------------------------------------------------------------------
dnl - sound plugin stuff
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(SOUND, [libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
# ---------------------------------------------------------------------------
# Power
# ---------------------------------------------------------------------------
PKG_CHECK_MODULES(POWER, upower-glib >= $UPOWER_REQUIRED_VERSION gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION $GUDEV_PKG libcanberra-gtk3 libnotify x11 xext xtst)
if test x$have_gudev != xno; then
PKG_CHECK_MODULES(BACKLIGHT_HELPER,
glib-2.0 >= $GLIB_REQUIRED_VERSION
gudev-1.0
)
fi
dnl ---------------------------------------------------------------------------
dnl - color
dnl ---------------------------------------------------------------------------
PKG_CHECK_MODULES(COLOR, [colord >= 0.1.9 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION libcanberra-gtk3])
dnl ---------------------------------------------------------------------------
dnl - wacom (disabled for s390/s390x and non Linux platforms)
dnl ---------------------------------------------------------------------------
case $host_os in
linux*)
if test "$host_cpu" = s390 -o "$host_cpu" = s390x; then
have_wacom=no
else
if test x$enable_gudev != xno; then
PKG_CHECK_MODULES(WACOM, [libwacom >= $LIBWACOM_REQUIRED_VERSION x11 xi xtst gudev-1.0 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION xorg-wacom librsvg-2.0 >= $LIBRSVG_REQUIRED_VERSION])
else
AC_MSG_ERROR([GUdev is necessary to compile Wacom support])
fi
have_wacom=yes
fi
;;
*)
have_wacom=no
;;
esac
AM_CONDITIONAL(HAVE_WACOM, test x$have_wacom = xyes)
dnl ==============================================
dnl PackageKit section
dnl ==============================================
have_packagekit=false
AC_ARG_ENABLE(packagekit,
AC_HELP_STRING([--disable-packagekit],
[turn off PackageKit support]),
[case "${enableval}" in
yes) WANT_PACKAGEKIT=yes ;;
no) WANT_PACKAGEKIT=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-packagekit) ;;
esac],
[WANT_PACKAGEKIT=yes]) dnl Default value
if test x$WANT_PACKAGEKIT = xyes ; then
PK_REQUIRED_VERSION=0.7.4
PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION gudev-1.0 libnotify >= $LIBNOTIFY_REQUIRED_VERSION,
[have_packagekit=true
AC_DEFINE(HAVE_PACKAGEKIT, 1, [Define if PackageKit should be used])],
[have_packagekit=false])
fi
AM_CONDITIONAL(HAVE_PACKAGEKIT, test "x$have_packagekit" = "xtrue")
AC_SUBST(PACKAGEKIT_CFLAGS)
AC_SUBST(PACKAGEKIT_LIBS)
dnl ==============================================
dnl smartcard section
dnl ==============================================
have_smartcard_support=false
AC_ARG_ENABLE(smartcard-support,
AC_HELP_STRING([--disable-smartcard-support],
[turn off smartcard support]),
[case "${enableval}" in
yes) WANT_SMARTCARD_SUPPORT=yes ;;
no) WANT_SMARTCARD_SUPPORT=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-smartcard-support) ;;
esac],
[WANT_SMARTCARD_SUPPORT=no])
if test x$WANT_SMARTCARD_SUPPORT = xyes ; then
AC_MSG_ERROR(Smartcard support is broken in this version)
NSS_REQUIRED_VERSION=3.11.2
PKG_CHECK_MODULES(NSS, nss >= $NSS_REQUIRED_VERSION,
[have_smartcard_support=true
AC_DEFINE(SMARTCARD_SUPPORT, 1, [Define if smartcard support should be enabled])],
[have_smartcard_support=false])
fi
AM_CONDITIONAL(SMARTCARD_SUPPORT, test "x$have_smartcard_support" = "xtrue")
AC_SUBST(NSS_CFLAGS)
AC_SUBST(NSS_LIBS)
AC_ARG_WITH(nssdb,
AC_HELP_STRING([--with-nssdb],
[where system NSS database is]))
NSS_DATABASE=""
if test "x$have_smartcard_support" = "xtrue"; then
if ! test -z "$with_nssdb" ; then
NSS_DATABASE="$with_nssdb"
else
NSS_DATABASE="${sysconfdir}/pki/nssdb"
fi
else
if ! test -z "$with_nssdb" ; then
AC_MSG_WARN([nssdb specified when smartcard support is disabled])
fi
fi
AC_SUBST(NSS_DATABASE)
# ---------------------------------------------------------------------------
# Enable Profiling
# ---------------------------------------------------------------------------
AC_ARG_ENABLE(profiling,
[AC_HELP_STRING([--enable-profiling],
[turn on profiling])],
, enable_profiling=no)
if test "x$enable_profiling" = "xyes"; then
AC_DEFINE(ENABLE_PROFILING,1,[enable profiling])
fi
# ---------------------------------------------------------------------------
# Plugins
# ---------------------------------------------------------------------------
plugindir='$(libdir)/unity-settings-daemon-gsd_api_version'
AC_SUBST([plugindir])
PLUGIN_CFLAGS="-DG_LOG_DOMAIN=\"\\\"\$(plugin_name)-plugin\\\"\" -DPLUGIN_NAME=\"\\\"\$(plugin_name)\\\"\" "
AC_SUBST(PLUGIN_CFLAGS)
AC_ARG_ENABLE(man,
[AS_HELP_STRING([--enable-man],
[generate man pages [default=yes]])],,
enable_man=yes)
if test "$enable_man" != no; then
AC_PATH_PROG([XSLTPROC], [xsltproc])
if test -z "$XSLTPROC"; then
AC_MSG_ERROR([xsltproc is required for --enable-man])
fi
fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
dnl ---------------------------------------------------------------------------
dnl - Finish
dnl ---------------------------------------------------------------------------
# Turn on the additional warnings last, so warnings don't affect other tests.
AC_ARG_ENABLE(more-warnings,
[AC_HELP_STRING([--enable-more-warnings],
[Maximum compiler warnings])],
set_more_warnings="$enableval",[
if test -d $srcdir/.git; then
set_more_warnings=yes
else
set_more_warnings=no
fi
])
AC_MSG_CHECKING(for more warnings)
if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
AC_MSG_RESULT(yes)
CFLAGS="\
-Wall \
-Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
-Wnested-externs -Wpointer-arith \
-Wcast-align -Wsign-compare \
$CFLAGS"
for option in -Wno-strict-aliasing -Wno-sign-compare; do
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $option"
AC_MSG_CHECKING([whether gcc understands $option])
AC_TRY_COMPILE([], [],
has_option=yes,
has_option=no,)
if test $has_option = no; then
CFLAGS="$SAVE_CFLAGS"
fi
AC_MSG_RESULT($has_option)
unset has_option
unset SAVE_CFLAGS
done
unset option
else
AC_MSG_RESULT(no)
fi
#
# Enable Debug
#
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug],
[turn on debugging])],
, enable_debug=yes)
if test "$enable_debug" = "yes"; then
DEBUG_CFLAGS="-DG_ENABLE_DEBUG"
else
if test "x$enable_debug" = "xno"; then
DEBUG_CFLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS"
else
DEBUG_CFLAGS=""
fi
fi
AC_SUBST(DEBUG_CFLAGS)
AC_OUTPUT([
Makefile
gnome-settings-daemon/Makefile
plugins/Makefile
plugins/a11y-keyboard/Makefile
plugins/a11y-settings/Makefile
plugins/automount/Makefile
plugins/background/Makefile
plugins/clipboard/Makefile
plugins/color/Makefile
plugins/common/Makefile
plugins/cursor/Makefile
plugins/dummy/Makefile
plugins/power/Makefile
plugins/housekeeping/Makefile
plugins/keyboard/Makefile
plugins/media-keys/Makefile
plugins/media-keys/gvc/Makefile
plugins/mouse/Makefile
plugins/orientation/Makefile
plugins/remote-display/Makefile
plugins/screensaver-proxy/Makefile
plugins/smartcard/Makefile
plugins/sound/Makefile
plugins/updates/Makefile
plugins/wacom/Makefile
plugins/xrandr/Makefile
plugins/xsettings/Makefile
data/Makefile
data/unity-settings-daemon.pc
data/unity-settings-daemon-uninstalled.pc
data/libunity-settings-daemon.pc
po/Makefile.in
man/Makefile
tests/Makefile
])
dnl ---------------------------------------------------------------------------
dnl - Show summary
dnl ---------------------------------------------------------------------------
echo "
untiy-settings-daemon $VERSION
=============================
prefix: ${prefix}
exec_prefix: ${exec_prefix}
libdir: ${libdir}
bindir: ${bindir}
sbindir: ${sbindir}
sysconfdir: ${sysconfdir}
sysconfsubdir: ${sysconfsubdir}
localstatedir: ${localstatedir}
plugindir: ${plugindir}
datadir: ${datadir}
source code location: ${srcdir}
compiler: ${CC}
cflags: ${CFLAGS}
Maintainer mode: ${USE_MAINTAINER_MODE}
Session tracking: ${SESSION_TRACKING}
LCMS DICT support: ${have_new_lcms}
IBus support: ${enable_ibus}
Fcitx support: ${enable_fcitx}
Libnotify support: ${have_libnotify}
PackageKit support: ${have_packagekit}
Smartcard support: ${have_smartcard_support}
Cups support: ${enable_cups}
Wacom support: ${have_wacom}
${NSS_DATABASE:+\
System nssdb: ${NSS_DATABASE}
}\
Profiling support: ${enable_profiling}
"
./README 0000644 0000041 0000041 00000000000 13264221014 012104 0 ustar www-data www-data ./plugins/ 0000755 0000041 0000041 00000000000 13264221014 012717 5 ustar www-data www-data ./plugins/housekeeping/ 0000755 0000041 0000041 00000000000 13264221014 015405 5 ustar www-data www-data ./plugins/housekeeping/housekeeping.gnome-settings-plugin.in 0000644 0000041 0000041 00000000425 13264221014 024662 0 ustar www-data www-data [GNOME Settings Plugin]
Module=housekeeping
IAge=0
Priority=1
_Name=Housekeeping
_Description=Automatically prunes thumbnail caches and other transient files, and warns about low disk space
Authors=Michael J. Chudobiak
Copyright=Copyright © 2008 Michael J. Chudobiak
Website=
./plugins/housekeeping/test-housekeeping.c 0000644 0000041 0000041 00000000350 13264221014 021212 0 ustar www-data www-data #define NEW gsd_housekeeping_manager_new
#define START gsd_housekeeping_manager_start
#define STOP gsd_housekeeping_manager_stop
#define MANAGER GsdHousekeepingManager
#include "gsd-housekeeping-manager.h"
#include "test-plugin.h"
./plugins/housekeeping/gsd-disk-space.c 0000644 0000041 0000041 00000114706 13264221014 020360 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2008, Novell, Inc.
*
* Authors: Vincent Untz
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gsd-disk-space.h"
#include "gsd-ldsm-dialog.h"
#include "gsd-disk-space-helper.h"
#define GIGABYTE 1024 * 1024 * 1024
#define CHECK_EVERY_X_SECONDS 60
#define DISK_SPACE_ANALYZER "baobab"
#define SETTINGS_HOUSEKEEPING_DIR "org.gnome.settings-daemon.plugins.housekeeping"
#define SETTINGS_FREE_PC_NOTIFY_KEY "free-percent-notify"
#define SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY "free-percent-notify-again"
#define SETTINGS_FREE_SIZE_NO_NOTIFY "free-size-gb-no-notify"
#define SETTINGS_MIN_NOTIFY_PERIOD "min-notify-period"
#define SETTINGS_IGNORE_PATHS "ignore-paths"
#define PRIVACY_SETTINGS "org.gnome.desktop.privacy"
#define SETTINGS_PURGE_TRASH "remove-old-trash-files"
#define SETTINGS_PURGE_TEMP_FILES "remove-old-temp-files"
#define SETTINGS_PURGE_AFTER "old-files-age"
typedef struct
{
GUnixMountEntry *mount;
struct statvfs buf;
time_t notify_time;
} LdsmMountInfo;
static GHashTable *ldsm_notified_hash = NULL;
static unsigned int ldsm_timeout_id = 0;
static GUnixMountMonitor *ldsm_monitor = NULL;
static double free_percent_notify = 0.05;
static double free_percent_notify_again = 0.01;
static unsigned int free_size_gb_no_notify = 2;
static unsigned int min_notify_period = 10;
static GSList *ignore_paths = NULL;
static GSettings *settings = NULL;
static GSettings *privacy_settings = NULL;
static GsdLdsmDialog *dialog = NULL;
static NotifyNotification *notification = NULL;
static guint64 *time_read;
static gboolean purge_trash;
static gboolean purge_temp_files;
static guint purge_after;
static guint purge_trash_id = 0;
static guint purge_temp_id = 0;
static gchar*
ldsm_get_fs_id_for_path (const gchar *path)
{
GFile *file;
GFileInfo *fileinfo;
gchar *attr_id_fs;
file = g_file_new_for_path (path);
fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
if (fileinfo) {
attr_id_fs = g_strdup (g_file_info_get_attribute_string (fileinfo, G_FILE_ATTRIBUTE_ID_FILESYSTEM));
g_object_unref (fileinfo);
} else {
attr_id_fs = NULL;
}
g_object_unref (file);
return attr_id_fs;
}
static gboolean
ldsm_mount_has_trash (LdsmMountInfo *mount)
{
const gchar *user_data_dir;
gchar *user_data_attr_id_fs;
gchar *path_attr_id_fs;
gboolean mount_uses_user_trash = FALSE;
gchar *trash_files_dir;
gboolean has_trash = FALSE;
GDir *dir;
const gchar *path;
user_data_dir = g_get_user_data_dir ();
user_data_attr_id_fs = ldsm_get_fs_id_for_path (user_data_dir);
path = g_unix_mount_get_mount_path (mount->mount);
path_attr_id_fs = ldsm_get_fs_id_for_path (path);
if (g_strcmp0 (user_data_attr_id_fs, path_attr_id_fs) == 0) {
/* The volume that is low on space is on the same volume as our home
* directory. This means the trash is at $XDG_DATA_HOME/Trash,
* not at the root of the volume which is full.
*/
mount_uses_user_trash = TRUE;
}
g_free (user_data_attr_id_fs);
g_free (path_attr_id_fs);
/* I can't think of a better way to find out if a volume has any trash. Any suggestions? */
if (mount_uses_user_trash) {
trash_files_dir = g_build_filename (g_get_user_data_dir (), "Trash", "files", NULL);
} else {
gchar *uid;
uid = g_strdup_printf ("%d", getuid ());
trash_files_dir = g_build_filename (path, ".Trash", uid, "files", NULL);
if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) {
gchar *trash_dir;
g_free (trash_files_dir);
trash_dir = g_strdup_printf (".Trash-%s", uid);
trash_files_dir = g_build_filename (path, trash_dir, "files", NULL);
g_free (trash_dir);
if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) {
g_free (trash_files_dir);
g_free (uid);
return has_trash;
}
}
g_free (uid);
}
dir = g_dir_open (trash_files_dir, 0, NULL);
if (dir) {
if (g_dir_read_name (dir))
has_trash = TRUE;
g_dir_close (dir);
}
g_free (trash_files_dir);
return has_trash;
}
static void
ldsm_analyze_path (const gchar *path)
{
const gchar *argv[] = { DISK_SPACE_ANALYZER, path, NULL };
g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, NULL);
}
static gboolean
server_has_actions (void)
{
gboolean has;
GList *caps;
GList *l;
caps = notify_get_server_caps ();
if (caps == NULL) {
fprintf (stderr, "Failed to receive server caps.\n");
return FALSE;
}
l = g_list_find_custom (caps, "actions", (GCompareFunc)strcmp);
has = l != NULL;
g_list_foreach (caps, (GFunc) g_free, NULL);
g_list_free (caps);
return has;
}
static void
ignore_callback (NotifyNotification *n,
const char *action)
{
g_assert (action != NULL);
g_assert (strcmp (action, "ignore") == 0);
/* Do nothing */
notify_notification_close (n, NULL);
}
static void
examine_callback (NotifyNotification *n,
const char *action,
const char *path)
{
g_assert (action != NULL);
g_assert (strcmp (action, "examine") == 0);
ldsm_analyze_path (path);
notify_notification_close (n, NULL);
}
static gboolean
should_purge_file (GFile *file,
GCancellable *cancellable,
GDateTime *old)
{
GFileInfo *info;
GDateTime *date;
gboolean should_purge;
should_purge = FALSE;
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_TRASH_DELETION_DATE ","
G_FILE_ATTRIBUTE_UNIX_UID ","
G_FILE_ATTRIBUTE_TIME_CHANGED,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable,
NULL);
date = g_file_info_get_deletion_date (info);
if (date == NULL) {
guint uid;
guint64 ctime;
uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID);
if (uid != getuid ()) {
should_purge = FALSE;
goto out;
}
ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED);
date = g_date_time_new_from_unix_local ((gint64) ctime);
}
should_purge = g_date_time_difference (old, date) >= 0;
g_date_time_unref (date);
out:
g_object_unref (info);
return should_purge;
}
DeleteData *
delete_data_new (GFile *file,
GCancellable *cancellable,
GDateTime *old,
gboolean dry_run,
gboolean trash,
gint depth)
{
DeleteData *data;
data = g_new (DeleteData, 1);
data->ref_count = 1;
data->file = g_object_ref (file);
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
data->old = g_date_time_ref (old);
data->dry_run = dry_run;
data->trash = trash;
data->depth = depth;
data->name = g_file_get_parse_name (data->file);
return data;
}
static DeleteData *
delete_data_ref (DeleteData *data)
{
data->ref_count += 1;
return data;
}
void
delete_data_unref (DeleteData *data)
{
data->ref_count -= 1;
if (data->ref_count > 0)
return;
g_object_unref (data->file);
if (data->cancellable)
g_object_unref (data->cancellable);
g_date_time_unref (data->old);
g_free (data->name);
g_free (data);
}
static void
delete_batch (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source);
DeleteData *data = user_data;
GList *files, *f;
GFile *child_file;
DeleteData *child;
GFileInfo *info;
GError *error = NULL;
files = g_file_enumerator_next_files_finish (enumerator, res, &error);
g_debug ("GsdHousekeeping: purging %d children of %s", g_list_length (files), data->name);
if (files) {
for (f = files; f; f = f->next) {
if (g_cancellable_is_cancelled (data->cancellable))
break;
info = f->data;
child_file = g_file_get_child (data->file, g_file_info_get_name (info));
child = delete_data_new (child_file,
data->cancellable,
data->old,
data->dry_run,
data->trash,
data->depth + 1);
delete_recursively_by_age (child);
delete_data_unref (child);
g_object_unref (child_file);
}
g_list_free_full (files, g_object_unref);
if (!g_cancellable_is_cancelled (data->cancellable)) {
g_file_enumerator_next_files_async (enumerator, 20,
0,
data->cancellable,
delete_batch,
data);
return;
}
}
g_file_enumerator_close (enumerator, data->cancellable, NULL);
g_object_unref (enumerator);
if (data->depth > 0 && !g_cancellable_is_cancelled (data->cancellable)) {
if ((data->trash && data->depth > 1) ||
should_purge_file (data->file, data->cancellable, data->old)) {
g_debug ("GsdHousekeeping: purging %s\n", data->name);
if (!data->dry_run) {
g_file_delete (data->file, data->cancellable, NULL);
}
}
}
delete_data_unref (data);
}
static void
delete_subdir (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GFile *file = G_FILE (source);
DeleteData *data = user_data;
GFileEnumerator *enumerator;
GError *error = NULL;
g_debug ("GsdHousekeeping: purging %s in %s\n",
data->trash ? "trash" : "temporary files", data->name);
enumerator = g_file_enumerate_children_finish (file, res, &error);
if (error) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY))
g_warning ("Failed to enumerate children of %s: %s\n", data->name, error->message);
}
if (enumerator) {
g_file_enumerator_next_files_async (enumerator, 20,
0,
data->cancellable,
delete_batch,
delete_data_ref (data));
} else if (data->depth > 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) {
if ((data->trash && data->depth > 1) ||
should_purge_file (data->file, data->cancellable, data->old)) {
if (!data->dry_run) {
g_file_delete (data->file, data->cancellable, NULL);
}
}
}
if (error)
g_error_free (error);
delete_data_unref (data);
}
static void
delete_subdir_check_symlink (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GFile *file = G_FILE (source);
DeleteData *data = user_data;
GFileInfo *info;
GFileType type;
info = g_file_query_info_finish (file, res, NULL);
if (!info) {
delete_data_unref (data);
return;
}
type = g_file_info_get_file_type (info);
g_object_unref (info);
if (type == G_FILE_TYPE_SYMBOLIC_LINK) {
if (should_purge_file (data->file, data->cancellable, data->old)) {
g_debug ("Purging %s leaf node", data->name);
if (!data->dry_run) {
g_file_delete (data->file, data->cancellable, NULL);
}
}
} else {
g_file_enumerate_children_async (data->file,
G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
0,
data->cancellable,
delete_subdir,
delete_data_ref (data));
}
delete_data_unref (data);
}
void
delete_recursively_by_age (DeleteData *data)
{
if (data->trash && (data->depth == 1) &&
!should_purge_file (data->file, data->cancellable, data->old)) {
/* no need to recurse into trashed directories */
return;
}
g_file_query_info_async (data->file,
G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
0,
data->cancellable,
delete_subdir_check_symlink,
delete_data_ref (data));
}
void
gsd_ldsm_purge_trash (GDateTime *old)
{
GFile *file;
DeleteData *data;
file = g_file_new_for_uri ("trash:");
data = delete_data_new (file, NULL, old, FALSE, TRUE, 0);
delete_recursively_by_age (data);
delete_data_unref (data);
g_object_unref (file);
}
void
gsd_ldsm_purge_temp_files (GDateTime *old)
{
DeleteData *data;
GFile *file;
file = g_file_new_for_path (g_get_tmp_dir ());
data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
delete_recursively_by_age (data);
delete_data_unref (data);
g_object_unref (file);
if (g_strcmp0 (g_get_tmp_dir (), "/var/tmp") != 0) {
file = g_file_new_for_path ("/var/tmp");
data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
delete_recursively_by_age (data);
delete_data_unref (data);
g_object_unref (file);
}
if (g_strcmp0 (g_get_tmp_dir (), "/tmp") != 0) {
file = g_file_new_for_path ("/tmp");
data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
delete_recursively_by_age (data);
delete_data_unref (data);
g_object_unref (file);
}
}
void
gsd_ldsm_show_empty_trash (void)
{
GFile *file;
GDateTime *old;
DeleteData *data;
old = g_date_time_new_now_local ();
file = g_file_new_for_uri ("trash:");
data = delete_data_new (file, NULL, old, TRUE, TRUE, 0);
g_object_unref (file);
g_date_time_unref (old);
delete_recursively_by_age (data);
delete_data_unref (data);
}
static gboolean
ldsm_purge_trash_and_temp (gpointer data)
{
GDateTime *now, *old;
now = g_date_time_new_now_local ();
old = g_date_time_add_days (now, - purge_after);
if (purge_trash) {
g_debug ("housekeeping: purge trash older than %u days", purge_after);
gsd_ldsm_purge_trash (old);
}
if (purge_temp_files) {
g_debug ("housekeeping: purge temp files older than %u days", purge_after);
gsd_ldsm_purge_temp_files (old);
}
g_date_time_unref (old);
g_date_time_unref (now);
return G_SOURCE_CONTINUE;
}
static void
empty_trash_callback (NotifyNotification *n,
const char *action)
{
GDateTime *old;
g_assert (action != NULL);
g_assert (strcmp (action, "empty-trash") == 0);
old = g_date_time_new_now_local ();
gsd_ldsm_purge_trash (old);
g_date_time_unref (old);
notify_notification_close (n, NULL);
}
static void
on_notification_closed (NotifyNotification *n)
{
g_object_unref (notification);
notification = NULL;
}
static gboolean
ldsm_notify_for_mount (LdsmMountInfo *mount,
gboolean multiple_volumes,
gboolean other_usable_volumes)
{
gchar *name, *program;
gint64 free_space;
gint response;
gboolean has_trash;
gboolean has_disk_analyzer;
gboolean retval = TRUE;
gchar *path;
/* Don't show a notice if one is already displayed */
if (dialog != NULL || notification != NULL)
return retval;
name = g_unix_mount_guess_name (mount->mount);
free_space = (gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail;
has_trash = ldsm_mount_has_trash (mount);
path = g_strdup (g_unix_mount_get_mount_path (mount->mount));
program = g_find_program_in_path (DISK_SPACE_ANALYZER);
has_disk_analyzer = (program != NULL);
g_free (program);
if (server_has_actions ()) {
char *free_space_str;
char *summary;
char *body;
free_space_str = g_format_size (free_space);
if (multiple_volumes) {
summary = g_strdup_printf (_("Low Disk Space on \"%s\""), name);
if (has_trash) {
body = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining. You may free up some space by emptying the trash."),
name,
free_space_str);
} else {
body = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining."),
name,
free_space_str);
}
} else {
summary = g_strdup (_("Low Disk Space"));
if (has_trash) {
body = g_strdup_printf (_("This computer has only %s disk space remaining. You may free up some space by emptying the trash."),
free_space_str);
} else {
body = g_strdup_printf (_("This computer has only %s disk space remaining."),
free_space_str);
}
}
g_free (free_space_str);
notification = notify_notification_new (summary, body, "drive-harddisk-symbolic");
g_free (summary);
g_free (body);
g_signal_connect (notification,
"closed",
G_CALLBACK (on_notification_closed),
NULL);
notify_notification_set_app_name (notification, _("Disk space"));
notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL);
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_DEFAULT);
if (has_disk_analyzer) {
notify_notification_add_action (notification,
"examine",
_("Examine"),
(NotifyActionCallback) examine_callback,
g_strdup (path),
g_free);
}
if (has_trash) {
notify_notification_add_action (notification,
"empty-trash",
_("Empty Trash"),
(NotifyActionCallback) empty_trash_callback,
NULL,
NULL);
}
notify_notification_add_action (notification,
"ignore",
_("Ignore"),
(NotifyActionCallback) ignore_callback,
NULL,
NULL);
notify_notification_set_category (notification, "device");
if (!notify_notification_show (notification, NULL)) {
g_warning ("failed to send disk space notification\n");
}
} else {
dialog = gsd_ldsm_dialog_new (other_usable_volumes,
multiple_volumes,
has_disk_analyzer,
has_trash,
free_space,
name,
path);
g_object_ref (G_OBJECT (dialog));
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
dialog = NULL;
switch (response) {
case GTK_RESPONSE_CANCEL:
retval = FALSE;
break;
case GSD_LDSM_DIALOG_RESPONSE_ANALYZE:
retval = FALSE;
ldsm_analyze_path (path);
break;
case GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH:
retval = TRUE;
gsd_ldsm_show_empty_trash ();
break;
case GTK_RESPONSE_NONE:
case GTK_RESPONSE_DELETE_EVENT:
retval = TRUE;
break;
default:
g_assert_not_reached ();
}
}
g_free (name);
g_free (path);
return retval;
}
static gboolean
ldsm_mount_has_space (LdsmMountInfo *mount)
{
gdouble free_space;
free_space = (double) mount->buf.f_bavail / (double) mount->buf.f_blocks;
/* enough free space, nothing to do */
if (free_space > free_percent_notify)
return TRUE;
if (((gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail) > ((gint64) free_size_gb_no_notify * GIGABYTE))
return TRUE;
/* If we got here, then this volume is low on space */
return FALSE;
}
static gboolean
ldsm_mount_is_virtual (LdsmMountInfo *mount)
{
if (mount->buf.f_blocks == 0) {
/* Filesystems with zero blocks are virtual */
return TRUE;
}
return FALSE;
}
static gint
ldsm_ignore_path_compare (gconstpointer a,
gconstpointer b)
{
return g_strcmp0 ((const gchar *)a, (const gchar *)b);
}
static gboolean
ldsm_mount_is_user_ignore (const gchar *path)
{
if (g_slist_find_custom (ignore_paths, path, (GCompareFunc) ldsm_ignore_path_compare) != NULL)
return TRUE;
else
return FALSE;
}
static void
ldsm_free_mount_info (gpointer data)
{
LdsmMountInfo *mount = data;
g_return_if_fail (mount != NULL);
g_unix_mount_free (mount->mount);
g_free (mount);
}
static void
ldsm_maybe_warn_mounts (GList *mounts,
gboolean multiple_volumes,
gboolean other_usable_volumes)
{
GList *l;
gboolean done = FALSE;
for (l = mounts; l != NULL; l = l->next) {
LdsmMountInfo *mount_info = l->data;
LdsmMountInfo *previous_mount_info;
gdouble free_space;
gdouble previous_free_space;
time_t curr_time;
const gchar *path;
gboolean show_notify;
if (done) {
/* Don't show any more dialogs if the user took action with the last one. The user action
* might free up space on multiple volumes, making the next dialog redundant.
*/
ldsm_free_mount_info (mount_info);
continue;
}
path = g_unix_mount_get_mount_path (mount_info->mount);
previous_mount_info = g_hash_table_lookup (ldsm_notified_hash, path);
if (previous_mount_info != NULL)
previous_free_space = (gdouble) previous_mount_info->buf.f_bavail / (gdouble) previous_mount_info->buf.f_blocks;
free_space = (gdouble) mount_info->buf.f_bavail / (gdouble) mount_info->buf.f_blocks;
if (previous_mount_info == NULL) {
/* We haven't notified for this mount yet */
show_notify = TRUE;
mount_info->notify_time = time (NULL);
g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info);
} else if ((previous_free_space - free_space) > free_percent_notify_again) {
/* We've notified for this mount before and free space has decreased sufficiently since last time to notify again */
curr_time = time (NULL);
if (difftime (curr_time, previous_mount_info->notify_time) > (gdouble)(min_notify_period * 60)) {
show_notify = TRUE;
mount_info->notify_time = curr_time;
} else {
/* It's too soon to show the dialog again. However, we still replace the LdsmMountInfo
* struct in the hash table, but give it the notfiy time from the previous dialog.
* This will stop the notification from reappearing unnecessarily as soon as the timeout expires.
*/
show_notify = FALSE;
mount_info->notify_time = previous_mount_info->notify_time;
}
g_hash_table_replace (ldsm_notified_hash, g_strdup (path), mount_info);
} else {
/* We've notified for this mount before, but the free space hasn't decreased sufficiently to notify again */
ldsm_free_mount_info (mount_info);
show_notify = FALSE;
}
if (show_notify) {
if (ldsm_notify_for_mount (mount_info, multiple_volumes, other_usable_volumes))
done = TRUE;
}
}
}
static gboolean
ldsm_check_all_mounts (gpointer data)
{
GList *mounts;
GList *l;
GList *check_mounts = NULL;
GList *full_mounts = NULL;
guint number_of_mounts;
guint number_of_full_mounts;
gboolean multiple_volumes = FALSE;
gboolean other_usable_volumes = FALSE;
/* We iterate through the static mounts in /etc/fstab first, seeing if
* they're mounted by checking if the GUnixMountPoint has a corresponding GUnixMountEntry.
* Iterating through the static mounts means we automatically ignore dynamically mounted media.
*/
mounts = g_unix_mount_points_get (time_read);
for (l = mounts; l != NULL; l = l->next) {
GUnixMountPoint *mount_point = l->data;
GUnixMountEntry *mount;
LdsmMountInfo *mount_info;
const gchar *path;
path = g_unix_mount_point_get_mount_path (mount_point);
mount = g_unix_mount_at (path, time_read);
g_unix_mount_point_free (mount_point);
if (mount == NULL) {
/* The GUnixMountPoint is not mounted */
continue;
}
mount_info = g_new0 (LdsmMountInfo, 1);
mount_info->mount = mount;
path = g_unix_mount_get_mount_path (mount);
if (g_unix_mount_is_readonly (mount)) {
ldsm_free_mount_info (mount_info);
continue;
}
if (ldsm_mount_is_user_ignore (g_unix_mount_get_mount_path (mount))) {
ldsm_free_mount_info (mount_info);
continue;
}
if (gsd_should_ignore_unix_mount (mount)) {
ldsm_free_mount_info (mount_info);
continue;
}
if (statvfs (path, &mount_info->buf) != 0) {
ldsm_free_mount_info (mount_info);
continue;
}
if (ldsm_mount_is_virtual (mount_info)) {
ldsm_free_mount_info (mount_info);
continue;
}
check_mounts = g_list_prepend (check_mounts, mount_info);
}
g_list_free (mounts);
number_of_mounts = g_list_length (check_mounts);
if (number_of_mounts > 1)
multiple_volumes = TRUE;
for (l = check_mounts; l != NULL; l = l->next) {
LdsmMountInfo *mount_info = l->data;
if (!ldsm_mount_has_space (mount_info)) {
full_mounts = g_list_prepend (full_mounts, mount_info);
} else {
g_hash_table_remove (ldsm_notified_hash, g_unix_mount_get_mount_path (mount_info->mount));
ldsm_free_mount_info (mount_info);
}
}
number_of_full_mounts = g_list_length (full_mounts);
if (number_of_mounts > number_of_full_mounts)
other_usable_volumes = TRUE;
ldsm_maybe_warn_mounts (full_mounts, multiple_volumes,
other_usable_volumes);
g_list_free (check_mounts);
g_list_free (full_mounts);
return TRUE;
}
static gboolean
ldsm_is_hash_item_not_in_mounts (gpointer key,
gpointer value,
gpointer user_data)
{
GList *l;
for (l = (GList *) user_data; l != NULL; l = l->next) {
GUnixMountEntry *mount = l->data;
const char *path;
path = g_unix_mount_get_mount_path (mount);
if (strcmp (path, key) == 0)
return FALSE;
}
return TRUE;
}
static void
ldsm_mounts_changed (GObject *monitor,
gpointer data)
{
GList *mounts;
/* remove the saved data for mounts that got removed */
mounts = g_unix_mounts_get (time_read);
g_hash_table_foreach_remove (ldsm_notified_hash,
ldsm_is_hash_item_not_in_mounts, mounts);
g_list_free_full (mounts, (GDestroyNotify) g_unix_mount_free);
/* check the status now, for the new mounts */
ldsm_check_all_mounts (NULL);
/* and reset the timeout */
if (ldsm_timeout_id)
g_source_remove (ldsm_timeout_id);
ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS,
ldsm_check_all_mounts, NULL);
}
static gboolean
ldsm_is_hash_item_in_ignore_paths (gpointer key,
gpointer value,
gpointer user_data)
{
return ldsm_mount_is_user_ignore (key);
}
static void
gsd_ldsm_get_config (void)
{
gchar **settings_list;
free_percent_notify = g_settings_get_double (settings, SETTINGS_FREE_PC_NOTIFY_KEY);
free_percent_notify_again = g_settings_get_double (settings, SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY);
free_size_gb_no_notify = g_settings_get_int (settings, SETTINGS_FREE_SIZE_NO_NOTIFY);
min_notify_period = g_settings_get_int (settings, SETTINGS_MIN_NOTIFY_PERIOD);
if (ignore_paths != NULL) {
g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
g_clear_pointer (&ignore_paths, g_slist_free);
}
settings_list = g_settings_get_strv (settings, SETTINGS_IGNORE_PATHS);
if (settings_list != NULL) {
guint i;
for (i = 0; settings_list[i] != NULL; i++)
ignore_paths = g_slist_prepend (ignore_paths, g_strdup (settings_list[i]));
/* Make sure we dont leave stale entries in ldsm_notified_hash */
g_hash_table_foreach_remove (ldsm_notified_hash,
ldsm_is_hash_item_in_ignore_paths, NULL);
g_strfreev (settings_list);
}
purge_trash = g_settings_get_boolean (privacy_settings, SETTINGS_PURGE_TRASH);
purge_temp_files = g_settings_get_boolean (privacy_settings, SETTINGS_PURGE_TEMP_FILES);
purge_after = g_settings_get_uint (privacy_settings, SETTINGS_PURGE_AFTER);
}
static void
gsd_ldsm_update_config (GSettings *settings,
const gchar *key,
gpointer user_data)
{
gsd_ldsm_get_config ();
}
void
gsd_ldsm_setup (gboolean check_now)
{
if (ldsm_notified_hash || ldsm_timeout_id || ldsm_monitor) {
g_warning ("Low disk space monitor already initialized.");
return;
}
ldsm_notified_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
ldsm_free_mount_info);
settings = g_settings_new (SETTINGS_HOUSEKEEPING_DIR);
privacy_settings = g_settings_new (PRIVACY_SETTINGS);
gsd_ldsm_get_config ();
g_signal_connect (G_OBJECT (settings), "changed",
G_CALLBACK (gsd_ldsm_update_config), NULL);
ldsm_monitor = g_unix_mount_monitor_new ();
g_unix_mount_monitor_set_rate_limit (ldsm_monitor, 1000);
g_signal_connect (ldsm_monitor, "mounts-changed",
G_CALLBACK (ldsm_mounts_changed), NULL);
if (check_now)
ldsm_check_all_mounts (NULL);
ldsm_timeout_id = g_timeout_add_seconds (CHECK_EVERY_X_SECONDS,
ldsm_check_all_mounts, NULL);
purge_trash_id = g_timeout_add_seconds (3600, ldsm_purge_trash_and_temp, NULL);
}
void
gsd_ldsm_clean (void)
{
if (purge_trash_id)
g_source_remove (purge_trash_id);
purge_trash_id = 0;
if (purge_temp_id)
g_source_remove (purge_temp_id);
purge_temp_id = 0;
if (ldsm_timeout_id)
g_source_remove (ldsm_timeout_id);
ldsm_timeout_id = 0;
if (ldsm_notified_hash)
g_hash_table_destroy (ldsm_notified_hash);
ldsm_notified_hash = NULL;
if (ldsm_monitor)
g_object_unref (ldsm_monitor);
ldsm_monitor = NULL;
if (settings != NULL) {
g_object_unref (settings);
}
g_clear_object (&privacy_settings);
if (dialog) {
gtk_widget_destroy (GTK_WIDGET (dialog));
dialog = NULL;
}
if (notification != NULL) {
notify_notification_close (notification, NULL);
notification = NULL;
}
if (ignore_paths) {
g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
g_slist_free (ignore_paths);
}
}
./plugins/housekeeping/gsd-ldsm-dialog.c 0000644 0000041 0000041 00000050523 13264221014 020525 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* gsd-ldsm-dialog.c
* Copyright (C) Chris Coulson 2009
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include
#include
#include "gsd-ldsm-dialog.h"
#define SETTINGS_HOUSEKEEPING_DIR "org.gnome.settings-daemon.plugins.housekeeping"
enum
{
PROP_0,
PROP_OTHER_USABLE_PARTITIONS,
PROP_OTHER_PARTITIONS,
PROP_HAS_TRASH,
PROP_SPACE_REMAINING,
PROP_PARTITION_NAME,
PROP_MOUNT_PATH
};
struct GsdLdsmDialogPrivate
{
GtkWidget *primary_label;
GtkWidget *secondary_label;
GtkWidget *ignore_check_button;
gboolean other_usable_partitions;
gboolean other_partitions;
gboolean has_trash;
gint64 space_remaining;
gchar *partition_name;
gchar *mount_path;
};
#define GSD_LDSM_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogPrivate))
static void gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass);
static void gsd_ldsm_dialog_init (GsdLdsmDialog *dialog);
G_DEFINE_TYPE (GsdLdsmDialog, gsd_ldsm_dialog, GTK_TYPE_DIALOG);
static const gchar*
gsd_ldsm_dialog_get_checkbutton_text (GsdLdsmDialog *dialog)
{
g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
if (dialog->priv->other_partitions)
return _("Don't show any warnings again for this file system");
else
return _("Don't show any warnings again");
}
static gchar*
gsd_ldsm_dialog_get_primary_text (GsdLdsmDialog *dialog)
{
gchar *primary_text, *free_space;
g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
free_space = g_format_size (dialog->priv->space_remaining);
if (dialog->priv->other_partitions) {
primary_text = g_strdup_printf (_("The volume \"%s\" has only %s disk space remaining."),
dialog->priv->partition_name, free_space);
} else {
primary_text = g_strdup_printf (_("This computer has only %s disk space remaining."),
free_space);
}
g_free (free_space);
return primary_text;
}
static const gchar*
gsd_ldsm_dialog_get_secondary_text (GsdLdsmDialog *dialog)
{
g_return_val_if_fail (GSD_IS_LDSM_DIALOG (dialog), NULL);
if (dialog->priv->other_usable_partitions) {
if (dialog->priv->has_trash) {
return _("You can free up disk space by emptying the Trash, removing " \
"unused programs or files, or moving files to another disk or partition.");
} else {
return _("You can free up disk space by removing unused programs or files, " \
"or by moving files to another disk or partition.");
}
} else {
if (dialog->priv->has_trash) {
return _("You can free up disk space by emptying the Trash, removing unused " \
"programs or files, or moving files to an external disk.");
} else {
return _("You can free up disk space by removing unused programs or files, " \
"or by moving files to an external disk.");
}
}
}
static gint
ignore_path_compare (gconstpointer a,
gconstpointer b)
{
return g_strcmp0 ((const gchar *)a, (const gchar *)b);
}
static gboolean
update_ignore_paths (GSList **ignore_paths,
const gchar *mount_path,
gboolean ignore)
{
GSList *found;
gchar *path_to_remove;
found = g_slist_find_custom (*ignore_paths, mount_path, (GCompareFunc) ignore_path_compare);
if (ignore && (found == NULL)) {
*ignore_paths = g_slist_prepend (*ignore_paths, g_strdup (mount_path));
return TRUE;
}
if (!ignore && (found != NULL)) {
path_to_remove = found->data;
*ignore_paths = g_slist_remove (*ignore_paths, path_to_remove);
g_free (path_to_remove);
return TRUE;
}
return FALSE;
}
static void
ignore_check_button_toggled_cb (GtkToggleButton *button,
gpointer user_data)
{
GsdLdsmDialog *dialog = (GsdLdsmDialog *)user_data;
GSettings *settings;
gchar **settings_list;
gboolean ignore, updated;
gint i;
GSList *ignore_paths = NULL;
settings = g_settings_new (SETTINGS_HOUSEKEEPING_DIR);
settings_list = g_settings_get_strv (settings, "ignore-paths");
for (i = 0; i < G_N_ELEMENTS (settings_list); i++) {
if (settings_list[i] != NULL)
ignore_paths = g_slist_append (ignore_paths, g_strdup (settings_list[i]));
}
ignore = gtk_toggle_button_get_active (button);
updated = update_ignore_paths (&ignore_paths, dialog->priv->mount_path, ignore);
g_strfreev (settings_list);
if (updated) {
GSList *l;
GPtrArray *array = g_ptr_array_new ();
for (l = ignore_paths; l != NULL; l = l->next)
g_ptr_array_add (array, l->data);
g_ptr_array_add (array, NULL);
if (!g_settings_set_strv (settings, "ignore-paths", (const gchar **) array->pdata)) {
g_warning ("Cannot change ignore preference - failed to commit changes");
}
g_ptr_array_free (array, FALSE);
}
g_slist_foreach (ignore_paths, (GFunc) g_free, NULL);
g_slist_free (ignore_paths);
g_object_unref (settings);
}
static void
gsd_ldsm_dialog_init (GsdLdsmDialog *dialog)
{
GtkWidget *main_vbox, *text_vbox, *hbox;
GtkWidget *image;
dialog->priv = GSD_LDSM_DIALOG_GET_PRIVATE (dialog);
main_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
/* Set up all the window stuff here */
gtk_window_set_title (GTK_WINDOW (dialog), _("Low Disk Space"));
gtk_window_set_icon_name (GTK_WINDOW (dialog),
GTK_STOCK_DIALOG_WARNING);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
gtk_window_set_focus_on_map (GTK_WINDOW (dialog), FALSE);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
/* Create the image */
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
/* Create the labels */
dialog->priv->primary_label = gtk_label_new (NULL);
gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->primary_label), TRUE);
gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->primary_label), FALSE);
gtk_misc_set_alignment (GTK_MISC (dialog->priv->primary_label), 0.0, 0.0);
gtk_label_set_max_width_chars (GTK_LABEL (dialog->priv->primary_label), 72);
dialog->priv->secondary_label = gtk_label_new (NULL);
gtk_label_set_line_wrap (GTK_LABEL (dialog->priv->secondary_label), TRUE);
gtk_label_set_single_line_mode (GTK_LABEL (dialog->priv->secondary_label), FALSE);
gtk_misc_set_alignment (GTK_MISC (dialog->priv->secondary_label), 0.0, 0.0);
gtk_label_set_max_width_chars (GTK_LABEL (dialog->priv->secondary_label), 72);
/* Create the check button to ignore future warnings */
dialog->priv->ignore_check_button = gtk_check_button_new ();
/* The button should be inactive if the dialog was just called.
* I suppose it could be possible for the user to manually edit the GSettings key between
* the mount being checked and the dialog appearing, but I don't think it matters
* too much */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->ignore_check_button), FALSE);
g_signal_connect (dialog->priv->ignore_check_button, "toggled",
G_CALLBACK (ignore_check_button_toggled_cb), dialog);
/* Now set up the dialog's GtkBox's' */
gtk_box_set_spacing (GTK_BOX (main_vbox), 14);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
text_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->primary_label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->secondary_label, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (text_vbox), dialog->priv->ignore_check_button, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), text_vbox, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
/* Set up the action area */
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 6);
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), 5);
gtk_widget_show_all (hbox);
}
static void
gsd_ldsm_dialog_finalize (GObject *object)
{
GsdLdsmDialog *self;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
self = GSD_LDSM_DIALOG (object);
if (self->priv->partition_name)
g_free (self->priv->partition_name);
if (self->priv->mount_path)
g_free (self->priv->mount_path);
G_OBJECT_CLASS (gsd_ldsm_dialog_parent_class)->finalize (object);
}
static void
gsd_ldsm_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GsdLdsmDialog *self;
g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
self = GSD_LDSM_DIALOG (object);
switch (prop_id)
{
case PROP_OTHER_USABLE_PARTITIONS:
self->priv->other_usable_partitions = g_value_get_boolean (value);
break;
case PROP_OTHER_PARTITIONS:
self->priv->other_partitions = g_value_get_boolean (value);
break;
case PROP_HAS_TRASH:
self->priv->has_trash = g_value_get_boolean (value);
break;
case PROP_SPACE_REMAINING:
self->priv->space_remaining = g_value_get_int64 (value);
break;
case PROP_PARTITION_NAME:
self->priv->partition_name = g_value_dup_string (value);
break;
case PROP_MOUNT_PATH:
self->priv->mount_path = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gsd_ldsm_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GsdLdsmDialog *self;
g_return_if_fail (GSD_IS_LDSM_DIALOG (object));
self = GSD_LDSM_DIALOG (object);
switch (prop_id)
{
case PROP_OTHER_USABLE_PARTITIONS:
g_value_set_boolean (value, self->priv->other_usable_partitions);
break;
case PROP_OTHER_PARTITIONS:
g_value_set_boolean (value, self->priv->other_partitions);
break;
case PROP_HAS_TRASH:
g_value_set_boolean (value, self->priv->has_trash);
break;
case PROP_SPACE_REMAINING:
g_value_set_int64 (value, self->priv->space_remaining);
break;
case PROP_PARTITION_NAME:
g_value_set_string (value, self->priv->partition_name);
break;
case PROP_MOUNT_PATH:
g_value_set_string (value, self->priv->mount_path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gsd_ldsm_dialog_class_init (GsdLdsmDialogClass *klass)
{
GObjectClass* object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_ldsm_dialog_finalize;
object_class->set_property = gsd_ldsm_dialog_set_property;
object_class->get_property = gsd_ldsm_dialog_get_property;
g_object_class_install_property (object_class,
PROP_OTHER_USABLE_PARTITIONS,
g_param_spec_boolean ("other-usable-partitions",
"other-usable-partitions",
"Set to TRUE if there are other usable partitions on the system",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_OTHER_PARTITIONS,
g_param_spec_boolean ("other-partitions",
"other-partitions",
"Set to TRUE if there are other partitions on the system",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_HAS_TRASH,
g_param_spec_boolean ("has-trash",
"has-trash",
"Set to TRUE if the partition has files in it's trash folder that can be deleted",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_SPACE_REMAINING,
g_param_spec_int64 ("space-remaining",
"space-remaining",
"Specify how much space is remaining in bytes",
G_MININT64, G_MAXINT64, 0,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_PARTITION_NAME,
g_param_spec_string ("partition-name",
"partition-name",
"Specify the name of the partition",
"Unknown",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_MOUNT_PATH,
g_param_spec_string ("mount-path",
"mount-path",
"Specify the mount path for the partition",
"Unknown",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (GsdLdsmDialogPrivate));
}
GsdLdsmDialog*
gsd_ldsm_dialog_new (gboolean other_usable_partitions,
gboolean other_partitions,
gboolean display_baobab,
gboolean display_empty_trash,
gint64 space_remaining,
const gchar *partition_name,
const gchar *mount_path)
{
GsdLdsmDialog *dialog;
GtkWidget *button_empty_trash, *button_ignore, *button_analyze;
GtkWidget *empty_trash_image, *analyze_image, *ignore_image;
gchar *primary_text, *primary_text_markup;
const gchar *secondary_text, *checkbutton_text;
dialog = GSD_LDSM_DIALOG (g_object_new (GSD_TYPE_LDSM_DIALOG,
"other-usable-partitions", other_usable_partitions,
"other-partitions", other_partitions,
"has-trash", display_empty_trash,
"space-remaining", space_remaining,
"partition-name", partition_name,
"mount-path", mount_path,
NULL));
/* Add some buttons */
if (dialog->priv->has_trash) {
button_empty_trash = gtk_dialog_add_button (GTK_DIALOG (dialog),
_("Empty Trash"),
GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH);
empty_trash_image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON (button_empty_trash), empty_trash_image);
}
if (display_baobab) {
button_analyze = gtk_dialog_add_button (GTK_DIALOG (dialog),
_("Examine…"),
GSD_LDSM_DIALOG_RESPONSE_ANALYZE);
analyze_image = gtk_image_new_from_icon_name ("baobab", GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON (button_analyze), analyze_image);
}
button_ignore = gtk_dialog_add_button (GTK_DIALOG (dialog),
_("Ignore"),
GTK_RESPONSE_CANCEL);
ignore_image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON (button_ignore), ignore_image);
gtk_widget_grab_default (button_ignore);
/* Set the label text */
primary_text = gsd_ldsm_dialog_get_primary_text (dialog);
primary_text_markup = g_markup_printf_escaped ("%s", primary_text);
gtk_label_set_markup (GTK_LABEL (dialog->priv->primary_label), primary_text_markup);
secondary_text = gsd_ldsm_dialog_get_secondary_text (dialog);
gtk_label_set_text (GTK_LABEL (dialog->priv->secondary_label), secondary_text);
checkbutton_text = gsd_ldsm_dialog_get_checkbutton_text (dialog);
gtk_button_set_label (GTK_BUTTON (dialog->priv->ignore_check_button), checkbutton_text);
g_free (primary_text);
g_free (primary_text_markup);
return dialog;
}
./plugins/housekeeping/gsd-ldsm-dialog.h 0000644 0000041 0000041 00000005077 13264221014 020536 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* gsd-ldsm-dialog.c
* Copyright (C) Chris Coulson 2009
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _GSD_LDSM_DIALOG_H_
#define _GSD_LDSM_DIALOG_H_
#include
#include
G_BEGIN_DECLS
#define GSD_TYPE_LDSM_DIALOG (gsd_ldsm_dialog_get_type ())
#define GSD_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialog))
#define GSD_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass))
#define GSD_IS_LDSM_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_LDSM_DIALOG))
#define GSD_IS_LDSM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_LDSM_DIALOG))
#define GSD_LDSM_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_LDSM_DIALOG, GsdLdsmDialogClass))
enum
{
GSD_LDSM_DIALOG_RESPONSE_EMPTY_TRASH = -20,
GSD_LDSM_DIALOG_RESPONSE_ANALYZE = -21
};
typedef struct GsdLdsmDialogPrivate GsdLdsmDialogPrivate;
typedef struct _GsdLdsmDialogClass GsdLdsmDialogClass;
typedef struct _GsdLdsmDialog GsdLdsmDialog;
struct _GsdLdsmDialogClass
{
GtkDialogClass parent_class;
};
struct _GsdLdsmDialog
{
GtkDialog parent_instance;
GsdLdsmDialogPrivate *priv;
};
GType gsd_ldsm_dialog_get_type (void) G_GNUC_CONST;
GsdLdsmDialog * gsd_ldsm_dialog_new (gboolean other_usable_partitions,
gboolean other_partitions,
gboolean display_baobab,
gboolean display_empty_trash,
gint64 space_remaining,
const gchar *partition_name,
const gchar *mount_path);
G_END_DECLS
#endif /* _GSD_LDSM_DIALOG_H_ */
./plugins/housekeeping/gsd-housekeeping-manager.h 0000644 0000041 0000041 00000004705 13264221014 022435 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Michael J. Chudobiak
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_HOUSEKEEPING_MANAGER_H
#define __GSD_HOUSEKEEPING_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_HOUSEKEEPING_MANAGER (gsd_housekeeping_manager_get_type ())
#define GSD_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManager))
#define GSD_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass))
#define GSD_IS_HOUSEKEEPING_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER))
#define GSD_IS_HOUSEKEEPING_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_HOUSEKEEPING_MANAGER))
#define GSD_HOUSEKEEPING_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerClass))
typedef struct GsdHousekeepingManagerPrivate GsdHousekeepingManagerPrivate;
typedef struct {
GObject parent;
GsdHousekeepingManagerPrivate *priv;
} GsdHousekeepingManager;
typedef struct {
GObjectClass parent_class;
} GsdHousekeepingManagerClass;
GType gsd_housekeeping_manager_get_type (void);
GsdHousekeepingManager * gsd_housekeeping_manager_new (void);
gboolean gsd_housekeeping_manager_start (GsdHousekeepingManager *manager,
GError **error);
void gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager);
G_END_DECLS
#endif /* __GSD_HOUSEKEEPING_MANAGER_H */
./plugins/housekeeping/gsd-housekeeping-manager.c 0000644 0000041 0000041 00000037365 13264221014 022440 0 ustar www-data www-data /*
* Copyright (C) 2008 Michael J. Chudobiak
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include "gnome-settings-profile.h"
#include "gsd-housekeeping-manager.h"
#include "gsd-disk-space.h"
/* General */
#define INTERVAL_ONCE_A_DAY 24*60*60
#define INTERVAL_TWO_MINUTES 2*60
/* Thumbnail cleaner */
#define THUMB_PREFIX "org.gnome.desktop.thumbnail-cache"
#define THUMB_AGE_KEY "maximum-age"
#define THUMB_SIZE_KEY "maximum-size"
#define GSD_HOUSEKEEPING_DBUS_PATH "/org/gnome/SettingsDaemon/Housekeeping"
static const gchar introspection_xml[] =
""
" "
" "
" "
" "
"";
struct GsdHousekeepingManagerPrivate {
GSettings *settings;
guint long_term_cb;
guint short_term_cb;
GDBusNodeInfo *introspection_data;
GDBusConnection *connection;
GCancellable *bus_cancellable;
};
#define GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_HOUSEKEEPING_MANAGER, GsdHousekeepingManagerPrivate))
static void gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass);
static void gsd_housekeeping_manager_init (GsdHousekeepingManager *housekeeping_manager);
G_DEFINE_TYPE (GsdHousekeepingManager, gsd_housekeeping_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
typedef struct {
glong now;
glong max_age;
goffset total_size;
goffset max_size;
} PurgeData;
typedef struct {
time_t mtime;
char *path;
glong size;
} ThumbData;
static void
thumb_data_free (gpointer data)
{
ThumbData *info = data;
if (info) {
g_free (info->path);
g_free (info);
}
}
static GList *
read_dir_for_purge (const char *path, GList *files)
{
GFile *read_path;
GFileEnumerator *enum_dir;
read_path = g_file_new_for_path (path);
enum_dir = g_file_enumerate_children (read_path,
G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_TIME_MODIFIED ","
G_FILE_ATTRIBUTE_STANDARD_SIZE,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (enum_dir != NULL) {
GFileInfo *info;
while ((info = g_file_enumerator_next_file (enum_dir, NULL, NULL)) != NULL) {
const char *name;
name = g_file_info_get_name (info);
if (strlen (name) == 36 && strcmp (name + 32, ".png") == 0) {
ThumbData *td;
GFile *entry;
char *entry_path;
GTimeVal mod_time;
entry = g_file_get_child (read_path, name);
entry_path = g_file_get_path (entry);
g_object_unref (entry);
g_file_info_get_modification_time (info, &mod_time);
td = g_new0 (ThumbData, 1);
td->path = entry_path;
td->mtime = mod_time.tv_sec;
td->size = g_file_info_get_size (info);
files = g_list_prepend (files, td);
}
g_object_unref (info);
}
g_object_unref (enum_dir);
}
g_object_unref (read_path);
return files;
}
static void
purge_old_thumbnails (ThumbData *info, PurgeData *purge_data)
{
if ((purge_data->now - info->mtime) > purge_data->max_age) {
g_unlink (info->path);
info->size = 0;
} else {
purge_data->total_size += info->size;
}
}
static int
sort_file_mtime (ThumbData *file1, ThumbData *file2)
{
return file1->mtime - file2->mtime;
}
static char **
get_thumbnail_dirs (void)
{
GPtrArray *array;
char *path;
array = g_ptr_array_new ();
/* check new XDG cache */
path = g_build_filename (g_get_user_cache_dir (),
"thumbnails",
"normal",
NULL);
g_ptr_array_add (array, path);
path = g_build_filename (g_get_user_cache_dir (),
"thumbnails",
"large",
NULL);
g_ptr_array_add (array, path);
path = g_build_filename (g_get_user_cache_dir (),
"thumbnails",
"fail",
"gnome-thumbnail-factory",
NULL);
g_ptr_array_add (array, path);
/* cleanup obsolete locations too */
path = g_build_filename (g_get_home_dir (),
".thumbnails",
"normal",
NULL);
g_ptr_array_add (array, path);
path = g_build_filename (g_get_home_dir (),
".thumbnails",
"large",
NULL);
g_ptr_array_add (array, path);
path = g_build_filename (g_get_home_dir (),
".thumbnails",
"fail",
"gnome-thumbnail-factory",
NULL);
g_ptr_array_add (array, path);
g_ptr_array_add (array, NULL);
return (char **) g_ptr_array_free (array, FALSE);
}
static void
purge_thumbnail_cache (GsdHousekeepingManager *manager)
{
char **paths;
GList *files;
PurgeData purge_data;
GTimeVal current_time;
guint i;
g_debug ("housekeeping: checking thumbnail cache size and freshness");
purge_data.max_age = g_settings_get_int (manager->priv->settings, THUMB_AGE_KEY) * 24 * 60 * 60;
purge_data.max_size = g_settings_get_int (manager->priv->settings, THUMB_SIZE_KEY) * 1024 * 1024;
/* if both are set to -1, we don't need to read anything */
if ((purge_data.max_age < 0) && (purge_data.max_size < 0))
return;
paths = get_thumbnail_dirs ();
files = NULL;
for (i = 0; paths[i] != NULL; i++)
files = read_dir_for_purge (paths[i], files);
g_strfreev (paths);
g_get_current_time (¤t_time);
purge_data.now = current_time.tv_sec;
purge_data.total_size = 0;
if (purge_data.max_age >= 0)
g_list_foreach (files, (GFunc) purge_old_thumbnails, &purge_data);
if ((purge_data.total_size > purge_data.max_size) && (purge_data.max_size >= 0)) {
GList *scan;
files = g_list_sort (files, (GCompareFunc) sort_file_mtime);
for (scan = files; scan && (purge_data.total_size > purge_data.max_size); scan = scan->next) {
ThumbData *info = scan->data;
g_unlink (info->path);
purge_data.total_size -= info->size;
}
}
g_list_foreach (files, (GFunc) thumb_data_free, NULL);
g_list_free (files);
}
static gboolean
do_cleanup (GsdHousekeepingManager *manager)
{
purge_thumbnail_cache (manager);
return TRUE;
}
static gboolean
do_cleanup_once (GsdHousekeepingManager *manager)
{
do_cleanup (manager);
manager->priv->short_term_cb = 0;
return FALSE;
}
static void
do_cleanup_soon (GsdHousekeepingManager *manager)
{
if (manager->priv->short_term_cb == 0) {
g_debug ("housekeeping: will tidy up in 2 minutes");
manager->priv->short_term_cb = g_timeout_add_seconds (INTERVAL_TWO_MINUTES,
(GSourceFunc) do_cleanup_once,
manager);
}
}
static void
settings_changed_callback (GSettings *settings,
const char *key,
GsdHousekeepingManager *manager)
{
do_cleanup_soon (manager);
}
static void
handle_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GDateTime *now;
now = g_date_time_new_now_local ();
if (g_strcmp0 (method_name, "EmptyTrash") == 0) {
gsd_ldsm_purge_trash (now);
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "RemoveTempFiles") == 0) {
gsd_ldsm_purge_temp_files (now);
g_dbus_method_invocation_return_value (invocation, NULL);
}
g_date_time_unref (now);
}
static const GDBusInterfaceVTable interface_vtable =
{
handle_method_call,
NULL, /* Get Property */
NULL, /* Set Property */
};
static void
on_bus_gotten (GObject *source_object,
GAsyncResult *res,
GsdHousekeepingManager *manager)
{
GDBusConnection *connection;
GError *error = NULL;
GDBusInterfaceInfo **infos;
int i;
if (manager->priv->bus_cancellable == NULL ||
g_cancellable_is_cancelled (manager->priv->bus_cancellable)) {
g_warning ("Operation has been cancelled, so not retrieving session bus");
return;
}
connection = g_bus_get_finish (res, &error);
if (connection == NULL) {
g_warning ("Could not get session bus: %s", error->message);
g_error_free (error);
return;
}
manager->priv->connection = connection;
infos = manager->priv->introspection_data->interfaces;
for (i = 0; infos[i] != NULL; i++) {
g_dbus_connection_register_object (connection,
GSD_HOUSEKEEPING_DBUS_PATH,
infos[i],
&interface_vtable,
manager,
NULL,
NULL);
}
}
static void
register_manager_dbus (GsdHousekeepingManager *manager)
{
manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
g_assert (manager->priv->introspection_data != NULL);
manager->priv->bus_cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SESSION,
manager->priv->bus_cancellable,
(GAsyncReadyCallback) on_bus_gotten,
manager);
}
gboolean
gsd_housekeeping_manager_start (GsdHousekeepingManager *manager,
GError **error)
{
gchar *dir;
g_debug ("Starting housekeeping manager");
gnome_settings_profile_start (NULL);
/* Create ~/.local/ as early as possible */
g_mkdir_with_parents(g_get_user_data_dir (), 0700);
/* Create ~/.local/share/applications/, see
* https://bugzilla.gnome.org/show_bug.cgi?id=703048 */
dir = g_build_filename (g_get_user_data_dir (), "applications", NULL);
g_mkdir (dir, 0700);
g_free (dir);
gsd_ldsm_setup (FALSE);
manager->priv->settings = g_settings_new (THUMB_PREFIX);
g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
G_CALLBACK (settings_changed_callback), manager);
/* Clean once, a few minutes after start-up */
do_cleanup_soon (manager);
/* Clean periodically, on a daily basis. */
manager->priv->long_term_cb = g_timeout_add_seconds (INTERVAL_ONCE_A_DAY,
(GSourceFunc) do_cleanup,
manager);
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_housekeeping_manager_stop (GsdHousekeepingManager *manager)
{
GsdHousekeepingManagerPrivate *p = manager->priv;
g_debug ("Stopping housekeeping manager");
if (manager->priv->bus_cancellable != NULL) {
g_cancellable_cancel (manager->priv->bus_cancellable);
g_object_unref (manager->priv->bus_cancellable);
manager->priv->bus_cancellable = NULL;
}
if (manager->priv->introspection_data) {
g_dbus_node_info_unref (manager->priv->introspection_data);
manager->priv->introspection_data = NULL;
}
if (manager->priv->connection != NULL) {
g_object_unref (manager->priv->connection);
manager->priv->connection = NULL;
}
if (p->short_term_cb) {
g_source_remove (p->short_term_cb);
p->short_term_cb = 0;
}
if (p->long_term_cb) {
g_source_remove (p->long_term_cb);
p->long_term_cb = 0;
/* Do a clean-up on shutdown if and only if the size or age
limits have been set to paranoid levels (zero) */
if ((g_settings_get_int (p->settings, THUMB_AGE_KEY) == 0) ||
(g_settings_get_int (p->settings, THUMB_SIZE_KEY) == 0)) {
do_cleanup (manager);
}
g_object_unref (p->settings);
p->settings = NULL;
}
gsd_ldsm_clean ();
}
static void
gsd_housekeeping_manager_class_init (GsdHousekeepingManagerClass *klass)
{
g_type_class_add_private (klass, sizeof (GsdHousekeepingManagerPrivate));
}
static void
gsd_housekeeping_manager_init (GsdHousekeepingManager *manager)
{
manager->priv = GSD_HOUSEKEEPING_MANAGER_GET_PRIVATE (manager);
}
GsdHousekeepingManager *
gsd_housekeeping_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_HOUSEKEEPING_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
register_manager_dbus (manager_object);
}
return GSD_HOUSEKEEPING_MANAGER (manager_object);
}
./plugins/housekeeping/gsd-empty-trash-test.c 0000644 0000041 0000041 00000002360 13264221014 021557 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2011, Red Hat, Inc.
*
* Authors: Cosimo Cecchi
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include "gsd-disk-space.h"
int
main (int argc,
char **argv)
{
GMainLoop *loop;
gtk_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
gsd_ldsm_show_empty_trash ();
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}
./plugins/housekeeping/gsd-disk-space.h 0000644 0000041 0000041 00000003646 13264221014 020365 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2008, Novell, Inc.
*
* Authors: Vincent Untz
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_DISK_SPACE_H
#define __GSD_DISK_SPACE_H
#include
G_BEGIN_DECLS
typedef struct {
gint ref_count;
GFile *file;
GCancellable *cancellable;
GDateTime *old;
gboolean dry_run;
gboolean trash;
gchar *name;
gint depth;
} DeleteData;
void delete_data_unref (DeleteData *data);
DeleteData *delete_data_new (GFile *file,
GCancellable *cancellable,
GDateTime *old,
gboolean dry_run,
gboolean trash,
gint depth);
void delete_recursively_by_age (DeleteData *data);
void gsd_ldsm_setup (gboolean check_now);
void gsd_ldsm_clean (void);
/* for the test */
void gsd_ldsm_show_empty_trash (void);
void gsd_ldsm_purge_trash (GDateTime *old);
void gsd_ldsm_purge_temp_files (GDateTime *old);
G_END_DECLS
#endif /* __GSD_DISK_SPACE_H */
./plugins/housekeeping/gsd-housekeeping-plugin.c 0000644 0000041 0000041 00000002051 13264221014 022304 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Michael J. Chudobiak
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-housekeeping-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdHousekeeping, gsd_housekeeping)
./plugins/housekeeping/gsd-disk-space-test.c 0000644 0000041 0000041 00000002513 13264221014 021325 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2008, Novell, Inc.
*
* Authors: Vincent Untz
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gsd-disk-space.h"
int
main (int argc,
char **argv)
{
GMainLoop *loop;
gtk_init (&argc, &argv);
notify_init ("gsd-disk-space-test");
loop = g_main_loop_new (NULL, FALSE);
gsd_ldsm_setup (TRUE);
g_main_loop_run (loop);
gsd_ldsm_clean ();
g_main_loop_unref (loop);
return 0;
}
./plugins/housekeeping/gsd-disk-space-helper.c 0000644 0000041 0000041 00000006672 13264221014 021637 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2008, Novell, Inc.
* Copyright (c) 2012, Red Hat, Inc.
*
* Authors: Vincent Untz
* Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gsd-disk-space-helper.h"
gboolean
gsd_should_ignore_unix_mount (GUnixMountEntry *mount)
{
const char *fs, *device;
guint i;
/* This is borrowed from GLib and used as a way to determine
* which mounts we should ignore by default. GLib doesn't
* expose this in a way that allows it to be used for this
* purpose
*/
/* We also ignore network filesystems */
const gchar *ignore_fs[] = {
"adfs",
"afs",
"auto",
"autofs",
"autofs4",
"cifs",
"cxfs",
"devfs",
"devpts",
"ecryptfs",
"fdescfs",
"gfs",
"gfs2",
"kernfs",
"linprocfs",
"linsysfs",
"lustre",
"lustre_lite",
"ncpfs",
"nfs",
"nfs4",
"nfsd",
"ocfs2",
"proc",
"procfs",
"ptyfs",
"rpc_pipefs",
"selinuxfs",
"smbfs",
"sysfs",
"tmpfs",
"usbfs",
"zfs",
NULL
};
const gchar *ignore_devices[] = {
"none",
"sunrpc",
"devpts",
"nfsd",
"/dev/loop",
"/dev/vn",
NULL
};
fs = g_unix_mount_get_fs_type (mount);
device = g_unix_mount_get_device_path (mount);
for (i = 0; ignore_fs[i] != NULL; i++)
if (g_str_equal (ignore_fs[i], fs))
return TRUE;
for (i = 0; ignore_devices[i] != NULL; i++)
if (g_str_equal (ignore_devices[i], device))
return TRUE;
return FALSE;
}
gboolean
gsd_is_removable_mount (GUnixMountEntry *mount)
{
const char *mount_path;
char *path;
mount_path = g_unix_mount_get_mount_path (mount);
if (mount_path == NULL)
return FALSE;
path = g_strdup_printf ("/run/media/%s", g_get_user_name ());
if (g_str_has_prefix (mount_path, path)) {
g_free (path);
return TRUE;
}
g_free (path);
return FALSE;
}
./plugins/housekeeping/Makefile.am 0000644 0000041 0000041 00000004614 13264221014 017446 0 ustar www-data www-data plugin_name = housekeeping
COMMON_FILES = \
gsd-disk-space.c \
gsd-disk-space.h \
gsd-ldsm-dialog.c \
gsd-ldsm-dialog.h \
gsd-disk-space-helper.h \
gsd-disk-space-helper.c
noinst_PROGRAMS = gsd-disk-space-test gsd-empty-trash-test
gsd_disk_space_test_SOURCES = \
gsd-disk-space-test.c \
$(COMMON_FILES)
gsd_disk_space_test_LDADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS)
gsd_disk_space_test_CFLAGS = \
$(SETTINGS_PLUGIN_CFLAGS) \
$(GIOUNIX_CFLAGS) \
$(LIBNOTIFY_CFLAGS) \
$(AM_CFLAGS)
gsd_empty_trash_test_SOURCES = \
gsd-empty-trash-test.c \
$(COMMON_FILES)
gsd_empty_trash_test_LDADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS)
gsd_empty_trash_test_CFLAGS = \
$(SETTINGS_PLUGIN_CFLAGS) \
$(GIOUNIX_CFLAGS) \
$(LIBNOTIFY_CFLAGS) \
$(AM_CFLAGS)
libexec_PROGRAMS = usd-test-housekeeping
usd_test_housekeeping_SOURCES = \
test-housekeeping.c \
gsd-housekeeping-manager.c \
gsd-housekeeping-manager.h \
$(COMMON_FILES)
usd_test_housekeeping_CPPFLAGS = \
-I$(top_srcdir)/data/ \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
$(AM_CPPFLAGS)
usd_test_housekeeping_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(MOUSE_CFLAGS) \
$(AM_CFLAGS)
usd_test_housekeeping_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/plugins/common/libcommon.la \
$(SETTINGS_DAEMON_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
plugin_LTLIBRARIES = libhousekeeping.la
libhousekeeping_la_SOURCES = \
$(COMMON_FILES) \
gsd-housekeeping-manager.c \
gsd-housekeeping-manager.h \
gsd-housekeeping-plugin.c
libhousekeeping_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libhousekeeping_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(GIOUNIX_CFLAGS) \
$(LIBNOTIFY_CFLAGS) \
$(AM_CFLAGS)
libhousekeeping_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
libhousekeeping_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS)
plugin_in_files = housekeeping.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = (plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/housekeeping/gsd-disk-space-helper.h 0000644 0000041 0000041 00000002423 13264221014 021632 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* vim: set et sw=8 ts=8:
*
* Copyright (c) 2008, Novell, Inc.
* Copyright (c) 2012, Red Hat, Inc.
*
* Authors: Vincent Untz
* Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_DISK_SPACE_HELPER_H
#define __GSD_DISK_SPACE_HELPER_H
#include
#include
G_BEGIN_DECLS
gboolean gsd_should_ignore_unix_mount (GUnixMountEntry *mount);
gboolean gsd_is_removable_mount (GUnixMountEntry *mount);
G_END_DECLS
#endif /* __GSD_DISK_SPACE_HELPER_H */
./plugins/power/ 0000755 0000041 0000041 00000000000 13264221014 014053 5 ustar www-data www-data ./plugins/power/gsd-power-constants-update.pl 0000755 0000041 0000041 00000002542 13264221014 021617 0 ustar www-data www-data #!/usr/bin/env perl
# Author : Simos Xenitellis .
# Author : Bastien Nocera
# Version : 1.2
#
# Input : gsd-power-constants.h
# Output : gsdpowerconstants.py
#
use strict;
# Used for reading the keysymdef symbols.
my @constantselements;
die "Could not open file gsd-power-constants.h: $!\n" unless open(IN_CONSTANTS, "<:utf8", "gsd-power-constants.h");
# Output: gtk+/gdk/gdkkeysyms.h
die "Could not open file gsdpowerconstants.py: $!\n" unless open(OUT_CONSTANTS, ">:utf8", "gsdpowerconstants.py");
print OUT_CONSTANTS<)
{
next if ( ! /^#define / );
@constantselements = split(/\s+/);
die "Internal error, no \@constantselements: $_\n" unless @constantselements;
my $constant = $constantselements[1];
my $value = $constantselements[2];
printf OUT_CONSTANTS "%s = %s;\n", $constant, $value;
}
close IN_CONSTANTS;
printf "We just finished converting gsd-power-constants.h to gsdpowerconstants.py\nThank you\n";
./plugins/power/gsd-backlight-helper.c 0000644 0000041 0000041 00000016234 13264221014 020205 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gsd-backlight-linux.h"
#define GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS 0
#define GSD_BACKLIGHT_HELPER_EXIT_CODE_FAILED 1
#define GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID 3
#define GSD_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER 4
#define GSD_BACKLIGHT_HELPER_EXIT_CODE_NO_DEVICES 5
static gboolean
gsd_backlight_helper_write (const gchar *filename, gint value, GError **error)
{
gchar *filename_path = NULL;
gchar *text = NULL;
gint retval;
gint length;
gint fd = -1;
gboolean ret = TRUE;
filename_path = g_build_filename (filename, "brightness", NULL);
fd = open (filename_path, O_WRONLY);
if (fd < 0) {
ret = FALSE;
g_set_error (error, 1, 0, "failed to open filename: %s", filename);
goto out;
}
/* convert to text */
text = g_strdup_printf ("%i", value);
length = strlen (text);
/* write to device file */
retval = write (fd, text, length);
if (retval != length) {
ret = FALSE;
g_set_error (error, 1, 0, "writing '%s' to %s failed", text, filename);
goto out;
}
out:
if (fd >= 0)
close (fd);
g_free (text);
g_free (filename_path);
return ret;
}
static gint
gsd_backlight_helper_read_value (const gchar *filename, GError **error)
{
gchar *contents = NULL;
gint value;
if (g_file_get_contents (filename, &contents, NULL, error))
value = atoi (contents);
else
value = -1;
g_free (contents);
if (value < 0 && *error == NULL)
g_set_error (error, 1, 0, "got invalid backlight value from %s", filename);
return value;
}
static gint
gsd_backlight_helper_get (const gchar *filename, GError **error)
{
gchar *filename_path = NULL;
gint value;
filename_path = g_build_filename (filename, "brightness", NULL);
value = gsd_backlight_helper_read_value (filename_path, error);
g_free (filename_path);
return value;
}
static gint
gsd_backlight_helper_get_max (const gchar *filename, GError **error)
{
gchar *filename_path = NULL;
gint value;
filename_path = g_build_filename (filename, "max_brightness", NULL);
value = gsd_backlight_helper_read_value (filename_path, error);
g_free (filename_path);
return value;
}
static gint
clamp_minimum (gint max, gint value)
{
gint minimum;
/* If the interface has less than 100 possible values, it's
* likely that 0 doesn't turn the backlight off so we let 0 be
* set in that case. */
if (max > 99)
minimum = 1;
else
minimum = 0;
return MAX (value, minimum);
}
int
main (int argc, char *argv[])
{
GOptionContext *context;
gint uid;
gint euid;
guint retval = 0;
GError *error = NULL;
gint set_brightness = -1;
gboolean get_brightness = FALSE;
gboolean get_max_brightness = FALSE;
gchar *filename = NULL;
GsdBacklightType type;
const GOptionEntry options[] = {
{ "set-brightness", '\0', 0, G_OPTION_ARG_INT, &set_brightness,
/* command line argument */
"Set the current brightness", NULL },
{ "get-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_brightness,
/* command line argument */
"Get the current brightness", NULL },
{ "get-max-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_max_brightness,
/* command line argument */
"Get the number of brightness levels supported", NULL },
{ NULL}
};
context = g_option_context_new (NULL);
g_option_context_set_summary (context, "GNOME Settings Daemon Backlight Helper");
g_option_context_add_main_entries (context, options, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
#ifndef __linux__
/* the g-s-d plugin should only call this helper on linux */
g_critical ("Attempting to call gsb-backlight-helper on non-Linux");
g_assert_not_reached ();
#endif
/* no input */
if (set_brightness == -1 && !get_brightness && !get_max_brightness) {
g_print ("%s\n", "No valid option was specified");
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
/* find device */
filename = gsd_backlight_helper_get_best_backlight (&type);
if (filename == NULL) {
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_NO_DEVICES;
g_print ("%s: %s\n",
"Could not get or set the value of the backlight",
"No backlight devices present");
goto out;
}
/* GetBrightness */
if (get_brightness) {
gint value;
value = gsd_backlight_helper_get (filename, &error);
if (value < 0) {
g_print ("%s: %s\n",
"Could not get the value of the backlight",
error->message);
g_error_free (error);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
/* just print the contents to stdout */
g_print ("%d", value);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
goto out;
}
/* GetSteps */
if (get_max_brightness) {
gint value;
value = gsd_backlight_helper_get_max (filename, &error);
if (value < 0) {
g_print ("%s: %s\n",
"Could not get the maximum value of the backlight",
error->message);
g_error_free (error);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
/* just print the contents to stdout */
g_print ("%d", value);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
goto out;
}
/* check calling UID */
uid = getuid ();
euid = geteuid ();
if (uid != 0 || euid != 0) {
g_print ("%s\n",
"This program can only be used by the root user");
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
/* SetBrightness */
if (set_brightness != -1) {
gboolean ret = FALSE;
gint max = gsd_backlight_helper_get_max (filename, &error);
if (max < 0) {
g_print ("%s: %s\n",
"Could not get the maximum value of the backlight",
error->message);
g_error_free (error);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
if (type == GSD_BACKLIGHT_TYPE_RAW)
set_brightness = clamp_minimum (max, set_brightness);
ret = gsd_backlight_helper_write (filename, set_brightness, &error);
if (!ret) {
g_print ("%s: %s\n",
"Could not set the value of the backlight",
error->message);
g_error_free (error);
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
goto out;
}
}
/* success */
retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
out:
g_free (filename);
return retval;
}
./plugins/power/gsdpowerconstants.py 0000644 0000041 0000041 00000001132 13264221014 020211 0 ustar www-data www-data
# File auto-generated from script http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/power/gsd-power-constants-update.pl
# Modified by the GTK+ Team and others 1997-2012. See the AUTHORS
# file for a list of people on the GTK+ Team. See the ChangeLog
# files for a list of changes. These files are distributed with
# GTK+ at ftp://ftp.gtk.org/pub/gtk/.
SCREENSAVER_TIMEOUT_BLANK = 15;
IDLE_DIM_BLANK_DISABLED_MIN = 60;
IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 4.0/5.0;
MINIMUM_IDLE_DIM_DELAY = 10;
POWER_UP_TIME_ON_AC = 15;
GSD_MOCK_DEFAULT_BRIGHTNESS = 50;
GSD_MOCK_MAX_BRIGHTNESS = 100;
./plugins/power/gsm-presence-flag.h 0000644 0000041 0000041 00000002212 13264221014 017520 0 ustar www-data www-data /* -*- 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
* Lesser 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#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__ */
./plugins/power/gpm-common.h 0000644 0000041 0000041 00000007711 13264221014 016303 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2005-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#ifndef __GPMCOMMON_H
#define __GPMCOMMON_H
#include
#include
#include "gsd-rr.h"
G_BEGIN_DECLS
/* UPower helpers */
gchar *gpm_get_timestring (guint time);
const gchar *gpm_device_to_localised_string (UpDevice *device);
const gchar *gpm_device_kind_to_localised_string (UpDeviceKind kind,
guint number);
const gchar *gpm_device_kind_to_icon (UpDeviceKind kind);
const gchar *gpm_device_technology_to_localised_string (UpDeviceTechnology technology_enum);
const gchar *gpm_device_state_to_localised_string (UpDeviceState state);
GIcon *gpm_upower_get_device_icon (UpDevice *device,
gboolean use_symbolic);
gchar *gpm_upower_get_device_summary (UpDevice *device);
gchar *gpm_upower_get_device_description (UpDevice *device);
/* Power helpers */
gboolean gsd_power_is_hardware_a_vm (void);
guint gsd_power_enable_screensaver_watchdog (void);
void reset_idletime (void);
/* Backlight helpers */
/* on ACPI machines we have 4-16 levels, on others it's ~150 */
#define BRIGHTNESS_STEP_AMOUNT(max) ((max) < 20 ? 1 : (max) / 20)
#define ABS_TO_PERCENTAGE(min, max, value) gsd_power_backlight_abs_to_percentage(min, max, value)
#define PERCENTAGE_TO_ABS(min, max, value) (min + (((max - min) * value) / 100))
int gsd_power_backlight_abs_to_percentage (int min, int max, int value);
gboolean backlight_available (GsdRRScreen *rr_screen);
int backlight_get_abs (GsdRRScreen *rr_screen, GError **error);
int backlight_get_percentage (GsdRRScreen *rr_screen, GError **error);
int backlight_get_min (GsdRRScreen *rr_screen);
int backlight_get_max (GsdRRScreen *rr_screen, GError **error);
gboolean backlight_set_percentage (GsdRRScreen *rr_screen,
guint value,
GError **error);
int backlight_step_up (GsdRRScreen *rr_screen, GError **error);
int backlight_step_down (GsdRRScreen *rr_screen, GError **error);
int backlight_set_abs (GsdRRScreen *rr_screen,
guint value,
GError **error);
/* RandR helpers */
gboolean external_monitor_is_connected (GsdRRScreen *screen);
/* Sound helpers */
void play_loop_start (guint *id);
void play_loop_stop (guint *id);
G_END_DECLS
#endif /* __GPMCOMMON_H */
./plugins/power/gsm-inhibitor-flag.h 0000644 0000041 0000041 00000002404 13264221014 017706 0 ustar www-data www-data /* -*- 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
* Lesser 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __GSM_INHIBITOR_FLAG_H__
#define __GSM_INHIBITOR_FLAG_H__
#include
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__ */
./plugins/power/test-power.c 0000644 0000041 0000041 00000000305 13264221014 016326 0 ustar www-data www-data #define NEW gsd_power_manager_new
#define START gsd_power_manager_start
#define STOP gsd_power_manager_stop
#define MANAGER GsdPowerManager
#include "gsd-power-manager.h"
#include "test-plugin.h"
./plugins/power/gsd-power-manager.c 0000644 0000041 0000041 00000443205 13264221014 017546 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
* Copyright (C) 2011-2012 Richard Hughes
* Copyright (C) 2011 Ritesh Khadgaray
* Copyright (C) 2012-2013 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#define UPOWER_ENABLE_DEPRECATED 1
#include
#include
#include
#include
#include
#include
#include "gsd-power-constants.h"
#include "gsm-inhibitor-flag.h"
#include "gsm-presence-flag.h"
#include "gsm-manager-logout-mode.h"
#include "gpm-common.h"
#include "gnome-settings-plugin.h"
#include "gnome-settings-profile.h"
#include "gnome-settings-bus.h"
#include "gsd-enums.h"
#include "gsd-power-manager.h"
#include "gsd-rr.h"
#include "gsd-idle-monitor.h"
#define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager"
#define GNOME_SESSION_DBUS_PATH_PRESENCE "/org/gnome/SessionManager/Presence"
#define GNOME_SESSION_DBUS_INTERFACE_PRESENCE "org.gnome.SessionManager.Presence"
#define UPOWER_DBUS_NAME "org.freedesktop.UPower"
#define UPOWER_DBUS_PATH "/org/freedesktop/UPower"
#define UPOWER_DBUS_PATH_KBDBACKLIGHT "/org/freedesktop/UPower/KbdBacklight"
#define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower"
#define UPOWER_DBUS_INTERFACE_KBDBACKLIGHT "org.freedesktop.UPower.KbdBacklight"
#define GSD_POWER_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.power"
#define GSD_XRANDR_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.xrandr"
#define GSD_POWER_DBUS_NAME GSD_DBUS_NAME ".Power"
#define GSD_POWER_DBUS_PATH GSD_DBUS_PATH "/Power"
#define GSD_POWER_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Power"
#define GSD_POWER_DBUS_INTERFACE_SCREEN GSD_POWER_DBUS_INTERFACE ".Screen"
#define GSD_POWER_DBUS_INTERFACE_KEYBOARD GSD_POWER_DBUS_INTERFACE ".Keyboard"
#define GSD_POWER_MANAGER_NOTIFY_TIMEOUT_SHORT 10 * 1000 /* ms */
#define GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG 30 * 1000 /* ms */
#define GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT 30 /* seconds */
#define SYSTEMD_DBUS_NAME "org.freedesktop.login1"
#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1"
#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager"
/* Keep this in sync with gnome-shell */
#define SCREENSAVER_FADE_TIME 10 /* seconds */
/* Time between notifying the user about a critical action and executing it.
* This can be changed with the GSD_ACTION_DELAY constant. */
#ifndef GSD_ACTION_DELAY
#define GSD_ACTION_DELAY 20
#endif /* !GSD_ACTION_DELAY */
static const gchar introspection_xml[] =
""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
"";
#define GSD_POWER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManagerPrivate))
typedef enum {
GSD_POWER_IDLE_MODE_NORMAL,
GSD_POWER_IDLE_MODE_DIM,
GSD_POWER_IDLE_MODE_BLANK,
GSD_POWER_IDLE_MODE_SLEEP
} GsdPowerIdleMode;
struct GsdPowerManagerPrivate
{
/* D-Bus */
GsdSessionManager *session;
guint name_id;
GDBusNodeInfo *introspection_data;
GDBusConnection *connection;
GCancellable *bus_cancellable;
GDBusProxy *session_presence_proxy;
/* Settings */
GSettings *settings;
GSettings *settings_bus;
GSettings *settings_screensaver;
GSettings *settings_xrandr;
gboolean use_time_primary;
guint action_percentage;
guint action_time;
guint critical_percentage;
guint critical_time;
guint low_percentage;
guint low_time;
/* Screensaver */
GsdScreenSaver *screensaver_proxy;
gboolean screensaver_active;
/* State */
gboolean lid_is_closed;
UpClient *up_client;
gchar *previous_summary;
GIcon *previous_icon;
GPtrArray *devices_array;
UpDevice *device_composite;
GsdRRScreen *rr_screen;
NotifyNotification *notification_ups_discharging;
NotifyNotification *notification_low;
NotifyNotification *notification_sleep_warning;
NotifyNotification *notification_logout_warning;
GsdPowerActionType sleep_action_type;
gboolean battery_is_low; /* laptop battery low, or UPS discharging */
/* Brightness */
gboolean backlight_available;
gint pre_dim_brightness; /* level, not percentage */
/* Keyboard */
GDBusProxy *upower_kdb_proxy;
gint kbd_brightness_max;
gint kbd_brightness_old;
gint kbd_brightness_pre_dim;
/* Sound */
guint32 critical_alert_timeout_id;
/* systemd stuff */
GDBusProxy *logind_proxy;
gint inhibit_lid_switch_fd;
gboolean inhibit_lid_switch_taken;
gboolean inhibit_lid_switch_action;
gint inhibit_suspend_fd;
gboolean inhibit_suspend_taken;
guint inhibit_lid_switch_timer_id;
gboolean is_virtual_machine;
/* Idles */
GsdIdleMonitor *idle_monitor;
guint idle_dim_id;
guint idle_blank_id;
guint idle_sleep_warning_id;
guint idle_sleep_id;
GsdPowerIdleMode current_idle_mode;
guint temporary_unidle_on_ac_id;
GsdPowerIdleMode previous_idle_mode;
guint xscreensaver_watchdog_timer_id;
};
enum {
PROP_0,
};
static void gsd_power_manager_class_init (GsdPowerManagerClass *klass);
static void gsd_power_manager_init (GsdPowerManager *power_manager);
static UpDevice *engine_get_composite_device (GsdPowerManager *manager, UpDevice *original_device);
static UpDevice *engine_update_composite_device (GsdPowerManager *manager, UpDevice *original_device);
static GIcon *engine_get_icon (GsdPowerManager *manager);
static gchar *engine_get_summary (GsdPowerManager *manager);
static gdouble engine_get_percentage (GsdPowerManager *manager);
static void do_power_action_type (GsdPowerManager *manager, GsdPowerActionType action_type);
static void do_lid_closed_action (GsdPowerManager *manager);
static void inhibit_lid_switch (GsdPowerManager *manager);
static void uninhibit_lid_switch (GsdPowerManager *manager);
static void main_battery_or_ups_low_changed (GsdPowerManager *manager, gboolean is_low);
static void device_properties_changed_cb (UpDevice *device, GParamSpec *pspec, GsdPowerManager *manager);
static gboolean idle_is_session_inhibited (GsdPowerManager *manager, guint mask, gboolean *is_inhibited);
static void idle_set_mode (GsdPowerManager *manager, GsdPowerIdleMode mode);
static void idle_triggered_idle_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data);
static void idle_became_active_cb (GsdIdleMonitor *monitor, guint watch_id, gpointer user_data);
G_DEFINE_TYPE (GsdPowerManager, gsd_power_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
GQuark
gsd_power_manager_error_quark (void)
{
static GQuark quark = 0;
if (!quark)
quark = g_quark_from_static_string ("gsd_power_manager_error");
return quark;
}
static void
notify_close_if_showing (NotifyNotification **notification)
{
if (*notification == NULL)
return;
notify_notification_close (*notification, NULL);
g_clear_object (notification);
}
typedef enum {
WARNING_NONE = 0,
WARNING_DISCHARGING = 1,
WARNING_LOW = 2,
WARNING_CRITICAL = 3,
WARNING_ACTION = 4
} GsdPowerManagerWarning;
static GVariant *
engine_get_icon_property_variant (GsdPowerManager *manager)
{
GIcon *icon;
GVariant *retval;
icon = engine_get_icon (manager);
if (icon != NULL) {
char *str;
str = g_icon_to_string (icon);
g_object_unref (icon);
retval = g_variant_new_string (str);
g_free (str);
} else {
retval = g_variant_new_string ("");
}
return retval;
}
static GVariant *
engine_get_tooltip_property_variant (GsdPowerManager *manager)
{
char *tooltip;
GVariant *retval;
tooltip = engine_get_summary (manager);
retval = g_variant_new_string (tooltip != NULL ? tooltip : "");
g_free (tooltip);
return retval;
}
static void
engine_emit_changed (GsdPowerManager *manager,
gboolean icon_changed,
gboolean state_changed)
{
GVariantBuilder props_builder;
GVariant *props_changed = NULL;
GError *error = NULL;
/* not yet connected to the bus */
if (manager->priv->connection == NULL)
return;
g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));
if (icon_changed)
g_variant_builder_add (&props_builder, "{sv}", "Icon",
engine_get_icon_property_variant (manager));
if (state_changed)
g_variant_builder_add (&props_builder, "{sv}", "Tooltip",
engine_get_tooltip_property_variant (manager));
g_variant_builder_add (&props_builder, "{sv}", "Percentage",
g_variant_new_double (engine_get_percentage (manager)));
props_changed = g_variant_new ("(s@a{sv}@as)", GSD_POWER_DBUS_INTERFACE,
g_variant_builder_end (&props_builder),
g_variant_new_strv (NULL, 0));
g_variant_ref_sink (props_changed);
if (!g_dbus_connection_emit_signal (manager->priv->connection,
NULL,
GSD_POWER_DBUS_PATH,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
props_changed,
&error))
goto out;
out:
if (error) {
g_warning ("%s", error->message);
g_clear_error (&error);
}
if (props_changed)
g_variant_unref (props_changed);
}
static GsdPowerManagerWarning
engine_get_warning_csr (GsdPowerManager *manager, UpDevice *device)
{
gdouble percentage;
/* get device properties */
g_object_get (device, "percentage", &percentage, NULL);
if (percentage < 26.0f)
return WARNING_LOW;
else if (percentage < 13.0f)
return WARNING_CRITICAL;
return WARNING_NONE;
}
static GsdPowerManagerWarning
engine_get_warning_percentage (GsdPowerManager *manager, UpDevice *device)
{
gdouble percentage;
/* get device properties */
g_object_get (device, "percentage", &percentage, NULL);
if (percentage <= manager->priv->action_percentage)
return WARNING_ACTION;
if (percentage <= manager->priv->critical_percentage)
return WARNING_CRITICAL;
if (percentage <= manager->priv->low_percentage)
return WARNING_LOW;
return WARNING_NONE;
}
static GsdPowerManagerWarning
engine_get_warning_time (GsdPowerManager *manager, UpDevice *device)
{
UpDeviceKind kind;
gint64 time_to_empty;
/* get device properties */
g_object_get (device,
"kind", &kind,
"time-to-empty", &time_to_empty,
NULL);
/* this is probably an error condition */
if (time_to_empty == 0) {
g_debug ("time zero, falling back to percentage for %s",
up_device_kind_to_string (kind));
return engine_get_warning_percentage (manager, device);
}
if (time_to_empty <= manager->priv->action_time)
return WARNING_ACTION;
if (time_to_empty <= manager->priv->critical_time)
return WARNING_CRITICAL;
if (time_to_empty <= manager->priv->low_time)
return WARNING_LOW;
return WARNING_NONE;
}
/**
* This gets the possible engine state for the device according to the
* policy, which could be per-percent, or per-time.
**/
static GsdPowerManagerWarning
engine_get_warning (GsdPowerManager *manager, UpDevice *device)
{
UpDeviceKind kind;
UpDeviceState state;
GsdPowerManagerWarning warning_type;
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
NULL);
/* default to no engine */
warning_type = WARNING_NONE;
/* if the device in question is on ac, don't give a warning */
if (state == UP_DEVICE_STATE_CHARGING)
goto out;
if (kind == UP_DEVICE_KIND_MOUSE ||
kind == UP_DEVICE_KIND_KEYBOARD) {
warning_type = engine_get_warning_csr (manager, device);
} else if (kind == UP_DEVICE_KIND_UPS ||
kind == UP_DEVICE_KIND_MEDIA_PLAYER ||
kind == UP_DEVICE_KIND_TABLET ||
kind == UP_DEVICE_KIND_COMPUTER ||
kind == UP_DEVICE_KIND_PDA) {
warning_type = engine_get_warning_percentage (manager, device);
} else if (kind == UP_DEVICE_KIND_PHONE) {
warning_type = engine_get_warning_percentage (manager, device);
} else if (kind == UP_DEVICE_KIND_BATTERY) {
/* only use the time when it is accurate, and settings is not disabled */
if (manager->priv->use_time_primary)
warning_type = engine_get_warning_time (manager, device);
else
warning_type = engine_get_warning_percentage (manager, device);
}
/* If we have no important engines, we should test for discharging */
if (warning_type == WARNING_NONE) {
if (state == UP_DEVICE_STATE_DISCHARGING)
warning_type = WARNING_DISCHARGING;
}
out:
return warning_type;
}
static gchar *
engine_get_summary (GsdPowerManager *manager)
{
guint i;
GPtrArray *array;
UpDevice *device;
UpDeviceState state;
GString *tooltip = NULL;
gchar *part;
gboolean is_present;
/* need to get AC state */
tooltip = g_string_new ("");
/* do we have specific device types? */
array = manager->priv->devices_array;
for (i=0;ilen;i++) {
device = g_ptr_array_index (array, i);
g_object_get (device,
"is-present", &is_present,
"state", &state,
NULL);
if (!is_present)
continue;
if (state == UP_DEVICE_STATE_EMPTY)
continue;
part = gpm_upower_get_device_summary (device);
if (part != NULL)
g_string_append_printf (tooltip, "%s\n", part);
g_free (part);
}
/* remove the last \n */
g_string_truncate (tooltip, tooltip->len-1);
g_debug ("tooltip: %s", tooltip->str);
return g_string_free (tooltip, FALSE);
}
static gdouble
engine_get_percentage (GsdPowerManager *manager)
{
guint i;
GPtrArray *array;
UpDevice *device;
UpDeviceKind kind;
gboolean is_present;
gdouble percentage;
array = manager->priv->devices_array;
for (i = 0; i < array->len ; i++) {
device = g_ptr_array_index (array, i);
/* get device properties */
g_object_get (device,
"kind", &kind,
"is-present", &is_present,
NULL);
/* if battery then use composite device to cope with multiple batteries */
if (kind == UP_DEVICE_KIND_BATTERY)
device = engine_get_composite_device (manager, device);
if (is_present) {
/* Doing it here as it could be a composite device */
g_object_get (device, "percentage", &percentage, NULL);
return percentage;
}
}
return -1;
}
static GIcon *
engine_get_icon_priv (GsdPowerManager *manager,
UpDeviceKind device_kind,
GsdPowerManagerWarning warning,
gboolean use_state)
{
guint i;
GPtrArray *array;
UpDevice *device;
GsdPowerManagerWarning warning_temp;
UpDeviceKind kind;
UpDeviceState state;
gboolean is_present;
/* do we have specific device types? */
array = manager->priv->devices_array;
for (i=0;ilen;i++) {
device = g_ptr_array_index (array, i);
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
"is-present", &is_present,
NULL);
/* if battery then use composite device to cope with multiple batteries */
if (kind == UP_DEVICE_KIND_BATTERY)
device = engine_get_composite_device (manager, device);
warning_temp = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device),
"engine-warning-old"));
if (kind == device_kind && is_present) {
if (warning != WARNING_NONE) {
if (warning_temp == warning)
return gpm_upower_get_device_icon (device, TRUE);
continue;
}
if (use_state) {
if (state == UP_DEVICE_STATE_CHARGING ||
state == UP_DEVICE_STATE_DISCHARGING)
return gpm_upower_get_device_icon (device, TRUE);
continue;
}
return gpm_upower_get_device_icon (device, TRUE);
}
}
return NULL;
}
static GIcon *
engine_get_icon (GsdPowerManager *manager)
{
GIcon *icon = NULL;
/* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_CRITICAL, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_CRITICAL, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_CRITICAL, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_CRITICAL, FALSE);
if (icon != NULL)
return icon;
/* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_LOW, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_LOW, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_LOW, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_LOW, FALSE);
if (icon != NULL)
return icon;
/* we try (DIS)CHARGING: BATTERY, UPS */
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, TRUE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, TRUE);
if (icon != NULL)
return icon;
/* we try PRESENT: BATTERY, UPS */
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, FALSE);
if (icon != NULL)
return icon;
icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, FALSE);
if (icon != NULL)
return icon;
/* do not show an icon */
return NULL;
}
static gboolean
engine_recalculate_state_icon (GsdPowerManager *manager)
{
GIcon *icon;
/* show a different icon if we are disconnected */
icon = engine_get_icon (manager);
if (g_icon_equal (icon, manager->priv->previous_icon)) {
g_clear_object (&icon);
return FALSE;
}
g_clear_object (&manager->priv->previous_icon);
manager->priv->previous_icon = icon;
g_debug ("Icon changed");
return TRUE;
}
static gboolean
engine_recalculate_state_summary (GsdPowerManager *manager)
{
char *summary;
summary = engine_get_summary (manager);
if (g_strcmp0 (manager->priv->previous_summary, summary) == 0) {
g_free (summary);
return FALSE;
}
g_free (manager->priv->previous_summary);
manager->priv->previous_summary = summary;
g_debug ("Summary changed");
return TRUE;
}
static void
engine_recalculate_state (GsdPowerManager *manager)
{
gboolean icon_changed = FALSE;
gboolean state_changed = FALSE;
icon_changed = engine_recalculate_state_icon (manager);
state_changed = engine_recalculate_state_summary (manager);
/* only emit if the icon or summary has changed */
if (icon_changed || state_changed)
engine_emit_changed (manager, icon_changed, state_changed);
}
static UpDevice *
engine_get_composite_device (GsdPowerManager *manager,
UpDevice *original_device)
{
guint battery_devices = 0;
GPtrArray *array;
UpDevice *device;
UpDeviceKind kind;
UpDeviceKind original_kind;
guint i;
/* get the type of the original device */
g_object_get (original_device,
"kind", &original_kind,
NULL);
/* find out how many batteries in the system */
array = manager->priv->devices_array;
for (i=0;ilen;i++) {
device = g_ptr_array_index (array, i);
g_object_get (device,
"kind", &kind,
NULL);
if (kind == original_kind)
battery_devices++;
}
/* just use the original device if only one primary battery */
if (battery_devices <= 1)
return original_device;
/* use the composite device */
device = manager->priv->device_composite;
/* return composite device or original device */
return device;
}
static UpDevice *
engine_update_composite_device (GsdPowerManager *manager,
UpDevice *original_device)
{
guint i;
gdouble percentage = 0.0;
gdouble energy = 0.0;
gdouble energy_full = 0.0;
gdouble energy_rate = 0.0;
gdouble energy_total = 0.0;
gdouble energy_full_total = 0.0;
gdouble energy_rate_total = 0.0;
gint64 time_to_empty = 0;
gint64 time_to_full = 0;
guint battery_devices = 0;
gboolean is_charging = FALSE;
gboolean is_discharging = FALSE;
gboolean is_fully_charged = TRUE;
GPtrArray *array;
UpDevice *device;
UpDeviceState state;
UpDeviceKind kind;
UpDeviceKind original_kind;
/* get the type of the original device */
g_object_get (original_device,
"kind", &original_kind,
NULL);
/* update the composite device */
array = manager->priv->devices_array;
for (i=0;ilen;i++) {
device = g_ptr_array_index (array, i);
g_object_get (device,
"kind", &kind,
"state", &state,
"energy", &energy,
"energy-full", &energy_full,
"energy-rate", &energy_rate,
NULL);
if (kind != original_kind)
continue;
/* one of these will be charging or discharging */
if (state == UP_DEVICE_STATE_CHARGING)
is_charging = TRUE;
if (state == UP_DEVICE_STATE_DISCHARGING)
is_discharging = TRUE;
if (state != UP_DEVICE_STATE_FULLY_CHARGED)
is_fully_charged = FALSE;
/* sum up composite */
energy_total += energy;
energy_full_total += energy_full;
energy_rate_total += energy_rate;
battery_devices++;
}
/* just use the original device if only one primary battery */
if (battery_devices == 1) {
g_debug ("using original device as only one primary battery");
device = original_device;
goto out;
}
/* use percentage weighted for each battery capacity */
if (energy_full_total > 0.0)
percentage = 100.0 * energy_total / energy_full_total;
/* set composite state */
if (is_charging)
state = UP_DEVICE_STATE_CHARGING;
else if (is_discharging)
state = UP_DEVICE_STATE_DISCHARGING;
else if (is_fully_charged)
state = UP_DEVICE_STATE_FULLY_CHARGED;
else
state = UP_DEVICE_STATE_UNKNOWN;
/* calculate a quick and dirty time remaining value */
if (energy_rate_total > 0) {
if (state == UP_DEVICE_STATE_DISCHARGING)
time_to_empty = 3600 * (energy_total / energy_rate_total);
else if (state == UP_DEVICE_STATE_CHARGING)
time_to_full = 3600 * ((energy_full_total - energy_total) / energy_rate_total);
}
/* okay, we can use the composite device */
device = manager->priv->device_composite;
g_debug ("printing composite device");
g_object_set (device,
"energy", energy,
"energy-full", energy_full,
"energy-rate", energy_rate,
"time-to-empty", time_to_empty,
"time-to-full", time_to_full,
"percentage", percentage,
"state", state,
NULL);
/* force update of icon */
if (engine_recalculate_state_icon (manager))
engine_emit_changed (manager, TRUE, FALSE);
out:
/* return composite device or original device */
return device;
}
static void
engine_device_add (GsdPowerManager *manager, UpDevice *device)
{
GsdPowerManagerWarning warning;
UpDeviceState state;
UpDeviceKind kind;
UpDevice *composite;
/* assign warning */
warning = engine_get_warning (manager, device);
g_object_set_data (G_OBJECT(device),
"engine-warning-old",
GUINT_TO_POINTER(warning));
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
NULL);
/* add old state for transitions */
g_debug ("adding %s with state %s",
up_device_get_object_path (device), up_device_state_to_string (state));
g_object_set_data (G_OBJECT(device),
"engine-state-old",
GUINT_TO_POINTER(state));
if (kind == UP_DEVICE_KIND_BATTERY) {
g_debug ("updating because we added a device");
composite = engine_update_composite_device (manager, device);
/* get the same values for the composite device */
warning = engine_get_warning (manager, composite);
g_object_set_data (G_OBJECT(composite),
"engine-warning-old",
GUINT_TO_POINTER(warning));
g_object_get (composite, "state", &state, NULL);
g_object_set_data (G_OBJECT(composite),
"engine-state-old",
GUINT_TO_POINTER(state));
}
g_ptr_array_add (manager->priv->devices_array, g_object_ref(device));
g_signal_connect (device, "notify::state",
G_CALLBACK (device_properties_changed_cb), manager);
g_signal_connect (device, "notify::warning-level",
G_CALLBACK (device_properties_changed_cb), manager);
}
static gboolean
engine_coldplug (GsdPowerManager *manager)
{
guint i;
GPtrArray *array = NULL;
UpDevice *device;
engine_recalculate_state (manager);
/* add to database */
array = up_client_get_devices (manager->priv->up_client);
if (array == NULL)
goto out;
for (i=0;ilen;i++) {
device = g_ptr_array_index (array, i);
engine_device_add (manager, device);
}
out:
if (array != NULL)
g_ptr_array_unref (array);
/* never repeat */
return FALSE;
}
static void
engine_device_added_cb (UpClient *client, UpDevice *device, GsdPowerManager *manager)
{
/* add to list */
g_ptr_array_add (manager->priv->devices_array, g_object_ref (device));
engine_recalculate_state (manager);
}
static void
engine_device_removed_cb (UpClient *client, const char *object_path, GsdPowerManager *manager)
{
guint i;
for (i = 0; i < manager->priv->devices_array->len; i++) {
UpDevice *device = g_ptr_array_index (manager->priv->devices_array, i);
if (g_strcmp0 (object_path, up_device_get_object_path (device)) == 0) {
g_ptr_array_remove_index (manager->priv->devices_array, i);
break;
}
}
}
static void
on_notification_closed (NotifyNotification *notification, gpointer data)
{
g_object_unref (notification);
}
static const gchar *
get_first_themed_icon_name (GIcon *icon)
{
const gchar* const *icon_names;
const gchar *icon_name = NULL;
/* no icon */
if (icon == NULL)
goto out;
/* just use the first icon */
icon_names = g_themed_icon_get_names (G_THEMED_ICON (icon));
if (icon_names != NULL)
icon_name = icon_names[0];
out:
return icon_name;
}
static void
create_notification (const char *summary,
const char *body,
GIcon *icon,
NotifyNotification **weak_pointer_location)
{
NotifyNotification *notification;
notification = notify_notification_new (summary,
body,
icon ? get_first_themed_icon_name (icon) : NULL);
*weak_pointer_location = notification;
g_object_add_weak_pointer (G_OBJECT (notification),
(gpointer *) weak_pointer_location);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
}
static void
engine_ups_discharging (GsdPowerManager *manager, UpDevice *device)
{
const gchar *title;
gchar *remaining_text = NULL;
gdouble percentage;
GIcon *icon = NULL;
gint64 time_to_empty;
GString *message;
UpDeviceKind kind;
/* get device properties */
g_object_get (device,
"kind", &kind,
"percentage", &percentage,
"time-to-empty", &time_to_empty,
NULL);
if (kind != UP_DEVICE_KIND_UPS)
return;
main_battery_or_ups_low_changed (manager, TRUE);
/* only show text if there is a valid time */
if (time_to_empty > 0)
remaining_text = gpm_get_timestring (time_to_empty);
/* TRANSLATORS: UPS is now discharging */
title = _("UPS Discharging");
message = g_string_new ("");
if (remaining_text != NULL) {
/* TRANSLATORS: tell the user how much time they have got */
g_string_append_printf (message, _("%s of UPS backup power remaining"),
remaining_text);
} else {
g_string_append (message, gpm_device_to_localised_string (device));
}
g_string_append_printf (message, " (%.0f%%)", percentage);
icon = gpm_upower_get_device_icon (device, TRUE);
/* close any existing notification of this class */
notify_close_if_showing (&manager->priv->notification_ups_discharging);
/* create a new notification */
create_notification (title, message->str,
icon,
&manager->priv->notification_ups_discharging);
notify_notification_set_timeout (manager->priv->notification_ups_discharging,
GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG);
notify_notification_set_urgency (manager->priv->notification_ups_discharging,
NOTIFY_URGENCY_NORMAL);
/* TRANSLATORS: this is the notification application name */
notify_notification_set_app_name (manager->priv->notification_ups_discharging, _("Power"));
notify_notification_set_hint (manager->priv->notification_ups_discharging,
"transient", g_variant_new_boolean (TRUE));
notify_notification_show (manager->priv->notification_ups_discharging, NULL);
g_string_free (message, TRUE);
if (icon != NULL)
g_object_unref (icon);
g_free (remaining_text);
}
static GsdPowerActionType
manager_critical_action_get (GsdPowerManager *manager,
gboolean is_ups)
{
GsdPowerActionType policy;
GVariant *result = NULL;
policy = g_settings_get_enum (manager->priv->settings, "critical-battery-action");
if (policy == GSD_POWER_ACTION_SUSPEND) {
if (is_ups == FALSE) {
result = g_dbus_proxy_call_sync (manager->priv->logind_proxy,
"CanSuspend",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
}
} else if (policy == GSD_POWER_ACTION_HIBERNATE) {
result = g_dbus_proxy_call_sync (manager->priv->logind_proxy,
"CanHibernate",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
} else {
/* Other actions need no check */
return policy;
}
if (result) {
const char *s;
g_variant_get (result, "(s)", &s);
if (g_strcmp0 (s, "yes") != 0)
policy = GSD_POWER_ACTION_SHUTDOWN;
g_variant_unref (result);
} else {
policy = GSD_POWER_ACTION_SHUTDOWN;
}
return policy;
}
static gboolean
manager_critical_action_do (GsdPowerManager *manager,
gboolean is_ups)
{
GsdPowerActionType action_type;
/* stop playing the alert as it's too late to do anything now */
play_loop_stop (&manager->priv->critical_alert_timeout_id);
action_type = manager_critical_action_get (manager, is_ups);
do_power_action_type (manager, action_type);
return FALSE;
}
static gboolean
manager_critical_action_do_cb (GsdPowerManager *manager)
{
manager_critical_action_do (manager, FALSE);
return FALSE;
}
static gboolean
manager_critical_ups_action_do_cb (GsdPowerManager *manager)
{
manager_critical_action_do (manager, TRUE);
return FALSE;
}
static gboolean
engine_just_laptop_battery (GsdPowerManager *manager)
{
UpDevice *device;
UpDeviceKind kind;
GPtrArray *array;
gboolean ret = TRUE;
guint i;
/* find if there are any other device types that mean we have to
* be more specific in our wording */
array = manager->priv->devices_array;
for (i=0; ilen; i++) {
device = g_ptr_array_index (array, i);
g_object_get (device, "kind", &kind, NULL);
if (kind != UP_DEVICE_KIND_BATTERY) {
ret = FALSE;
break;
}
}
return ret;
}
static void
engine_charge_low (GsdPowerManager *manager, UpDevice *device)
{
const gchar *title = NULL;
gboolean ret;
gchar *message = NULL;
gchar *tmp;
gchar *remaining_text;
gdouble percentage;
GIcon *icon = NULL;
gint64 time_to_empty;
UpDeviceKind kind;
/* get device properties */
g_object_get (device,
"kind", &kind,
"percentage", &percentage,
"time-to-empty", &time_to_empty,
NULL);
/* check to see if the batteries have not noticed we are on AC */
if (kind == UP_DEVICE_KIND_BATTERY) {
if (!up_client_get_on_battery (manager->priv->up_client)) {
g_warning ("ignoring low message as we are not on battery power");
goto out;
}
}
if (kind == UP_DEVICE_KIND_BATTERY) {
/* if the user has no other batteries, drop the "Laptop" wording */
ret = engine_just_laptop_battery (manager);
if (ret) {
/* TRANSLATORS: laptop battery low, and we only have one battery */
title = _("Battery low");
} else {
/* TRANSLATORS: laptop battery low, and we have more than one kind of battery */
title = _("Laptop battery low");
}
tmp = gpm_get_timestring (time_to_empty);
remaining_text = g_strconcat ("", tmp, "", NULL);
g_free (tmp);
/* TRANSLATORS: tell the user how much time they have got */
message = g_strdup_printf (_("Approximately %s remaining (%.0f%%)"), remaining_text, percentage);
g_free (remaining_text);
main_battery_or_ups_low_changed (manager, TRUE);
} else if (kind == UP_DEVICE_KIND_UPS) {
/* TRANSLATORS: UPS is starting to get a little low */
title = _("UPS low");
tmp = gpm_get_timestring (time_to_empty);
remaining_text = g_strconcat ("", tmp, "", NULL);
g_free (tmp);
/* TRANSLATORS: tell the user how much time they have got */
message = g_strdup_printf (_("Approximately %s of remaining UPS backup power (%.0f%%)"),
remaining_text, percentage);
g_free (remaining_text);
} else if (kind == UP_DEVICE_KIND_MOUSE) {
/* TRANSLATORS: mouse is getting a little low */
title = _("Mouse battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Wireless mouse is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_KEYBOARD) {
/* TRANSLATORS: keyboard is getting a little low */
title = _("Keyboard battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Wireless keyboard is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_PDA) {
/* TRANSLATORS: PDA is getting a little low */
title = _("PDA battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("PDA is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_PHONE) {
/* TRANSLATORS: cell phone (mobile) is getting a little low */
title = _("Cell phone battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Cell phone is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) {
/* TRANSLATORS: media player, e.g. mp3 is getting a little low */
title = _("Media player battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Media player is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_TABLET) {
/* TRANSLATORS: graphics tablet, e.g. wacom is getting a little low */
title = _("Tablet battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Tablet is low in power (%.0f%%)"), percentage);
} else if (kind == UP_DEVICE_KIND_COMPUTER) {
/* TRANSLATORS: computer, e.g. ipad is getting a little low */
title = _("Attached computer battery low");
/* TRANSLATORS: tell user more details */
message = g_strdup_printf (_("Attached computer is low in power (%.0f%%)"), percentage);
}
/* get correct icon */
icon = gpm_upower_get_device_icon (device, TRUE);
/* close any existing notification of this class */
notify_close_if_showing (&manager->priv->notification_low);
/* create a new notification */
create_notification (title, message,
icon,
&manager->priv->notification_low);
notify_notification_set_timeout (manager->priv->notification_low,
GSD_POWER_MANAGER_NOTIFY_TIMEOUT_LONG);
notify_notification_set_urgency (manager->priv->notification_low,
NOTIFY_URGENCY_NORMAL);
notify_notification_set_app_name (manager->priv->notification_low, _("Power"));
notify_notification_set_hint (manager->priv->notification_low,
"transient", g_variant_new_boolean (TRUE));
notify_notification_show (manager->priv->notification_low, NULL);
/* play the sound, using sounds from the naming spec */
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "battery-low",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("Battery is low"), NULL);
out:
if (icon != NULL)
g_object_unref (icon);
g_free (message);
}
static void
engine_charge_critical (GsdPowerManager *manager, UpDevice *device)
{
const gchar *title = NULL;
gboolean ret;
gchar *message = NULL;
gdouble percentage;
GIcon *icon = NULL;
gint64 time_to_empty;
GsdPowerActionType policy;
UpDeviceKind kind;
/* get device properties */
g_object_get (device,
"kind", &kind,
"percentage", &percentage,
"time-to-empty", &time_to_empty,
NULL);
/* check to see if the batteries have not noticed we are on AC */
if (kind == UP_DEVICE_KIND_BATTERY) {
if (!up_client_get_on_battery (manager->priv->up_client)) {
g_warning ("ignoring critically low message as we are not on battery power");
goto out;
}
}
if (kind == UP_DEVICE_KIND_BATTERY) {
/* if the user has no other batteries, drop the "Laptop" wording */
ret = engine_just_laptop_battery (manager);
if (ret) {
/* TRANSLATORS: laptop battery critically low, and only have one kind of battery */
title = _("Battery critically low");
} else {
/* TRANSLATORS: laptop battery critically low, and we have more than one type of battery */
title = _("Laptop battery critically low");
}
/* we have to do different warnings depending on the policy */
policy = manager_critical_action_get (manager, FALSE);
/* use different text for different actions */
if (policy == GSD_POWER_ACTION_NOTHING) {
/* TRANSLATORS: tell the use to insert the plug, as we're not going to do anything */
message = g_strdup (_("Plug in your AC adapter to avoid losing data."));
} else if (policy == GSD_POWER_ACTION_SUSPEND) {
/* TRANSLATORS: give the user a ultimatum */
message = g_strdup_printf (_("Computer will suspend very soon unless it is plugged in."));
} else if (policy == GSD_POWER_ACTION_HIBERNATE) {
/* TRANSLATORS: give the user a ultimatum */
message = g_strdup_printf (_("Computer will hibernate very soon unless it is plugged in."));
} else if (policy == GSD_POWER_ACTION_SHUTDOWN) {
/* TRANSLATORS: give the user a ultimatum */
message = g_strdup_printf (_("Computer will shutdown very soon unless it is plugged in."));
}
main_battery_or_ups_low_changed (manager, TRUE);
} else if (kind == UP_DEVICE_KIND_UPS) {
gchar *remaining_text;
gchar *tmp;
/* TRANSLATORS: the UPS is very low */
title = _("UPS critically low");
tmp = gpm_get_timestring (time_to_empty);
remaining_text = g_strconcat ("", tmp, "", NULL);
g_free (tmp);
/* TRANSLATORS: give the user a ultimatum */
message = g_strdup_printf (_("Approximately %s of remaining UPS power (%.0f%%). "
"Restore AC power to your computer to avoid losing data."),
remaining_text, percentage);
g_free (remaining_text);
} else if (kind == UP_DEVICE_KIND_MOUSE) {
/* TRANSLATORS: the mouse battery is very low */
title = _("Mouse battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Wireless mouse is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_KEYBOARD) {
/* TRANSLATORS: the keyboard battery is very low */
title = _("Keyboard battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Wireless keyboard is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_PDA) {
/* TRANSLATORS: the PDA battery is very low */
title = _("PDA battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("PDA is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_PHONE) {
/* TRANSLATORS: the cell battery is very low */
title = _("Cell phone battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Cell phone is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) {
/* TRANSLATORS: the cell battery is very low */
title = _("Cell phone battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Media player is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_TABLET) {
/* TRANSLATORS: the cell battery is very low */
title = _("Tablet battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Tablet is very low in power (%.0f%%). "
"This device will soon stop functioning if not charged."),
percentage);
} else if (kind == UP_DEVICE_KIND_COMPUTER) {
/* TRANSLATORS: the cell battery is very low */
title = _("Attached computer battery low");
/* TRANSLATORS: the device is just going to stop working */
message = g_strdup_printf (_("Attached computer is very low in power (%.0f%%). "
"The device will soon shutdown if not charged."),
percentage);
}
/* get correct icon */
icon = gpm_upower_get_device_icon (device, TRUE);
/* close any existing notification of this class */
notify_close_if_showing (&manager->priv->notification_low);
/* create a new notification */
create_notification (title, message,
icon,
&manager->priv->notification_low);
notify_notification_set_timeout (manager->priv->notification_low,
NOTIFY_EXPIRES_DEFAULT);
notify_notification_set_urgency (manager->priv->notification_low,
NOTIFY_URGENCY_CRITICAL);
notify_notification_set_app_name (manager->priv->notification_low, _("Power"));
notify_notification_show (manager->priv->notification_low, NULL);
switch (kind) {
case UP_DEVICE_KIND_BATTERY:
case UP_DEVICE_KIND_UPS:
g_debug ("critical charge level reached, starting sound loop");
play_loop_start (&manager->priv->critical_alert_timeout_id);
break;
default:
/* play the sound, using sounds from the naming spec */
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "battery-caution",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL);
break;
}
out:
if (icon != NULL)
g_object_unref (icon);
g_free (message);
}
static void
engine_charge_action (GsdPowerManager *manager, UpDevice *device)
{
const gchar *title = NULL;
gchar *message = NULL;
GIcon *icon = NULL;
GsdPowerActionType policy;
guint timer_id;
UpDeviceKind kind;
/* get device properties */
g_object_get (device,
"kind", &kind,
NULL);
/* check to see if the batteries have not noticed we are on AC */
if (kind == UP_DEVICE_KIND_BATTERY) {
if (!up_client_get_on_battery (manager->priv->up_client)) {
g_warning ("ignoring critically low message as we are not on battery power");
goto out;
}
}
if (kind == UP_DEVICE_KIND_BATTERY) {
/* TRANSLATORS: laptop battery is really, really, low */
title = _("Laptop battery critically low");
/* we have to do different warnings depending on the policy */
policy = manager_critical_action_get (manager, FALSE);
/* use different text for different actions */
if (policy == GSD_POWER_ACTION_NOTHING) {
/* TRANSLATORS: computer will shutdown without saving data */
message = g_strdup (_("The battery is below the critical level and "
"this computer will power-off when the "
"battery becomes completely empty."));
} else if (policy == GSD_POWER_ACTION_SUSPEND) {
/* TRANSLATORS: computer will suspend */
message = g_strdup (_("The battery is below the critical level and "
"this computer is about to suspend.\n"
"NOTE: A small amount of power is required "
"to keep your computer in a suspended state."));
} else if (policy == GSD_POWER_ACTION_HIBERNATE) {
/* TRANSLATORS: computer will hibernate */
message = g_strdup (_("The battery is below the critical level and "
"this computer is about to hibernate."));
} else if (policy == GSD_POWER_ACTION_SHUTDOWN) {
/* TRANSLATORS: computer will just shutdown */
message = g_strdup (_("The battery is below the critical level and "
"this computer is about to shutdown."));
}
/* wait 20 seconds for user-panic */
timer_id = g_timeout_add_seconds (GSD_ACTION_DELAY,
(GSourceFunc) manager_critical_action_do_cb,
manager);
g_source_set_name_by_id (timer_id, "[GsdPowerManager] battery critical-action");
} else if (kind == UP_DEVICE_KIND_UPS) {
/* TRANSLATORS: UPS is really, really, low */
title = _("UPS critically low");
/* we have to do different warnings depending on the policy */
policy = manager_critical_action_get (manager, TRUE);
/* use different text for different actions */
if (policy == GSD_POWER_ACTION_NOTHING) {
/* TRANSLATORS: computer will shutdown without saving data */
message = g_strdup (_("UPS is below the critical level and "
"this computer will power-off when the "
"UPS becomes completely empty."));
} else if (policy == GSD_POWER_ACTION_HIBERNATE) {
/* TRANSLATORS: computer will hibernate */
message = g_strdup (_("UPS is below the critical level and "
"this computer is about to hibernate."));
} else if (policy == GSD_POWER_ACTION_SHUTDOWN) {
/* TRANSLATORS: computer will just shutdown */
message = g_strdup (_("UPS is below the critical level and "
"this computer is about to shutdown."));
}
/* wait 20 seconds for user-panic */
timer_id = g_timeout_add_seconds (GSD_ACTION_DELAY,
(GSourceFunc) manager_critical_ups_action_do_cb,
manager);
g_source_set_name_by_id (timer_id, "[GsdPowerManager] ups critical-action");
}
/* not all types have actions */
if (title == NULL)
return;
/* get correct icon */
icon = gpm_upower_get_device_icon (device, TRUE);
/* close any existing notification of this class */
notify_close_if_showing (&manager->priv->notification_low);
/* create a new notification */
create_notification (title, message,
icon,
&manager->priv->notification_low);
notify_notification_set_timeout (manager->priv->notification_low,
NOTIFY_EXPIRES_DEFAULT);
notify_notification_set_urgency (manager->priv->notification_low,
NOTIFY_URGENCY_CRITICAL);
notify_notification_set_app_name (manager->priv->notification_low, _("Power"));
/* try to show */
notify_notification_show (manager->priv->notification_low, NULL);
/* play the sound, using sounds from the naming spec */
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "battery-caution",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL);
out:
if (icon != NULL)
g_object_unref (icon);
g_free (message);
}
static void
device_properties_changed_cb (UpDevice *device, GParamSpec *pspec, GsdPowerManager *manager)
{
UpDeviceKind kind;
UpDeviceState state;
UpDeviceState state_old;
GsdPowerManagerWarning warning_old;
GsdPowerManagerWarning warning;
/* get device properties */
g_object_get (device,
"kind", &kind,
NULL);
/* if battery then use composite device to cope with multiple batteries */
if (kind == UP_DEVICE_KIND_BATTERY) {
g_debug ("updating because %s changed", up_device_get_object_path (device));
device = engine_update_composite_device (manager, device);
}
/* get device properties (may be composite) */
g_object_get (device,
"state", &state,
NULL);
g_debug ("%s state is now %s", up_device_get_object_path (device), up_device_state_to_string (state));
/* see if any interesting state changes have happened */
state_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-state-old"));
if (state_old != state) {
if (state == UP_DEVICE_STATE_DISCHARGING) {
g_debug ("discharging");
engine_ups_discharging (manager, device);
} else if (state == UP_DEVICE_STATE_FULLY_CHARGED ||
state == UP_DEVICE_STATE_CHARGING) {
g_debug ("fully charged or charging, hiding notifications if any");
notify_close_if_showing (&manager->priv->notification_low);
notify_close_if_showing (&manager->priv->notification_ups_discharging);
main_battery_or_ups_low_changed (manager, FALSE);
}
/* save new state */
g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state));
}
/* check the warning state has not changed */
warning_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old"));
warning = engine_get_warning (manager, device);
if (warning != warning_old) {
if (warning == WARNING_LOW) {
g_debug ("** EMIT: charge-low");
engine_charge_low (manager, device);
} else if (warning == WARNING_CRITICAL) {
g_debug ("** EMIT: charge-critical");
engine_charge_critical (manager, device);
} else if (warning == WARNING_ACTION) {
g_debug ("charge-action");
engine_charge_action (manager, device);
}
/* save new state */
g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning));
}
engine_recalculate_state (manager);
}
static UpDevice *
engine_get_primary_device (GsdPowerManager *manager)
{
guint i;
UpDevice *device = NULL;
UpDevice *device_tmp;
UpDeviceKind kind;
UpDeviceState state;
gboolean is_present;
for (i=0; ipriv->devices_array->len; i++) {
device_tmp = g_ptr_array_index (manager->priv->devices_array, i);
/* get device properties */
g_object_get (device_tmp,
"kind", &kind,
"state", &state,
"is-present", &is_present,
NULL);
/* not present */
if (!is_present)
continue;
/* not discharging */
if (state != UP_DEVICE_STATE_DISCHARGING)
continue;
/* not battery */
if (kind != UP_DEVICE_KIND_BATTERY)
continue;
/* use composite device to cope with multiple batteries */
device = g_object_ref (engine_get_composite_device (manager, device_tmp));
break;
}
return device;
}
static void
gnome_session_shutdown_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GVariant *result;
GError *error = NULL;
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
res,
&error);
if (result == NULL) {
g_warning ("couldn't shutdown using gnome-session: %s",
error->message);
g_error_free (error);
} else {
g_variant_unref (result);
}
}
static void
gnome_session_shutdown (GsdPowerManager *manager)
{
g_dbus_proxy_call (G_DBUS_PROXY (manager->priv->session),
"Shutdown",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
gnome_session_shutdown_cb, NULL);
}
static void
gnome_session_logout_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GVariant *result;
GError *error = NULL;
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
res,
&error);
if (result == NULL) {
g_warning ("couldn't log out using gnome-session: %s",
error->message);
g_error_free (error);
} else {
g_variant_unref (result);
}
}
static void
gnome_session_logout (GsdPowerManager *manager,
guint logout_mode)
{
g_dbus_proxy_call (G_DBUS_PROXY (manager->priv->session),
"Logout",
g_variant_new ("(u)", logout_mode),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
gnome_session_logout_cb, NULL);
}
static void
action_poweroff (GsdPowerManager *manager)
{
if (manager->priv->logind_proxy == NULL) {
g_warning ("no systemd support");
return;
}
g_dbus_proxy_call (manager->priv->logind_proxy,
"PowerOff",
g_variant_new ("(b)", FALSE),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
NULL,
NULL);
}
static void
action_suspend (GsdPowerManager *manager)
{
if (manager->priv->logind_proxy == NULL) {
g_warning ("no systemd support");
return;
}
g_dbus_proxy_call (manager->priv->logind_proxy,
"Suspend",
g_variant_new ("(b)", FALSE),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
NULL,
NULL);
}
static void
action_hibernate (GsdPowerManager *manager)
{
if (manager->priv->logind_proxy == NULL) {
g_warning ("no systemd support");
return;
}
g_dbus_proxy_call (manager->priv->logind_proxy,
"Hibernate",
g_variant_new ("(b)", FALSE),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
NULL,
NULL);
}
static void
backlight_enable (GsdPowerManager *manager)
{
gboolean ret;
GError *error = NULL;
ret = gsd_rr_screen_set_dpms_mode (manager->priv->rr_screen,
GSD_RR_DPMS_ON,
&error);
if (!ret) {
g_warning ("failed to turn the panel on: %s",
error->message);
g_error_free (error);
}
g_debug ("TESTSUITE: Unblanked screen");
}
static void
backlight_disable (GsdPowerManager *manager)
{
gboolean ret;
GError *error = NULL;
ret = gsd_rr_screen_set_dpms_mode (manager->priv->rr_screen,
GSD_RR_DPMS_OFF,
&error);
if (!ret) {
g_warning ("failed to turn the panel off: %s",
error->message);
g_error_free (error);
}
g_debug ("TESTSUITE: Blanked screen");
}
static void
do_power_action_type (GsdPowerManager *manager,
GsdPowerActionType action_type)
{
switch (action_type) {
case GSD_POWER_ACTION_SUSPEND:
action_suspend (manager);
break;
case GSD_POWER_ACTION_INTERACTIVE:
gnome_session_shutdown (manager);
break;
case GSD_POWER_ACTION_HIBERNATE:
action_hibernate (manager);
break;
case GSD_POWER_ACTION_SHUTDOWN:
/* this is only used on critically low battery where
* hibernate is not available and is marginally better
* than just powering down the computer mid-write */
action_poweroff (manager);
break;
case GSD_POWER_ACTION_BLANK:
backlight_disable (manager);
break;
case GSD_POWER_ACTION_NOTHING:
break;
case GSD_POWER_ACTION_LOGOUT:
gnome_session_logout (manager, GSM_MANAGER_LOGOUT_MODE_FORCE);
break;
}
}
static GsmInhibitorFlag
get_idle_inhibitors_for_action (GsdPowerActionType action_type)
{
switch (action_type) {
case GSD_POWER_ACTION_BLANK:
case GSD_POWER_ACTION_SHUTDOWN:
case GSD_POWER_ACTION_INTERACTIVE:
return GSM_INHIBITOR_FLAG_IDLE;
case GSD_POWER_ACTION_HIBERNATE:
case GSD_POWER_ACTION_SUSPEND:
return GSM_INHIBITOR_FLAG_SUSPEND; /* in addition to idle */
case GSD_POWER_ACTION_NOTHING:
return 0;
case GSD_POWER_ACTION_LOGOUT:
return GSM_INHIBITOR_FLAG_LOGOUT; /* in addition to idle */
}
return 0;
}
static gboolean
is_action_inhibited (GsdPowerManager *manager, GsdPowerActionType action_type)
{
GsmInhibitorFlag flag;
gboolean is_inhibited;
flag = get_idle_inhibitors_for_action (action_type);
if (!flag)
return FALSE;
idle_is_session_inhibited (manager,
flag,
&is_inhibited);
return is_inhibited;
}
static gboolean
upower_kbd_get_brightness (GsdPowerManager *manager)
{
GVariant *k_now = NULL;
GError *error = NULL;
gint now;
k_now = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy,
"GetBrightness",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (k_now == NULL) {
if (error->domain != G_DBUS_ERROR ||
error->code != G_DBUS_ERROR_UNKNOWN_METHOD) {
g_warning ("Failed to get brightness: %s",
error->message);
}
g_error_free (error);
return -1;
}
g_variant_get (k_now, "(i)", &now);
g_variant_unref (k_now);
return now;
}
static gboolean
upower_kbd_set_brightness (GsdPowerManager *manager, guint value, GError **error)
{
GVariant *retval;
/* update h/w value */
retval = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy,
"SetBrightness",
g_variant_new ("(i)", (gint) value),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
error);
if (retval == NULL)
return FALSE;
g_variant_unref (retval);
return TRUE;
}
static int
upower_kbd_toggle (GsdPowerManager *manager,
GError **error)
{
gboolean ret;
int value = -1;
if (manager->priv->kbd_brightness_old >= 0) {
g_debug ("keyboard toggle off");
ret = upower_kbd_set_brightness (manager,
manager->priv->kbd_brightness_old,
error);
if (ret) {
/* succeeded, set to -1 since now no old value */
manager->priv->kbd_brightness_old = -1;
value = 0;
}
} else {
g_debug ("keyboard toggle on");
/* save the current value to restore later when untoggling */
manager->priv->kbd_brightness_old = upower_kbd_get_brightness (manager);
ret = upower_kbd_set_brightness (manager, 0, error);
if (!ret) {
/* failed, reset back to -1 */
manager->priv->kbd_brightness_old = -1;
} else {
value = 0;
}
}
if (ret)
return value;
return -1;
}
static gboolean
suspend_on_lid_close (GsdPowerManager *manager)
{
GsdXrandrBootBehaviour val;
if (manager->priv->inhibit_lid_switch_action)
return FALSE;
if (!external_monitor_is_connected (manager->priv->rr_screen))
return TRUE;
val = g_settings_get_enum (manager->priv->settings_xrandr, "default-monitors-setup");
return val == GSD_XRANDR_BOOT_BEHAVIOUR_DO_NOTHING;
}
static gboolean
inhibit_lid_switch_timer_cb (GsdPowerManager *manager)
{
if (suspend_on_lid_close (manager)) {
g_debug ("no external monitors for a while; uninhibiting lid close");
uninhibit_lid_switch (manager);
manager->priv->inhibit_lid_switch_timer_id = 0;
return G_SOURCE_REMOVE;
}
g_debug ("external monitor still there; trying again later");
return G_SOURCE_CONTINUE;
}
/* Sets up a timer to be triggered some seconds after closing the laptop lid
* when the laptop is *not* suspended for some reason. We'll check conditions
* again in the timeout handler to see if we can suspend then.
*/
static void
setup_inhibit_lid_switch_timer (GsdPowerManager *manager)
{
if (manager->priv->inhibit_lid_switch_timer_id != 0) {
g_debug ("lid close safety timer already set up");
return;
}
g_debug ("setting up lid close safety timer");
manager->priv->inhibit_lid_switch_timer_id = g_timeout_add_seconds (GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT,
(GSourceFunc) inhibit_lid_switch_timer_cb,
manager);
g_source_set_name_by_id (manager->priv->inhibit_lid_switch_timer_id, "[GsdPowerManager] lid close safety timer");
}
static void
restart_inhibit_lid_switch_timer (GsdPowerManager *manager)
{
if (manager->priv->inhibit_lid_switch_timer_id != 0) {
g_debug ("restarting lid close safety timer");
g_source_remove (manager->priv->inhibit_lid_switch_timer_id);
manager->priv->inhibit_lid_switch_timer_id = 0;
setup_inhibit_lid_switch_timer (manager);
}
}
static void
setup_lid_closed_action (GsdPowerManager *manager)
{
GsdPowerActionType policy;
if (up_client_get_on_battery (manager->priv->up_client)) {
policy = g_settings_get_enum (manager->priv->settings, "lid-close-battery-action");
} else {
policy = g_settings_get_enum (manager->priv->settings, "lid-close-ac-action");
}
if (policy == GSD_POWER_ACTION_NOTHING) {
inhibit_lid_switch (manager);
manager->priv->inhibit_lid_switch_action = TRUE;
} else {
uninhibit_lid_switch (manager);
manager->priv->inhibit_lid_switch_action = FALSE;
}
}
static void
do_lid_open_action (GsdPowerManager *manager)
{
/* play a sound, using sounds from the naming spec */
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "lid-open",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("Lid has been opened"),
NULL);
/* This might already have happened when resuming, but
* if we didn't sleep, we'll need to wake it up */
reset_idletime ();
}
static void
lock_screensaver (GsdPowerManager *manager)
{
gboolean do_lock;
do_lock = g_settings_get_boolean (manager->priv->settings_screensaver,
"lock-enabled");
if (!do_lock) {
g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver_proxy),
"SetActive",
g_variant_new ("(b)", TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
return;
}
g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver_proxy),
"Lock",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
}
static void
do_lid_closed_action (GsdPowerManager *manager)
{
/* play a sound, using sounds from the naming spec */
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "lid-close",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("Lid has been closed"),
NULL);
/* refresh RANDR so we get an accurate view of what monitors are plugged in when the lid is closed */
gsd_rr_screen_refresh (manager->priv->rr_screen, NULL); /* NULL-GError */
restart_inhibit_lid_switch_timer (manager);
if (suspend_on_lid_close (manager)) {
gboolean is_inhibited;
idle_is_session_inhibited (manager,
GSM_INHIBITOR_FLAG_SUSPEND,
&is_inhibited);
if (is_inhibited) {
g_debug ("Suspend is inhibited but lid is closed, locking the screen");
/* We put the screensaver on * as we're not suspending,
* but the lid is closed */
lock_screensaver (manager);
}
}
else {
if (manager->priv->inhibit_lid_switch_action)
lock_screensaver (manager);
}
}
static void
lid_state_changed_cb (UpClient *client, GParamSpec *pspec, GsdPowerManager *manager)
{
gboolean tmp;
if (!up_client_get_on_battery (client)) {
/* if we are playing a critical charge sound loop on AC, stop it */
play_loop_stop (&manager->priv->critical_alert_timeout_id);
notify_close_if_showing (&manager->priv->notification_low);
main_battery_or_ups_low_changed (manager, FALSE);
}
setup_lid_closed_action (manager);
/* same state */
tmp = up_client_get_lid_is_closed (manager->priv->up_client);
if (manager->priv->lid_is_closed == tmp)
return;
manager->priv->lid_is_closed = tmp;
g_debug ("up changed: lid is now %s", tmp ? "closed" : "open");
if (manager->priv->lid_is_closed)
do_lid_closed_action (manager);
else
do_lid_open_action (manager);
}
static const gchar *
idle_mode_to_string (GsdPowerIdleMode mode)
{
if (mode == GSD_POWER_IDLE_MODE_NORMAL)
return "normal";
if (mode == GSD_POWER_IDLE_MODE_DIM)
return "dim";
if (mode == GSD_POWER_IDLE_MODE_BLANK)
return "blank";
if (mode == GSD_POWER_IDLE_MODE_SLEEP)
return "sleep";
return "unknown";
}
static const char *
idle_watch_id_to_string (GsdPowerManager *manager, guint id)
{
if (id == manager->priv->idle_dim_id)
return "dim";
if (id == manager->priv->idle_blank_id)
return "blank";
if (id == manager->priv->idle_sleep_id)
return "sleep";
if (id == manager->priv->idle_sleep_warning_id)
return "sleep-warning";
return NULL;
}
static void
backlight_emit_changed (GsdPowerManager *manager)
{
gboolean ret;
GError *error = NULL;
/* not yet connected to the bus */
if (manager->priv->connection == NULL)
return;
ret = g_dbus_connection_emit_signal (manager->priv->connection,
NULL,
GSD_POWER_DBUS_PATH,
GSD_POWER_DBUS_INTERFACE_SCREEN,
"Changed",
NULL,
&error);
if (!ret) {
g_warning ("failed to emit Changed: %s", error->message);
g_error_free (error);
}
}
static gboolean
display_backlight_dim (GsdPowerManager *manager,
gint idle_percentage,
GError **error)
{
gint min;
gint max;
gint now;
gint idle;
gboolean ret = FALSE;
if (!manager->priv->backlight_available)
return TRUE;
now = backlight_get_abs (manager->priv->rr_screen, error);
if (now < 0) {
goto out;
}
/* is the dim brightness actually *dimmer* than the
* brightness we have now? */
min = backlight_get_min (manager->priv->rr_screen);
max = backlight_get_max (manager->priv->rr_screen, error);
if (max < 0) {
goto out;
}
idle = PERCENTAGE_TO_ABS (min, max, idle_percentage);
if (idle > now) {
g_debug ("brightness already now %i/%i, so "
"ignoring dim to %i/%i",
now, max, idle, max);
ret = TRUE;
goto out;
}
ret = backlight_set_abs (manager->priv->rr_screen,
idle,
error);
if (!ret) {
goto out;
}
/* save for undim */
manager->priv->pre_dim_brightness = now;
out:
return ret;
}
static gboolean
kbd_backlight_dim (GsdPowerManager *manager,
gint idle_percentage,
GError **error)
{
gboolean ret;
gint idle;
gint max;
gint now;
if (manager->priv->upower_kdb_proxy == NULL)
return TRUE;
now = upower_kbd_get_brightness (manager);
max = manager->priv->kbd_brightness_max;
idle = PERCENTAGE_TO_ABS (0, max, idle_percentage);
if (idle > now) {
g_debug ("kbd brightness already now %i/%i, so "
"ignoring dim to %i/%i",
now, max, idle, max);
return TRUE;
}
ret = upower_kbd_set_brightness (manager, idle, error);
if (!ret)
return FALSE;
/* save for undim */
manager->priv->kbd_brightness_pre_dim = now;
return TRUE;
}
static gboolean
is_session_active (GsdPowerManager *manager)
{
GVariant *variant;
gboolean is_session_active = FALSE;
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (manager->priv->session),
"SessionIsActive");
if (variant) {
is_session_active = g_variant_get_boolean (variant);
g_variant_unref (variant);
}
return is_session_active;
}
static void
idle_set_mode (GsdPowerManager *manager, GsdPowerIdleMode mode)
{
gboolean ret = FALSE;
GError *error = NULL;
gint idle_percentage;
GsdPowerActionType action_type;
gboolean is_active = FALSE;
/* Ignore attempts to set "less idle" modes */
if (mode <= manager->priv->current_idle_mode &&
mode != GSD_POWER_IDLE_MODE_NORMAL) {
g_debug ("Not going to 'less idle' mode %s (current: %s)",
idle_mode_to_string (mode),
idle_mode_to_string (manager->priv->current_idle_mode));
return;
}
/* ensure we're still on an active console */
is_active = is_session_active (manager);
if (!is_active) {
g_debug ("ignoring state transition to %s as inactive",
idle_mode_to_string (mode));
return;
}
/* don't do any power saving if we're a VM */
if (manager->priv->is_virtual_machine) {
g_debug ("ignoring state transition to %s as virtual machine",
idle_mode_to_string (mode));
return;
}
manager->priv->current_idle_mode = mode;
g_debug ("Doing a state transition: %s", idle_mode_to_string (mode));
/* if we're moving to an idle mode, make sure
* we add a watch to take us back to normal */
if (mode != GSD_POWER_IDLE_MODE_NORMAL) {
gsd_idle_monitor_add_user_active_watch (manager->priv->idle_monitor,
idle_became_active_cb,
manager,
NULL);
}
/* save current brightness, and set dim level */
if (mode == GSD_POWER_IDLE_MODE_DIM) {
/* display backlight */
idle_percentage = g_settings_get_int (manager->priv->settings,
"idle-brightness");
ret = display_backlight_dim (manager, idle_percentage, &error);
if (!ret) {
g_warning ("failed to set dim backlight to %i%%: %s",
idle_percentage,
error->message);
g_clear_error (&error);
}
/* keyboard backlight */
ret = kbd_backlight_dim (manager, idle_percentage, &error);
if (!ret) {
g_warning ("failed to set dim kbd backlight to %i%%: %s",
idle_percentage,
error->message);
g_clear_error (&error);
}
/* turn off screen and kbd */
} else if (mode == GSD_POWER_IDLE_MODE_BLANK) {
backlight_disable (manager);
/* only toggle keyboard if present and not already toggled */
if (manager->priv->upower_kdb_proxy &&
manager->priv->kbd_brightness_old == -1) {
if (upower_kbd_toggle (manager, &error) < 0) {
g_warning ("failed to turn the kbd backlight off: %s",
error->message);
g_error_free (error);
}
}
/* sleep */
} else if (mode == GSD_POWER_IDLE_MODE_SLEEP) {
if (up_client_get_on_battery (manager->priv->up_client)) {
action_type = g_settings_get_enum (manager->priv->settings,
"sleep-inactive-battery-type");
} else {
action_type = g_settings_get_enum (manager->priv->settings,
"sleep-inactive-ac-type");
}
do_power_action_type (manager, action_type);
/* turn on screen and restore user-selected brightness level */
} else if (mode == GSD_POWER_IDLE_MODE_NORMAL) {
backlight_enable (manager);
/* reset brightness if we dimmed */
if (manager->priv->pre_dim_brightness >= 0) {
ret = backlight_set_abs (manager->priv->rr_screen,
manager->priv->pre_dim_brightness,
&error);
if (!ret) {
g_warning ("failed to restore backlight to %i: %s",
manager->priv->pre_dim_brightness,
error->message);
g_clear_error (&error);
} else {
manager->priv->pre_dim_brightness = -1;
}
}
/* only toggle keyboard if present and already toggled off */
if (manager->priv->upower_kdb_proxy &&
manager->priv->kbd_brightness_old != -1) {
if (upower_kbd_toggle (manager, &error) < 0) {
g_warning ("failed to turn the kbd backlight on: %s",
error->message);
g_clear_error (&error);
}
}
/* reset kbd brightness if we dimmed */
if (manager->priv->kbd_brightness_pre_dim >= 0) {
ret = upower_kbd_set_brightness (manager,
manager->priv->kbd_brightness_pre_dim,
&error);
if (!ret) {
g_warning ("failed to restore kbd backlight to %i: %s",
manager->priv->kbd_brightness_pre_dim,
error->message);
g_error_free (error);
}
manager->priv->kbd_brightness_pre_dim = -1;
}
}
}
static gboolean
idle_is_session_inhibited (GsdPowerManager *manager,
GsmInhibitorFlag mask,
gboolean *is_inhibited)
{
GVariant *variant;
GsmInhibitorFlag inhibited_actions;
/* not yet connected to gnome-session */
if (manager->priv->session == NULL)
return FALSE;
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (manager->priv->session),
"InhibitedActions");
if (!variant)
return FALSE;
inhibited_actions = g_variant_get_uint32 (variant);
g_variant_unref (variant);
*is_inhibited = (inhibited_actions & mask);
return TRUE;
}
static void
clear_idle_watch (GsdIdleMonitor *monitor,
guint *id)
{
if (*id == 0)
return;
gsd_idle_monitor_remove_watch (monitor, *id);
*id = 0;
}
static void
idle_configure (GsdPowerManager *manager)
{
gboolean is_idle_inhibited;
GsdPowerActionType action_type;
guint timeout_blank;
guint timeout_sleep;
guint timeout_dim;
gboolean on_battery;
if (!idle_is_session_inhibited (manager,
GSM_INHIBITOR_FLAG_IDLE,
&is_idle_inhibited)) {
/* Session isn't available yet, postpone */
return;
}
/* are we inhibited from going idle */
if (!is_session_active (manager) || is_idle_inhibited) {
g_debug ("inhibited or inactive, so using normal state");
idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL);
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_blank_id);
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_sleep_id);
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_dim_id);
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_sleep_warning_id);
notify_close_if_showing (&manager->priv->notification_sleep_warning);
return;
}
/* set up blank callback only when the screensaver is on,
* as it's what will drive the blank */
on_battery = up_client_get_on_battery (manager->priv->up_client);
timeout_blank = 0;
if (manager->priv->screensaver_active) {
/* The tail is wagging the dog.
* The screensaver coming on will blank the screen.
* If an event occurs while the screensaver is on,
* the aggressive idle watch will handle it */
timeout_blank = SCREENSAVER_TIMEOUT_BLANK;
}
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_blank_id);
if (timeout_blank != 0) {
g_debug ("setting up blank callback for %is", timeout_blank);
manager->priv->idle_blank_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor,
timeout_blank * 1000,
idle_triggered_idle_cb, manager, NULL);
}
/* only do the sleep timeout when the session is idle
* and we aren't inhibited from sleeping (or logging out, etc.) */
action_type = g_settings_get_enum (manager->priv->settings, on_battery ?
"sleep-inactive-battery-type" : "sleep-inactive-ac-type");
timeout_sleep = 0;
if (!is_action_inhibited (manager, action_type)) {
timeout_sleep = g_settings_get_int (manager->priv->settings, on_battery ?
"sleep-inactive-battery-timeout" : "sleep-inactive-ac-timeout");
}
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_sleep_id);
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_sleep_warning_id);
if (timeout_sleep != 0) {
g_debug ("setting up sleep callback %is", timeout_sleep);
manager->priv->idle_sleep_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor,
timeout_sleep * 1000,
idle_triggered_idle_cb, manager, NULL);
if (action_type == GSD_POWER_ACTION_LOGOUT ||
action_type == GSD_POWER_ACTION_SUSPEND ||
action_type == GSD_POWER_ACTION_HIBERNATE) {
guint timeout_sleep_warning;
manager->priv->sleep_action_type = action_type;
timeout_sleep_warning = timeout_sleep * IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER;
if (timeout_sleep_warning < MINIMUM_IDLE_DIM_DELAY)
timeout_sleep_warning = 0;
g_debug ("setting up sleep warning callback %is", timeout_sleep_warning);
manager->priv->idle_sleep_warning_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor,
timeout_sleep_warning * 1000,
idle_triggered_idle_cb, manager, NULL);
}
}
if (manager->priv->idle_sleep_warning_id == 0)
notify_close_if_showing (&manager->priv->notification_sleep_warning);
/* set up dim callback for when the screen lock is not active,
* but only if we actually want to dim. */
timeout_dim = 0;
if (manager->priv->screensaver_active) {
/* Don't dim when the screen lock is active */
} else if (!on_battery) {
/* Don't dim when charging */
} else if (manager->priv->battery_is_low) {
/* Aggressively blank when battery is low */
timeout_dim = SCREENSAVER_TIMEOUT_BLANK;
} else {
if (g_settings_get_boolean (manager->priv->settings, "idle-dim")) {
timeout_dim = g_settings_get_uint (manager->priv->settings_bus,
"idle-delay");
if (timeout_dim == 0) {
timeout_dim = IDLE_DIM_BLANK_DISABLED_MIN;
} else {
timeout_dim *= IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER;
/* Don't bother dimming if the idle-delay is
* too low, we'll do that when we bring down the
* screen lock */
if (timeout_dim < MINIMUM_IDLE_DIM_DELAY)
timeout_dim = 0;
}
}
}
clear_idle_watch (manager->priv->idle_monitor,
&manager->priv->idle_dim_id);
if (timeout_dim != 0) {
g_debug ("setting up dim callback for %is", timeout_dim);
manager->priv->idle_dim_id = gsd_idle_monitor_add_idle_watch (manager->priv->idle_monitor,
timeout_dim * 1000,
idle_triggered_idle_cb, manager, NULL);
}
}
static void
main_battery_or_ups_low_changed (GsdPowerManager *manager,
gboolean is_low)
{
if (is_low == manager->priv->battery_is_low)
return;
manager->priv->battery_is_low = is_low;
idle_configure (manager);
}
static gboolean
temporary_unidle_done_cb (GsdPowerManager *manager)
{
idle_set_mode (manager, manager->priv->previous_idle_mode);
manager->priv->temporary_unidle_on_ac_id = 0;
return FALSE;
}
static void
set_temporary_unidle_on_ac (GsdPowerManager *manager,
gboolean enable)
{
if (!enable) {
if (manager->priv->temporary_unidle_on_ac_id != 0) {
g_source_remove (manager->priv->temporary_unidle_on_ac_id);
manager->priv->temporary_unidle_on_ac_id = 0;
idle_set_mode (manager, manager->priv->previous_idle_mode);
}
} else {
/* Don't overwrite the previous idle mode when an unidle is
* already on-going */
if (manager->priv->temporary_unidle_on_ac_id != 0) {
g_source_remove (manager->priv->temporary_unidle_on_ac_id);
} else {
manager->priv->previous_idle_mode = manager->priv->current_idle_mode;
idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL);
}
manager->priv->temporary_unidle_on_ac_id = g_timeout_add_seconds (POWER_UP_TIME_ON_AC,
(GSourceFunc) temporary_unidle_done_cb,
manager);
}
}
static void
up_client_on_battery_cb (UpClient *client,
GParamSpec *pspec,
GsdPowerManager *manager)
{
if (up_client_get_on_battery (manager->priv->up_client)) {
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "power-unplug",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("On battery power"), NULL);
} else {
ca_context_play (ca_gtk_context_get (), 0,
CA_PROP_EVENT_ID, "power-plug",
/* TRANSLATORS: this is the sound description */
CA_PROP_EVENT_DESCRIPTION, _("On AC power"), NULL);
}
idle_configure (manager);
if (manager->priv->lid_is_closed)
return;
if (manager->priv->current_idle_mode == GSD_POWER_IDLE_MODE_BLANK ||
manager->priv->current_idle_mode == GSD_POWER_IDLE_MODE_DIM ||
manager->priv->temporary_unidle_on_ac_id != 0)
set_temporary_unidle_on_ac (manager, TRUE);
}
static void
gsd_power_manager_finalize (GObject *object)
{
GsdPowerManager *manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_POWER_MANAGER (object));
manager = GSD_POWER_MANAGER (object);
g_return_if_fail (manager->priv != NULL);
g_clear_object (&manager->priv->connection);
if (manager->priv->name_id != 0)
g_bus_unown_name (manager->priv->name_id);
G_OBJECT_CLASS (gsd_power_manager_parent_class)->finalize (object);
}
static void
gsd_power_manager_class_init (GsdPowerManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_power_manager_finalize;
g_type_class_add_private (klass, sizeof (GsdPowerManagerPrivate));
}
static void
session_presence_proxy_ready_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
manager->priv->session_presence_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (manager->priv->session_presence_proxy == NULL) {
g_warning ("Could not connect to gnome-sesson: %s",
error->message);
g_error_free (error);
return;
}
}
static void
handle_screensaver_active (GsdPowerManager *manager,
GVariant *parameters)
{
gboolean active;
g_variant_get (parameters, "(b)", &active);
g_debug ("Received screensaver ActiveChanged signal: %d (old: %d)", active, manager->priv->screensaver_active);
if (manager->priv->screensaver_active != active) {
manager->priv->screensaver_active = active;
idle_configure (manager);
/* Setup blank as soon as the screensaver comes on,
* and its fade has finished.
*
* See also idle_configure() */
if (active)
idle_set_mode (manager, GSD_POWER_IDLE_MODE_BLANK);
}
}
static void
screensaver_signal_cb (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
if (g_strcmp0 (signal_name, "ActiveChanged") == 0)
handle_screensaver_active (GSD_POWER_MANAGER (user_data), parameters);
}
static void
power_keyboard_proxy_ready_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GVariant *k_max = NULL;
GError *error = NULL;
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
manager->priv->upower_kdb_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (manager->priv->upower_kdb_proxy == NULL) {
g_warning ("Could not connect to UPower: %s",
error->message);
g_error_free (error);
goto out;
}
k_max = g_dbus_proxy_call_sync (manager->priv->upower_kdb_proxy,
"GetMaxBrightness",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (k_max == NULL) {
if (error->domain != G_DBUS_ERROR ||
error->code != G_DBUS_ERROR_UNKNOWN_METHOD) {
g_warning ("Failed to get max brightness: %s",
error->message);
}
g_error_free (error);
goto out;
}
g_variant_get (k_max, "(i)", &manager->priv->kbd_brightness_max);
/* set brightness to max if not currently set so is something
* sensible */
if (upower_kbd_get_brightness (manager) < 0) {
gboolean ret;
ret = upower_kbd_set_brightness (manager,
manager->priv->kbd_brightness_max,
&error);
if (!ret) {
g_warning ("failed to initialize kbd backlight to %i: %s",
manager->priv->kbd_brightness_max,
error->message);
g_error_free (error);
}
}
out:
if (k_max != NULL)
g_variant_unref (k_max);
}
static void
show_sleep_warning (GsdPowerManager *manager)
{
/* close any existing notification of this class */
notify_close_if_showing (&manager->priv->notification_sleep_warning);
/* create a new notification */
switch (manager->priv->sleep_action_type) {
case GSD_POWER_ACTION_LOGOUT:
create_notification (_("Automatic logout"), _("You will soon log out because of inactivity."),
NULL,
&manager->priv->notification_sleep_warning);
break;
case GSD_POWER_ACTION_SUSPEND:
create_notification (_("Automatic suspend"), _("Computer will suspend very soon because of inactivity."),
NULL,
&manager->priv->notification_sleep_warning);
break;
case GSD_POWER_ACTION_HIBERNATE:
create_notification (_("Automatic hibernation"), _("Computer will suspend very soon because of inactivity."),
NULL,
&manager->priv->notification_sleep_warning);
break;
default:
g_assert_not_reached ();
break;
}
notify_notification_set_timeout (manager->priv->notification_sleep_warning,
NOTIFY_EXPIRES_DEFAULT);
notify_notification_set_urgency (manager->priv->notification_sleep_warning,
NOTIFY_URGENCY_CRITICAL);
notify_notification_set_app_name (manager->priv->notification_sleep_warning, _("Power"));
notify_notification_show (manager->priv->notification_sleep_warning, NULL);
if (manager->priv->sleep_action_type == GSD_POWER_ACTION_LOGOUT)
set_temporary_unidle_on_ac (manager, TRUE);
}
static void
idle_triggered_idle_cb (GsdIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
const char *id_name;
id_name = idle_watch_id_to_string (manager, watch_id);
if (id_name == NULL)
g_debug ("idletime watch: %i", watch_id);
else
g_debug ("idletime watch: %s (%i)", id_name, watch_id);
if (watch_id == manager->priv->idle_dim_id) {
idle_set_mode (manager, GSD_POWER_IDLE_MODE_DIM);
} else if (watch_id == manager->priv->idle_blank_id) {
idle_set_mode (manager, GSD_POWER_IDLE_MODE_BLANK);
} else if (watch_id == manager->priv->idle_sleep_id) {
idle_set_mode (manager, GSD_POWER_IDLE_MODE_SLEEP);
} else if (watch_id == manager->priv->idle_sleep_warning_id) {
show_sleep_warning (manager);
}
}
static void
idle_became_active_cb (GsdIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
g_debug ("idletime reset");
set_temporary_unidle_on_ac (manager, FALSE);
/* close any existing notification about idleness */
notify_close_if_showing (&manager->priv->notification_sleep_warning);
idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL);
}
static void
engine_settings_key_changed_cb (GSettings *settings,
const gchar *key,
GsdPowerManager *manager)
{
if (g_strcmp0 (key, "use-time-for-policy") == 0) {
manager->priv->use_time_primary = g_settings_get_boolean (settings, key);
return;
}
if (g_str_has_prefix (key, "sleep-inactive") ||
g_str_equal (key, "idle-delay") ||
g_str_equal (key, "idle-dim")) {
idle_configure (manager);
return;
}
if (g_str_has_prefix (key, "lid-close")) {
setup_lid_closed_action (manager);
return;
}
}
static void
engine_session_properties_changed_cb (GDBusProxy *session,
GVariant *changed,
char **invalidated,
GsdPowerManager *manager)
{
GVariant *v;
v = g_variant_lookup_value (changed, "SessionIsActive", G_VARIANT_TYPE_BOOLEAN);
if (v) {
gboolean active;
active = g_variant_get_boolean (v);
g_debug ("Received session is active change: now %s", active ? "active" : "inactive");
/* when doing the fast-user-switch into a new account,
* ensure the new account is undimmed and with the backlight on */
if (active)
idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL);
g_variant_unref (v);
}
v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32);
if (v) {
g_variant_unref (v);
g_debug ("Received gnome session inhibitor change");
idle_configure (manager);
}
}
static void
inhibit_lid_switch_done (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GDBusProxy *proxy = G_DBUS_PROXY (source);
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
GError *error = NULL;
GVariant *res;
GUnixFDList *fd_list = NULL;
gint idx;
res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
if (res == NULL) {
g_warning ("Unable to inhibit lid switch: %s", error->message);
g_error_free (error);
} else {
g_variant_get (res, "(h)", &idx);
manager->priv->inhibit_lid_switch_fd = g_unix_fd_list_get (fd_list, idx, &error);
if (manager->priv->inhibit_lid_switch_fd == -1) {
g_warning ("Failed to receive system inhibitor fd: %s", error->message);
g_error_free (error);
}
g_debug ("System inhibitor fd is %d", manager->priv->inhibit_lid_switch_fd);
g_object_unref (fd_list);
g_variant_unref (res);
}
}
static void
inhibit_lid_switch (GsdPowerManager *manager)
{
GVariant *params;
if (manager->priv->inhibit_lid_switch_taken) {
g_debug ("already inhibited lid-switch");
return;
}
g_debug ("Adding lid switch system inhibitor");
manager->priv->inhibit_lid_switch_taken = TRUE;
params = g_variant_new ("(ssss)",
"handle-lid-switch",
g_get_user_name (),
"Multiple displays attached",
"block");
g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
"Inhibit",
params,
0,
G_MAXINT,
NULL,
NULL,
inhibit_lid_switch_done,
manager);
}
static void
uninhibit_lid_switch (GsdPowerManager *manager)
{
if (manager->priv->inhibit_lid_switch_fd == -1) {
g_debug ("no lid-switch inhibitor");
return;
}
g_debug ("Removing lid switch system inhibitor");
close (manager->priv->inhibit_lid_switch_fd);
manager->priv->inhibit_lid_switch_fd = -1;
manager->priv->inhibit_lid_switch_taken = FALSE;
}
static void
inhibit_suspend_done (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GDBusProxy *proxy = G_DBUS_PROXY (source);
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
GError *error = NULL;
GVariant *res;
GUnixFDList *fd_list = NULL;
gint idx;
res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
if (res == NULL) {
g_warning ("Unable to inhibit suspend: %s", error->message);
g_error_free (error);
} else {
g_variant_get (res, "(h)", &idx);
manager->priv->inhibit_suspend_fd = g_unix_fd_list_get (fd_list, idx, &error);
if (manager->priv->inhibit_suspend_fd == -1) {
g_warning ("Failed to receive system inhibitor fd: %s", error->message);
g_error_free (error);
}
g_debug ("System inhibitor fd is %d", manager->priv->inhibit_suspend_fd);
g_object_unref (fd_list);
g_variant_unref (res);
}
}
/* We take a delay inhibitor here, which causes logind to send a
* PrepareForSleep signal, which gives us a chance to lock the screen
* and do some other preparations.
*/
static void
inhibit_suspend (GsdPowerManager *manager)
{
if (manager->priv->inhibit_suspend_taken) {
g_debug ("already inhibited lid-switch");
return;
}
g_debug ("Adding suspend delay inhibitor");
manager->priv->inhibit_suspend_taken = TRUE;
g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
"Inhibit",
g_variant_new ("(ssss)",
"sleep",
g_get_user_name (),
"GNOME needs to lock the screen",
"delay"),
0,
G_MAXINT,
NULL,
NULL,
inhibit_suspend_done,
manager);
}
static void
uninhibit_suspend (GsdPowerManager *manager)
{
if (manager->priv->inhibit_suspend_fd == -1) {
g_debug ("no suspend delay inhibitor");
return;
}
g_debug ("Removing suspend delay inhibitor");
close (manager->priv->inhibit_suspend_fd);
manager->priv->inhibit_suspend_fd = -1;
manager->priv->inhibit_suspend_taken = FALSE;
}
static void
on_randr_event (GsdRRScreen *screen, gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
if (suspend_on_lid_close (manager)) {
restart_inhibit_lid_switch_timer (manager);
return;
}
/* when a second monitor is plugged in, we take the
* handle-lid-switch inhibitor lock of logind to prevent
* it from suspending.
*
* Uninhibiting is done in the inhibit_lid_switch_timer,
* since we want to give users a few seconds when unplugging
* and replugging an external monitor, not suspend right away.
*/
inhibit_lid_switch (manager);
setup_inhibit_lid_switch_timer (manager);
}
#ifdef GSD_MOCK
static gboolean
received_sigusr2 (GsdPowerManager *manager)
{
on_randr_event (NULL, manager);
return TRUE;
}
#endif /* GSD_MOCK */
static void
handle_suspend_actions (GsdPowerManager *manager)
{
backlight_disable (manager);
uninhibit_suspend (manager);
}
static void
handle_resume_actions (GsdPowerManager *manager)
{
/* close existing notifications on resume, the system power
* state is probably different now */
notify_close_if_showing (&manager->priv->notification_low);
notify_close_if_showing (&manager->priv->notification_ups_discharging);
main_battery_or_ups_low_changed (manager, FALSE);
/* ensure we turn the panel back on after resume */
backlight_enable (manager);
/* And work-around Xorg bug:
* https://bugs.freedesktop.org/show_bug.cgi?id=59576 */
reset_idletime ();
/* set up the delay again */
inhibit_suspend (manager);
}
static void
logind_proxy_signal_cb (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
gboolean is_about_to_suspend;
if (g_strcmp0 (signal_name, "PrepareForSleep") != 0)
return;
g_variant_get (parameters, "(b)", &is_about_to_suspend);
if (is_about_to_suspend) {
handle_suspend_actions (manager);
} else {
handle_resume_actions (manager);
}
}
gboolean
gsd_power_manager_start (GsdPowerManager *manager,
GError **error)
{
g_debug ("Starting power manager");
gnome_settings_profile_start (NULL);
/* coldplug the list of screens */
manager->priv->rr_screen = gsd_rr_screen_new (gdk_screen_get_default (), error);
if (manager->priv->rr_screen == NULL) {
g_debug ("Couldn't detect any screens, disabling plugin");
return FALSE;
}
/* Check for XTEST support */
if (supports_xtest () == FALSE) {
g_debug ("XTEST extension required, disabling plugin");
return FALSE;
}
/* Set up the logind proxy */
manager->priv->logind_proxy =
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
0,
NULL,
SYSTEMD_DBUS_NAME,
SYSTEMD_DBUS_PATH,
SYSTEMD_DBUS_INTERFACE,
NULL,
error);
if (manager->priv->logind_proxy == NULL) {
g_debug ("No systemd (logind) support, disabling plugin");
return FALSE;
}
g_signal_connect (manager->priv->logind_proxy, "g-signal",
G_CALLBACK (logind_proxy_signal_cb),
manager);
/* Set up a delay inhibitor to be informed about suspend attempts */
inhibit_suspend (manager);
/* track the active session */
manager->priv->session = gnome_settings_bus_get_session_proxy ();
g_signal_connect (manager->priv->session, "g-properties-changed",
G_CALLBACK (engine_session_properties_changed_cb),
manager);
manager->priv->screensaver_proxy = gnome_settings_bus_get_screen_saver_proxy ();
g_signal_connect (manager->priv->screensaver_proxy, "g-signal",
G_CALLBACK (screensaver_signal_cb), manager);
manager->priv->kbd_brightness_old = -1;
manager->priv->kbd_brightness_pre_dim = -1;
manager->priv->pre_dim_brightness = -1;
manager->priv->settings = g_settings_new (GSD_POWER_SETTINGS_SCHEMA);
g_signal_connect (manager->priv->settings, "changed",
G_CALLBACK (engine_settings_key_changed_cb), manager);
manager->priv->settings_screensaver = g_settings_new ("org.gnome.desktop.screensaver");
manager->priv->settings_bus = g_settings_new ("org.gnome.desktop.session");
g_signal_connect (manager->priv->settings_bus, "changed",
G_CALLBACK (engine_settings_key_changed_cb), manager);
manager->priv->settings_xrandr = g_settings_new (GSD_XRANDR_SETTINGS_SCHEMA);
manager->priv->up_client = up_client_new ();
manager->priv->lid_is_closed = up_client_get_lid_is_closed (manager->priv->up_client);
g_signal_connect (manager->priv->up_client, "device-added",
G_CALLBACK (engine_device_added_cb), manager);
g_signal_connect (manager->priv->up_client, "device-removed",
G_CALLBACK (engine_device_removed_cb), manager);
g_signal_connect_after (manager->priv->up_client, "notify::lid-is-closed",
G_CALLBACK (lid_state_changed_cb), manager);
g_signal_connect (manager->priv->up_client, "notify::on-battery",
G_CALLBACK (up_client_on_battery_cb), manager);
g_signal_connect_after (manager->priv->up_client, "notify::on-battery",
G_CALLBACK (lid_state_changed_cb), manager);
/* connect to UPower for keyboard backlight control */
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
UPOWER_DBUS_NAME,
UPOWER_DBUS_PATH_KBDBACKLIGHT,
UPOWER_DBUS_INTERFACE_KBDBACKLIGHT,
NULL,
power_keyboard_proxy_ready_cb,
manager);
/* connect to the session */
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
0,
NULL,
GNOME_SESSION_DBUS_NAME,
GNOME_SESSION_DBUS_PATH_PRESENCE,
GNOME_SESSION_DBUS_INTERFACE_PRESENCE,
NULL,
session_presence_proxy_ready_cb,
manager);
manager->priv->devices_array = g_ptr_array_new_with_free_func (g_object_unref);
/* create a fake virtual composite battery */
manager->priv->device_composite = up_device_new ();
g_object_set (manager->priv->device_composite,
"kind", UP_DEVICE_KIND_BATTERY,
"is-rechargeable", TRUE,
"native-path", "dummy:composite_battery",
"power-supply", TRUE,
"is-present", TRUE,
NULL);
/* get percentage policy */
manager->priv->low_percentage = g_settings_get_int (manager->priv->settings,
"percentage-low");
manager->priv->critical_percentage = g_settings_get_int (manager->priv->settings,
"percentage-critical");
manager->priv->action_percentage = g_settings_get_int (manager->priv->settings,
"percentage-action");
/* get time policy */
manager->priv->low_time = g_settings_get_int (manager->priv->settings,
"time-low");
manager->priv->critical_time = g_settings_get_int (manager->priv->settings,
"time-critical");
manager->priv->action_time = g_settings_get_int (manager->priv->settings,
"time-action");
/* we can disable this if the time remaining is inaccurate or just plain wrong */
manager->priv->use_time_primary = g_settings_get_boolean (manager->priv->settings,
"use-time-for-policy");
/* create IDLETIME watcher */
manager->priv->idle_monitor = g_object_ref (gsd_idle_monitor_get_core ());
/* set up the screens */
g_signal_connect (manager->priv->rr_screen, "changed", G_CALLBACK (on_randr_event), manager);
on_randr_event (manager->priv->rr_screen, manager);
#ifdef GSD_MOCK
g_unix_signal_add (SIGUSR2, (GSourceFunc) received_sigusr2, manager);
#endif /* GSD_MOCK */
/* check whether a backlight is available */
manager->priv->backlight_available = backlight_available (manager->priv->rr_screen);
/* ensure the default dpms timeouts are cleared */
backlight_enable (manager);
/* coldplug the engine */
engine_coldplug (manager);
idle_configure (manager);
manager->priv->xscreensaver_watchdog_timer_id = gsd_power_enable_screensaver_watchdog ();
/* don't blank inside a VM */
manager->priv->is_virtual_machine = gsd_power_is_hardware_a_vm ();
setup_lid_closed_action (manager);
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_power_manager_stop (GsdPowerManager *manager)
{
GPtrArray *devices;
int i;
g_debug ("Stopping power manager");
if (manager->priv->inhibit_lid_switch_timer_id != 0) {
g_source_remove (manager->priv->inhibit_lid_switch_timer_id);
manager->priv->inhibit_lid_switch_timer_id = 0;
}
if (manager->priv->bus_cancellable != NULL) {
g_cancellable_cancel (manager->priv->bus_cancellable);
g_object_unref (manager->priv->bus_cancellable);
manager->priv->bus_cancellable = NULL;
}
if (manager->priv->introspection_data) {
g_dbus_node_info_unref (manager->priv->introspection_data);
manager->priv->introspection_data = NULL;
}
g_signal_handlers_disconnect_by_data (manager->priv->up_client, manager);
g_clear_object (&manager->priv->session);
g_clear_object (&manager->priv->settings);
g_clear_object (&manager->priv->settings_screensaver);
g_clear_object (&manager->priv->settings_bus);
g_clear_object (&manager->priv->up_client);
if (manager->priv->inhibit_lid_switch_fd != -1) {
close (manager->priv->inhibit_lid_switch_fd);
manager->priv->inhibit_lid_switch_fd = -1;
manager->priv->inhibit_lid_switch_taken = FALSE;
manager->priv->inhibit_lid_switch_action = FALSE;
}
if (manager->priv->inhibit_suspend_fd != -1) {
close (manager->priv->inhibit_suspend_fd);
manager->priv->inhibit_suspend_fd = -1;
manager->priv->inhibit_suspend_taken = FALSE;
}
g_clear_object (&manager->priv->logind_proxy);
if (manager->priv->rr_screen) {
g_signal_handlers_disconnect_by_data (manager->priv->rr_screen, manager);
g_clear_object (&manager->priv->rr_screen);
}
devices = manager->priv->devices_array;
if (devices != NULL) {
for (i = 0; i < devices->len; i++)
g_signal_handlers_disconnect_by_data (g_ptr_array_index (devices, i), manager);
g_ptr_array_unref (devices);
manager->priv->devices_array = NULL;
}
g_clear_object (&manager->priv->device_composite);
g_clear_object (&manager->priv->previous_icon);
g_clear_pointer (&manager->priv->previous_summary, g_free);
g_clear_object (&manager->priv->session_presence_proxy);
g_clear_object (&manager->priv->screensaver_proxy);
play_loop_stop (&manager->priv->critical_alert_timeout_id);
g_clear_object (&manager->priv->idle_monitor);
if (manager->priv->xscreensaver_watchdog_timer_id > 0) {
g_source_remove (manager->priv->xscreensaver_watchdog_timer_id);
manager->priv->xscreensaver_watchdog_timer_id = 0;
}
}
static void
gsd_power_manager_init (GsdPowerManager *manager)
{
manager->priv = GSD_POWER_MANAGER_GET_PRIVATE (manager);
manager->priv->inhibit_lid_switch_fd = -1;
manager->priv->inhibit_suspend_fd = -1;
manager->priv->inhibit_lid_switch_action = FALSE;
manager->priv->bus_cancellable = g_cancellable_new ();
}
/* returns new level */
static void
handle_method_call_keyboard (GsdPowerManager *manager,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
gint now;
gint step;
gint value = -1;
gboolean ret;
guint percentage;
GError *error = NULL;
if (g_strcmp0 (method_name, "StepUp") == 0) {
g_debug ("keyboard step up");
now = upower_kbd_get_brightness (manager);
step = BRIGHTNESS_STEP_AMOUNT (manager->priv->kbd_brightness_max);
value = MIN (now + step,
manager->priv->kbd_brightness_max);
ret = upower_kbd_set_brightness (manager, value, &error);
} else if (g_strcmp0 (method_name, "StepDown") == 0) {
g_debug ("keyboard step down");
now = upower_kbd_get_brightness (manager);
step = BRIGHTNESS_STEP_AMOUNT (manager->priv->kbd_brightness_max);
value = MAX (now - step, 0);
ret = upower_kbd_set_brightness (manager, value, &error);
} else if (g_strcmp0 (method_name, "Toggle") == 0) {
value = upower_kbd_toggle (manager, &error);
ret = (value >= 0);
} else {
g_assert_not_reached ();
}
/* return value */
if (!ret) {
g_dbus_method_invocation_take_error (invocation,
error);
} else {
percentage = ABS_TO_PERCENTAGE (0,
manager->priv->kbd_brightness_max,
value);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(u)",
percentage));
}
}
static void
handle_method_call_screen (GsdPowerManager *manager,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
gboolean ret = FALSE;
gint value = -1;
guint value_tmp;
GError *error = NULL;
if (!manager->priv->backlight_available) {
g_set_error_literal (&error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"Screen backlight not available");
goto out;
}
if (g_strcmp0 (method_name, "GetPercentage") == 0) {
g_debug ("screen get percentage");
value = backlight_get_percentage (manager->priv->rr_screen, &error);
} else if (g_strcmp0 (method_name, "SetPercentage") == 0) {
g_debug ("screen set percentage");
g_variant_get (parameters, "(u)", &value_tmp);
ret = backlight_set_percentage (manager->priv->rr_screen, value_tmp, &error);
if (ret) {
value = value_tmp;
backlight_emit_changed (manager);
}
} else if (g_strcmp0 (method_name, "StepUp") == 0) {
g_debug ("screen step up");
value = backlight_step_up (manager->priv->rr_screen, &error);
if (value != -1)
backlight_emit_changed (manager);
} else if (g_strcmp0 (method_name, "StepDown") == 0) {
g_debug ("screen step down");
value = backlight_step_down (manager->priv->rr_screen, &error);
if (value != -1)
backlight_emit_changed (manager);
} else {
g_assert_not_reached ();
}
out:
/* return value */
if (value < 0) {
g_dbus_method_invocation_take_error (invocation,
error);
} else {
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(u)",
value));
}
}
static GVariant *
device_to_variant_blob (UpDevice *device)
{
const gchar *object_path;
gchar *device_icon;
gdouble percentage;
GIcon *icon;
guint64 time_empty, time_full;
guint64 time_state = 0;
GVariant *value;
UpDeviceKind kind;
UpDeviceState state;
icon = gpm_upower_get_device_icon (device, TRUE);
device_icon = g_icon_to_string (icon);
g_object_get (device,
"kind", &kind,
"percentage", &percentage,
"state", &state,
"time-to-empty", &time_empty,
"time-to-full", &time_full,
NULL);
/* only return time for these simple states */
if (state == UP_DEVICE_STATE_DISCHARGING)
time_state = time_empty;
else if (state == UP_DEVICE_STATE_CHARGING)
time_state = time_full;
/* get an object path, even for the composite device */
object_path = up_device_get_object_path (device);
if (object_path == NULL)
object_path = GSD_DBUS_PATH;
/* format complex object */
value = g_variant_new ("(susdut)",
object_path,
kind,
device_icon,
percentage,
state,
time_state);
g_free (device_icon);
g_object_unref (icon);
return value;
}
static void
handle_method_call_main (GsdPowerManager *manager,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
GPtrArray *array;
guint i;
GVariantBuilder *builder;
GVariant *tuple = NULL;
GVariant *value = NULL;
UpDevice *device;
/* return object */
if (g_strcmp0 (method_name, "GetPrimaryDevice") == 0) {
/* get the virtual device */
device = engine_get_primary_device (manager);
if (device == NULL) {
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gnome.SettingsDaemon.Power.Failed",
"There is no primary device.");
return;
}
/* return the value */
value = device_to_variant_blob (device);
tuple = g_variant_new_tuple (&value, 1);
g_dbus_method_invocation_return_value (invocation, tuple);
g_object_unref (device);
return;
}
/* return array */
if (g_strcmp0 (method_name, "GetDevices") == 0) {
/* create builder */
builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)"));
/* add each tuple to the array */
array = manager->priv->devices_array;
for (i=0; ilen; i++) {
device = g_ptr_array_index (array, i);
value = device_to_variant_blob (device);
g_variant_builder_add_value (builder, value);
}
/* return the value */
value = g_variant_builder_end (builder);
tuple = g_variant_new_tuple (&value, 1);
g_dbus_method_invocation_return_value (invocation, tuple);
g_variant_builder_unref (builder);
return;
}
g_assert_not_reached ();
}
static void
handle_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
/* Check session pointer as a proxy for whether the manager is in the
start or stop state */
if (manager->priv->session == NULL) {
return;
}
g_debug ("Calling method '%s.%s' for Power",
interface_name, method_name);
if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE) == 0) {
handle_method_call_main (manager,
method_name,
parameters,
invocation);
} else if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE_SCREEN) == 0) {
handle_method_call_screen (manager,
method_name,
parameters,
invocation);
} else if (g_strcmp0 (interface_name, GSD_POWER_DBUS_INTERFACE_KEYBOARD) == 0) {
handle_method_call_keyboard (manager,
method_name,
parameters,
invocation);
} else {
g_warning ("not recognised interface: %s", interface_name);
}
}
static GVariant *
handle_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error, gpointer user_data)
{
GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
GVariant *retval = NULL;
/* Check session pointer as a proxy for whether the manager is in the
start or stop state */
if (manager->priv->session == NULL) {
return NULL;
}
if (g_strcmp0 (property_name, "Icon") == 0) {
retval = engine_get_icon_property_variant (manager);
} else if (g_strcmp0 (property_name, "Tooltip") == 0) {
retval = engine_get_tooltip_property_variant (manager);
} else if (g_strcmp0 (property_name, "Percentage") == 0) {
gdouble percentage;
percentage = engine_get_percentage (manager);
if (percentage >= 0)
retval = g_variant_new_double (percentage);
}
return retval;
}
static const GDBusInterfaceVTable interface_vtable =
{
handle_method_call,
handle_get_property,
NULL, /* SetProperty */
};
static void
on_bus_gotten (GObject *source_object,
GAsyncResult *res,
GsdPowerManager *manager)
{
GDBusConnection *connection;
GDBusInterfaceInfo **infos;
GError *error = NULL;
guint i;
connection = g_bus_get_finish (res, &error);
if (connection == NULL) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Could not get session bus: %s", error->message);
g_error_free (error);
return;
}
manager->priv->connection = connection;
infos = manager->priv->introspection_data->interfaces;
for (i = 0; infos[i] != NULL; i++) {
g_dbus_connection_register_object (connection,
GSD_POWER_DBUS_PATH,
infos[i],
&interface_vtable,
manager,
NULL,
NULL);
}
manager->priv->name_id = g_bus_own_name_on_connection (connection,
GSD_POWER_DBUS_NAME,
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
NULL,
NULL,
NULL);
}
static void
register_manager_dbus (GsdPowerManager *manager)
{
manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
g_assert (manager->priv->introspection_data != NULL);
g_bus_get (G_BUS_TYPE_SESSION,
manager->priv->bus_cancellable,
(GAsyncReadyCallback) on_bus_gotten,
manager);
}
GsdPowerManager *
gsd_power_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_POWER_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
register_manager_dbus (manager_object);
}
return GSD_POWER_MANAGER (manager_object);
}
./plugins/power/gsd-power-manager.h 0000644 0000041 0000041 00000004672 13264221014 017554 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_POWER_MANAGER_H
#define __GSD_POWER_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_POWER_MANAGER (gsd_power_manager_get_type ())
#define GSD_POWER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManager))
#define GSD_POWER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_POWER_MANAGER, GsdPowerManagerClass))
#define GSD_IS_POWER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_POWER_MANAGER))
#define GSD_IS_POWER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_POWER_MANAGER))
#define GSD_POWER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_POWER_MANAGER, GsdPowerManagerClass))
#define GSD_POWER_MANAGER_ERROR (gsd_power_manager_error_quark ())
typedef struct GsdPowerManagerPrivate GsdPowerManagerPrivate;
typedef struct
{
GObject parent;
GsdPowerManagerPrivate *priv;
} GsdPowerManager;
typedef struct
{
GObjectClass parent_class;
} GsdPowerManagerClass;
enum
{
GSD_POWER_MANAGER_ERROR_FAILED
};
GType gsd_power_manager_get_type (void);
GQuark gsd_power_manager_error_quark (void);
GsdPowerManager * gsd_power_manager_new (void);
gboolean gsd_power_manager_start (GsdPowerManager *manager,
GError **error);
void gsd_power_manager_stop (GsdPowerManager *manager);
G_END_DECLS
#endif /* __GSD_POWER_MANAGER_H */
./plugins/power/gsd-power-constants.h 0000644 0000041 0000041 00000003305 13264221014 020146 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2013 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/* The blank delay when the screensaver is active */
#define SCREENSAVER_TIMEOUT_BLANK 15 /* seconds */
/* The dim delay when dimming on idle is requested but idle-delay
* is set to "Never" */
#define IDLE_DIM_BLANK_DISABLED_MIN 60 /* seconds */
/* Which fraction of the idle-delay is the idle-dim delay */
#define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 4.0/5.0
/* The dim delay under which we do not bother dimming */
#define MINIMUM_IDLE_DIM_DELAY 10 /* seconds */
/* The amount of time we'll undim if the machine is idle when plugged in */
#define POWER_UP_TIME_ON_AC 15 /* seconds */
/* Default brightness values for the mock backlight used in the test suite */
#define GSD_MOCK_DEFAULT_BRIGHTNESS 50
#define GSD_MOCK_MAX_BRIGHTNESS 100
./plugins/power/gsd-power-plugin.c 0000644 0000041 0000041 00000002015 13264221014 017420 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-power-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdPower, gsd_power)
./plugins/power/gsd-backlight-linux.c 0000644 0000041 0000041 00000004541 13264221014 020063 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#include
#include "config.h"
#include "gsd-backlight-linux.h"
#ifdef HAVE_GUDEV
#include
static gchar *
gsd_backlight_helper_get_type (GList *devices, const gchar *type)
{
const gchar *type_tmp;
GList *d;
for (d = devices; d != NULL; d = d->next) {
type_tmp = g_udev_device_get_sysfs_attr (d->data, "type");
if (g_strcmp0 (type_tmp, type) == 0)
return g_strdup (g_udev_device_get_sysfs_path (d->data));
}
return NULL;
}
#endif /* HAVE_GUDEV */
char *
gsd_backlight_helper_get_best_backlight (GsdBacklightType *type)
{
#ifdef HAVE_GUDEV
gchar *path = NULL;
GList *devices;
GUdevClient *client;
client = g_udev_client_new (NULL);
devices = g_udev_client_query_by_subsystem (client, "backlight");
if (devices == NULL)
goto out;
/* search the backlight devices and prefer the types:
* firmware -> platform -> raw */
path = gsd_backlight_helper_get_type (devices, "firmware");
if (path != NULL) {
if (type)
*type = GSD_BACKLIGHT_TYPE_FIRMWARE;
goto out;
}
path = gsd_backlight_helper_get_type (devices, "platform");
if (path != NULL) {
if (type)
*type = GSD_BACKLIGHT_TYPE_PLATFORM;
goto out;
}
path = gsd_backlight_helper_get_type (devices, "raw");
if (path != NULL) {
if (type)
*type = GSD_BACKLIGHT_TYPE_RAW;
goto out;
}
out:
g_object_unref (client);
g_list_foreach (devices, (GFunc) g_object_unref, NULL);
g_list_free (devices);
return path;
#endif /* HAVE_GUDEV */
return NULL;
}
./plugins/power/com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in 0000644 0000041 0000041 00000002230 13264221014 027463 0 ustar www-data www-data
Unity Settings Daemon
http://git.gnome.org/browse/gnome-settings-daemon
battery
<_description>Modify the laptop brightness
<_message>Authentication is required to modify the laptop brightness
no
no
yes
@libexecdir@/usd-backlight-helper
./plugins/power/gsd-power-enums-update.c 0000644 0000041 0000041 00000001606 13264221014 020536 0 ustar www-data www-data #include
#include
static void
output_enum_values (GType class_type)
{
GEnumClass *eclass;
guint i;
eclass = G_ENUM_CLASS (g_type_class_peek (class_type));
for (i = 0; i < eclass->n_values; i++) {
GEnumValue *value = &(eclass->values[i]);
g_print ("%s = %d;\n", value->value_name, value->value);
}
}
static void
output_flags_values (GType class_type)
{
GFlagsClass *fclass;
guint i;
fclass = G_FLAGS_CLASS (g_type_class_peek (class_type));
for (i = 0; i < fclass->n_values; i++) {
GFlagsValue *value = &(fclass->values[i]);
g_print ("%s = %d;\n", value->value_name, value->value);
}
}
int
main (int argc, char **argv)
{
g_type_class_ref (GSD_POWER_TYPE_INHIBITOR_FLAG);
g_type_class_ref (GSD_POWER_TYPE_PRESENCE_STATUS);
output_flags_values (GSD_POWER_TYPE_INHIBITOR_FLAG);
output_enum_values (GSD_POWER_TYPE_PRESENCE_STATUS);
return 0;
}
./plugins/power/test.py 0000755 0000041 0000041 00000066161 13264221014 015421 0 ustar www-data www-data #!/usr/bin/env python
'''GNOME settings daemon tests for power plugin.'''
__author__ = 'Martin Pitt '
__copyright__ = '(C) 2013 Canonical Ltd.'
__license__ = 'GPL v2 or later'
import unittest
import subprocess
import sys
import time
import os
import os.path
import signal
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
builddir = os.environ.get('BUILDDIR', os.path.dirname(__file__))
sys.path.insert(0, os.path.join(project_root, 'tests'))
sys.path.insert(0, builddir)
import gsdtestcase
import gsdpowerconstants
import gsdpowerenums
import dbus
from gi.repository import Gio
class PowerPluginTest(gsdtestcase.GSDTestCase):
'''Test the power plugin'''
def setUp(self):
self.daemon_death_expected = False
self.session_log_write = open(os.path.join(self.workdir, 'gnome-session.log'), 'wb')
self.session = subprocess.Popen(['gnome-session', '-f',
'-a', os.path.join(self.workdir, 'autostart'),
'--session=dummy', '--debug'],
stdout=self.session_log_write,
stderr=subprocess.STDOUT)
# wait until the daemon is on the bus
try:
self.wait_for_bus_object('org.gnome.SessionManager',
'/org/gnome/SessionManager')
except:
# on failure, print log
with open(self.session_log_write.name) as f:
print('----- session log -----\n%s\n------' % f.read())
raise
self.session_log = open(self.session_log_write.name)
self.obj_session_mgr = self.session_bus_con.get_object(
'org.gnome.SessionManager', '/org/gnome/SessionManager')
# start mock upowerd
(self.upowerd, self.obj_upower) = self.spawn_server_template(
'upower', {'OnBattery': True, 'LidIsClosed': False}, stdout=subprocess.PIPE)
gsdtestcase.set_nonblock(self.upowerd.stdout)
# start mock gnome-shell screensaver
(self.screensaver, self.obj_screensaver) = self.spawn_server_template(
'gnome_screensaver', stdout=subprocess.PIPE)
gsdtestcase.set_nonblock(self.screensaver.stdout)
self.start_logind()
# Set up the gnome-session presence
obj_session_presence = self.session_bus_con.get_object(
'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence')
self.obj_session_presence_props = dbus.Interface(obj_session_presence, dbus.PROPERTIES_IFACE)
# ensure that our tests don't lock the screen when the screensaver
# gets active
self.settings_screensaver = Gio.Settings('org.gnome.desktop.screensaver')
self.settings_screensaver['lock-enabled'] = False
self.settings_gsd_power = Gio.Settings('org.gnome.settings-daemon.plugins.power')
# start power plugin
self.settings_gsd_power['active'] = False
Gio.Settings.sync()
self.plugin_log_write = open(os.path.join(self.workdir, 'plugin_power.log'), 'wb')
# avoid painfully long delays of actions for tests
env = os.environ.copy()
env['GSD_DISABLE_BACKLIGHT_HELPER'] = '1'
self.daemon = subprocess.Popen(
[os.path.join(builddir, 'usd-test-power')],
# comment out this line if you want to see the logs in real time
stdout=self.plugin_log_write,
stderr=subprocess.STDOUT,
env=env)
# you can use this for reading the current daemon log in tests
self.plugin_log = open(self.plugin_log_write.name)
# wait until plugin is ready
timeout = 100
while timeout > 0:
time.sleep(0.1)
timeout -= 1
log = self.plugin_log.read()
if 'System inhibitor fd is' in log:
break
# always start with zero idle time
self.reset_idle_timer()
# flush notification log
try:
self.p_notify.stdout.read()
except IOError:
pass
def tearDown(self):
daemon_running = self.daemon.poll() == None
if daemon_running:
self.daemon.terminate()
self.daemon.wait()
self.plugin_log.close()
self.plugin_log_write.flush()
self.plugin_log_write.close()
self.upowerd.terminate()
self.upowerd.wait()
self.screensaver.terminate()
self.screensaver.wait()
self.stop_session()
self.stop_logind()
# reset all changed gsettings, so that tests are independent from each
# other
for schema in [self.settings_gsd_power, self.settings_session, self.settings_screensaver]:
for k in schema.list_keys():
schema.reset(k)
Gio.Settings.sync()
try:
os.unlink('GSD_MOCK_EXTERNAL_MONITOR')
except OSError:
pass
try:
os.unlink('GSD_MOCK_brightness')
except OSError:
pass
# we check this at the end so that the other cleanup always happens
self.assertTrue(daemon_running or self.daemon_death_expected, 'daemon died during the test')
def stop_session(self):
'''Stop GNOME session'''
assert self.session
self.session.terminate()
self.session.wait()
self.session_log_write.flush()
self.session_log_write.close()
self.session_log.close()
def get_status(self):
return self.obj_session_presence_props.Get('org.gnome.SessionManager.Presence', 'status')
def get_brightness(self):
f = open('GSD_MOCK_brightness', 'r')
ret = f.read()
f.close()
return int(ret)
def set_has_external_monitor(self, external):
f = open('GSD_MOCK_EXTERNAL_MONITOR', 'w')
if external:
f.write('1')
else:
f.write('0')
f.close ()
os.kill(self.daemon.pid, signal.SIGUSR2)
def check_for_logout(self, timeout):
'''Check that logout is requested.
Fail after the tiven timeout.
'''
# check that it request suspend
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested suspend
try:
log = self.session_log.read()
except IOError:
break
if log and (b'GsmManager: requesting logout' in log):
break
else:
self.fail('timed out waiting for gnome-session logout call')
def check_no_logout(self, seconds):
'''Check that no logout is requested in the given time'''
# wait for specified time to ensure it didn't do anything
time.sleep(seconds)
# check that it did not logout
log = self.session_log.read()
if log:
self.assertFalse(b'GsmManager: requesting logout' in log, 'unexpected logout request')
def check_for_suspend(self, timeout):
'''Check that Suspend() or Hibernate() is requested.
Fail after the tiven timeout.
'''
# check that it request suspend
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested suspend
try:
log = self.logind.stdout.read()
except IOError:
break
if log and (b' Suspend ' in log or b' Hibernate ' in log):
break
else:
self.fail('timed out waiting for logind Suspend() call')
def check_no_suspend(self, seconds):
'''Check that no Suspend or Hibernate is requested in the given time'''
# wait for specified time to ensure it didn't do anything
time.sleep(seconds)
# check that it did not suspend or hibernate
log = self.logind.stdout.read()
if log:
self.assertFalse(b' Suspend' in log, 'unexpected Suspend request')
self.assertFalse(b' Hibernate' in log, 'unexpected Hibernate request')
def check_no_dim(self, seconds):
'''Check that mode is not set to dim in the given time'''
# wait for specified time to ensure it didn't do anything
time.sleep(seconds)
# check that we don't dim
log = self.plugin_log.read()
if log:
self.assertFalse(b'Doing a state transition: dim' in log, 'unexpected dim request')
def check_dim(self, timeout):
'''Check that mode is set to dim in the given time'''
# wait for specified time to ensure it didn't do anything
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested dim
log = self.plugin_log.read()
if 'Doing a state transition: dim' in log:
break
else:
self.fail('timed out waiting for dim')
def check_undim(self, timeout):
'''Check that mode is set to normal in the given time'''
# wait for specified time to ensure it didn't do anything
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested normal
log = self.plugin_log.read()
if 'Doing a state transition: normal' in log:
break
else:
self.fail('timed out waiting for normal mode')
def check_blank(self, timeout):
'''Check that blank is requested.
Fail after the given timeout.
'''
# check that it request blank
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested blank
log = self.plugin_log.read()
if 'TESTSUITE: Blanked screen' in log:
break
else:
self.fail('timed out waiting for blank')
def check_unblank(self, timeout):
'''Check that unblank is requested.
Fail after the given timeout.
'''
# check that it request blank
while timeout > 0:
time.sleep(1)
timeout -= 1
# check that it requested unblank
log = self.plugin_log.read()
if 'TESTSUITE: Unblanked screen' in log:
break
else:
self.fail('timed out waiting for unblank')
def check_no_blank(self, seconds):
'''Check that no blank is requested in the given time'''
# wait for specified time to ensure it didn't blank
time.sleep(seconds)
# check that it did not blank
log = self.plugin_log.read()
self.assertFalse('TESTSUITE: Blanked screen' in log, 'unexpected blank request')
def test_sleep_inactive_blank(self):
'''screensaver/blank interaction'''
# create suspend inhibitor which should have no effect on the idle
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND))
self.obj_screensaver.SetActive(True)
self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on')
# blank is supposed to happen straight away
self.check_blank(2)
# wiggle the mouse now and check for unblank; this is expected to pop up
# the locked screen saver
self.reset_idle_timer()
self.check_unblank(2)
self.assertTrue(self.get_brightness() == gsdpowerconstants.GSD_MOCK_DEFAULT_BRIGHTNESS , 'incorrect unblanked brightness')
# Check for no blank before the normal blank timeout
self.check_no_blank(gsdpowerconstants.SCREENSAVER_TIMEOUT_BLANK - 4)
self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on')
# and check for blank after the blank timeout
self.check_blank(10)
# Drop inhibitor
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
def test_session_idle_delay(self):
'''verify that session idle delay works as expected when changed'''
# Verify that idle is set after 5 seconds
self.settings_session['idle-delay'] = 5
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
time.sleep(7)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE)
# Raise the idle delay, and see that we stop being idle
# and get idle again after the timeout
self.settings_session['idle-delay'] = 10
self.reset_idle_timer()
time.sleep(5)
os.kill(self.session.pid, signal.SIGUSR2)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
time.sleep(10)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE)
# Lower the delay again, and see that we get idle as we should
self.settings_session['idle-delay'] = 5
self.reset_idle_timer()
time.sleep(2)
os.kill(self.session.pid, signal.SIGUSR2)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
time.sleep(5)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE)
def test_idle_time_reset_on_resume(self):
'''Check that the IDLETIME is reset when resuming'''
# Go idle
self.settings_session['idle-delay'] = 5
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
time.sleep(7)
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_IDLE)
# Go to sleep
self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [True], dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# Wake up
self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [False], dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# And check we're not idle
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
def test_sleep_inactive_battery(self):
'''sleep-inactive-battery-timeout'''
self.settings_session['idle-delay'] = 2
self.settings_gsd_power['sleep-inactive-battery-timeout'] = 5
self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend'
# wait for idle delay; should not yet suspend
self.check_no_suspend(2)
# suspend should happen after inactive sleep timeout + 1 s notification
# delay + 1 s error margin
self.check_for_suspend(7)
def test_sleep_inhibition(self):
'''Does not sleep under idle inhibition'''
idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER)
self.settings_session['idle-delay'] = idle_delay
self.settings_gsd_power['sleep-inactive-battery-timeout'] = 5
self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend'
# create inhibitor
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_IDLE | gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND))
self.check_no_suspend(idle_delay + 2)
self.check_no_dim(0)
# Check that we didn't go to idle either
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
def test_lock_on_lid_close(self):
'''Check that we do lock on lid closing, if the machine will not suspend'''
self.settings_screensaver['lock-enabled'] = True
# create inhibitor
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND))
# Close the lid
self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check that we've blanked
time.sleep(2)
self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on')
self.check_blank(2)
# Drop the inhibit and see whether we suspend
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
self.check_for_suspend(5)
def test_blank_on_lid_close(self):
'''Check that we do blank on lid closing, if the machine will not suspend'''
# create inhibitor
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND))
# Close the lid
self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check that we've blanked
self.check_blank(4)
# Drop the inhibit and see whether we suspend
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
self.check_for_suspend(5)
def test_unblank_on_lid_open(self):
'''Check that we do unblank on lid opening, if the machine will not suspend'''
# create inhibitor
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_SUSPEND))
# Close the lid
self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check that we've blanked
self.check_blank(2)
# Reopen the lid
self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', False)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check for unblanking
self.check_unblank(2)
# Drop the inhibit
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
def test_dim(self):
'''Check that we do go to dim'''
idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER)
self.settings_session['idle-delay'] = idle_delay
self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1
self.settings_gsd_power['sleep-inactive-battery-type'] = 'suspend'
# This is an absolute percentage, and our brightness is 0..100
dim_level = self.settings_gsd_power['idle-brightness'];
# Check that we're not idle
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
# Wait and check we're not idle, but dimmed
self.check_dim(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY)
self.assertTrue(self.get_brightness() == dim_level, 'incorrect dim brightness')
self.assertEqual(self.get_status(), gsdpowerenums.GSM_PRESENCE_STATUS_AVAILABLE)
# Bring down the screensaver
self.obj_screensaver.SetActive(True)
self.assertTrue(self.obj_screensaver.GetActive(), 'screensaver not turned on')
# Check that we blank
self.check_blank(2)
# Go to sleep
self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [True], dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# Wake up
self.obj_logind.EmitSignal('', 'PrepareForSleep', 'b', [False], dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# And check that we have the pre-dim brightness
self.assertTrue(self.get_brightness() == gsdpowerconstants.GSD_MOCK_DEFAULT_BRIGHTNESS , 'incorrect unblanked brightness')
def test_no_suspend_lid_close(self):
'''Check that we don't suspend on lid close with an external monitor'''
# Add an external monitor
self.set_has_external_monitor(True)
time.sleep (1)
# Close the lid
self.obj_upower.Set('org.freedesktop.UPower', 'LidIsClosed', True)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check for no suspend, and for no screen blanking
self.check_no_suspend (10)
self.check_no_blank(0)
# Unplug the external monitor
self.set_has_external_monitor(False)
self.check_for_suspend (10)
def test_action_critical_battery(self):
'''action on critical battery'''
# add a fake battery with 30%/2 hours charge to upower
bat_path = self.obj_upower.AddDischargingBattery('mock_BAT', 'Mock Bat', 30.0, 1200)
obj_bat = self.system_bus_con.get_object('org.freedesktop.UPower', bat_path)
self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat_path],
dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# now change battery to critical charge
obj_bat.Set('org.freedesktop.UPower.Device', 'TimeToEmpty',
dbus.Int64(30, variant_level=1),
dbus_interface=dbus.PROPERTIES_IFACE)
obj_bat.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [obj_bat.object_path],
dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(0.5)
# we should have gotten a notification now
notify_log = self.p_notify.stdout.read()
self.check_for_suspend(5)
# verify notification
self.assertRegex(notify_log, b'[0-9.]+ Notify "Power" 0 "battery-.*" ".*battery critical.*"')
def test_action_critical_battery_on_start(self):
'''action on critical battery on startup'''
# add a fake battery with 2%/1 minute charge to upower
bat_path = self.obj_upower.AddDischargingBattery('mock_BAT', 'Mock Bat', 2.0, 60)
obj_bat = self.system_bus_con.get_object('org.freedesktop.UPower', bat_path)
self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat_path],
dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(5)
# we should have gotten a notification now
notify_log = self.p_notify.stdout.read()
self.check_for_suspend(5)
# verify notification
self.assertRegex(notify_log, b'[0-9.]+ Notify "Power" 0 "battery-.*" ".*battery critical.*"')
def test_action_multiple_batteries(self):
'''critical actions for multiple batteries'''
# add two fake batteries to upower
bat1_path = self.obj_upower.AddDischargingBattery('mock_BAT1', 'Bat0', 30.0, 1200)
obj_bat1 = self.system_bus_con.get_object('org.freedesktop.UPower', bat1_path)
self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat1_path],
dbus_interface='org.freedesktop.DBus.Mock')
bat2_path = self.obj_upower.AddDischargingBattery('mock_BAT2', 'Bat2', 40.0, 1600)
obj_bat2 = self.system_bus_con.get_object('org.freedesktop.UPower', bat2_path)
self.obj_upower.EmitSignal('', 'DeviceAdded', 's', [bat2_path],
dbus_interface='org.freedesktop.DBus.Mock')
time.sleep(1)
# now change one battery to critical charge
obj_bat1.Set('org.freedesktop.UPower.Device', 'TimeToEmpty',
dbus.Int64(30, variant_level=1),
dbus_interface=dbus.PROPERTIES_IFACE)
obj_bat1.Set('org.freedesktop.UPower.Device', 'Energy',
dbus.Double(0.5, variant_level=1),
dbus_interface=dbus.PROPERTIES_IFACE)
obj_bat1.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [bat1_path],
dbus_interface='org.freedesktop.DBus.Mock')
# wait long enough to ensure it didn't do anything (as we still have
# the second battery)
self.check_no_suspend(5)
# now change the other battery to critical charge as well
obj_bat2.Set('org.freedesktop.UPower.Device', 'TimeToEmpty',
dbus.Int64(25, variant_level=1),
dbus_interface=dbus.PROPERTIES_IFACE)
obj_bat2.Set('org.freedesktop.UPower.Device', 'Energy',
dbus.Double(0.4, variant_level=1),
dbus_interface=dbus.PROPERTIES_IFACE)
obj_bat2.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
self.obj_upower.EmitSignal('', 'DeviceChanged', 's', [bat2_path],
dbus_interface='org.freedesktop.DBus.Mock')
self.check_for_suspend(5)
def test_forced_logout(self):
'''Test forced logout'''
self.daemon_death_expected = True
idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER)
self.settings_session['idle-delay'] = idle_delay
self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1
self.settings_gsd_power['sleep-inactive-battery-type'] = 'logout'
self.check_for_logout(idle_delay + 2)
# The notification should have been received before the logout, but it's saved anyway
notify_log = self.p_notify.stdout.read()
self.assertTrue(b'You will soon log out because of inactivity.' in notify_log)
def test_forced_logout_inhibition(self):
'''Test we don't force logout when inhibited'''
idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER)
self.settings_session['idle-delay'] = idle_delay
self.settings_gsd_power['sleep-inactive-battery-timeout'] = idle_delay + 1
self.settings_gsd_power['sleep-inactive-battery-type'] = 'logout'
# create suspend inhibitor which should stop us logging out
inhibit_id = self.obj_session_mgr.Inhibit(
'testsuite', dbus.UInt32(0), 'for testing',
dbus.UInt32(gsdpowerenums.GSM_INHIBITOR_FLAG_LOGOUT))
self.check_no_logout(idle_delay + 3)
# Drop inhibitor
self.obj_session_mgr.Uninhibit(dbus.UInt32(inhibit_id))
def test_unindle_on_ac_plug(self):
idle_delay = round(gsdpowerconstants.MINIMUM_IDLE_DIM_DELAY / gsdpowerconstants.IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER)
self.settings_session['idle-delay'] = idle_delay
# Wait for idle
self.check_dim(idle_delay + 2)
# Plug in the AC
self.obj_upower.Set('org.freedesktop.UPower', 'OnBattery', False)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check that we undim
self.check_undim(gsdpowerconstants.POWER_UP_TIME_ON_AC / 2)
# And wait a little more to see us dim again
self.check_dim(idle_delay + 2)
# Unplug the AC
self.obj_upower.Set('org.freedesktop.UPower', 'OnBattery', True)
self.obj_upower.EmitSignal('', 'Changed', '', [], dbus_interface='org.freedesktop.DBus.Mock')
# Check that we undim
self.check_undim(gsdpowerconstants.POWER_UP_TIME_ON_AC / 2)
# And wait a little more to see us dim again
self.check_dim(idle_delay + 2)
# avoid writing to stderr
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
./plugins/power/gpm-common.c 0000644 0000041 0000041 00000202452 13264221014 016275 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2005-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gpm-common.h"
#include "gsd-power-constants.h"
#include "gsd-power-manager.h"
#include "gsd-backlight-linux.h"
#include "gsd-rr.h"
#define XSCREENSAVER_WATCHDOG_TIMEOUT 120 /* seconds */
#define UPS_SOUND_LOOP_ID 99
#define GSD_POWER_MANAGER_CRITICAL_ALERT_TIMEOUT 5 /* seconds */
/* take a discrete value with offset and convert to percentage */
int
gsd_power_backlight_abs_to_percentage (int min, int max, int value)
{
g_return_val_if_fail (max > min, -1);
g_return_val_if_fail (value >= min, -1);
g_return_val_if_fail (value <= max, -1);
return (((value - min) * 100) / (max - min));
}
#define GPM_UP_TIME_PRECISION 5*60
#define GPM_UP_TEXT_MIN_TIME 120
/**
* Return value: The time string, e.g. "2 hours 3 minutes"
**/
gchar *
gpm_get_timestring (guint time_secs)
{
char* timestring = NULL;
gint hours;
gint minutes;
/* Add 0.5 to do rounding */
minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
if (minutes == 0) {
timestring = g_strdup (_("Unknown time"));
return timestring;
}
if (minutes < 60) {
timestring = g_strdup_printf (ngettext ("%i minute",
"%i minutes",
minutes), minutes);
return timestring;
}
hours = minutes / 60;
minutes = minutes % 60;
if (minutes == 0)
timestring = g_strdup_printf (ngettext (
"%i hour",
"%i hours",
hours), hours);
else
/* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
* Swap order with "%2$s %2$i %1$s %1$i if needed */
timestring = g_strdup_printf (_("%i %s %i %s"),
hours, ngettext ("hour", "hours", hours),
minutes, ngettext ("minute", "minutes", minutes));
return timestring;
}
static const gchar *
gpm_upower_get_device_icon_index (UpDevice *device)
{
gdouble percentage;
/* get device properties */
g_object_get (device, "percentage", &percentage, NULL);
if (percentage < 10)
return "000";
else if (percentage < 30)
return "020";
else if (percentage < 50)
return "040";
else if (percentage < 70)
return "060";
else if (percentage < 90)
return "080";
return "100";
}
static const gchar *
gpm_upower_get_device_icon_suffix (UpDevice *device)
{
gdouble percentage;
/* get device properties */
g_object_get (device, "percentage", &percentage, NULL);
if (percentage < 10)
return "caution";
else if (percentage < 30)
return "low";
else if (percentage < 60)
return "good";
return "full";
}
GIcon *
gpm_upower_get_device_icon (UpDevice *device, gboolean use_symbolic)
{
GString *filename;
gchar **iconnames;
const gchar *kind_str;
const gchar *suffix_str;
const gchar *index_str;
UpDeviceKind kind;
UpDeviceState state;
gboolean is_present;
gdouble percentage;
GIcon *icon = NULL;
g_return_val_if_fail (device != NULL, NULL);
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
"percentage", &percentage,
"is-present", &is_present,
NULL);
/* get correct icon prefix */
filename = g_string_new (NULL);
/* get the icon from some simple rules */
if (kind == UP_DEVICE_KIND_LINE_POWER) {
if (use_symbolic)
g_string_append (filename, "ac-adapter-symbolic;");
g_string_append (filename, "ac-adapter;");
} else if (kind == UP_DEVICE_KIND_MONITOR) {
if (use_symbolic)
g_string_append (filename, "gpm-monitor-symbolic;");
g_string_append (filename, "gpm-monitor;");
} else {
kind_str = up_device_kind_to_string (kind);
if (!is_present) {
if (use_symbolic)
g_string_append (filename, "battery-missing-symbolic;");
g_string_append_printf (filename, "gpm-%s-missing;", kind_str);
g_string_append_printf (filename, "gpm-%s-000;", kind_str);
g_string_append (filename, "battery-missing;");
} else {
switch (state) {
case UP_DEVICE_STATE_EMPTY:
if (use_symbolic)
g_string_append (filename, "battery-empty-symbolic;");
g_string_append_printf (filename, "gpm-%s-empty;", kind_str);
g_string_append_printf (filename, "gpm-%s-000;", kind_str);
g_string_append (filename, "battery-empty;");
break;
case UP_DEVICE_STATE_FULLY_CHARGED:
if (use_symbolic) {
g_string_append (filename, "battery-full-charged-symbolic;");
g_string_append (filename, "battery-full-charging-symbolic;");
}
g_string_append_printf (filename, "gpm-%s-full;", kind_str);
g_string_append_printf (filename, "gpm-%s-100;", kind_str);
g_string_append (filename, "battery-full-charged;");
g_string_append (filename, "battery-full-charging;");
break;
case UP_DEVICE_STATE_CHARGING:
case UP_DEVICE_STATE_PENDING_CHARGE:
suffix_str = gpm_upower_get_device_icon_suffix (device);
index_str = gpm_upower_get_device_icon_index (device);
if (use_symbolic)
g_string_append_printf (filename, "battery-%s-charging-symbolic;", suffix_str);
g_string_append_printf (filename, "gpm-%s-%s-charging;", kind_str, index_str);
g_string_append_printf (filename, "battery-%s-charging;", suffix_str);
break;
case UP_DEVICE_STATE_DISCHARGING:
case UP_DEVICE_STATE_PENDING_DISCHARGE:
suffix_str = gpm_upower_get_device_icon_suffix (device);
index_str = gpm_upower_get_device_icon_index (device);
if (use_symbolic)
g_string_append_printf (filename, "battery-%s-symbolic;", suffix_str);
g_string_append_printf (filename, "gpm-%s-%s;", kind_str, index_str);
g_string_append_printf (filename, "battery-%s;", suffix_str);
break;
default:
if (use_symbolic)
g_string_append (filename, "battery-missing-symbolic;");
g_string_append (filename, "gpm-battery-missing;");
g_string_append (filename, "battery-missing;");
}
}
}
/* nothing matched */
if (filename->len == 0) {
g_warning ("nothing matched, falling back to default icon");
g_string_append (filename, "dialog-warning;");
}
g_debug ("got filename: %s", filename->str);
iconnames = g_strsplit (filename->str, ";", -1);
icon = g_themed_icon_new_from_names (iconnames, -1);
g_strfreev (iconnames);
g_string_free (filename, TRUE);
return icon;
}
/**
* gpm_precision_round_down:
* @value: The input value
* @smallest: The smallest increment allowed
*
* 101, 10 100
* 95, 10 90
* 0, 10 0
* 112, 10 110
* 100, 10 100
**/
static gint
gpm_precision_round_down (gfloat value, gint smallest)
{
gfloat division;
if (fabs (value) < 0.01)
return 0;
if (smallest == 0) {
g_warning ("divisor zero");
return 0;
}
division = (gfloat) value / (gfloat) smallest;
division = floorf (division);
division *= smallest;
return (gint) division;
}
gchar *
gpm_upower_get_device_summary (UpDevice *device)
{
const gchar *kind_desc = NULL;
const gchar *device_desc = NULL;
GString *description;
guint time_to_full_round;
guint time_to_empty_round;
gchar *time_to_full_str = NULL;
gchar *time_to_empty_str = NULL;
UpDeviceKind kind;
UpDeviceState state;
gdouble percentage;
gboolean is_present;
gint64 time_to_full;
gint64 time_to_empty;
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
"percentage", &percentage,
"is-present", &is_present,
"time-to-full", &time_to_full,
"time-to-empty", &time_to_empty,
NULL);
description = g_string_new (NULL);
kind_desc = gpm_device_kind_to_localised_string (kind, 1);
device_desc = gpm_device_to_localised_string (device);
/* not installed */
if (!is_present) {
g_string_append (description, device_desc);
goto out;
}
/* don't display all the extra stuff for keyboards and mice */
if (kind == UP_DEVICE_KIND_MOUSE ||
kind == UP_DEVICE_KIND_KEYBOARD ||
kind == UP_DEVICE_KIND_PDA) {
g_string_append (description, kind_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
goto out;
}
/* we care if we are on AC */
if (kind == UP_DEVICE_KIND_PHONE) {
if (state == UP_DEVICE_STATE_CHARGING || !(state == UP_DEVICE_STATE_DISCHARGING)) {
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
goto out;
}
g_string_append (description, kind_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
goto out;
}
/* precalculate so we don't get Unknown time remaining */
time_to_full_round = gpm_precision_round_down (time_to_full, GPM_UP_TIME_PRECISION);
time_to_empty_round = gpm_precision_round_down (time_to_empty, GPM_UP_TIME_PRECISION);
/* we always display "Laptop battery 16 minutes remaining" as we need to clarify what device we are refering to */
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
g_string_append (description, device_desc);
if (kind == UP_DEVICE_KIND_BATTERY && time_to_empty_round > GPM_UP_TEXT_MIN_TIME) {
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
g_string_append (description, " - ");
/* TRANSLATORS: The laptop battery is charged, and we know a time.
* The parameter is the time, e.g. 7 hours 6 minutes */
g_string_append_printf (description, _("provides %s laptop runtime"), time_to_empty_str);
}
goto out;
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
if (time_to_empty_round > GPM_UP_TEXT_MIN_TIME) {
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
/* TRANSLATORS: the device is discharging, and we have a time remaining
* The first parameter is the device type, e.g. "Laptop battery" and
* the second is the time, e.g. 7 hours 6 minutes */
g_string_append_printf (description, _("%s %s remaining"),
kind_desc, time_to_empty_str);
g_string_append_printf (description, " (%.0f%%)", percentage);
} else {
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
}
goto out;
}
if (state == UP_DEVICE_STATE_CHARGING) {
if (time_to_full_round > GPM_UP_TEXT_MIN_TIME &&
time_to_empty_round > GPM_UP_TEXT_MIN_TIME) {
/* display both discharge and charge time */
time_to_full_str = gpm_get_timestring (time_to_full_round);
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
/* TRANSLATORS: device is charging, and we have a time to full and a percentage
* The first parameter is the device type, e.g. "Laptop battery" and
* the second is the time, e.g. "7 hours 6 minutes" */
g_string_append_printf (description, _("%s %s until charged"),
kind_desc, time_to_full_str);
g_string_append_printf (description, " (%.0f%%)", percentage);
g_string_append (description, " - ");
/* TRANSLATORS: the device is charging, and we have a time to full and empty.
* The parameter is a time string, e.g. "7 hours 6 minutes" */
g_string_append_printf (description, _("provides %s battery runtime"),
time_to_empty_str);
} else if (time_to_full_round > GPM_UP_TEXT_MIN_TIME) {
/* display only charge time */
time_to_full_str = gpm_get_timestring (time_to_full_round);
/* TRANSLATORS: device is charging, and we have a time to full and a percentage.
* The first parameter is the device type, e.g. "Laptop battery" and
* the second is the time, e.g. "7 hours 6 minutes" */
g_string_append_printf (description, _("%s %s until charged"),
kind_desc, time_to_full_str);
g_string_append_printf (description, " (%.0f%%)", percentage);
} else {
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
}
goto out;
}
if (state == UP_DEVICE_STATE_PENDING_DISCHARGE) {
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
goto out;
}
if (state == UP_DEVICE_STATE_PENDING_CHARGE) {
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
goto out;
}
if (state == UP_DEVICE_STATE_EMPTY) {
g_string_append (description, device_desc);
goto out;
}
/* fallback */
g_warning ("in an undefined state we are not charging or "
"discharging and the batteries are also not charged");
g_string_append (description, device_desc);
g_string_append_printf (description, " (%.0f%%)", percentage);
out:
g_free (time_to_full_str);
g_free (time_to_empty_str);
return g_string_free (description, FALSE);
}
gchar *
gpm_upower_get_device_description (UpDevice *device)
{
GString *details;
const gchar *text;
gchar *time_str;
UpDeviceKind kind;
UpDeviceState state;
UpDeviceTechnology technology;
gdouble percentage;
gdouble capacity;
gdouble energy;
gdouble energy_full;
gdouble energy_full_design;
gdouble energy_rate;
gboolean is_present;
gint64 time_to_full;
gint64 time_to_empty;
gchar *vendor = NULL;
gchar *serial = NULL;
gchar *model = NULL;
g_return_val_if_fail (device != NULL, NULL);
/* get device properties */
g_object_get (device,
"kind", &kind,
"state", &state,
"percentage", &percentage,
"is-present", &is_present,
"time-to-full", &time_to_full,
"time-to-empty", &time_to_empty,
"technology", &technology,
"capacity", &capacity,
"energy", &energy,
"energy-full", &energy_full,
"energy-full-design", &energy_full_design,
"energy-rate", &energy_rate,
"vendor", &vendor,
"serial", &serial,
"model", &model,
NULL);
details = g_string_new ("");
text = gpm_device_kind_to_localised_string (kind, 1);
/* TRANSLATORS: the type of data, e.g. Laptop battery */
g_string_append_printf (details, "%s %s\n", _("Product:"), text);
if (!is_present) {
/* TRANSLATORS: device is missing */
g_string_append_printf (details, "%s %s\n", _("Status:"), _("Missing"));
} else if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: device is charged */
g_string_append_printf (details, "%s %s\n", _("Status:"), _("Charged"));
} else if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: device is charging */
g_string_append_printf (details, "%s %s\n", _("Status:"), _("Charging"));
} else if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: device is discharging */
g_string_append_printf (details, "%s %s\n", _("Status:"), _("Discharging"));
}
if (percentage >= 0) {
/* TRANSLATORS: percentage */
g_string_append_printf (details, "%s %.1f%%\n", _("Percentage charge:"), percentage);
}
if (vendor) {
/* TRANSLATORS: manufacturer */
g_string_append_printf (details, "%s %s\n", _("Vendor:"), vendor);
}
if (technology != UP_DEVICE_TECHNOLOGY_UNKNOWN) {
text = gpm_device_technology_to_localised_string (technology);
/* TRANSLATORS: how the battery is made, e.g. Lithium Ion */
g_string_append_printf (details, "%s %s\n", _("Technology:"), text);
}
if (serial) {
/* TRANSLATORS: serial number of the battery */
g_string_append_printf (details, "%s %s\n", _("Serial number:"), serial);
}
if (model) {
/* TRANSLATORS: model number of the battery */
g_string_append_printf (details, "%s %s\n", _("Model:"), model);
}
if (time_to_full > 0) {
time_str = gpm_get_timestring (time_to_full);
/* TRANSLATORS: time to fully charged */
g_string_append_printf (details, "%s %s\n", _("Charge time:"), time_str);
g_free (time_str);
}
if (time_to_empty > 0) {
time_str = gpm_get_timestring (time_to_empty);
/* TRANSLATORS: time to empty */
g_string_append_printf (details, "%s %s\n", _("Discharge time:"), time_str);
g_free (time_str);
}
if (capacity > 0) {
const gchar *condition;
if (capacity > 99) {
/* TRANSLATORS: Excellent, Good, Fair and Poor are all related to battery Capacity */
condition = _("Excellent");
} else if (capacity > 90) {
condition = _("Good");
} else if (capacity > 70) {
condition = _("Fair");
} else {
condition = _("Poor");
}
/* TRANSLATORS: %.1f is a percentage and %s the condition (Excellent, Good, ...) */
g_string_append_printf (details, "%s %.1f%% (%s)\n",
_("Capacity:"), capacity, condition);
}
if (kind == UP_DEVICE_KIND_BATTERY) {
if (energy > 0) {
/* TRANSLATORS: current charge */
g_string_append_printf (details, "%s %.1f Wh\n",
_("Current charge:"), energy);
}
if (energy_full > 0 &&
energy_full_design != energy_full) {
/* TRANSLATORS: last full is the charge the battery was seen to charge to */
g_string_append_printf (details, "%s %.1f Wh\n",
_("Last full charge:"), energy_full);
}
if (energy_full_design > 0) {
/* Translators: */
/* TRANSLATORS: Design charge is the amount of charge the battery is designed to have when brand new */
g_string_append_printf (details, "%s %.1f Wh\n",
_("Design charge:"), energy_full_design);
}
if (energy_rate > 0) {
/* TRANSLATORS: the charge or discharge rate */
g_string_append_printf (details, "%s %.1f W\n",
_("Charge rate:"), energy_rate);
}
}
if (kind == UP_DEVICE_KIND_MOUSE ||
kind == UP_DEVICE_KIND_KEYBOARD) {
if (energy > 0) {
/* TRANSLATORS: the current charge for CSR devices */
g_string_append_printf (details, "%s %.0f/7\n",
_("Current charge:"), energy);
}
if (energy_full_design > 0) {
/* TRANSLATORS: the design charge for CSR devices */
g_string_append_printf (details, "%s %.0f/7\n",
_("Design charge:"), energy_full_design);
}
}
/* remove the last \n */
g_string_truncate (details, details->len-1);
g_free (vendor);
g_free (serial);
g_free (model);
return g_string_free (details, FALSE);
}
const gchar *
gpm_device_kind_to_localised_string (UpDeviceKind kind, guint number)
{
const gchar *text = NULL;
switch (kind) {
case UP_DEVICE_KIND_LINE_POWER:
/* TRANSLATORS: system power cord */
text = ngettext ("AC adapter", "AC adapters", number);
break;
case UP_DEVICE_KIND_BATTERY:
/* TRANSLATORS: laptop primary battery */
text = ngettext ("Laptop battery", "Laptop batteries", number);
break;
case UP_DEVICE_KIND_UPS:
/* TRANSLATORS: battery-backed AC power source */
text = ngettext ("UPS", "UPSs", number);
break;
case UP_DEVICE_KIND_MONITOR:
/* TRANSLATORS: a monitor is a device to measure voltage and current */
text = ngettext ("Monitor", "Monitors", number);
break;
case UP_DEVICE_KIND_MOUSE:
/* TRANSLATORS: wireless mice with internal batteries */
text = ngettext ("Mouse", "Mice", number);
break;
case UP_DEVICE_KIND_KEYBOARD:
/* TRANSLATORS: wireless keyboard with internal battery */
text = ngettext ("Keyboard", "Keyboards", number);
break;
case UP_DEVICE_KIND_PDA:
/* TRANSLATORS: portable device */
text = ngettext ("PDA", "PDAs", number);
break;
case UP_DEVICE_KIND_PHONE:
/* TRANSLATORS: cell phone (mobile...) */
text = ngettext ("Cell phone", "Cell phones", number);
break;
#if UP_CHECK_VERSION(0,9,5)
case UP_DEVICE_KIND_MEDIA_PLAYER:
/* TRANSLATORS: media player, mp3 etc */
text = ngettext ("Media player", "Media players", number);
break;
case UP_DEVICE_KIND_TABLET:
/* TRANSLATORS: tablet device */
text = ngettext ("Tablet", "Tablets", number);
break;
case UP_DEVICE_KIND_COMPUTER:
/* TRANSLATORS: tablet device */
text = ngettext ("Computer", "Computers", number);
break;
#endif
default:
g_warning ("enum unrecognised: %i", kind);
text = up_device_kind_to_string (kind);
}
return text;
}
const gchar *
gpm_device_kind_to_icon (UpDeviceKind kind)
{
const gchar *icon = NULL;
switch (kind) {
case UP_DEVICE_KIND_LINE_POWER:
icon = "ac-adapter";
break;
case UP_DEVICE_KIND_BATTERY:
icon = "battery";
break;
case UP_DEVICE_KIND_UPS:
icon = "network-wired";
break;
case UP_DEVICE_KIND_MONITOR:
icon = "application-certificate";
break;
case UP_DEVICE_KIND_MOUSE:
icon = "input-mouse";
break;
case UP_DEVICE_KIND_KEYBOARD:
icon = "input-keyboard";
break;
case UP_DEVICE_KIND_PDA:
icon = "pda";
break;
case UP_DEVICE_KIND_PHONE:
icon = "phone";
break;
#if UP_CHECK_VERSION(0,9,5)
case UP_DEVICE_KIND_MEDIA_PLAYER:
icon = "multimedia-player";
break;
case UP_DEVICE_KIND_TABLET:
icon = "input-tablet";
break;
case UP_DEVICE_KIND_COMPUTER:
icon = "computer-apple-ipad";
break;
#endif
default:
g_warning ("enum unrecognised: %i", kind);
icon = "gtk-help";
}
return icon;
}
const gchar *
gpm_device_technology_to_localised_string (UpDeviceTechnology technology_enum)
{
const gchar *technology = NULL;
switch (technology_enum) {
case UP_DEVICE_TECHNOLOGY_LITHIUM_ION:
/* TRANSLATORS: battery technology */
technology = _("Lithium Ion");
break;
case UP_DEVICE_TECHNOLOGY_LITHIUM_POLYMER:
/* TRANSLATORS: battery technology */
technology = _("Lithium Polymer");
break;
case UP_DEVICE_TECHNOLOGY_LITHIUM_IRON_PHOSPHATE:
/* TRANSLATORS: battery technology */
technology = _("Lithium Iron Phosphate");
break;
case UP_DEVICE_TECHNOLOGY_LEAD_ACID:
/* TRANSLATORS: battery technology */
technology = _("Lead acid");
break;
case UP_DEVICE_TECHNOLOGY_NICKEL_CADMIUM:
/* TRANSLATORS: battery technology */
technology = _("Nickel Cadmium");
break;
case UP_DEVICE_TECHNOLOGY_NICKEL_METAL_HYDRIDE:
/* TRANSLATORS: battery technology */
technology = _("Nickel metal hydride");
break;
case UP_DEVICE_TECHNOLOGY_UNKNOWN:
/* TRANSLATORS: battery technology */
technology = _("Unknown technology");
break;
default:
g_assert_not_reached ();
break;
}
return technology;
}
const gchar *
gpm_device_state_to_localised_string (UpDeviceState state)
{
const gchar *state_string = NULL;
switch (state) {
case UP_DEVICE_STATE_CHARGING:
/* TRANSLATORS: battery state */
state_string = _("Charging");
break;
case UP_DEVICE_STATE_DISCHARGING:
/* TRANSLATORS: battery state */
state_string = _("Discharging");
break;
case UP_DEVICE_STATE_EMPTY:
/* TRANSLATORS: battery state */
state_string = _("Empty");
break;
case UP_DEVICE_STATE_FULLY_CHARGED:
/* TRANSLATORS: battery state */
state_string = _("Charged");
break;
case UP_DEVICE_STATE_PENDING_CHARGE:
/* TRANSLATORS: battery state */
state_string = _("Waiting to charge");
break;
case UP_DEVICE_STATE_PENDING_DISCHARGE:
/* TRANSLATORS: battery state */
state_string = _("Waiting to discharge");
break;
default:
g_assert_not_reached ();
break;
}
return state_string;
}
const gchar *
gpm_device_to_localised_string (UpDevice *device)
{
UpDeviceState state;
UpDeviceKind kind;
gboolean present;
/* get device parameters */
g_object_get (device,
"is-present", &present,
"kind", &kind,
"state", &state,
NULL);
/* laptop battery */
if (kind == UP_DEVICE_KIND_BATTERY) {
if (!present) {
/* TRANSLATORS: device not present */
return _("Laptop battery not present");
}
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Laptop battery is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Laptop battery is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Laptop battery is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Laptop battery is charged");
}
if (state == UP_DEVICE_STATE_PENDING_CHARGE) {
/* TRANSLATORS: battery state */
return _("Laptop battery is waiting to charge");
}
if (state == UP_DEVICE_STATE_PENDING_DISCHARGE) {
/* TRANSLATORS: battery state */
return _("Laptop battery is waiting to discharge");
}
}
/* UPS */
if (kind == UP_DEVICE_KIND_UPS) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("UPS is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("UPS is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("UPS is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("UPS is charged");
}
}
/* mouse */
if (kind == UP_DEVICE_KIND_MOUSE) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Mouse is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Mouse is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Mouse is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Mouse is charged");
}
}
/* keyboard */
if (kind == UP_DEVICE_KIND_KEYBOARD) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Keyboard is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Keyboard is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Keyboard is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Keyboard is charged");
}
}
/* PDA */
if (kind == UP_DEVICE_KIND_PDA) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("PDA is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("PDA is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("PDA is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("PDA is charged");
}
}
/* phone */
if (kind == UP_DEVICE_KIND_PHONE) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Cell phone is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Cell phone is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Cell phone is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Cell phone is charged");
}
}
#if UP_CHECK_VERSION(0,9,5)
/* media player */
if (kind == UP_DEVICE_KIND_MEDIA_PLAYER) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Media player is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Media player is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Media player is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Media player is charged");
}
}
/* tablet */
if (kind == UP_DEVICE_KIND_TABLET) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Tablet is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Tablet is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Tablet is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Tablet is charged");
}
}
/* computer */
if (kind == UP_DEVICE_KIND_COMPUTER) {
if (state == UP_DEVICE_STATE_CHARGING) {
/* TRANSLATORS: battery state */
return _("Computer is charging");
}
if (state == UP_DEVICE_STATE_DISCHARGING) {
/* TRANSLATORS: battery state */
return _("Computer is discharging");
}
if (state == UP_DEVICE_STATE_EMPTY) {
/* TRANSLATORS: battery state */
return _("Computer is empty");
}
if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
/* TRANSLATORS: battery state */
return _("Computer is charged");
}
}
#endif
return gpm_device_kind_to_localised_string (kind, 1);
}
static gboolean
parse_vm_kernel_cmdline (gboolean *is_virtual_machine)
{
gboolean ret = FALSE;
GRegex *regex;
GMatchInfo *match;
char *contents;
char *word;
const char *arg;
if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, NULL))
return ret;
regex = g_regex_new ("gnome.is_vm=(\\S+)", 0, G_REGEX_MATCH_NOTEMPTY, NULL);
if (!g_regex_match (regex, contents, G_REGEX_MATCH_NOTEMPTY, &match))
goto out;
word = g_match_info_fetch (match, 0);
g_debug ("Found command-line match '%s'", word);
arg = word + strlen ("gnome.is_vm=");
if (*arg != '0' && *arg != '1') {
g_warning ("Invalid value '%s' for gnome.is_vm passed in kernel command line.\n", arg);
} else {
*is_virtual_machine = atoi (arg);
ret = TRUE;
}
g_free (word);
out:
g_match_info_free (match);
g_regex_unref (regex);
g_free (contents);
if (ret)
g_debug ("Kernel command-line parsed to %d", *is_virtual_machine);
return ret;
}
gboolean
gsd_power_is_hardware_a_vm (void)
{
const gchar *str;
gboolean ret = FALSE;
GError *error = NULL;
GVariant *inner;
GVariant *variant = NULL;
GDBusConnection *connection;
if (parse_vm_kernel_cmdline (&ret))
return ret;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
NULL,
&error);
if (connection == NULL) {
g_warning ("system bus not available: %s", error->message);
g_error_free (error);
goto out;
}
variant = g_dbus_connection_call_sync (connection,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.DBus.Properties",
"Get",
g_variant_new ("(ss)",
"org.freedesktop.systemd1.Manager",
"Virtualization"),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (variant == NULL) {
g_debug ("Failed to get property '%s': %s", "Virtualization", error->message);
g_error_free (error);
goto out;
}
/* on bare-metal hardware this is the empty string,
* otherwise an identifier such as "kvm", "vmware", etc. */
g_variant_get (variant, "(v)", &inner);
str = g_variant_get_string (inner, NULL);
if (str != NULL && str[0] != '\0')
ret = TRUE;
out:
if (connection != NULL)
g_object_unref (connection);
if (variant != NULL)
g_variant_unref (variant);
return ret;
}
/* This timer goes off every few minutes, whether the user is idle or not,
to try and clean up anything that has gone wrong.
It calls disable_builtin_screensaver() so that if xset has been used,
or some other program (like xlock) has messed with the XSetScreenSaver()
settings, they will be set back to sensible values (if a server extension
is in use, messing with xlock can cause the screensaver to never get a wakeup
event, and could cause monitor power-saving to occur, and all manner of
heinousness.)
This code was originally part of gnome-screensaver, see
http://git.gnome.org/browse/gnome-screensaver/tree/src/gs-watcher-x11.c?id=fec00b12ec46c86334cfd36b37771cc4632f0d4d#n530
*/
static gboolean
disable_builtin_screensaver (gpointer unused)
{
int current_server_timeout, current_server_interval;
int current_prefer_blank, current_allow_exp;
int desired_server_timeout, desired_server_interval;
int desired_prefer_blank, desired_allow_exp;
XGetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
¤t_server_timeout,
¤t_server_interval,
¤t_prefer_blank,
¤t_allow_exp);
desired_server_timeout = current_server_timeout;
desired_server_interval = current_server_interval;
desired_prefer_blank = current_prefer_blank;
desired_allow_exp = current_allow_exp;
desired_server_interval = 0;
/* I suspect (but am not sure) that DontAllowExposures might have
something to do with powering off the monitor as well, at least
on some systems that don't support XDPMS? Who know... */
desired_allow_exp = AllowExposures;
/* When we're not using an extension, set the server-side timeout to 0,
so that the server never gets involved with screen blanking, and we
do it all ourselves. (However, when we *are* using an extension,
we tell the server when to notify us, and rather than blanking the
screen, the server will send us an X event telling us to blank.)
*/
desired_server_timeout = 0;
if (desired_server_timeout != current_server_timeout
|| desired_server_interval != current_server_interval
|| desired_prefer_blank != current_prefer_blank
|| desired_allow_exp != current_allow_exp) {
g_debug ("disabling server builtin screensaver:"
" (xset s %d %d; xset s %s; xset s %s)",
desired_server_timeout,
desired_server_interval,
(desired_prefer_blank ? "blank" : "noblank"),
(desired_allow_exp ? "expose" : "noexpose"));
XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
desired_server_timeout,
desired_server_interval,
desired_prefer_blank,
desired_allow_exp);
XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
}
return TRUE;
}
guint
gsd_power_enable_screensaver_watchdog (void)
{
int dummy;
/* Make sure that Xorg's DPMS extension never gets in our
* way. The defaults are now applied in Fedora 20 from
* being "0" by default to being "600" by default */
gdk_error_trap_push ();
if (DPMSQueryExtension(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &dummy, &dummy))
DPMSSetTimeouts (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 0, 0, 0);
gdk_error_trap_pop_ignored ();
return g_timeout_add_seconds (XSCREENSAVER_WATCHDOG_TIMEOUT,
disable_builtin_screensaver,
NULL);
}
static GsdRROutput *
get_primary_output (GsdRRScreen *rr_screen)
{
GsdRROutput *output = NULL;
GsdRROutput **outputs;
guint i;
/* search all X11 outputs for the device id */
outputs = gsd_rr_screen_list_outputs (rr_screen);
if (outputs == NULL)
goto out;
for (i = 0; outputs[i] != NULL; i++) {
if (gsd_rr_output_is_connected (outputs[i]) &&
gsd_rr_output_is_laptop (outputs[i]) &&
gsd_rr_output_get_backlight_min (outputs[i]) >= 0 &&
gsd_rr_output_get_backlight_max (outputs[i]) > 0) {
output = outputs[i];
break;
}
}
out:
return output;
}
#ifdef GSD_MOCK
static void
backlight_set_mock_value (gint value)
{
const char *filename;
char *contents;
g_debug ("Settings mock brightness: %d", value);
filename = "GSD_MOCK_brightness";
contents = g_strdup_printf ("%d", value);
g_file_set_contents (filename, contents, -1, NULL);
g_free (contents);
}
static gint64
backlight_get_mock_value (const char *argument)
{
const char *filename;
char *contents;
gint64 ret;
if (g_str_equal (argument, "get-max-brightness")) {
g_debug ("Returning max mock brightness: %d", GSD_MOCK_MAX_BRIGHTNESS);
return GSD_MOCK_MAX_BRIGHTNESS;
}
if (g_str_equal (argument, "get-brightness")) {
filename = "GSD_MOCK_brightness";
ret = GSD_MOCK_DEFAULT_BRIGHTNESS;
} else {
g_assert_not_reached ();
}
if (g_file_get_contents (filename, &contents, NULL, NULL)) {
ret = g_ascii_strtoll (contents, NULL, 0);
g_free (contents);
g_debug ("Returning mock brightness: %"G_GINT64_FORMAT, ret);
} else {
ret = GSD_MOCK_DEFAULT_BRIGHTNESS;
backlight_set_mock_value (GSD_MOCK_DEFAULT_BRIGHTNESS);
g_debug ("Returning default mock brightness: %"G_GINT64_FORMAT, ret);
}
return ret;
}
#endif /* GSD_MOCK */
gboolean
backlight_available (GsdRRScreen *rr_screen)
{
char *path;
#ifdef GSD_MOCK
return TRUE;
#endif
if (get_primary_output (rr_screen) != NULL)
return TRUE;
path = gsd_backlight_helper_get_best_backlight (NULL);
if (path == NULL)
return FALSE;
g_free (path);
return TRUE;
}
/**
* backlight_helper_get_value:
*
* Gets a brightness value from the PolicyKit helper.
*
* Return value: the signed integer value from the helper, or -1
* for failure. If -1 then @error is set.
**/
static gint64
backlight_helper_get_value (const gchar *argument, GError **error)
{
gboolean ret;
gchar *stdout_data = NULL;
gint exit_status = 0;
gint64 value = -1;
gchar *command = NULL;
gchar *endptr = NULL;
#ifdef GSD_MOCK
return backlight_get_mock_value (argument);
#endif
#ifndef __linux__
/* non-Linux platforms won't have /sys/class/backlight */
g_set_error_literal (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"The sysfs backlight helper is only for Linux");
goto out;
#endif
/* get the data */
command = g_strdup_printf (LIBEXECDIR "/usd-backlight-helper --%s",
argument);
ret = g_spawn_command_line_sync (command,
&stdout_data,
NULL,
&exit_status,
error);
g_debug ("executed %s retval: %i", command, exit_status);
if (!ret)
goto out;
if (WEXITSTATUS (exit_status) != 0) {
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"usd-backlight-helper failed: %s",
stdout_data ? stdout_data : "No reason");
goto out;
}
/* parse */
value = g_ascii_strtoll (stdout_data, &endptr, 10);
/* parsing error */
if (endptr == stdout_data) {
value = -1;
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"failed to parse value: %s",
stdout_data);
goto out;
}
/* out of range */
if (value > G_MAXINT) {
value = -1;
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"value out of range: %s",
stdout_data);
goto out;
}
/* Fetching the value failed, for some other reason */
if (value < 0) {
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"value negative, but helper did not fail: %s",
stdout_data);
goto out;
}
out:
g_free (command);
g_free (stdout_data);
return value;
}
/**
* backlight_helper_set_value:
*
* Sets a brightness value using the PolicyKit helper.
*
* Return value: Success. If FALSE then @error is set.
**/
static gboolean
backlight_helper_set_value (const gchar *argument,
gint value,
GError **error)
{
gboolean ret = FALSE;
gint exit_status = 0;
gchar *command = NULL;
#ifdef GSD_MOCK
backlight_set_mock_value (value);
return TRUE;
#endif
#ifndef __linux__
/* non-Linux platforms won't have /sys/class/backlight */
g_set_error_literal (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"The sysfs backlight helper is only for Linux");
goto out;
#endif
/* get the data */
command = g_strdup_printf ("pkexec " LIBEXECDIR "/usd-backlight-helper --%s %i",
argument, value);
ret = g_spawn_command_line_sync (command,
NULL,
NULL,
&exit_status,
error);
g_debug ("executed %s retval: %i", command, exit_status);
if (!ret || WEXITSTATUS (exit_status) != 0)
goto out;
out:
g_free (command);
return ret;
}
int
backlight_get_abs (GsdRRScreen *rr_screen, GError **error)
{
GsdRROutput *output;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
return gsd_rr_output_get_backlight (output,
error);
}
/* fall back to the polkit helper */
return backlight_helper_get_value ("get-brightness", error);
}
int
backlight_get_percentage (GsdRRScreen *rr_screen, GError **error)
{
GsdRROutput *output;
gint now;
gint value = -1;
gint min = 0;
gint max;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
min = gsd_rr_output_get_backlight_min (output);
max = gsd_rr_output_get_backlight_max (output);
now = gsd_rr_output_get_backlight (output, error);
if (now < 0)
goto out;
value = ABS_TO_PERCENTAGE (min, max, now);
goto out;
}
/* fall back to the polkit helper */
max = backlight_helper_get_value ("get-max-brightness", error);
if (max < 0)
goto out;
now = backlight_helper_get_value ("get-brightness", error);
if (now < 0)
goto out;
value = ABS_TO_PERCENTAGE (min, max, now);
out:
return value;
}
int
backlight_get_min (GsdRRScreen *rr_screen)
{
GsdRROutput *output;
/* if we have no xbacklight device, then hardcode zero as sysfs
* offsets everything to 0 as min */
output = get_primary_output (rr_screen);
if (output == NULL)
return 0;
/* get xbacklight value, which maybe non-zero */
return gsd_rr_output_get_backlight_min (output);
}
int
backlight_get_max (GsdRRScreen *rr_screen, GError **error)
{
gint value;
GsdRROutput *output;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
value = gsd_rr_output_get_backlight_max (output);
if (value < 0) {
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"failed to get backlight max");
}
return value;
}
/* fall back to the polkit helper */
return backlight_helper_get_value ("get-max-brightness", error);
}
gboolean
backlight_set_percentage (GsdRRScreen *rr_screen,
guint value,
GError **error)
{
GsdRROutput *output;
gboolean ret = FALSE;
gint min = 0;
gint max;
guint discrete;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
min = gsd_rr_output_get_backlight_min (output);
max = gsd_rr_output_get_backlight_max (output);
if (min < 0 || max < 0) {
g_warning ("no xrandr backlight capability");
return ret;
}
discrete = PERCENTAGE_TO_ABS (min, max, value);
ret = gsd_rr_output_set_backlight (output,
discrete,
error);
return ret;
}
/* fall back to the polkit helper */
max = backlight_helper_get_value ("get-max-brightness", error);
if (max < 0)
return ret;
discrete = PERCENTAGE_TO_ABS (min, max, value);
ret = backlight_helper_set_value ("set-brightness",
discrete,
error);
return ret;
}
int
backlight_step_up (GsdRRScreen *rr_screen, GError **error)
{
GsdRROutput *output;
gboolean ret = FALSE;
gint percentage_value = -1;
gint min = 0;
gint max;
gint now;
gint step;
guint discrete;
GsdRRCrtc *crtc;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
crtc = gsd_rr_output_get_crtc (output);
if (crtc == NULL) {
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"no crtc for %s",
gsd_rr_output_get_name (output));
return percentage_value;
}
min = gsd_rr_output_get_backlight_min (output);
max = gsd_rr_output_get_backlight_max (output);
now = gsd_rr_output_get_backlight (output, error);
if (now < 0)
return percentage_value;
step = BRIGHTNESS_STEP_AMOUNT (max - min + 1);
discrete = MIN (now + step, max);
ret = gsd_rr_output_set_backlight (output,
discrete,
error);
if (ret)
percentage_value = ABS_TO_PERCENTAGE (min, max, discrete);
return percentage_value;
}
/* fall back to the polkit helper */
now = backlight_helper_get_value ("get-brightness", error);
if (now < 0)
return percentage_value;
max = backlight_helper_get_value ("get-max-brightness", error);
if (max < 0)
return percentage_value;
step = BRIGHTNESS_STEP_AMOUNT (max - min + 1);
discrete = MIN (now + step, max);
ret = backlight_helper_set_value ("set-brightness",
discrete,
error);
if (ret)
percentage_value = ABS_TO_PERCENTAGE (min, max, discrete);
return percentage_value;
}
int
backlight_step_down (GsdRRScreen *rr_screen, GError **error)
{
GsdRROutput *output;
gboolean ret = FALSE;
gint percentage_value = -1;
gint min = 0;
gint max;
gint now;
gint step;
guint discrete;
GsdRRCrtc *crtc;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
crtc = gsd_rr_output_get_crtc (output);
if (crtc == NULL) {
g_set_error (error,
GSD_POWER_MANAGER_ERROR,
GSD_POWER_MANAGER_ERROR_FAILED,
"no crtc for %s",
gsd_rr_output_get_name (output));
return percentage_value;
}
min = gsd_rr_output_get_backlight_min (output);
max = gsd_rr_output_get_backlight_max (output);
now = gsd_rr_output_get_backlight (output, error);
if (now < 0)
return percentage_value;
step = BRIGHTNESS_STEP_AMOUNT (max - min + 1);
discrete = MAX (now - step, 0);
ret = gsd_rr_output_set_backlight (output,
discrete,
error);
if (ret)
percentage_value = ABS_TO_PERCENTAGE (min, max, discrete);
return percentage_value;
}
/* fall back to the polkit helper */
now = backlight_helper_get_value ("get-brightness", error);
if (now < 0)
return percentage_value;
max = backlight_helper_get_value ("get-max-brightness", error);
if (max < 0)
return percentage_value;
step = BRIGHTNESS_STEP_AMOUNT (max - min + 1);
discrete = MAX (now - step, 0);
ret = backlight_helper_set_value ("set-brightness",
discrete,
error);
if (ret)
percentage_value = ABS_TO_PERCENTAGE (min, max, discrete);
return percentage_value;
}
int
backlight_set_abs (GsdRRScreen *rr_screen,
guint value,
GError **error)
{
GsdRROutput *output;
gboolean ret = FALSE;
/* prefer xbacklight */
output = get_primary_output (rr_screen);
if (output != NULL) {
ret = gsd_rr_output_set_backlight (output,
value,
error);
return ret;
}
/* fall back to the polkit helper */
ret = backlight_helper_set_value ("set-brightness",
value,
error);
return ret;
}
void
reset_idletime (void)
{
static gboolean inited = FALSE;
static KeyCode keycode1, keycode2;
static gboolean first_keycode = FALSE;
if (inited == FALSE) {
keycode1 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Shift_L);
keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Shift_R);
}
gdk_error_trap_push ();
/* send a left or right alt key; first press, then release */
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), first_keycode ? keycode1 : keycode2, True, CurrentTime);
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), first_keycode ? keycode1 : keycode2, False, CurrentTime);
first_keycode = !first_keycode;
gdk_error_trap_pop_ignored ();
}
static gboolean
randr_output_is_on (GsdRROutput *output)
{
GsdRRCrtc *crtc;
crtc = gsd_rr_output_get_crtc (output);
if (!crtc)
return FALSE;
return gsd_rr_crtc_get_current_mode (crtc) != NULL;
}
gboolean
external_monitor_is_connected (GsdRRScreen *screen)
{
GsdRROutput **outputs;
guint i;
#ifdef GSD_MOCK
char *mock_external_monitor_contents;
if (g_file_get_contents ("GSD_MOCK_EXTERNAL_MONITOR", &mock_external_monitor_contents, NULL, NULL)) {
if (mock_external_monitor_contents[0] == '1') {
g_free (mock_external_monitor_contents);
return TRUE;
} else if (mock_external_monitor_contents[0] == '0') {
g_free (mock_external_monitor_contents);
return FALSE;
}
g_warning ("Unhandled value for GSD_MOCK_EXTERNAL_MONITOR contents: %s", mock_external_monitor_contents);
g_free (mock_external_monitor_contents);
}
#endif /* GSD_MOCK */
/* see if we have more than one screen plugged in */
outputs = gsd_rr_screen_list_outputs (screen);
for (i = 0; outputs[i] != NULL; i++) {
if (randr_output_is_on (outputs[i]) &&
!gsd_rr_output_is_laptop (outputs[i]))
return TRUE;
}
return FALSE;
}
static void
play_sound (void)
{
ca_context_play (ca_gtk_context_get (), UPS_SOUND_LOOP_ID,
CA_PROP_EVENT_ID, "battery-caution",
CA_PROP_EVENT_DESCRIPTION, _("Battery is critically low"), NULL);
}
static gboolean
play_loop_timeout_cb (gpointer user_data)
{
play_sound ();
return TRUE;
}
void
play_loop_start (guint *id)
{
if (*id != 0)
return;
*id = g_timeout_add_seconds (GSD_POWER_MANAGER_CRITICAL_ALERT_TIMEOUT,
(GSourceFunc) play_loop_timeout_cb,
NULL);
play_sound ();
}
void
play_loop_stop (guint *id)
{
if (*id == 0)
return;
ca_context_cancel (ca_gtk_context_get (), UPS_SOUND_LOOP_ID);
g_source_remove (*id);
*id = 0;
}
./plugins/power/Makefile.am 0000644 0000041 0000041 00000012664 13264221014 016120 0 ustar www-data www-data BUILT_SOURCES =
plugin_name = power
plugin_LTLIBRARIES = \
libpower.la
libpower_la_SOURCES = \
gpm-common.c \
gpm-common.h \
gsd-backlight-linux.c \
gsd-backlight-linux.h \
gsd-power-manager.c \
gsd-power-manager.h \
gsm-inhibitor-flag.h \
gsm-presence-flag.h \
gsm-manager-logout-mode.h \
gsd-power-constants.h \
gsd-power-plugin.c
libpower_la_CPPFLAGS = \
-I$(top_srcdir)/data/ \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
-DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
-DSBINDIR=\"$(sbindir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
$(AM_CPPFLAGS)
libpower_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(POWER_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
libpower_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libpower_la_LIBADD = \
$(top_builddir)/plugins/common/libcommon.la \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \
$(POWER_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
plugin_in_files = \
power.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
com.ubuntu.unity-settings-daemon.plugins.power.policy.in: com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in Makefile
$(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
@INTLTOOL_POLICY_RULE@
polkit_policydir = $(datadir)/polkit-1/actions
polkit_policy_in_files = com.ubuntu.unity-settings-daemon.plugins.power.policy.in
polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy)
# so it always gets included in the tarball
usd_backlight_helper_SOURCES = \
gsd-backlight-linux.c \
gsd-backlight-linux.h \
gsd-backlight-helper.c
noinst_PROGRAMS = usd-test-power
usd_test_power_SOURCES = \
gpm-common.c \
gpm-common.h \
gsd-backlight-linux.c \
gsd-backlight-linux.h \
gsd-power-manager.c \
gsd-power-manager.h \
gsm-inhibitor-flag.h \
gsm-presence-flag.h \
gsm-manager-logout-mode.h \
test-power.c
usd_test_power_CFLAGS = $(libpower_la_CFLAGS)
usd_test_power_CPPFLAGS = $(libpower_la_CPPFLAGS) -DGSD_MOCK=1 -DGSD_ACTION_DELAY=1
usd_test_power_LDADD = \
-lm \
$(top_builddir)/plugins/common/libcommon.la \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/gnome-settings-daemon/libunity-settings-daemon.la \
$(POWER_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
EXTRA_DIST = \
$(plugin_in_files) \
$(gsd_backlight_helper_SOURCES) \
$(NULL)
if HAVE_GUDEV
libexec_PROGRAMS = usd-backlight-helper
usd_backlight_helper_LDFLAGS = \
$(BACKLIGHT_HELPER_LIBS) \
-lm
usd_backlight_helper_CFLAGS = \
$(BACKLIGHT_HELPER_CFLAGS)
EXTRA_DIST += \
com.ubuntu.unity-settings-daemon.plugins.power.policy.in.in
endif
# Enums
GSD_POWER_ENUM_FILES = gsd-power-enums.c gsd-power-enums.h
gsd-power-enums.h: gsm-inhibitor-flag.h gsm-presence-flag.h Makefile
$(AM_V_GEN)($(GLIB_MKENUMS) \
--fhead "#ifndef GSD_POWER_ENUMS_H\n#define GSD_POWER_ENUMS_H\n\n#include \n\nG_BEGIN_DECLS\n" \
--fprod "/* enumerations from \"@filename@\" */\n" \
--vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define GSD_POWER_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
--ftail "G_END_DECLS\n\n#endif /* !GSD_POWER_ENUMS_H */" $(srcdir)/gsm-inhibitor-flag.h $(srcdir)/gsm-presence-flag.h > $@)
gsd-power-enums.c: gsd-power-constants.h gsm-inhibitor-flag.h gsm-presence-flag.h Makefile gsd-power-enums.h
$(AM_V_GEN)($(GLIB_MKENUMS) \
--fhead "#include \"gsm-inhibitor-flag.h\"\n#include \"gsm-presence-flag.h\"\n#include \"gsd-power-enums.h\"" \
--fprod "\n/* enumerations from \"@filename@\" */" \
--vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
--vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
--vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
$(srcdir)/gsm-inhibitor-flag.h $(srcdir)/gsm-presence-flag.h > $@)
BUILT_SOURCES += $(GSD_POWER_ENUM_FILES)
gsdpowerconstants.py: gsd-power-constants-update.pl gsd-power-constants.h
$(AM_V_GEN) $(srcdir)/gsd-power-constants-update.pl
gsdpowerenums.py: gsd-power-enums-update gsd-power-enums.h gsd-power-enums.c
$(AM_V_GEN) $(builddir)/gsd-power-enums-update > $@
noinst_PROGRAMS += gsd-power-enums-update
gsd_power_enums_update_SOURCES = \
gsd-power-enums-update.c \
gsd-power-enums.h \
gsd-power-enums.c
gsd_power_enums_update_CFLAGS = $(libpower_la_CFLAGS)
gsd_power_enums_update_CPPFLAGS = $(libpower_la_CPPFLAGS) -I$(top_builddir)/plugins/power
gsd_power_enums_update_LDFLAGS = $(POWER_LIBS)
EXTRA_DIST += gsd-power-constants-update.pl gsdpowerconstants.py gsdpowerenums.py test.py
check-local: $(top_builddir)/tests/shiftkey usd-test-power test.py gsdpowerconstants.py gsdpowerenums.py
# This is how you run a single test
# BUILDDIR=$(builddir) TOP_BUILDDIR=$(top_builddir) ${PYTHON} $(srcdir)/test.py PowerPluginTest.test_sleep_inactive_blank
BUILDDIR=$(builddir) TOP_BUILDDIR=$(top_builddir) ${PYTHON} $(srcdir)/test.py
clean-local:
rm -f *~
CLEANFILES = \
$(plugin_DATA) \
$(GSD_POWER_ENUM_FILES) \
gsdpowerenums.py \
com.ubuntu.unity-settings-daemon.plugins.power.policy \
com.ubuntu.unity-settings-daemon.plugins.power.policy.in
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/power/power.gnome-settings-plugin.in 0000644 0000041 0000041 00000000250 13264221014 021772 0 ustar www-data www-data [GNOME Settings Plugin]
Module=power
IAge=0
Priority=1
_Name=Power
_Description=Power plugin
Authors=Richard Hughes
Copyright=Copyright © 2011 Richard Hughes
Website=
./plugins/power/gsd-backlight-linux.h 0000644 0000041 0000041 00000002140 13264221014 020061 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
typedef enum {
GSD_BACKLIGHT_TYPE_FIRMWARE,
GSD_BACKLIGHT_TYPE_PLATFORM,
GSD_BACKLIGHT_TYPE_RAW,
} GsdBacklightType;
char *gsd_backlight_helper_get_best_backlight (GsdBacklightType *type);
./plugins/power/gsm-manager-logout-mode.h 0000644 0000041 0000041 00000002233 13264221014 020653 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 William Jon McCann
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#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 */
./plugins/updates/ 0000755 0000041 0000041 00000000000 13264221014 014364 5 ustar www-data www-data ./plugins/updates/updates.gnome-settings-plugin.in 0000644 0000041 0000041 00000000241 13264221014 022614 0 ustar www-data www-data [GNOME Settings Plugin]
Module=updates
IAge=0
Priority=300
_Name=Updates
_Description=Updates plugin
Authors=Richard Hughes
Copyright=Copyright © 2011
Website=
./plugins/updates/gsd-updates-manager.h 0000644 0000041 0000041 00000004205 13264221014 020366 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011 Richard Hughes
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_UPDATES_MANAGER_H
#define __GSD_UPDATES_MANAGER_H
#include
#include
G_BEGIN_DECLS
#define GSD_TYPE_UPDATES_MANAGER (gsd_updates_manager_get_type ())
#define GSD_UPDATES_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManager))
#define GSD_UPDATES_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerClass))
#define GSD_IS_UPDATES_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UPDATES_MANAGER))
#define GSD_IS_UPDATES_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_UPDATES_MANAGER))
#define GSD_UPDATES_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerClass))
typedef struct GsdUpdatesManagerPrivate GsdUpdatesManagerPrivate;
typedef struct
{
GObject parent;
GsdUpdatesManagerPrivate *priv;
} GsdUpdatesManager;
typedef struct
{
GObjectClass parent_class;
} GsdUpdatesManagerClass;
GType gsd_updates_manager_get_type (void) G_GNUC_CONST;
GsdUpdatesManager *gsd_updates_manager_new (void);
gboolean gsd_updates_manager_start (GsdUpdatesManager *manager, GError **error);
void gsd_updates_manager_stop (GsdUpdatesManager *manager);
G_END_DECLS
#endif /* __GSD_UPDATES_MANAGER_H */
./plugins/updates/gsd-updates-common.h 0000644 0000041 0000041 00000004215 13264221014 020245 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#ifndef __GSD_UPDATES_COMMON_H
#define __GSD_UPDATES_COMMON_H
G_BEGIN_DECLS
#define GSD_SETTINGS_BANNED_FIRMWARE "banned-firmware"
#define GSD_SETTINGS_CONNECTION_USE_MOBILE "connection-use-mobile"
#define GSD_SETTINGS_ENABLE_CHECK_FIRMWARE "enable-check-firmware"
#define GSD_SETTINGS_FREQUENCY_GET_UPDATES "frequency-get-updates"
#define GSD_SETTINGS_FREQUENCY_GET_UPGRADES "frequency-get-upgrades"
#define GSD_SETTINGS_FREQUENCY_REFRESH_CACHE "frequency-refresh-cache"
#define GSD_SETTINGS_FREQUENCY_UPDATES_NOTIFICATION "frequency-updates-notification"
#define GSD_SETTINGS_IGNORED_DEVICES "ignored-devices"
#define GSD_SETTINGS_LAST_UPDATES_NOTIFICATION "last-updates-notification"
#define GSD_SETTINGS_MEDIA_REPO_FILENAMES "media-repo-filenames"
#define GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES "notify-distro-upgrades"
#define GSD_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.updates"
#define GSD_SETTINGS_UPDATE_BATTERY "update-battery"
#define GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES "auto-download-updates"
G_END_DECLS
#endif /* __GSD_UPDATES_COMMON_H */
./plugins/updates/gsd-updates-firmware.h 0000644 0000041 0000041 00000003670 13264221014 020575 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#ifndef __GSD_UPDATES_FIRMWARE_H
#define __GSD_UPDATES_FIRMWARE_H
#include
G_BEGIN_DECLS
#define GSD_UPDATES_TYPE_FIRMWARE (gsd_updates_firmware_get_type ())
#define GSD_UPDATES_FIRMWARE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmware))
#define GSD_UPDATES_FIRMWARE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmwareClass))
#define GSD_UPDATES_IS_FIRMWARE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_UPDATES_TYPE_FIRMWARE))
typedef struct GsdUpdatesFirmwarePrivate GsdUpdatesFirmwarePrivate;
typedef struct
{
GObject parent;
GsdUpdatesFirmwarePrivate *priv;
} GsdUpdatesFirmware;
typedef struct
{
GObjectClass parent_class;
} GsdUpdatesFirmwareClass;
GType gsd_updates_firmware_get_type (void);
GsdUpdatesFirmware *gsd_updates_firmware_new (void);
G_END_DECLS
#endif /* __GSD_UPDATES_FIRMWARE_H */
./plugins/updates/gsd-updates-refresh.c 0000644 0000041 0000041 00000047577 13264221014 020430 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2007-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#include "config.h"
#include
#include
#include
#include "gnome-settings-bus.h"
#include "gsd-updates-common.h"
#include "gsd-updates-refresh.h"
static void gsd_updates_refresh_finalize (GObject *object);
#define GSD_UPDATES_REFRESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshPrivate))
#define PERIODIC_CHECK_TIME 60*60 /* poke PackageKit every hour */
#define LOGIN_TIMEOUT 3 /* seconds */
#define SESSION_STARTUP_TIMEOUT 10 /* seconds */
enum {
PRESENCE_STATUS_AVAILABLE = 0,
PRESENCE_STATUS_INVISIBLE,
PRESENCE_STATUS_BUSY,
PRESENCE_STATUS_IDLE,
PRESENCE_STATUS_UNKNOWN
};
/*
* at startup, after a small delay, force a GetUpdates call
* every hour (or any event) check:
- if we are online, idle and on AC power, it's been more than a day
since we refreshed then RefreshCache
- if we are online and it's been longer than the timeout since
getting the updates period then GetUpdates
*/
struct GsdUpdatesRefreshPrivate
{
gboolean session_idle;
gboolean on_battery;
gboolean network_active;
guint timeout_id;
guint periodic_id;
UpClient *client;
GSettings *settings;
GsdSessionManager *proxy_session;
PkControl *control;
};
enum {
REFRESH_CACHE,
GET_UPDATES,
GET_UPGRADES,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GsdUpdatesRefresh, gsd_updates_refresh, G_TYPE_OBJECT)
static void
gsd_updates_refresh_class_init (GsdUpdatesRefreshClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_updates_refresh_finalize;
g_type_class_add_private (klass, sizeof (GsdUpdatesRefreshPrivate));
signals [REFRESH_CACHE] =
g_signal_new ("refresh-cache",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals [GET_UPDATES] =
g_signal_new ("get-updates",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals [GET_UPGRADES] =
g_signal_new ("get-upgrades",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
get_time_refresh_cache_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesRefresh *refresh)
{
PkControl *control = PK_CONTROL (object);
GError *error = NULL;
guint seconds;
guint thresh;
/* get the result */
seconds = pk_control_get_time_since_action_finish (control, res, &error);
if (seconds == 0) {
g_warning ("failed to get time: %s", error->message);
g_error_free (error);
return;
}
/* have we passed the timout? */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
if (seconds < thresh) {
g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
return;
}
/* send signal */
g_debug ("emitting refresh-cache");
g_signal_emit (refresh, signals [REFRESH_CACHE], 0);
}
static void
maybe_refresh_cache (GsdUpdatesRefresh *refresh)
{
guint thresh;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
/* if we don't want to auto check for updates, don't do this either */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
if (thresh == 0) {
g_debug ("not when policy is set to never");
return;
}
/* only do the refresh cache when the user is idle */
if (!refresh->priv->session_idle) {
g_debug ("not when session active");
return;
}
/* get this each time, as it may have changed behind out back */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_REFRESH_CACHE);
if (thresh == 0) {
g_debug ("not when policy is set to never");
return;
}
/* get the time since the last refresh */
pk_control_get_time_since_action_async (refresh->priv->control,
PK_ROLE_ENUM_REFRESH_CACHE,
NULL,
(GAsyncReadyCallback) get_time_refresh_cache_cb,
refresh);
}
static void
get_time_get_updates_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh)
{
PkControl *control = PK_CONTROL (object);
GError *error = NULL;
guint seconds;
guint thresh;
/* get the result */
seconds = pk_control_get_time_since_action_finish (control, res, &error);
if (seconds == 0) {
g_warning ("failed to get time: %s", error->message);
g_error_free (error);
return;
}
/* have we passed the timout? */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
if (seconds < thresh) {
g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
return;
}
/* send signal */
g_debug ("emitting get-updates");
g_signal_emit (refresh, signals [GET_UPDATES], 0);
}
static void
maybe_get_updates (GsdUpdatesRefresh *refresh)
{
guint thresh;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
/* if we don't want to auto check for updates, don't do this either */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
if (thresh == 0) {
g_debug ("not when policy is set to never");
return;
}
/* get the time since the last refresh */
pk_control_get_time_since_action_async (refresh->priv->control,
PK_ROLE_ENUM_GET_UPDATES,
NULL,
(GAsyncReadyCallback) get_time_get_updates_cb,
refresh);
}
static void
get_time_get_upgrades_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesRefresh *refresh)
{
PkControl *control = PK_CONTROL (object);
GError *error = NULL;
guint seconds;
guint thresh;
/* get the result */
seconds = pk_control_get_time_since_action_finish (control, res, &error);
if (seconds == 0) {
g_warning ("failed to get time: %s", error->message);
g_error_free (error);
return;
}
/* have we passed the timout? */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPDATES);
if (seconds < thresh) {
g_debug ("not before timeout, thresh=%u, now=%u",
thresh, seconds);
return;
}
/* send signal */
g_debug ("emitting get-upgrades");
g_signal_emit (refresh, signals [GET_UPGRADES], 0);
}
static void
maybe_get_upgrades (GsdUpdatesRefresh *refresh)
{
guint thresh;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
/* get this each time, as it may have changed behind out back */
thresh = g_settings_get_int (refresh->priv->settings,
GSD_SETTINGS_FREQUENCY_GET_UPGRADES);
if (thresh == 0) {
g_debug ("not when policy is set to never");
return;
}
/* get the time since the last refresh */
pk_control_get_time_since_action_async (refresh->priv->control,
PK_ROLE_ENUM_GET_DISTRO_UPGRADES,
NULL,
(GAsyncReadyCallback) get_time_get_upgrades_cb,
refresh);
}
static gboolean
change_state_cb (GsdUpdatesRefresh *refresh)
{
/* check all actions */
maybe_refresh_cache (refresh);
maybe_get_updates (refresh);
maybe_get_upgrades (refresh);
return FALSE;
}
static gboolean
change_state (GsdUpdatesRefresh *refresh)
{
gboolean ret;
g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
/* no point continuing if we have no network */
if (!refresh->priv->network_active) {
g_debug ("not when no network");
return FALSE;
}
/* not on battery unless overridden */
ret = g_settings_get_boolean (refresh->priv->settings,
GSD_SETTINGS_UPDATE_BATTERY);
if (!ret && refresh->priv->on_battery) {
g_debug ("not when on battery");
return FALSE;
}
/* wait a little time for things to settle down */
if (refresh->priv->timeout_id != 0)
g_source_remove (refresh->priv->timeout_id);
g_debug ("defering action for %i seconds",
SESSION_STARTUP_TIMEOUT);
refresh->priv->timeout_id =
g_timeout_add_seconds (SESSION_STARTUP_TIMEOUT,
(GSourceFunc) change_state_cb,
refresh);
g_source_set_name_by_id (refresh->priv->timeout_id,
"[GsdUpdatesRefresh] change-state");
return TRUE;
}
static void
settings_key_changed_cb (GSettings *client,
const gchar *key,
GsdUpdatesRefresh *refresh)
{
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
if (g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPDATES) == 0 ||
g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPGRADES) == 0 ||
g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE) == 0 ||
g_strcmp0 (key, GSD_SETTINGS_UPDATE_BATTERY) == 0)
change_state (refresh);
}
static gboolean
convert_network_state (GsdUpdatesRefresh *refresh, PkNetworkEnum state)
{
/* offline */
if (state == PK_NETWORK_ENUM_OFFLINE)
return FALSE;
/* online */
if (state == PK_NETWORK_ENUM_ONLINE ||
state == PK_NETWORK_ENUM_WIFI ||
state == PK_NETWORK_ENUM_WIRED)
return TRUE;
/* check policy */
if (state == PK_NETWORK_ENUM_MOBILE)
return g_settings_get_boolean (refresh->priv->settings,
GSD_SETTINGS_CONNECTION_USE_MOBILE);
/* not recognised */
g_warning ("state unknown: %i", state);
return TRUE;
}
static void
notify_network_state_cb (PkControl *control,
GParamSpec *pspec,
GsdUpdatesRefresh *refresh)
{
PkNetworkEnum state;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
g_object_get (control, "network-state", &state, NULL);
refresh->priv->network_active = convert_network_state (refresh, state);
g_debug ("setting online %i", refresh->priv->network_active);
if (refresh->priv->network_active)
change_state (refresh);
}
static gboolean
periodic_timeout_cb (gpointer user_data)
{
GsdUpdatesRefresh *refresh = GSD_UPDATES_REFRESH (user_data);
g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
/* debug so we can catch polling */
g_debug ("polling check");
/* triggered once an hour */
change_state (refresh);
/* always return */
return TRUE;
}
static void
gsd_updates_refresh_client_changed_cb (UpClient *client,
GsdUpdatesRefresh *refresh)
{
gboolean on_battery;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
/* get the on-battery state */
on_battery = up_client_get_on_battery (refresh->priv->client);
if (on_battery == refresh->priv->on_battery) {
g_debug ("same state as before, ignoring");
return;
}
/* save in local cache */
g_debug ("setting on_battery %i", on_battery);
refresh->priv->on_battery = on_battery;
if (!on_battery)
change_state (refresh);
}
static void
get_properties_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesRefresh *refresh)
{
PkNetworkEnum state;
GError *error = NULL;
PkControl *control = PK_CONTROL(object);
gboolean ret;
/* get the result */
ret = pk_control_get_properties_finish (control, res, &error);
if (!ret) {
/* TRANSLATORS: backend is broken, and won't tell us what it supports */
g_warning ("could not get properties");
g_error_free (error);
goto out;
}
/* get values */
g_object_get (control,
"network-state", &state,
NULL);
refresh->priv->network_active = convert_network_state (refresh, state);
out:
return;
}
static void
session_presence_signal_cb (GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
GsdUpdatesRefresh *refresh)
{
guint status;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
if (g_strcmp0 (signal_name, "StatusChanged") != 0)
return;
/* map status code into boolean */
g_variant_get (parameters, "(u)", &status);
refresh->priv->session_idle = (status == PRESENCE_STATUS_IDLE);
g_debug ("setting is_idle %i",
refresh->priv->session_idle);
if (refresh->priv->session_idle)
change_state (refresh);
}
static void
gsd_updates_refresh_init (GsdUpdatesRefresh *refresh)
{
GVariant *status;
guint status_code;
refresh->priv = GSD_UPDATES_REFRESH_GET_PRIVATE (refresh);
refresh->priv->on_battery = FALSE;
refresh->priv->network_active = FALSE;
refresh->priv->timeout_id = 0;
refresh->priv->periodic_id = 0;
/* we need to know the updates frequency */
refresh->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA);
g_signal_connect (refresh->priv->settings, "changed",
G_CALLBACK (settings_key_changed_cb), refresh);
/* we need to query the last cache refresh time */
refresh->priv->control = pk_control_new ();
g_signal_connect (refresh->priv->control, "notify::network-state",
G_CALLBACK (notify_network_state_cb),
refresh);
/* get network state */
pk_control_get_properties_async (refresh->priv->control,
NULL,
(GAsyncReadyCallback) get_properties_cb,
refresh);
/* use a UpClient */
refresh->priv->client = up_client_new ();
g_signal_connect (refresh->priv->client, "changed",
G_CALLBACK (gsd_updates_refresh_client_changed_cb), refresh);
/* get the battery state */
refresh->priv->on_battery = up_client_get_on_battery (refresh->priv->client);
g_debug ("setting on battery %i", refresh->priv->on_battery);
/* use gnome-session for the idle detection */
refresh->priv->proxy_session =
gnome_settings_bus_get_session_proxy ();
if (refresh->priv->proxy_session != NULL) {
g_signal_connect (G_DBUS_PROXY (refresh->priv->proxy_session),
"g-signal",
G_CALLBACK (session_presence_signal_cb),
refresh);
status = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (refresh->priv->proxy_session),
"status");
if (status) {
g_variant_get (status, "u", &status_code);
refresh->priv->session_idle = (status_code == PRESENCE_STATUS_IDLE);
g_variant_unref (status);
}
else {
refresh->priv->session_idle = FALSE;
}
}
/* we check this in case we miss one of the async signals */
refresh->priv->periodic_id =
g_timeout_add_seconds (PERIODIC_CHECK_TIME,
periodic_timeout_cb, refresh);
g_source_set_name_by_id (refresh->priv->periodic_id,
"[GsdUpdatesRefresh] periodic check");
/* check system state */
change_state (refresh);
}
static void
gsd_updates_refresh_finalize (GObject *object)
{
GsdUpdatesRefresh *refresh;
g_return_if_fail (GSD_IS_UPDATES_REFRESH (object));
refresh = GSD_UPDATES_REFRESH (object);
g_return_if_fail (refresh->priv != NULL);
if (refresh->priv->timeout_id != 0)
g_source_remove (refresh->priv->timeout_id);
if (refresh->priv->periodic_id != 0)
g_source_remove (refresh->priv->periodic_id);
g_signal_handlers_disconnect_by_data (refresh->priv->client, refresh);
g_signal_handlers_disconnect_by_data (refresh->priv->proxy_session, refresh);
g_object_unref (refresh->priv->control);
g_object_unref (refresh->priv->settings);
g_object_unref (refresh->priv->client);
if (refresh->priv->proxy_session != NULL)
g_object_unref (refresh->priv->proxy_session);
G_OBJECT_CLASS (gsd_updates_refresh_parent_class)->finalize (object);
}
GsdUpdatesRefresh *
gsd_updates_refresh_new (void)
{
GsdUpdatesRefresh *refresh;
refresh = g_object_new (GSD_TYPE_UPDATES_REFRESH, NULL);
return GSD_UPDATES_REFRESH (refresh);
}
./plugins/updates/gsd-updates-refresh.h 0000644 0000041 0000041 00000003612 13264221014 020413 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2007-2011 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#ifndef __GSD_UPDATES_REFRESH_H
#define __GSD_UPDATES_REFRESH_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_UPDATES_REFRESH (gsd_updates_refresh_get_type ())
#define GSD_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefresh))
#define GSD_UPDATES_REFRESH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshClass))
#define GSD_IS_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UPDATES_REFRESH))
typedef struct GsdUpdatesRefreshPrivate GsdUpdatesRefreshPrivate;
typedef struct
{
GObject parent;
GsdUpdatesRefreshPrivate *priv;
} GsdUpdatesRefresh;
typedef struct
{
GObjectClass parent_class;
} GsdUpdatesRefreshClass;
GType gsd_updates_refresh_get_type (void);
GsdUpdatesRefresh *gsd_updates_refresh_new (void);
G_END_DECLS
#endif /* __GSD_UPDATES_REFRESH_H */
./plugins/updates/gsd-updates-firmware.c 0000644 0000041 0000041 00000107504 13264221014 020571 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007-2012 Richard Hughes
*
* Licensed under the GNU General Public License Version 2
*
* 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.
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
#include
#endif /* HAVE_UNISTD_H */
#include
#include
#include
#include
#ifdef HAVE_GUDEV
#include
#endif
#include "gsd-updates-common.h"
#include "gsd-updates-firmware.h"
static void gsd_updates_firmware_finalize (GObject *object);
#define GSD_UPDATES_FIRMWARE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_UPDATES_TYPE_FIRMWARE, GsdUpdatesFirmwarePrivate))
#define GSD_UPDATES_FIRMWARE_MISSING_DIR "/run/udev/firmware-missing"
#define GSD_UPDATES_FIRMWARE_LOADING_DIR "/lib/firmware"
#define GSD_UPDATES_FIRMWARE_LOGIN_DELAY 10 /* seconds */
#define GSD_UPDATES_FIRMWARE_PROCESS_DELAY 2 /* seconds */
#define GSD_UPDATES_FIRMWARE_INSERT_DELAY 2 /* seconds */
#define GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM "/usr/sbin/pk-device-rebind"
struct GsdUpdatesFirmwarePrivate
{
GSettings *settings;
GFileMonitor *monitor;
GPtrArray *array_requested;
PkTask *task;
GPtrArray *packages_found;
guint timeout_id;
};
typedef enum {
FIRMWARE_SUBSYSTEM_USB,
FIRMWARE_SUBSYSTEM_PCI,
FIRMWARE_SUBSYSTEM_UNKNOWN
} FirmwareSubsystem;
typedef struct {
gchar *filename;
gchar *sysfs_path;
gchar *model;
gchar *id;
FirmwareSubsystem subsystem;
} GsdUpdatesFirmwareRequest;
G_DEFINE_TYPE (GsdUpdatesFirmware, gsd_updates_firmware, G_TYPE_OBJECT)
static void install_package_ids (GsdUpdatesFirmware *firmware);
static void ignore_devices (GsdUpdatesFirmware *firmware);
static gboolean
subsystem_can_replug (FirmwareSubsystem subsystem)
{
if (subsystem == FIRMWARE_SUBSYSTEM_USB)
return TRUE;
return FALSE;
}
static GsdUpdatesFirmwareRequest *
request_new (const gchar *filename, const gchar *sysfs_path)
{
GsdUpdatesFirmwareRequest *req;
#ifdef HAVE_GUDEV
GUdevDevice *device;
GUdevClient *client;
const gchar *subsystem;
const gchar *model;
const gchar *id_vendor;
const gchar *id_product;
#endif
req = g_new0 (GsdUpdatesFirmwareRequest, 1);
req->filename = g_strdup (filename);
req->sysfs_path = g_strdup (sysfs_path);
req->subsystem = FIRMWARE_SUBSYSTEM_UNKNOWN;
#ifdef HAVE_GUDEV
/* get all subsystems */
client = g_udev_client_new (NULL);
device = g_udev_client_query_by_sysfs_path (client, sysfs_path);
if (device == NULL)
goto out;
/* find subsystem, which will affect if we have to replug, or reboot */
subsystem = g_udev_device_get_subsystem (device);
if (g_strcmp0 (subsystem, "usb") == 0) {
req->subsystem = FIRMWARE_SUBSYSTEM_USB;
} else if (g_strcmp0 (subsystem, "pci") == 0) {
req->subsystem = FIRMWARE_SUBSYSTEM_PCI;
} else {
g_warning ("subsystem unrecognised: %s", subsystem);
}
/* get model, so we can show something sensible */
model = g_udev_device_get_property (device, "ID_MODEL");
if (model != NULL && model[0] != '\0') {
req->model = g_strdup (model);
/* replace invalid chars */
g_strdelimit (req->model, "_", ' ');
}
/* create ID so we can ignore the specific device */
id_vendor = g_udev_device_get_property (device, "ID_VENDOR");
id_product = g_udev_device_get_property (device, "ID_MODEL_ID");
req->id = g_strdup_printf ("%s_%s", id_vendor, id_product);
out:
if (device != NULL)
g_object_unref (device);
g_object_unref (client);
#endif
return req;
}
static void
request_free (GsdUpdatesFirmwareRequest *req)
{
g_free (req->filename);
g_free (req->model);
g_free (req->sysfs_path);
g_free (req->id);
g_free (req);
}
static gboolean
device_rebind (GsdUpdatesFirmware *firmware)
{
gboolean ret;
gchar *argv[4];
gchar *rebind_stderr = NULL;
gchar *rebind_stdout = NULL;
GError *error = NULL;
gint exit_status = 0;
guint i;
GPtrArray *array;
const GsdUpdatesFirmwareRequest *req;
GString *string;
string = g_string_new ("");
/* make a string array of all the devices to replug */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
g_string_append_printf (string, "%s ", req->sysfs_path);
}
/* remove trailing space */
if (string->len > 0)
g_string_set_size (string, string->len-1);
/* use PolicyKit to do this as root */
argv[0] = "pkexec";
argv[1] = GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM;
argv[2] = string->str;
argv[3] = NULL;
ret = g_spawn_sync (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH,
NULL, NULL,
&rebind_stdout,
&rebind_stderr,
&exit_status,
&error);
if (!ret) {
g_warning ("failed to spawn '%s': %s",
argv[1], error->message);
g_error_free (error);
goto out;
}
/* if we failed to rebind the device */
if (exit_status != 0) {
g_warning ("failed to rebind: %s, %s",
rebind_stdout, rebind_stderr);
ret = FALSE;
goto out;
}
out:
g_free (rebind_stdout);
g_free (rebind_stderr);
g_string_free (string, TRUE);
return ret;
}
static void
libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
{
GsdUpdatesFirmware *firmware = GSD_UPDATES_FIRMWARE (data);
if (g_strcmp0 (action, "install-firmware") == 0) {
install_package_ids (firmware);
} else if (g_strcmp0 (action, "ignore-devices") == 0) {
ignore_devices (firmware);
} else {
g_warning ("unknown action id: %s", action);
}
notify_notification_close (notification, NULL);
}
static void
on_notification_closed (NotifyNotification *notification, gpointer data)
{
g_object_unref (notification);
}
static void
require_restart (GsdUpdatesFirmware *firmware)
{
const gchar *message;
gboolean ret;
GError *error = NULL;
NotifyNotification *notification;
/* TRANSLATORS: we need to restart so the new hardware can re-request the firmware */
message = _("You will need to restart this computer before the hardware will work correctly.");
/* TRANSLATORS: title of libnotify bubble */
notification = notify_notification_new (_("Additional software was installed"), message, NULL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
/* show the bubble */
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
}
static void
require_replug (GsdUpdatesFirmware *firmware)
{
const gchar *message;
gboolean ret;
GError *error = NULL;
NotifyNotification *notification;
/* TRANSLATORS: we need to remove an replug so the new hardware can re-request the firmware */
message = _("You will need to remove and then reinsert the hardware before it will work correctly.");
/* TRANSLATORS: title of libnotify bubble */
notification = notify_notification_new (_("Additional software was installed"), message, NULL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
/* show the bubble */
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
}
static void
require_nothing (GsdUpdatesFirmware *firmware)
{
const gchar *message;
gboolean ret;
GError *error = NULL;
NotifyNotification *notification;
/* TRANSLATORS: we need to remove an replug so the new hardware can re-request the firmware */
message = _("Your hardware has been set up and is now ready to use.");
/* TRANSLATORS: title of libnotify bubble */
notification = notify_notification_new (_("Additional software was installed"), message, NULL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
/* show the bubble */
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
}
static void
install_packages_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesFirmware *firmware)
{
PkClient *client = PK_CLIENT (object);
GError *error = NULL;
PkResults *results = NULL;
GPtrArray *array = NULL;
gboolean restart = FALSE;
const GsdUpdatesFirmwareRequest *req;
gboolean ret;
guint i;
PkError *error_code = NULL;
/* get the results */
results = pk_client_generic_finish (client, res, &error);
if (results == NULL) {
g_warning ("failed to install file: %s", error->message);
g_error_free (error);
goto out;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to install file: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
goto out;
}
/* go through all the requests, and find the worst type */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
ret = subsystem_can_replug (req->subsystem);
if (!ret) {
restart = TRUE;
break;
}
}
/* can we just rebind the device */
ret = g_file_test (GSD_UPDATES_FIRMWARE_DEVICE_REBIND_PROGRAM, G_FILE_TEST_EXISTS);
if (ret) {
ret = device_rebind (firmware);
if (ret) {
require_nothing (firmware);
goto out;
}
} else {
/* give the user the correct message */
if (restart)
require_restart (firmware);
else
require_replug (firmware);
}
/* clear array */
g_ptr_array_set_size (firmware->priv->array_requested, 0);
out:
if (error_code != NULL)
g_object_unref (error_code);
if (array != NULL)
g_ptr_array_unref (array);
if (results != NULL)
g_object_unref (results);
}
static gchar **
package_array_to_strv (GPtrArray *array)
{
PkPackage *item;
gchar **results;
guint i;
results = g_new0 (gchar *, array->len+1);
for (i=0; ilen; i++) {
item = g_ptr_array_index (array, i);
results[i] = g_strdup (pk_package_get_id (item));
}
return results;
}
static void
install_package_ids (GsdUpdatesFirmware *firmware)
{
gchar **package_ids;
/* install all of the firmware files */
package_ids = package_array_to_strv (firmware->priv->packages_found);
pk_client_install_packages_async (PK_CLIENT(firmware->priv->task),
TRUE, package_ids,
NULL,
NULL, NULL,
(GAsyncReadyCallback) install_packages_cb,
firmware);
g_strfreev (package_ids);
}
static void
ignore_devices (GsdUpdatesFirmware *firmware)
{
gchar *existing = NULL;
GsdUpdatesFirmwareRequest *req;
GPtrArray *array;
GString *string;
guint i;
/* get from settings */
existing = g_settings_get_string (firmware->priv->settings,
GSD_SETTINGS_IGNORED_DEVICES);
/* get existing string */
string = g_string_new (existing);
if (string->len > 0)
g_string_append (string, ",");
/* add all listed devices */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
g_string_append_printf (string, "%s,", req->id);
}
/* remove final ',' */
if (string->len > 2)
g_string_set_size (string, string->len - 1);
/* set new string */
g_settings_set_string (firmware->priv->settings,
GSD_SETTINGS_IGNORED_DEVICES,
string->str);
g_free (existing);
g_string_free (string, TRUE);
}
static PkPackage *
check_available (GsdUpdatesFirmware *firmware, const gchar *filename)
{
guint length = 0;
GPtrArray *array = NULL;
GError *error = NULL;
PkPackage *item = NULL;
PkBitfield filter;
PkResults *results;
gchar **values = NULL;
PkError *error_code = NULL;
/* search for newest not installed package */
filter = pk_bitfield_from_enums (PK_FILTER_ENUM_NOT_INSTALLED,
PK_FILTER_ENUM_NEWEST, -1);
values = g_strsplit (filename, "&", -1);
results = pk_client_search_files (PK_CLIENT(firmware->priv->task),
filter,
values,
NULL,
NULL, NULL,
&error);
if (results == NULL) {
g_warning ("failed to search file %s: %s",
filename, error->message);
g_error_free (error);
goto out;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to search file: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
goto out;
}
/* make sure we have one package */
array = pk_results_get_package_array (results);
if (array->len == 0)
g_debug ("no package providing %s found", filename);
else if (array->len != 1)
g_warning ("not one package providing %s found (%i)", filename, length);
else
item = g_object_ref (g_ptr_array_index (array, 0));
out:
g_strfreev (values);
if (error_code != NULL)
g_object_unref (error_code);
if (array != NULL)
g_ptr_array_unref (array);
if (results != NULL)
g_object_unref (results);
return item;
}
static void
remove_duplicate (GPtrArray *array)
{
guint i, j;
const gchar *val;
const gchar *val_tmp;
/* remove each duplicate entry */
for (i=0; ilen; i++) {
val = g_ptr_array_index (array, i);
for (j=i+1; jlen; j++) {
val_tmp = g_ptr_array_index (array, j);
if (g_strcmp0 (val_tmp, val) == 0)
g_ptr_array_remove_index_fast (array, j);
}
}
}
static gboolean
delay_timeout_cb (gpointer data)
{
guint i;
gboolean ret;
GString *string;
GsdUpdatesFirmware *firmware = GSD_UPDATES_FIRMWARE (data);
NotifyNotification *notification;
GPtrArray *array;
GError *error = NULL;
PkPackage *item = NULL;
const GsdUpdatesFirmwareRequest *req;
gboolean has_data = FALSE;
/* message string */
string = g_string_new ("");
/* try to find each firmware file in an available package */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
/* save to new array if we found one package for this file */
item = check_available (firmware, req->filename);
if (item != NULL) {
g_ptr_array_add (firmware->priv->packages_found, item);
g_object_unref (item);
}
}
/* nothing to do */
if (firmware->priv->packages_found->len == 0) {
g_debug ("no packages providing any of the missing firmware");
goto out;
}
/* check we don't want the same package more than once */
remove_duplicate (firmware->priv->packages_found);
/* have we got any models to array */
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
if (req->model != NULL) {
has_data = TRUE;
break;
}
}
/* TRANSLATORS: we need another package to keep udev quiet */
g_string_append (string, _("Additional firmware is required to make hardware in this computer function correctly."));
/* sdd what information we have */
if (has_data) {
g_string_append (string, "\n");
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
if (req->model != NULL)
g_string_append_printf (string, "\n• %s", req->model);
}
g_string_append (string, "\n");
}
/* TRANSLATORS: title of libnotify bubble */
notification = notify_notification_new (_("Additional firmware required"), string->str, NULL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
notify_notification_add_action (notification, "install-firmware",
/* TRANSLATORS: button label */
_("Install firmware"), libnotify_cb, firmware, NULL);
notify_notification_add_action (notification, "ignore-devices",
/* TRANSLATORS: we should ignore this device and not ask anymore */
_("Ignore devices"), libnotify_cb, firmware, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
out:
g_string_free (string, TRUE);
/* never repeat */
return FALSE;
}
static void
remove_banned (GsdUpdatesFirmware *firmware, GPtrArray *array)
{
gboolean ret;
gchar **banned = NULL;
gchar *banned_str;
GsdUpdatesFirmwareRequest *req;
guint i, j;
/* get from settings */
banned_str = g_settings_get_string (firmware->priv->settings,
GSD_SETTINGS_BANNED_FIRMWARE);
if (banned_str == NULL) {
g_warning ("could not read banned list");
goto out;
}
/* nothing in list, common case */
if (banned_str[0] == '\0') {
g_debug ("nothing in banned list");
goto out;
}
/* split using "," */
banned = g_strsplit (banned_str, ",", 0);
/* remove any banned pattern matches */
i = 0;
while (i < array->len) {
ret = FALSE;
req = g_ptr_array_index (array, i);
for (j=0; banned[j] != NULL; j++) {
ret = g_pattern_match_simple (banned[j], req->filename);
if (ret) {
g_debug ("match %s for %s, removing",
banned[j], req->filename);
g_ptr_array_remove_index_fast (array, i);
break;
}
}
if (!ret)
i++;
}
out:
g_free (banned_str);
g_strfreev (banned);
}
static void
remove_ignored (GsdUpdatesFirmware *firmware, GPtrArray *array)
{
gboolean ret;
gchar **ignored = NULL;
gchar *ignored_str;
GsdUpdatesFirmwareRequest *req;
guint i, j;
/* get from settings */
ignored_str = g_settings_get_string (firmware->priv->settings,
GSD_SETTINGS_IGNORED_DEVICES);
if (ignored_str == NULL) {
g_warning ("could not read ignored list");
goto out;
}
/* nothing in list, common case */
if (ignored_str[0] == '\0') {
g_debug ("nothing in ignored list");
goto out;
}
/* split using "," */
ignored = g_strsplit (ignored_str, ",", 0);
/* remove any ignored pattern matches */
i = 0;
while (i < array->len) {
ret = FALSE;
req = g_ptr_array_index (array, i);
if (req->id == NULL)
continue;
for (j=0; ignored[j] != NULL; j++) {
ret = g_pattern_match_simple (ignored[j], req->id);
if (ret) {
g_debug ("match %s for %s, removing", ignored[j], req->id);
g_ptr_array_remove_index_fast (array, i);
break;
}
}
if (!ret)
i++;
}
out:
g_free (ignored_str);
g_strfreev (ignored);
}
static gchar *
udev_text_decode (const gchar *data)
{
guint i;
guint j;
gchar *decode;
decode = g_strdup (data);
for (i = 0, j = 0; data[i] != '\0'; j++) {
if (memcmp (&data[i], "\\x2f", 4) == 0) {
decode[j] = '/';
i += 4;
} else if (memcmp (&data[i], "\\x5c", 4) == 0) {
decode[j] = '\\';
i += 4;
} else {
decode[j] = data[i];
i++;
}
}
decode[j] = '\0';
return decode;
}
static gchar *
get_device (GsdUpdatesFirmware *firmware, const gchar *filename)
{
GFile *file;
GFileInfo *info;
const gchar *symlink_path;
gchar *syspath = NULL;
GError *error = NULL;
gchar *target = NULL;
gchar *tmp;
/* get the file data */
file = g_file_new_for_path (filename);
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
if (info == NULL) {
g_warning ("Failed to get symlink: %s",
error->message);
g_error_free (error);
goto out;
}
/* /devices/pci0000:00/0000:00:1d.0/usb5/5-2/firmware/5-2 */
symlink_path = g_file_info_get_symlink_target (info);
if (symlink_path == NULL) {
g_warning ("failed to get symlink target");
goto out;
}
/* prepend sys to make '/sys/devices/pci0000:00/0000:00:1d.0/usb5/5-2/firmware/5-2' */
syspath = g_strconcat ("/sys", symlink_path, NULL);
/* start with the longest, and try to find a sub-path that exists */
tmp = &syspath[strlen (syspath)];
while (tmp != NULL) {
*tmp = '\0';
g_debug ("testing %s", target);
if (g_file_test (syspath, G_FILE_TEST_EXISTS)) {
target = g_strdup (syspath);
goto out;
}
tmp = g_strrstr (syspath, "/");
}
out:
if (info != NULL)
g_object_unref (info);
g_object_unref (file);
g_free (syspath);
return target;
}
static void
add_filename (GsdUpdatesFirmware *firmware, const gchar *filename_no_path)
{
gboolean ret;
gchar *filename_path = NULL;
gchar *missing_path = NULL;
gchar *sysfs_path = NULL;
GsdUpdatesFirmwareRequest *req;
GPtrArray *array;
guint i;
/* this is the file we want to load */
filename_path = g_build_filename (GSD_UPDATES_FIRMWARE_LOADING_DIR,
filename_no_path, NULL);
/* file already exists */
ret = g_file_test (filename_path, G_FILE_TEST_EXISTS);
if (ret)
goto out;
/* this is the file that udev created for us */
missing_path = g_build_filename (GSD_UPDATES_FIRMWARE_MISSING_DIR,
filename_no_path, NULL);
g_debug ("filename=%s -> %s", missing_path, filename_path);
/* get symlink target */
sysfs_path = get_device (firmware, missing_path);
if (sysfs_path == NULL)
goto out;
/* find any previous requests with this path or firmware */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
if (g_strcmp0 (sysfs_path, req->sysfs_path) == 0) {
g_debug ("ignoring previous sysfs request for %s",
sysfs_path);
goto out;
}
if (g_strcmp0 (filename_path, req->filename) == 0) {
g_debug ("ignoring previous filename request for %s",
filename_path);
goto out;
}
}
/* create new request object */
req = request_new (filename_path, sysfs_path);
g_ptr_array_add (firmware->priv->array_requested, req);
out:
g_free (missing_path);
g_free (filename_path);
g_free (sysfs_path);
}
static void
scan_directory (GsdUpdatesFirmware *firmware)
{
gboolean ret;
GError *error = NULL;
GDir *dir;
const gchar *filename;
gchar *filename_decoded;
guint i;
GPtrArray *array;
const GsdUpdatesFirmwareRequest *req;
guint scan_id = 0;
/* should we check and show the user */
ret = g_settings_get_boolean (firmware->priv->settings,
GSD_SETTINGS_ENABLE_CHECK_FIRMWARE);
if (!ret) {
g_debug ("not showing thanks to GSettings");
return;
}
/* open the directory of requests */
dir = g_dir_open (GSD_UPDATES_FIRMWARE_MISSING_DIR, 0, &error);
if (dir == NULL) {
if (error->code != G_FILE_ERROR_NOENT) {
g_warning ("failed to open directory: %s",
error->message);
}
g_error_free (error);
return;
}
/* find all the firmware requests */
filename = g_dir_read_name (dir);
while (filename != NULL) {
filename_decoded = udev_text_decode (filename);
add_filename (firmware, filename_decoded);
g_free (filename_decoded);
/* next file */
filename = g_dir_read_name (dir);
}
g_dir_close (dir);
/* debugging */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
g_debug ("requested: %s", req->filename);
}
/* remove banned files */
remove_banned (firmware, array);
/* remove ignored devices */
remove_ignored (firmware, array);
/* debugging */
array = firmware->priv->array_requested;
for (i=0; ilen; i++) {
req = g_ptr_array_index (array, i);
g_debug ("searching for: %s", req->filename);
}
/* don't spam the user at startup, so wait a little delay */
if (array->len > 0) {
scan_id = g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_PROCESS_DELAY,
delay_timeout_cb,
firmware);
g_source_set_name_by_id (scan_id, "[GsdUpdatesFirmware] process");
}
}
static gboolean
scan_directory_cb (GsdUpdatesFirmware *firmware)
{
scan_directory (firmware);
firmware->priv->timeout_id = 0;
return FALSE;
}
static void
monitor_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
GsdUpdatesFirmware *firmware)
{
if (firmware->priv->timeout_id > 0) {
g_debug ("clearing timeout as device changed");
g_source_remove (firmware->priv->timeout_id);
}
/* wait for the device to settle */
firmware->priv->timeout_id =
g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_INSERT_DELAY,
(GSourceFunc) scan_directory_cb,
firmware);
g_source_set_name_by_id (firmware->priv->timeout_id,
"[GsdUpdatesFirmware] changed");
}
static void
gsd_updates_firmware_class_init (GsdUpdatesFirmwareClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_updates_firmware_finalize;
g_type_class_add_private (klass, sizeof (GsdUpdatesFirmwarePrivate));
}
static void
gsd_updates_firmware_init (GsdUpdatesFirmware *firmware)
{
GFile *file;
GError *error = NULL;
firmware->priv = GSD_UPDATES_FIRMWARE_GET_PRIVATE (firmware);
firmware->priv->timeout_id = 0;
firmware->priv->packages_found = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
firmware->priv->array_requested = g_ptr_array_new_with_free_func ((GDestroyNotify) request_free);
firmware->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA);
firmware->priv->task = pk_task_new ();
g_object_set (firmware->priv->task,
"background", TRUE,
NULL);
/* setup watch for new hardware */
file = g_file_new_for_path (GSD_UPDATES_FIRMWARE_MISSING_DIR);
firmware->priv->monitor = g_file_monitor (file,
G_FILE_MONITOR_NONE,
NULL,
&error);
if (firmware->priv->monitor == NULL) {
g_warning ("failed to setup monitor: %s", error->message);
g_error_free (error);
goto out;
}
/* limit to one per second */
g_file_monitor_set_rate_limit (firmware->priv->monitor, 1000);
/* get notified of changes */
g_signal_connect (firmware->priv->monitor, "changed",
G_CALLBACK (monitor_changed_cb), firmware);
out:
g_object_unref (file);
firmware->priv->timeout_id =
g_timeout_add_seconds (GSD_UPDATES_FIRMWARE_LOGIN_DELAY,
(GSourceFunc) scan_directory_cb,
firmware);
g_source_set_name_by_id (firmware->priv->timeout_id,
"[GsdUpdatesFirmware] login coldplug");
}
static void
gsd_updates_firmware_finalize (GObject *object)
{
GsdUpdatesFirmware *firmware;
g_return_if_fail (GSD_UPDATES_IS_FIRMWARE (object));
firmware = GSD_UPDATES_FIRMWARE (object);
g_return_if_fail (firmware->priv != NULL);
g_ptr_array_unref (firmware->priv->array_requested);
g_ptr_array_unref (firmware->priv->packages_found);
g_object_unref (PK_CLIENT(firmware->priv->task));
g_object_unref (firmware->priv->settings);
if (firmware->priv->monitor != NULL)
g_object_unref (firmware->priv->monitor);
if (firmware->priv->timeout_id > 0)
g_source_remove (firmware->priv->timeout_id);
G_OBJECT_CLASS (gsd_updates_firmware_parent_class)->finalize (object);
}
GsdUpdatesFirmware *
gsd_updates_firmware_new (void)
{
GsdUpdatesFirmware *firmware;
firmware = g_object_new (GSD_UPDATES_TYPE_FIRMWARE, NULL);
return GSD_UPDATES_FIRMWARE (firmware);
}
./plugins/updates/gsd-updates-plugin.c 0000644 0000041 0000041 00000002024 13264221014 020242 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011 Richard Hughes
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-updates-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdUpdates, gsd_updates)
./plugins/updates/updates-design.svg 0000644 0000041 0000041 00000101240 13264221014 020017 0 ustar www-data www-data
./plugins/updates/gsd-updates-manager.c 0000644 0000041 0000041 00000161515 13264221014 020371 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011 Richard Hughes
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include "gsd-enums.h"
#include "gsd-updates-manager.h"
#include "gsd-updates-firmware.h"
#include "gsd-updates-refresh.h"
#include "gsd-updates-common.h"
#include "gnome-settings-profile.h"
#include "gnome-settings-bus.h"
#define GSD_UPDATES_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerPrivate))
#define MAX_FAILED_GET_UPDATES 10 /* the maximum number of tries */
#define GSD_UPDATES_ICON_NORMAL "software-update-available-symbolic"
#define GSD_UPDATES_ICON_URGENT "software-update-urgent-symbolic"
#define GSD_UPDATES_CHECK_OFFLINE_TIMEOUT 30 /* time in seconds */
struct GsdUpdatesManagerPrivate
{
GCancellable *cancellable;
GsdUpdatesRefresh *refresh;
GsdUpdatesFirmware *firmware;
GSettings *settings_proxy;
GSettings *settings_ftp;
GSettings *settings_gsd;
GSettings *settings_http;
guint number_updates_critical_last_shown;
guint offline_update_id;
PkError *offline_update_error;
NotifyNotification *notification_updates;
PkControl *control;
PkTask *task;
guint inhibit_cookie;
GsdSessionManager *proxy_session;
guint update_viewer_watcher_id;
GVolumeMonitor *volume_monitor;
guint failed_get_updates_count;
GPtrArray *update_packages;
};
static void gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass);
static void gsd_updates_manager_init (GsdUpdatesManager *updates_manager);
G_DEFINE_TYPE (GsdUpdatesManager, gsd_updates_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static void
child_exit_cb (GPid pid, gint status, gpointer user_data)
{
g_spawn_close_pid (pid);
}
static void
clear_offline_updates_message (void)
{
gboolean ret;
GError *error = NULL;
gchar *argv[3];
GPid pid;
argv[0] = "pkexec";
argv[1] = LIBEXECDIR "/pk-clear-offline-update";
argv[2] = NULL;
ret = g_spawn_async (NULL,
argv,
NULL,
G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
NULL,
NULL,
&pid,
&error);
if (!ret) {
g_warning ("Failure clearing offline update message: %s",
error->message);
g_error_free (error);
return;
}
g_child_watch_add (pid, child_exit_cb, NULL);
}
static void
show_offline_updates_error (GsdUpdatesManager *manager)
{
const gchar *title;
gboolean show_geeky = FALSE;
GString *msg;
GtkWidget *dialog;
/* TRANSLATORS: this is when the offline update failed */
title = _("Failed To Update");
msg = g_string_new ("");
switch (pk_error_get_code (manager->priv->offline_update_error)) {
case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
/* TRANSLATORS: the transaction could not be completed
* as a previous transaction was unfinished */
g_string_append (msg, _("A previous update was unfinished."));
show_geeky = TRUE;
break;
case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
case PK_ERROR_ENUM_NO_CACHE:
case PK_ERROR_ENUM_NO_NETWORK:
case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY:
case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
/* TRANSLATORS: the package manager needed to download
* something with no network available */
g_string_append (msg, _("Network access was required but not available."));
break;
case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
case PK_ERROR_ENUM_GPG_FAILURE:
case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE:
case PK_ERROR_ENUM_PACKAGE_CORRUPT:
/* TRANSLATORS: if the package is not signed correctly
* */
g_string_append (msg, _("An update was not signed in the correct way."));
show_geeky = TRUE;
break;
case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
case PK_ERROR_ENUM_FILE_CONFLICTS:
case PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE:
case PK_ERROR_ENUM_PACKAGE_CONFLICTS:
/* TRANSLATORS: the transaction failed in a way the user
* probably cannot comprehend. Package management systems
* really are teh suck.*/
g_string_append (msg, _("The update could not be completed."));
show_geeky = TRUE;
break;
case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
/* TRANSLATORS: the user aborted the update manually */
g_string_append (msg, _("The update was cancelled."));
break;
case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
/* TRANSLATORS: the user must have updated manually after
* the updates were prepared */
g_string_append (msg, _("An offline update was requested but no packages required updating."));
break;
case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
/* TRANSLATORS: we ran out of disk space */
g_string_append (msg, _("No space was left on the drive."));
break;
case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD:
case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL:
case PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE:
/* TRANSLATORS: the update process failed in a general
* way, usually this message will come from source distros
* like gentoo */
g_string_append (msg, _("An update failed to install correctly."));
show_geeky = TRUE;
break;
default:
/* TRANSLATORS: We didn't handle the error type */
g_string_append (msg, _("The offline update failed in an unexpected way."));
show_geeky = TRUE;
break;
}
if (show_geeky) {
g_string_append_printf (msg, "\n%s\n\n%s",
/* TRANSLATORS: these are geeky messages from the
* package manager no mortal is supposed to understand,
* but google might know what they mean */
_("Detailed errors from the package manager follow:"),
pk_error_get_details (manager->priv->offline_update_error));
}
dialog = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"%s", title);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", msg->str);
g_signal_connect_swapped (dialog, "response",
G_CALLBACK (gtk_widget_destroy),
dialog);
gtk_widget_show (dialog);
clear_offline_updates_message ();
g_string_free (msg, TRUE);
}
static void
libnotify_action_cb (NotifyNotification *notification,
gchar *action,
gpointer user_data)
{
gboolean ret;
GError *error = NULL;
GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data);
notify_notification_close (notification, NULL);
if (g_strcmp0 (action, "distro-upgrade-info") == 0) {
ret = g_spawn_command_line_async (DATADIR "/PackageKit/pk-upgrade-distro.sh",
&error);
if (!ret) {
g_warning ("Failure launching pk-upgrade-distro.sh: %s",
error->message);
g_error_free (error);
}
goto out;
}
if (g_strcmp0 (action, "show-update-viewer") == 0) {
ret = g_spawn_command_line_async (BINDIR "/gpk-update-viewer",
&error);
if (!ret) {
g_warning ("Failure launching update viewer: %s",
error->message);
g_error_free (error);
}
goto out;
}
if (g_strcmp0 (action, "clear-offline-updates") == 0) {
clear_offline_updates_message ();
goto out;
}
if (g_strcmp0 (action, "error-offline-updates") == 0) {
show_offline_updates_error (manager);
goto out;
}
if (g_strcmp0 (action, "cancel") == 0) {
/* try to cancel */
g_cancellable_cancel (manager->priv->cancellable);
goto out;
}
g_warning ("unknown action id: %s", action);
out:
return;
}
static void
on_notification_closed (NotifyNotification *notification, gpointer data)
{
g_object_unref (notification);
}
static void
get_distro_upgrades_finished_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesManager *manager)
{
const gchar *title;
gboolean ret;
gchar *name = NULL;
GError *error = NULL;
GPtrArray *array = NULL;
GString *string = NULL;
guint i;
NotifyNotification *notification;
PkClient *client = PK_CLIENT(object);
PkDistroUpgrade *item;
PkError *error_code = NULL;
PkResults *results;
PkUpdateStateEnum state;
/* get the results */
results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
if (results == NULL) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error_free (error);
return;
}
if (error->domain != PK_CLIENT_ERROR ||
error->code != PK_CLIENT_ERROR_NOT_SUPPORTED) {
g_warning ("failed to get upgrades: %s",
error->message);
}
g_error_free (error);
goto out;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to get upgrades: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
goto out;
}
/* process results */
array = pk_results_get_distro_upgrade_array (results);
/* any updates? */
if (array->len == 0) {
g_debug ("no upgrades");
goto out;
}
/* do we do the notification? */
ret = g_settings_get_boolean (manager->priv->settings_gsd,
GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES);
if (!ret) {
g_debug ("ignoring due to GSettings");
goto out;
}
/* find the upgrade string */
string = g_string_new ("");
for (i=0; i < array->len; i++) {
item = (PkDistroUpgrade *) g_ptr_array_index (array, i);
g_object_get (item,
"name", &name,
"state", &state,
NULL);
g_string_append_printf (string, "%s (%s)\n",
name,
pk_distro_upgrade_enum_to_string (state));
g_free (name);
}
if (string->len != 0)
g_string_set_size (string, string->len-1);
/* TRANSLATORS: a distro update is available, e.g. Fedora 8 to Fedora 9 */
title = _("Distribution upgrades available");
notification = notify_notification_new (title,
string->str,
GSD_UPDATES_ICON_NORMAL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
notify_notification_add_action (notification, "distro-upgrade-info",
/* TRANSLATORS: provides more information about the upgrade */
_("More information"),
libnotify_action_cb,
manager, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
out:
if (error_code != NULL)
g_object_unref (error_code);
if (array != NULL)
g_ptr_array_unref (array);
if (string != NULL)
g_string_free (string, TRUE);
if (results != NULL)
g_object_unref (results);
}
static void
due_get_upgrades_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
{
/* optimize the amount of downloaded data by setting the cache age */
pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
g_settings_get_int (manager->priv->settings_gsd,
GSD_SETTINGS_FREQUENCY_GET_UPGRADES));
/* get new distro upgrades list */
pk_client_get_distro_upgrades_async (PK_CLIENT(manager->priv->task),
NULL,
NULL, NULL,
(GAsyncReadyCallback) get_distro_upgrades_finished_cb,
manager);
}
static void
refresh_cache_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager)
{
PkClient *client = PK_CLIENT(object);
PkResults *results;
GError *error = NULL;
PkError *error_code = NULL;
/* get the results */
results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
if (results == NULL) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error_free (error);
return;
}
g_warning ("failed to refresh the cache: %s",
error->message);
g_error_free (error);
return;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to refresh the cache: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
}
if (error_code != NULL)
g_object_unref (error_code);
if (results != NULL)
g_object_unref (results);
}
static void
due_refresh_cache_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
{
/* optimize the amount of downloaded data by setting the cache age */
pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
g_settings_get_int (manager->priv->settings_gsd,
GSD_SETTINGS_FREQUENCY_REFRESH_CACHE));
pk_client_refresh_cache_async (PK_CLIENT(manager->priv->task),
TRUE,
NULL,
NULL, NULL,
(GAsyncReadyCallback) refresh_cache_finished_cb,
manager);
}
static void
notify_critical_updates (GsdUpdatesManager *manager, GPtrArray *array)
{
const gchar *message;
const gchar *title;
gboolean ret;
GError *error = NULL;
NotifyNotification *notification;
/* if the number of critical updates is the same as the last notification,
* then skip the notifcation as we don't want to bombard the user every hour */
if (array->len == manager->priv->number_updates_critical_last_shown) {
g_debug ("ignoring as user ignored last warning");
return;
}
/* save for comparison later */
manager->priv->number_updates_critical_last_shown = array->len;
/* TRANSLATORS: title in the libnotify popup */
title = ngettext ("Update", "Updates", array->len);
/* TRANSLATORS: message when there are security updates */
message = ngettext ("An important software update is available",
"Important software updates are available", array->len);
/* close any existing notification */
if (manager->priv->notification_updates != NULL) {
notify_notification_close (manager->priv->notification_updates, NULL);
manager->priv->notification_updates = NULL;
}
/* do the bubble */
g_debug ("title=%s, message=%s", title, message);
notification = notify_notification_new (title,
message,
GSD_UPDATES_ICON_URGENT);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, 15000);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL);
notify_notification_add_action (notification, "show-update-viewer",
/* TRANSLATORS: button: open the update viewer to install updates*/
_("Install updates"), libnotify_action_cb, manager, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
/* track so we can prevent doubled notifications */
manager->priv->notification_updates = notification;
g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates),
(void **) &manager->priv->notification_updates);
}
static void
notify_normal_updates_maybe (GsdUpdatesManager *manager, GPtrArray *array)
{
const gchar *message;
const gchar *title;
gboolean ret;
GError *error = NULL;
guint64 time_last_notify;
guint64 time_now;
guint freq_updates_notify;
NotifyNotification *notification;
/* find out if enough time has passed since the last notification */
time_now = g_get_real_time () / 1000000;
freq_updates_notify = g_settings_get_int (manager->priv->settings_gsd,
GSD_SETTINGS_FREQUENCY_UPDATES_NOTIFICATION);
g_settings_get (manager->priv->settings_gsd,
GSD_SETTINGS_LAST_UPDATES_NOTIFICATION,
"t", &time_last_notify);
if (time_last_notify > 0 &&
(guint64) freq_updates_notify > time_now - time_last_notify) {
g_debug ("not showing non-critical notification as already shown %i hours ago",
(guint) (time_now - time_last_notify) / (60 * 60));
return;
}
/* TRANSLATORS: title in the libnotify popup */
title = ngettext ("Update", "Updates", array->len);
/* TRANSLATORS: message when there are non-security updates */
message = ngettext ("A software update is available.",
"Software updates are available.", array->len);
/* close any existing notification */
if (manager->priv->notification_updates != NULL) {
notify_notification_close (manager->priv->notification_updates, NULL);
manager->priv->notification_updates = NULL;
}
/* do the bubble */
g_debug ("title=%s, message=%s", title, message);
notification = notify_notification_new (title,
message,
GSD_UPDATES_ICON_NORMAL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, 15000);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
notify_notification_add_action (notification, "show-update-viewer",
/* TRANSLATORS: button: open the update viewer to install updates*/
_("Install updates"), libnotify_action_cb, manager, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
/* reset notification time */
g_settings_set (manager->priv->settings_gsd,
GSD_SETTINGS_LAST_UPDATES_NOTIFICATION,
"t", time_now);
/* track so we can prevent doubled notifications */
manager->priv->notification_updates = notification;
g_object_add_weak_pointer (G_OBJECT (manager->priv->notification_updates),
(void **) &manager->priv->notification_updates);
}
static void
notify_failed_get_updates_maybe (GsdUpdatesManager *manager)
{
const gchar *button;
const gchar *message;
const gchar *title;
gboolean ret;
GError *error = NULL;
NotifyNotification *notification;
/* give the user a break */
if (manager->priv->failed_get_updates_count++ < MAX_FAILED_GET_UPDATES) {
g_debug ("failed GetUpdates, but will retry %i more times before notification",
MAX_FAILED_GET_UPDATES - manager->priv->failed_get_updates_count);
goto out;
}
/* TRANSLATORS: the updates mechanism */
title = _("Updates");
/* TRANSLATORS: we failed to get the updates multiple times,
* and now we need to inform the user that something might be wrong */
message = _("Unable to access software updates");
/* TRANSLATORS: try again, this time launching the update viewer */
button = _("Try again");
notification = notify_notification_new (title,
message,
GSD_UPDATES_ICON_NORMAL);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, 120*1000);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
notify_notification_add_action (notification, "show-update-viewer",
button,
libnotify_action_cb,
manager, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("failed to show notification: %s",
error->message);
g_error_free (error);
}
out:
/* reset, even if the message failed */
manager->priv->failed_get_updates_count = 0;
}
static void
check_updates_for_importance (GsdUpdatesManager *manager)
{
guint i;
PkPackage *pkg;
GPtrArray *important_array;
/* check each package */
important_array = g_ptr_array_new ();
for (i = 0; i < manager->priv->update_packages->len; i++) {
pkg = g_ptr_array_index (manager->priv->update_packages, i);
if (pk_package_get_info (pkg) == PK_INFO_ENUM_SECURITY ||
pk_package_get_info (pkg) == PK_INFO_ENUM_IMPORTANT)
g_ptr_array_add (important_array, pkg);
}
if (important_array->len > 0) {
notify_critical_updates (manager,
important_array);
} else {
notify_normal_updates_maybe (manager,
manager->priv->update_packages);
}
g_ptr_array_unref (important_array);
}
static void
package_download_finished_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesManager *manager)
{
PkClient *client = PK_CLIENT(object);
PkResults *results;
GError *error = NULL;
PkError *error_code = NULL;
/* get the results */
results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
if (results == NULL) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error_free (error);
return;
}
g_warning ("failed to download: %s",
error->message);
g_error_free (error);
notify_failed_get_updates_maybe (manager);
return;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to download: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
switch (pk_error_get_code (error_code)) {
case PK_ERROR_ENUM_CANCELLED_PRIORITY:
case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
g_debug ("ignoring error");
break;
default:
notify_failed_get_updates_maybe (manager);
break;
}
goto out;
}
/* check to see if should notify */
check_updates_for_importance (manager);
out:
if (error_code != NULL)
g_object_unref (error_code);
if (results != NULL)
g_object_unref (results);
}
static void
auto_download_updates (GsdUpdatesManager *manager)
{
gchar **package_ids;
guint i;
PkPackage *pkg;
/* download each package */
package_ids = g_new0 (gchar *, manager->priv->update_packages->len + 1);
for (i = 0; i < manager->priv->update_packages->len; i++) {
pkg = g_ptr_array_index (manager->priv->update_packages, i);
package_ids[i] = g_strdup (pk_package_get_id (pkg));
}
#if PK_CHECK_VERSION(0,8,1)
/* we've set only-download in PkTask */
pk_task_update_packages_async (manager->priv->task,
package_ids,
manager->priv->cancellable,
NULL, NULL,
(GAsyncReadyCallback) package_download_finished_cb,
manager);
#else
/* download them all */
pk_client_download_packages_async (PK_CLIENT(manager->priv->task),
package_ids,
NULL, /* this means system cache */
manager->priv->cancellable,
NULL, NULL,
(GAsyncReadyCallback) package_download_finished_cb,
manager);
#endif
g_strfreev (package_ids);
}
static void
get_updates_finished_cb (GObject *object,
GAsyncResult *res,
GsdUpdatesManager *manager)
{
PkClient *client = PK_CLIENT(object);
PkResults *results;
GError *error = NULL;
gboolean ret;
PkError *error_code = NULL;
/* get the results */
results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
if (results == NULL) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error_free (error);
return;
}
g_warning ("failed to get updates: %s",
error->message);
g_error_free (error);
notify_failed_get_updates_maybe (manager);
goto out;
}
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_warning ("failed to get updates: %s, %s",
pk_error_enum_to_string (pk_error_get_code (error_code)),
pk_error_get_details (error_code));
switch (pk_error_get_code (error_code)) {
case PK_ERROR_ENUM_CANCELLED_PRIORITY:
case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
g_debug ("ignoring error");
break;
default:
notify_failed_get_updates_maybe (manager);
break;
}
goto out;
}
/* we succeeded, so clear the count */
manager->priv->failed_get_updates_count = 0;
/* so we can download or check for important & security updates */
if (manager->priv->update_packages != NULL)
g_ptr_array_unref (manager->priv->update_packages);
manager->priv->update_packages = pk_results_get_package_array (results);
/* we have no updates */
if (manager->priv->update_packages->len == 0) {
g_debug ("no updates");
goto out;
}
/* should we auto-download the updates? */
ret = g_settings_get_boolean (manager->priv->settings_gsd,
GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES);
if (ret) {
auto_download_updates (manager);
goto out;
}
/* just check to see if should notify */
check_updates_for_importance (manager);
out:
if (error_code != NULL)
g_object_unref (error_code);
if (results != NULL)
g_object_unref (results);
}
static void
query_updates (GsdUpdatesManager *manager)
{
/* optimize the amount of downloaded data by setting the cache age */
pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
g_settings_get_int (manager->priv->settings_gsd,
GSD_SETTINGS_FREQUENCY_GET_UPDATES));
/* get new update list */
pk_client_get_updates_async (PK_CLIENT(manager->priv->task),
pk_bitfield_value (PK_FILTER_ENUM_NONE),
manager->priv->cancellable,
NULL, NULL,
(GAsyncReadyCallback) get_updates_finished_cb,
manager);
}
static void
due_get_updates_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
{
query_updates (manager);
}
static gchar *
get_proxy_http (GsdUpdatesManager *manager)
{
gboolean ret;
gchar *host = NULL;
gchar *password = NULL;
gchar *proxy = NULL;
gchar *username = NULL;
GString *string = NULL;
guint port;
GDesktopProxyMode proxy_mode;
proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode");
if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL)
goto out;
host = g_settings_get_string (manager->priv->settings_http,
"host");
if (host == NULL)
goto out;
port = g_settings_get_int (manager->priv->settings_http,
"port");
/* use an HTTP auth string? */
ret = g_settings_get_boolean (manager->priv->settings_http,
"use-authentication");
if (ret) {
username = g_settings_get_string (manager->priv->settings_http,
"authentication-user");
password = g_settings_get_string (manager->priv->settings_http,
"authentication-password");
}
/* make PackageKit proxy string */
string = g_string_new (host);
if (port > 0)
g_string_append_printf (string, ":%i", port);
if (username != NULL && password != NULL)
g_string_append_printf (string, "@%s:%s", username, password);
else if (username != NULL)
g_string_append_printf (string, "@%s", username);
else if (password != NULL)
g_string_append_printf (string, "@:%s", password);
proxy = g_string_free (string, FALSE);
out:
g_free (host);
g_free (username);
g_free (password);
return proxy;
}
static gchar *
get_proxy_ftp (GsdUpdatesManager *manager)
{
gchar *host = NULL;
gchar *proxy = NULL;
GString *string = NULL;
guint port;
GDesktopProxyMode proxy_mode;
proxy_mode = g_settings_get_enum (manager->priv->settings_proxy, "mode");
if (proxy_mode != G_DESKTOP_PROXY_MODE_MANUAL)
goto out;
host = g_settings_get_string (manager->priv->settings_ftp,
"host");
if (host == NULL)
goto out;
port = g_settings_get_int (manager->priv->settings_ftp,
"port");
if (port == 0)
goto out;
/* make PackageKit proxy string */
string = g_string_new (host);
if (port > 0)
g_string_append_printf (string, ":%i", port);
proxy = g_string_free (string, FALSE);
out:
g_free (host);
return proxy;
}
static void
set_proxy_cb (GObject *object, GAsyncResult *res, gpointer user_data)
{
gboolean ret;
GError *error = NULL;
PkControl *control = PK_CONTROL (object);
/* get the result */
ret = pk_control_set_proxy_finish (control, res, &error);
if (!ret) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("failed to set proxies: %s", error->message);
g_error_free (error);
}
}
static void
reload_proxy_settings (GsdUpdatesManager *manager)
{
gchar *proxy_http;
gchar *proxy_ftp;
proxy_http = get_proxy_http (manager);
proxy_ftp = get_proxy_ftp (manager);
/* send to daemon */
pk_control_set_proxy_async (manager->priv->control,
proxy_http,
proxy_ftp,
NULL,
set_proxy_cb,
manager);
g_free (proxy_http);
g_free (proxy_ftp);
}
static void
settings_changed_cb (GSettings *settings,
const char *key,
GsdUpdatesManager *manager)
{
reload_proxy_settings (manager);
}
static void
settings_gsd_changed_cb (GSettings *settings,
const char *key,
GsdUpdatesManager *manager)
{
}
static void
session_inhibit (GsdUpdatesManager *manager)
{
const gchar *reason;
GError *error = NULL;
GVariant *retval = NULL;
/* state invalid somehow */
if (manager->priv->inhibit_cookie != 0) {
g_warning ("already locked");
goto out;
}
/* TRANSLATORS: the reason why we've inhibited it */
reason = _("A transaction that cannot be interrupted is running");
retval = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->proxy_session),
"Inhibit",
g_variant_new ("(susu)",
"gnome-settings-daemon", /* app-id */
0, /* xid */
reason, /* reason */
4 /* flags */),
G_DBUS_CALL_FLAGS_NONE,
-1,
manager->priv->cancellable,
&error);
if (retval == NULL) {
g_warning ("failed to inhibit gnome-session: %s",
error->message);
g_error_free (error);
goto out;
}
/* get cookie */
g_variant_get (retval, "(u)",
&manager->priv->inhibit_cookie);
out:
if (retval != NULL)
g_variant_unref (retval);
}
static void
session_uninhibit (GsdUpdatesManager *manager)
{
GError *error = NULL;
GVariant *retval = NULL;
/* state invalid somehow */
if (manager->priv->inhibit_cookie == 0) {
g_warning ("not locked");
goto out;
}
retval = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->proxy_session),
"Uninhibit",
g_variant_new ("(u)",
manager->priv->inhibit_cookie),
G_DBUS_CALL_FLAGS_NONE,
-1,
manager->priv->cancellable,
&error);
if (retval == NULL) {
g_warning ("failed to uninhibit gnome-session: %s",
error->message);
g_error_free (error);
goto out;
}
out:
manager->priv->inhibit_cookie = 0;
if (retval != NULL)
g_variant_unref (retval);
}
static void
notify_locked_cb (PkControl *control,
GParamSpec *pspec,
GsdUpdatesManager *manager)
{
gboolean locked;
g_object_get (control, "locked", &locked, NULL);
/* TODO: locked is a bit harsh, we can probably still allow
* reboot when packages are downloading or the transaction is
* depsolving */
if (locked) {
session_inhibit (manager);
} else {
session_uninhibit (manager);
}
}
static void
update_viewer_appeared_cb (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data);
/* close any existing notification */
if (manager->priv->notification_updates != NULL) {
g_debug ("update viewer on the bus, clearing bubble");
notify_notification_close (manager->priv->notification_updates, NULL);
manager->priv->notification_updates = NULL;
}
}
static gboolean
file_exists_in_root (const gchar *root, const gchar *filename)
{
gboolean ret = FALSE;
GFile *source;
gchar *source_path;
source_path = g_build_filename (root, filename, NULL);
source = g_file_new_for_path (source_path);
/* ignore virtual mountpoints */
if (!g_file_is_native (source))
goto out;
/* an interesting file exists */
ret = g_file_query_exists (source, NULL);
g_debug ("checking for %s: %s", source_path, ret ? "yes" : "no");
if (!ret)
goto out;
out:
g_free (source_path);
g_object_unref (source);
return ret;
}
static void
mount_added_cb (GVolumeMonitor *volume_monitor,
GMount *mount,
GsdUpdatesManager *manager)
{
gboolean ret = FALSE;
gchar **filenames = NULL;
gchar *media_repo_filenames;
gchar *root_path;
GFile *root;
guint i;
/* check if any installed media is an install disk */
root = g_mount_get_root (mount);
root_path = g_file_get_path (root);
/* use settings */
media_repo_filenames = g_settings_get_string (manager->priv->settings_gsd,
GSD_SETTINGS_MEDIA_REPO_FILENAMES);
if (media_repo_filenames == NULL) {
g_warning ("failed to get media repo filenames");
goto out;
}
/* search each possible filename */
filenames = g_strsplit (media_repo_filenames, ",", -1);
for (i=0; filenames[i] != NULL; i++) {
ret = file_exists_in_root (root_path, filenames[i]);
if (ret)
break;
}
/* do an updates check with the new media */
if (ret)
query_updates (manager);
out:
g_strfreev (filenames);
g_free (media_repo_filenames);
g_free (root_path);
g_object_unref (root);
}
#define PK_OFFLINE_UPDATE_RESULTS_GROUP "PackageKit Offline Update Results"
#define PK_OFFLINE_UPDATE_RESULTS_FILENAME "/var/lib/PackageKit/offline-update-competed"
static gboolean
check_offline_update_cb (gpointer user_data)
{
const gchar *message;
const gchar *title;
gboolean ret;
gboolean success;
gchar *error_code = NULL;
gchar *error_details = NULL;
gchar *packages = NULL;
GError *error = NULL;
GKeyFile *key_file = NULL;
GsdUpdatesManager *manager = (GsdUpdatesManager *) user_data;
guint i;
guint num_packages = 1;
NotifyNotification *notification;
PkErrorEnum error_enum = PK_ERROR_ENUM_UNKNOWN;
/* was any offline update attempted */
if (!g_file_test (PK_OFFLINE_UPDATE_RESULTS_FILENAME, G_FILE_TEST_EXISTS))
goto out;
/* open the file and see what happened */
key_file = g_key_file_new ();
ret = g_key_file_load_from_file (key_file,
PK_OFFLINE_UPDATE_RESULTS_FILENAME,
G_KEY_FILE_NONE,
&error);
if (!ret) {
g_warning ("failed to open %s: %s",
PK_OFFLINE_UPDATE_RESULTS_FILENAME,
error->message);
g_error_free (error);
goto out;
}
success = g_key_file_get_boolean (key_file,
PK_OFFLINE_UPDATE_RESULTS_GROUP,
"Success",
NULL);
if (success) {
packages = g_key_file_get_string (key_file,
PK_OFFLINE_UPDATE_RESULTS_GROUP,
"Packages",
NULL);
if (packages == NULL) {
g_warning ("No 'Packages' in %s",
PK_OFFLINE_UPDATE_RESULTS_FILENAME);
goto out;
}
/* count the packages for translators */
for (i = 0; packages[i] != '\0'; i++) {
if (packages[i] == ',')
num_packages++;
}
/* TRANSLATORS: title in the libnotify popup */
title = ngettext ("Software Update Installed",
"Software Updates Installed",
num_packages);
/* TRANSLATORS: message when we've done offline updates */
message = ngettext ("An important OS update has been installed.",
"Important OS updates have been installed.",
num_packages);
/* no need to keep the file around anymore */
clear_offline_updates_message ();
} else {
/* get error details */
manager->priv->offline_update_error = pk_error_new ();
error_code = g_key_file_get_string (key_file,
PK_OFFLINE_UPDATE_RESULTS_GROUP,
"ErrorCode",
NULL);
if (error_code != NULL)
error_enum = pk_error_enum_from_string (error_code);
error_details = g_key_file_get_string (key_file,
PK_OFFLINE_UPDATE_RESULTS_GROUP,
"ErrorDetails",
NULL);
g_object_set (manager->priv->offline_update_error,
"code", error_enum,
"details", error_details,
NULL);
/* TRANSLATORS: title in the libnotify popup */
title = _("Software Updates Failed");
/* TRANSLATORS: message when we've not done offline updates */
message = _("An important OS update failed to be installed.");
}
/* do the bubble */
g_debug ("title=%s, message=%s", title, message);
notification = notify_notification_new (title,
message,
GSD_UPDATES_ICON_URGENT);
notify_notification_set_hint_string (notification, "desktop-entry", "gpk-update-viewer");
notify_notification_set_app_name (notification, _("Software Updates"));
notify_notification_set_timeout (notification, -1);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
if (success) {
#if 0
notify_notification_add_action (notification, "review-offline-updates",
/* TRANSLATORS: button: review the offline update changes */
_("Review"), libnotify_action_cb, manager, NULL);
#endif
} else {
notify_notification_add_action (notification, "error-offline-updates",
/* TRANSLATORS: button: review the offline update changes */
_("Show details"), libnotify_action_cb, manager, NULL);
}
notify_notification_add_action (notification, "clear-offline-updates",
/* TRANSLATORS: button: clear notification */
_("OK"), libnotify_action_cb, manager, NULL);
g_signal_connect (notification, "closed",
G_CALLBACK (on_notification_closed), NULL);
ret = notify_notification_show (notification, &error);
if (!ret) {
g_warning ("error: %s", error->message);
g_error_free (error);
}
out:
g_free (packages);
g_free (error_code);
g_free (error_details);
if (key_file != NULL)
g_key_file_free (key_file);
manager->priv->offline_update_id = 0;
return FALSE;
}
gboolean
gsd_updates_manager_start (GsdUpdatesManager *manager,
GError **error)
{
gboolean ret = FALSE;
g_debug ("Starting updates manager");
/* use PackageKit */
manager->priv->cancellable = g_cancellable_new ();
manager->priv->control = pk_control_new ();
g_signal_connect (manager->priv->control, "notify::locked",
G_CALLBACK (notify_locked_cb), manager);
manager->priv->task = pk_task_new ();
g_object_set (manager->priv->task,
"background", TRUE,
"interactive", FALSE,
#if PK_CHECK_VERSION(0,8,1)
"only-download", TRUE,
#endif
NULL);
/* watch UDev for missing firmware */
manager->priv->firmware = gsd_updates_firmware_new ();
/* get automatic callbacks about when we should check for
* updates, refresh-caches and upgrades */
manager->priv->refresh = gsd_updates_refresh_new ();
g_signal_connect (manager->priv->refresh, "get-upgrades",
G_CALLBACK (due_get_upgrades_cb), manager);
g_signal_connect (manager->priv->refresh, "refresh-cache",
G_CALLBACK (due_refresh_cache_cb), manager);
g_signal_connect (manager->priv->refresh, "get-updates",
G_CALLBACK (due_get_updates_cb), manager);
/* get proxy settings */
manager->priv->settings_proxy = g_settings_new ("org.gnome.system.proxy");
g_signal_connect (manager->priv->settings_proxy, "changed",
G_CALLBACK (settings_changed_cb), manager);
/* get http settings */
manager->priv->settings_http = g_settings_new ("org.gnome.system.proxy.http");
g_signal_connect (manager->priv->settings_http, "changed",
G_CALLBACK (settings_changed_cb), manager);
/* get ftp settings */
manager->priv->settings_ftp = g_settings_new ("org.gnome.system.proxy.ftp");
g_signal_connect (manager->priv->settings_ftp, "changed",
G_CALLBACK (settings_changed_cb), manager);
/* get ftp settings */
manager->priv->settings_gsd = g_settings_new ("org.gnome.settings-daemon.plugins.updates");
g_signal_connect (manager->priv->settings_gsd, "changed",
G_CALLBACK (settings_gsd_changed_cb), manager);
/* use gnome-session for the idle detection */
manager->priv->proxy_session =
gnome_settings_bus_get_session_proxy ();
if (manager->priv->proxy_session == NULL)
goto out;
/* if the update viewer is started, then hide the notification */
manager->priv->update_viewer_watcher_id =
g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.freedesktop.PackageKit.UpdateViewer",
G_BUS_NAME_WATCHER_FLAGS_NONE,
update_viewer_appeared_cb,
NULL,
manager,
NULL);
/* get a volume monitor so we can watch media */
manager->priv->volume_monitor = g_volume_monitor_get ();
g_signal_connect (manager->priv->volume_monitor, "mount-added",
G_CALLBACK (mount_added_cb), manager);
/* coldplug */
reload_proxy_settings (manager);
/* check for offline update */
manager->priv->offline_update_id =
g_timeout_add_seconds (GSD_UPDATES_CHECK_OFFLINE_TIMEOUT,
check_offline_update_cb,
manager);
/* success */
ret = TRUE;
g_debug ("Started updates manager");
out:
return ret;
}
void
gsd_updates_manager_stop (GsdUpdatesManager *manager)
{
g_debug ("Stopping updates manager");
g_clear_object (&manager->priv->settings_proxy);
g_clear_object (&manager->priv->settings_http);
g_clear_object (&manager->priv->settings_ftp);
g_clear_object (&manager->priv->settings_gsd);
g_clear_object (&manager->priv->control);
g_clear_object (&manager->priv->task);
g_clear_object (&manager->priv->refresh);
g_clear_object (&manager->priv->firmware);
g_clear_object (&manager->priv->proxy_session);
g_clear_object (&manager->priv->volume_monitor);
if (manager->priv->cancellable) {
g_cancellable_cancel (manager->priv->cancellable);
g_clear_object (&manager->priv->cancellable);
}
if (manager->priv->update_viewer_watcher_id != 0) {
g_bus_unwatch_name (manager->priv->update_viewer_watcher_id);
manager->priv->update_viewer_watcher_id = 0;
}
if (manager->priv->offline_update_id) {
g_source_remove (manager->priv->offline_update_id);
manager->priv->offline_update_id = 0;
}
if (manager->priv->update_packages != NULL) {
g_ptr_array_unref (manager->priv->update_packages);
manager->priv->update_packages = NULL;
}
g_clear_object (&manager->priv->offline_update_error);
}
static GObject *
gsd_updates_manager_constructor (
GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GsdUpdatesManager *m;
m = GSD_UPDATES_MANAGER (G_OBJECT_CLASS (gsd_updates_manager_parent_class)->constructor (
type,
n_construct_properties,
construct_properties));
return G_OBJECT (m);
}
static void
gsd_updates_manager_dispose (GObject *object)
{
GsdUpdatesManager *manager;
manager = GSD_UPDATES_MANAGER (object);
gsd_updates_manager_stop (manager);
G_OBJECT_CLASS (gsd_updates_manager_parent_class)->dispose (object);
}
static void
gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = gsd_updates_manager_constructor;
object_class->dispose = gsd_updates_manager_dispose;
g_type_class_add_private (klass, sizeof (GsdUpdatesManagerPrivate));
}
static void
gsd_updates_manager_init (GsdUpdatesManager *manager)
{
manager->priv = GSD_UPDATES_MANAGER_GET_PRIVATE (manager);
}
GsdUpdatesManager *
gsd_updates_manager_new (void)
{
if (manager_object) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_UPDATES_MANAGER, NULL);
g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object);
}
return GSD_UPDATES_MANAGER (manager_object);
}
./plugins/updates/Makefile.am 0000644 0000041 0000041 00000002205 13264221014 016417 0 ustar www-data www-data plugin_name = updates
plugin_LTLIBRARIES = \
libupdates.la
libupdates_la_SOURCES = \
gsd-updates-common.h \
gsd-updates-plugin.c \
gsd-updates-refresh.h \
gsd-updates-refresh.c \
gsd-updates-firmware.h \
gsd-updates-firmware.c \
gsd-updates-manager.h \
gsd-updates-manager.c
libupdates_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libupdates_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(GUDEV_CFLAGS) \
-DG_UDEV_API_IS_SUBJECT_TO_CHANGE \
$(PACKAGEKIT_CFLAGS) \
-DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE \
-DDATADIR=\"$(datadir)\" \
-DBINDIR=\"$(bindir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
-I$(top_srcdir)/data \
$(AM_CFLAGS)
libupdates_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libupdates_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS) \
$(PACKAGEKIT_LIBS)
plugin_in_files = \
updates.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = \
$(plugin_in_files)
CLEANFILES = \
$(plugin_DATA)
DISTCLEANFILES = \
$(plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/sound/ 0000755 0000041 0000041 00000000000 13264221014 014047 5 ustar www-data www-data ./plugins/sound/gsd-sound-manager.c 0000644 0000041 0000041 00000027256 13264221014 017542 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Lennart Poettering
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gsd-sound-manager.h"
#include "gnome-settings-profile.h"
#define GSD_SOUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerPrivate))
struct GsdSoundManagerPrivate
{
GSettings *settings;
GList *monitors;
guint timeout;
};
static void gsd_sound_manager_class_init (GsdSoundManagerClass *klass);
static void gsd_sound_manager_init (GsdSoundManager *sound_manager);
static void gsd_sound_manager_finalize (GObject *object);
G_DEFINE_TYPE (GsdSoundManager, gsd_sound_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static void
sample_info_cb (pa_context *c, const pa_sample_info *i, int eol, void *userdata)
{
pa_operation *o;
if (!i)
return;
g_debug ("Found sample %s", i->name);
/* We only flush those samples which have an XDG sound name
* attached, because only those originate from themeing */
if (!(pa_proplist_gets (i->proplist, PA_PROP_EVENT_ID)))
return;
g_debug ("Dropping sample %s from cache", i->name);
if (!(o = pa_context_remove_sample (c, i->name, NULL, NULL))) {
g_debug ("pa_context_remove_sample (): %s", pa_strerror (pa_context_errno (c)));
return;
}
pa_operation_unref (o);
/* We won't wait until the operation is actually executed to
* speed things up a bit.*/
}
static void
flush_cache (void)
{
pa_mainloop *ml = NULL;
pa_context *c = NULL;
pa_proplist *pl = NULL;
pa_operation *o = NULL;
g_debug ("Flushing sample cache");
if (!(ml = pa_mainloop_new ())) {
g_debug ("Failed to allocate pa_mainloop");
goto fail;
}
if (!(pl = pa_proplist_new ())) {
g_debug ("Failed to allocate pa_proplist");
goto fail;
}
pa_proplist_sets (pl, PA_PROP_APPLICATION_NAME, PACKAGE_NAME);
pa_proplist_sets (pl, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
pa_proplist_sets (pl, PA_PROP_APPLICATION_ID, "org.gnome.SettingsDaemon");
if (!(c = pa_context_new_with_proplist (pa_mainloop_get_api (ml), PACKAGE_NAME, pl))) {
g_debug ("Failed to allocate pa_context");
goto fail;
}
pa_proplist_free (pl);
pl = NULL;
if (pa_context_connect (c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
g_debug ("pa_context_connect(): %s", pa_strerror (pa_context_errno (c)));
goto fail;
}
/* Wait until the connection is established */
while (pa_context_get_state (c) != PA_CONTEXT_READY) {
if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) {
g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c)));
goto fail;
}
if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) {
g_debug ("pa_mainloop_iterate() failed");
goto fail;
}
}
/* Enumerate all cached samples */
if (!(o = pa_context_get_sample_info_list (c, sample_info_cb, NULL))) {
g_debug ("pa_context_get_sample_info_list(): %s", pa_strerror (pa_context_errno (c)));
goto fail;
}
/* Wait until our operation is finished and there's nothing
* more queued to send to the server */
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING || pa_context_is_pending (c)) {
if (!PA_CONTEXT_IS_GOOD (pa_context_get_state (c))) {
g_debug ("Connection failed: %s", pa_strerror (pa_context_errno (c)));
goto fail;
}
if (pa_mainloop_iterate (ml, TRUE, NULL) < 0) {
g_debug ("pa_mainloop_iterate() failed");
goto fail;
}
}
g_debug ("Sample cache flushed");
fail:
if (o) {
pa_operation_cancel (o);
pa_operation_unref (o);
}
if (c) {
pa_context_disconnect (c);
pa_context_unref (c);
}
if (pl)
pa_proplist_free (pl);
if (ml)
pa_mainloop_free (ml);
}
static gboolean
flush_cb (GsdSoundManager *manager)
{
flush_cache ();
manager->priv->timeout = 0;
return FALSE;
}
static void
trigger_flush (GsdSoundManager *manager)
{
if (manager->priv->timeout)
g_source_remove (manager->priv->timeout);
/* We delay the flushing a bit so that we can coalesce
* multiple changes into a single cache flush */
manager->priv->timeout = g_timeout_add (500, (GSourceFunc) flush_cb, manager);
}
static void
settings_changed_cb (GSettings *settings,
const char *key,
GsdSoundManager *manager)
{
trigger_flush (manager);
}
static void
register_config_callback (GsdSoundManager *manager)
{
manager->priv->settings = g_settings_new ("org.gnome.desktop.sound");
g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
G_CALLBACK (settings_changed_cb), manager);
}
static void
file_monitor_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event,
GsdSoundManager *manager)
{
g_debug ("Theme dir changed");
trigger_flush (manager);
}
static gboolean
register_directory_callback (GsdSoundManager *manager,
const char *path,
GError **error)
{
GFile *f;
GFileMonitor *m;
gboolean succ = FALSE;
g_debug ("Registering directory monitor for %s", path);
f = g_file_new_for_path (path);
m = g_file_monitor_directory (f, 0, NULL, error);
if (m != NULL) {
g_signal_connect (m, "changed", G_CALLBACK (file_monitor_changed_cb), manager);
manager->priv->monitors = g_list_prepend (manager->priv->monitors, m);
succ = TRUE;
}
g_object_unref (f);
return succ;
}
gboolean
gsd_sound_manager_start (GsdSoundManager *manager,
GError **error)
{
guint i;
const gchar * const * dirs;
char *p;
g_debug ("Starting sound manager");
gnome_settings_profile_start (NULL);
/* We listen for change of the selected theme ... */
register_config_callback (manager);
/* ... and we listen to changes of the theme base directories
* in $HOME ...*/
p = g_build_filename (g_get_user_data_dir (), "sounds", NULL);
/* See bug #694134 - the initial commit had the permissions below wrong
* so users may have the directory without the right permissions. Fix
* them up if so. */
if (!g_access (p, F_OK) && g_access (p, R_OK | W_OK | X_OK) != 0)
{
g_debug ("Permissions on %s wrong; resetting", p);
g_chmod (p, S_IRUSR | S_IWUSR | S_IXUSR);
}
if (g_mkdir_with_parents(p, 0700) == 0)
register_directory_callback (manager, p, NULL);
g_free (p);
/* ... and globally. */
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i] != NULL; i++) {
p = g_build_filename (dirs[i], "sounds", NULL);
if (g_file_test (p, G_FILE_TEST_IS_DIR))
register_directory_callback (manager, p, NULL);
g_free (p);
}
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_sound_manager_stop (GsdSoundManager *manager)
{
g_debug ("Stopping sound manager");
if (manager->priv->settings != NULL) {
g_object_unref (manager->priv->settings);
manager->priv->settings = NULL;
}
if (manager->priv->timeout) {
g_source_remove (manager->priv->timeout);
manager->priv->timeout = 0;
}
while (manager->priv->monitors) {
g_file_monitor_cancel (G_FILE_MONITOR (manager->priv->monitors->data));
g_object_unref (manager->priv->monitors->data);
manager->priv->monitors = g_list_delete_link (manager->priv->monitors, manager->priv->monitors);
}
}
static GObject *
gsd_sound_manager_constructor (
GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GsdSoundManager *m;
m = GSD_SOUND_MANAGER (G_OBJECT_CLASS (gsd_sound_manager_parent_class)->constructor (
type,
n_construct_properties,
construct_properties));
return G_OBJECT (m);
}
static void
gsd_sound_manager_dispose (GObject *object)
{
GsdSoundManager *manager;
manager = GSD_SOUND_MANAGER (object);
gsd_sound_manager_stop (manager);
G_OBJECT_CLASS (gsd_sound_manager_parent_class)->dispose (object);
}
static void
gsd_sound_manager_class_init (GsdSoundManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = gsd_sound_manager_constructor;
object_class->dispose = gsd_sound_manager_dispose;
object_class->finalize = gsd_sound_manager_finalize;
g_type_class_add_private (klass, sizeof (GsdSoundManagerPrivate));
}
static void
gsd_sound_manager_init (GsdSoundManager *manager)
{
manager->priv = GSD_SOUND_MANAGER_GET_PRIVATE (manager);
}
static void
gsd_sound_manager_finalize (GObject *object)
{
GsdSoundManager *sound_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_SOUND_MANAGER (object));
sound_manager = GSD_SOUND_MANAGER (object);
g_return_if_fail (sound_manager->priv);
G_OBJECT_CLASS (gsd_sound_manager_parent_class)->finalize (object);
}
GsdSoundManager *
gsd_sound_manager_new (void)
{
if (manager_object) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_SOUND_MANAGER, NULL);
g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object);
}
return GSD_SOUND_MANAGER (manager_object);
}
./plugins/sound/gsd-sound-manager.h 0000644 0000041 0000041 00000004120 13264221014 017530 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Lennart Poettering
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_SOUND_MANAGER_H
#define __GSD_SOUND_MANAGER_H
#include
#include
G_BEGIN_DECLS
#define GSD_TYPE_SOUND_MANAGER (gsd_sound_manager_get_type ())
#define GSD_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManager))
#define GSD_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass))
#define GSD_IS_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SOUND_MANAGER))
#define GSD_IS_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SOUND_MANAGER))
#define GSD_SOUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SOUND_MANAGER, GsdSoundManagerClass))
typedef struct GsdSoundManagerPrivate GsdSoundManagerPrivate;
typedef struct
{
GObject parent;
GsdSoundManagerPrivate *priv;
} GsdSoundManager;
typedef struct
{
GObjectClass parent_class;
} GsdSoundManagerClass;
GType gsd_sound_manager_get_type (void) G_GNUC_CONST;
GsdSoundManager *gsd_sound_manager_new (void);
gboolean gsd_sound_manager_start (GsdSoundManager *manager, GError **error);
void gsd_sound_manager_stop (GsdSoundManager *manager);
G_END_DECLS
#endif /* __GSD_SOUND_MANAGER_H */
./plugins/sound/gsd-sound-plugin.c 0000644 0000041 0000041 00000002025 13264221014 017411 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Lennart Poettering
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-sound-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdSound, gsd_sound)
./plugins/sound/sound.gnome-settings-plugin.in 0000644 0000041 0000041 00000000252 13264221014 021764 0 ustar www-data www-data [GNOME Settings Plugin]
Module=sound
IAge=0
Priority=5
_Name=Sound
_Description=Sound Sample Cache plugin
Authors=Lennart Poettering
Copyright=Copyright © 2008
Website=
./plugins/sound/test-sound.c 0000644 0000041 0000041 00000000305 13264221014 016316 0 ustar www-data www-data #define NEW gsd_sound_manager_new
#define START gsd_sound_manager_start
#define STOP gsd_sound_manager_stop
#define MANAGER GsdSoundManager
#include "gsd-sound-manager.h"
#include "test-plugin.h"
./plugins/sound/Makefile.am 0000644 0000041 0000041 00000002467 13264221014 016114 0 ustar www-data www-data plugin_name = sound
libexec_PROGRAMS = usd-test-sound
usd_test_sound_SOURCES = \
gsd-sound-manager.h \
gsd-sound-manager.c \
test-sound.c
usd_test_sound_CFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(SOUND_CFLAGS) \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
usd_test_sound_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/plugins/common/libcommon.la \
$(SOUND_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
plugin_LTLIBRARIES = \
libsound.la
libsound_la_SOURCES = \
gsd-sound-plugin.c \
gsd-sound-manager.h \
gsd-sound-manager.c
libsound_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libsound_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(SOUND_CFLAGS) \
$(AM_CFLAGS)
libsound_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libsound_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS) \
$(SOUND_LIBS)
plugin_in_files = \
sound.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = \
$(plugin_in_files)
CLEANFILES = \
$(plugin_DATA)
DISTCLEANFILES = \
$(plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/remote-display/ 0000755 0000041 0000041 00000000000 13264221014 015655 5 ustar www-data www-data ./plugins/remote-display/test-remote-display.c 0000644 0000041 0000041 00000000361 13264221014 021734 0 ustar www-data www-data #define NEW gsd_remote_display_manager_new
#define START gsd_remote_display_manager_start
#define STOP gsd_remote_display_manager_stop
#define MANAGER GsdRemoteDisplayManager
#include "gsd-remote-display-manager.h"
#include "test-plugin.h"
./plugins/remote-display/gsd-remote-display-manager.c 0000644 0000041 0000041 00000016421 13264221014 023146 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gnome-settings-bus.h"
#include "gnome-settings-profile.h"
#include "gsd-remote-display-manager.h"
#define GSD_REMOTE_DISPLAY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerPrivate))
struct GsdRemoteDisplayManagerPrivate
{
GSettings *desktop_settings;
GDBusProxy *vino_proxy;
GCancellable *cancellable;
guint vino_watch_id;
gboolean vnc_in_use;
};
static void gsd_remote_display_manager_class_init (GsdRemoteDisplayManagerClass *klass);
static void gsd_remote_display_manager_init (GsdRemoteDisplayManager *remote_display_manager);
G_DEFINE_TYPE (GsdRemoteDisplayManager, gsd_remote_display_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static void
update_settings_from_variant (GsdRemoteDisplayManager *manager,
GVariant *variant)
{
manager->priv->vnc_in_use = g_variant_get_boolean (variant);
g_debug ("%s because of remote display status (vnc: %d)",
!manager->priv->vnc_in_use ? "Enabling" : "Disabling",
manager->priv->vnc_in_use);
g_settings_set_boolean (manager->priv->desktop_settings,
"enable-animations",
!manager->priv->vnc_in_use);
}
static void
props_changed (GDBusProxy *proxy,
GVariant *changed_properties,
GStrv invalidated_properties,
GsdRemoteDisplayManager *manager)
{
GVariant *v;
v = g_variant_lookup_value (changed_properties, "Connected", G_VARIANT_TYPE_BOOLEAN);
if (v) {
g_debug ("Received connected change");
update_settings_from_variant (manager, v);
g_variant_unref (v);
}
}
static void
got_vino_proxy (GObject *source_object,
GAsyncResult *res,
GsdRemoteDisplayManager *manager)
{
GError *error = NULL;
GVariant *v;
manager->priv->vino_proxy = g_dbus_proxy_new_finish (res, &error);
if (manager->priv->vino_proxy == NULL) {
g_warning ("Failed to get Vino's D-Bus proxy: %s", error->message);
g_error_free (error);
return;
}
g_signal_connect (manager->priv->vino_proxy, "g-properties-changed",
G_CALLBACK (props_changed), manager);
v = g_dbus_proxy_get_cached_property (manager->priv->vino_proxy, "Connected");
if (v) {
g_debug ("Setting original state");
update_settings_from_variant (manager, v);
g_variant_unref (v);
}
}
static void
vino_appeared_cb (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
GsdRemoteDisplayManager *manager)
{
g_debug ("Vino appeared");
g_dbus_proxy_new (connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
name,
"/org/gnome/vino/screens/0",
"org.gnome.VinoScreen",
manager->priv->cancellable,
(GAsyncReadyCallback) got_vino_proxy,
manager);
}
static void
vino_vanished_cb (GDBusConnection *connection,
const char *name,
GsdRemoteDisplayManager *manager)
{
g_debug ("Vino vanished");
if (manager->priv->cancellable != NULL) {
g_cancellable_cancel (manager->priv->cancellable);
g_clear_object (&manager->priv->cancellable);
}
g_clear_object (&manager->priv->vino_proxy);
/* And reset for us to have animations */
g_settings_set_boolean (manager->priv->desktop_settings,
"enable-animations",
TRUE);
}
static gboolean
gsd_display_has_extension (const gchar *ext)
{
int op, event, error;
return XQueryExtension (gdk_x11_get_default_xdisplay (),
ext, &op, &event, &error);
}
gboolean
gsd_remote_display_manager_start (GsdRemoteDisplayManager *manager,
GError **error)
{
g_debug ("Starting remote-display manager");
gnome_settings_profile_start (NULL);
manager->priv->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
/* Check if spice is used:
* https://bugzilla.gnome.org/show_bug.cgi?id=680195#c7
* This doesn't change at run-time, so it's to the point */
if (g_file_test ("/dev/virtio-ports/com.redhat.spice.0", G_FILE_TEST_EXISTS)) {
g_debug ("Disabling animations because SPICE is in use");
g_settings_set_boolean (manager->priv->desktop_settings,
"enable-animations",
FALSE);
goto out;
}
/* Xvnc exposes an extension named VNC-EXTENSION */
if (gsd_display_has_extension ("VNC-EXTENSION")) {
g_debug ("Disabling animations because VNC-EXTENSION was detected");
g_settings_set_boolean (manager->priv->desktop_settings,
"enable-animations",
FALSE);
goto out;
}
/* Monitor Vino's usage */
manager->priv->vino_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.gnome.Vino",
G_BUS_NAME_WATCHER_FLAGS_NONE,
(GBusNameAppearedCallback) vino_appeared_cb,
(GBusNameVanishedCallback) vino_vanished_cb,
manager, NULL);
out:
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_remote_display_manager_stop (GsdRemoteDisplayManager *manager)
{
g_debug ("Stopping remote_display manager");
if (manager->priv->cancellable != NULL) {
g_cancellable_cancel (manager->priv->cancellable);
g_clear_object (&manager->priv->cancellable);
}
g_clear_object (&manager->priv->vino_proxy);
if (manager->priv->desktop_settings) {
g_settings_reset (manager->priv->desktop_settings, "enable-animations");
g_clear_object (&manager->priv->desktop_settings);
}
}
static void
gsd_remote_display_manager_class_init (GsdRemoteDisplayManagerClass *klass)
{
g_type_class_add_private (klass, sizeof (GsdRemoteDisplayManagerPrivate));
}
static void
gsd_remote_display_manager_init (GsdRemoteDisplayManager *manager)
{
manager->priv = GSD_REMOTE_DISPLAY_MANAGER_GET_PRIVATE (manager);
}
GsdRemoteDisplayManager *
gsd_remote_display_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_REMOTE_DISPLAY_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return GSD_REMOTE_DISPLAY_MANAGER (manager_object);
}
./plugins/remote-display/gsd-remote-display-plugin.c 0000644 0000041 0000041 00000002173 13264221014 023031 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-remote-display-manager.h"
struct GsdRemoteDisplayPluginPrivate {
GsdRemoteDisplayManager *manager;
};
GNOME_SETTINGS_PLUGIN_REGISTER (GsdRemoteDisplay, gsd_remote_display)
./plugins/remote-display/remote-display.gnome-settings-plugin.in 0000644 0000041 0000041 00000000323 13264221014 025377 0 ustar www-data www-data [GNOME Settings Plugin]
Module=remote-display
IAge=0
Priority=8
_Name=Remote Display
_Description=Disable animations on remote displays
Authors=Bastien Nocera
Copyright=Copyright © 2012 Bastien Nocera
Website=
./plugins/remote-display/gsd-remote-display-manager.h 0000644 0000041 0000041 00000005035 13264221014 023152 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_REMOTE_DISPLAY_MANAGER_H
#define __GSD_REMOTE_DISPLAY_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_REMOTE_DISPLAY_MANAGER (gsd_remote_display_manager_get_type ())
#define GSD_REMOTE_DISPLAY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManager))
#define GSD_REMOTE_DISPLAY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerClass))
#define GSD_IS_REMOTE_DISPLAY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER))
#define GSD_IS_REMOTE_DISPLAY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_REMOTE_DISPLAY_MANAGER))
#define GSD_REMOTE_DISPLAY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_REMOTE_DISPLAY_MANAGER, GsdRemoteDisplayManagerClass))
typedef struct GsdRemoteDisplayManagerPrivate GsdRemoteDisplayManagerPrivate;
typedef struct
{
GObject parent;
GsdRemoteDisplayManagerPrivate *priv;
} GsdRemoteDisplayManager;
typedef struct
{
GObjectClass parent_class;
} GsdRemoteDisplayManagerClass;
GType gsd_remote_display_manager_get_type (void);
GsdRemoteDisplayManager *gsd_remote_display_manager_new (void);
gboolean gsd_remote_display_manager_start (GsdRemoteDisplayManager *manager,
GError **error);
void gsd_remote_display_manager_stop (GsdRemoteDisplayManager *manager);
G_END_DECLS
#endif /* __GSD_REMOTE_DISPLAY_MANAGER_H */
./plugins/remote-display/Makefile.am 0000644 0000041 0000041 00000003015 13264221014 017710 0 ustar www-data www-data plugin_name = remote-display
plugin_LTLIBRARIES = libremote-display.la
libremote_display_la_SOURCES = \
gsd-remote-display-manager.c \
gsd-remote-display-manager.h \
gsd-remote-display-plugin.c
libremote_display_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libremote_display_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
libremote_display_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
libremote_display_la_LIBADD = $(SETTINGS_PLUGIN_LIBS)
libexec_PROGRAMS = usd-test-remote-display
usd_test_remote_display_SOURCES = \
test-remote-display.c \
gsd-remote-display-manager.c \
gsd-remote-display-manager.h
usd_test_remote_display_CPPFLAGS = \
-I$(top_srcdir)/data/ \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
$(AM_CPPFLAGS)
usd_test_remote_display_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
usd_test_remote_display_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/plugins/common/libcommon.la \
$(SETTINGS_DAEMON_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
plugin_in_files = remote-display.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/background/ 0000755 0000041 0000041 00000000000 13264221023 015036 5 ustar www-data www-data ./plugins/background/gsd-background-plugin.c 0000644 0000041 0000041 00000002034 13264221014 021367 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-background-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdBackground, gsd_background)
./plugins/background/test-background.c 0000644 0000041 0000041 00000000336 13264221014 020300 0 ustar www-data www-data #define NEW gsd_background_manager_new
#define START gsd_background_manager_start
#define STOP gsd_background_manager_stop
#define MANAGER GsdBackgroundManager
#include "gsd-background-manager.h"
#include "test-plugin.h"
./plugins/background/gsd-background-manager.h 0000644 0000041 0000041 00000004623 13264221014 021516 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_BACKGROUND_MANAGER_H
#define __GSD_BACKGROUND_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_BACKGROUND_MANAGER (gsd_background_manager_get_type ())
#define GSD_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManager))
#define GSD_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass))
#define GSD_IS_BACKGROUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_BACKGROUND_MANAGER))
#define GSD_IS_BACKGROUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_BACKGROUND_MANAGER))
#define GSD_BACKGROUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerClass))
typedef struct GsdBackgroundManagerPrivate GsdBackgroundManagerPrivate;
typedef struct
{
GObject parent;
GsdBackgroundManagerPrivate *priv;
} GsdBackgroundManager;
typedef struct
{
GObjectClass parent_class;
} GsdBackgroundManagerClass;
GType gsd_background_manager_get_type (void);
GsdBackgroundManager * gsd_background_manager_new (void);
gboolean gsd_background_manager_start (GsdBackgroundManager *manager,
GError **error);
void gsd_background_manager_stop (GsdBackgroundManager *manager);
G_END_DECLS
#endif /* __GSD_BACKGROUND_MANAGER_H */
./plugins/background/background.gnome-settings-plugin.in 0000644 0000041 0000041 00000000217 13264221014 023743 0 ustar www-data www-data [GNOME Settings Plugin]
Module=background
IAge=0
_Name=Background
_Description=Background plugin
Authors=
Copyright=Copyright © 2007
Website=
./plugins/background/gsd-background-manager.c 0000644 0000041 0000041 00000050563 13264221023 021515 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright © 2001 Ximian, Inc.
* Copyright (C) 2007 William Jon McCann
* Copyright 2007 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include
#include
#include "gnome-settings-bus.h"
#include "gnome-settings-profile.h"
#include "gsd-background-manager.h"
#define GSD_BACKGROUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_BACKGROUND_MANAGER, GsdBackgroundManagerPrivate))
struct GsdBackgroundManagerPrivate
{
GSettings *settings;
GnomeBG *bg;
GnomeBGCrossfade *fade;
GDBusProxy *proxy;
guint proxy_signal_id;
};
static void gsd_background_manager_class_init (GsdBackgroundManagerClass *klass);
static void gsd_background_manager_init (GsdBackgroundManager *background_manager);
static void gsd_background_manager_finalize (GObject *object);
static void setup_bg (GsdBackgroundManager *manager);
static void connect_screen_signals (GsdBackgroundManager *manager);
G_DEFINE_TYPE (GsdBackgroundManager, gsd_background_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static gboolean
dont_draw_background (GsdBackgroundManager *manager)
{
return !g_settings_get_boolean (manager->priv->settings,
"draw-background");
}
static gboolean
nautilus_is_drawing_background (GsdBackgroundManager *manager)
{
Atom window_id_atom;
Window nautilus_xid;
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *data;
Atom wmclass_atom;
gboolean running;
gint error;
gboolean show_desktop_icons;
show_desktop_icons = g_settings_get_boolean (manager->priv->settings,
"show-desktop-icons");
if (! show_desktop_icons) {
return FALSE;
}
window_id_atom = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
"NAUTILUS_DESKTOP_WINDOW_ID", True);
if (window_id_atom == None) {
return FALSE;
}
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
GDK_ROOT_WINDOW (),
window_id_atom,
0,
1,
False,
XA_WINDOW,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
&data);
if (data != NULL) {
nautilus_xid = *(Window *) data;
XFree (data);
} else {
return FALSE;
}
if (actual_type != XA_WINDOW) {
return FALSE;
}
if (actual_format != 32) {
return FALSE;
}
wmclass_atom = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "WM_CLASS", False);
gdk_error_trap_push ();
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
nautilus_xid,
wmclass_atom,
0,
24,
False,
XA_STRING,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
&data);
error = gdk_error_trap_pop ();
if (error == BadWindow) {
return FALSE;
}
if (actual_type == XA_STRING &&
nitems == 24 &&
bytes_after == 0 &&
actual_format == 8 &&
data != NULL &&
!strcmp ((char *)data, "desktop_window") &&
!strcmp ((char *)data + strlen ((char *)data) + 1, "Nautilus")) {
running = TRUE;
} else {
running = FALSE;
}
if (data != NULL) {
XFree (data);
}
return running;
}
static void
on_crossfade_finished (GsdBackgroundManager *manager)
{
g_object_unref (manager->priv->fade);
manager->priv->fade = NULL;
}
static void
draw_background (GsdBackgroundManager *manager,
gboolean use_crossfade)
{
GdkDisplay *display;
int n_screens;
int i;
if (nautilus_is_drawing_background (manager) ||
dont_draw_background (manager)) {
return;
}
gnome_settings_profile_start (NULL);
display = gdk_display_get_default ();
n_screens = gdk_display_get_n_screens (display);
for (i = 0; i < n_screens; ++i) {
GdkScreen *screen;
GdkWindow *root_window;
cairo_surface_t *surface;
screen = gdk_display_get_screen (display, i);
root_window = gdk_screen_get_root_window (screen);
surface = gnome_bg_create_surface (manager->priv->bg,
root_window,
gdk_screen_get_width (screen),
gdk_screen_get_height (screen),
TRUE);
if (use_crossfade) {
if (manager->priv->fade != NULL) {
g_object_unref (manager->priv->fade);
}
manager->priv->fade = gnome_bg_set_surface_as_root_with_crossfade (screen, surface);
g_signal_connect_swapped (manager->priv->fade, "finished",
G_CALLBACK (on_crossfade_finished),
manager);
} else {
gnome_bg_set_surface_as_root (screen, surface);
}
cairo_surface_destroy (surface);
}
gnome_settings_profile_end (NULL);
}
static void
on_bg_transitioned (GnomeBG *bg,
GsdBackgroundManager *manager)
{
draw_background (manager, FALSE);
}
static gboolean
settings_change_event_cb (GSettings *settings,
gpointer keys,
gint n_keys,
GsdBackgroundManager *manager)
{
gnome_bg_load_from_preferences (manager->priv->bg,
manager->priv->settings);
return FALSE;
}
static void
on_screen_size_changed (GdkScreen *screen,
GsdBackgroundManager *manager)
{
draw_background (manager, FALSE);
}
static void
watch_bg_preferences (GsdBackgroundManager *manager)
{
g_signal_connect (manager->priv->settings,
"change-event",
G_CALLBACK (settings_change_event_cb),
manager);
}
static void
on_bg_changed (GnomeBG *bg,
GsdBackgroundManager *manager)
{
draw_background (manager, TRUE);
}
static void
setup_bg (GsdBackgroundManager *manager)
{
g_return_if_fail (manager->priv->bg == NULL);
manager->priv->bg = gnome_bg_new ();
g_signal_connect (manager->priv->bg,
"changed",
G_CALLBACK (on_bg_changed),
manager);
g_signal_connect (manager->priv->bg,
"transitioned",
G_CALLBACK (on_bg_transitioned),
manager);
connect_screen_signals (manager);
watch_bg_preferences (manager);
gnome_bg_load_from_preferences (manager->priv->bg,
manager->priv->settings);
}
static void
setup_bg_and_draw_background (GsdBackgroundManager *manager)
{
setup_bg (manager);
draw_background (manager, FALSE);
}
static void
disconnect_session_manager_listener (GsdBackgroundManager *manager)
{
if (manager->priv->proxy && manager->priv->proxy_signal_id) {
g_signal_handler_disconnect (manager->priv->proxy,
manager->priv->proxy_signal_id);
manager->priv->proxy_signal_id = 0;
}
}
static void
on_session_manager_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
GsdBackgroundManager *manager = GSD_BACKGROUND_MANAGER (user_data);
if (g_strcmp0 (signal_name, "SessionRunning") == 0) {
setup_bg_and_draw_background (manager);
disconnect_session_manager_listener (manager);
}
}
static void
draw_background_after_session_loads (GsdBackgroundManager *manager)
{
manager->priv->proxy =
G_DBUS_PROXY (gnome_settings_bus_get_session_proxy ());
manager->priv->proxy_signal_id = g_signal_connect (manager->priv->proxy,
"g-signal",
G_CALLBACK (on_session_manager_signal),
manager);
}
static void
disconnect_screen_signals (GsdBackgroundManager *manager)
{
GdkDisplay *display;
int i;
int n_screens;
display = gdk_display_get_default ();
n_screens = gdk_display_get_n_screens (display);
for (i = 0; i < n_screens; ++i) {
GdkScreen *screen;
screen = gdk_display_get_screen (display, i);
g_signal_handlers_disconnect_by_func (screen,
G_CALLBACK (on_screen_size_changed),
manager);
}
}
static void
connect_screen_signals (GsdBackgroundManager *manager)
{
GdkDisplay *display;
int i;
int n_screens;
display = gdk_display_get_default ();
n_screens = gdk_display_get_n_screens (display);
for (i = 0; i < n_screens; ++i) {
GdkScreen *screen;
screen = gdk_display_get_screen (display, i);
g_signal_connect (screen,
"monitors-changed",
G_CALLBACK (on_screen_size_changed),
manager);
g_signal_connect (screen,
"size-changed",
G_CALLBACK (on_screen_size_changed),
manager);
}
}
static void
draw_background_changed (GSettings *settings,
const char *key,
GsdBackgroundManager *manager)
{
if (dont_draw_background (manager) == FALSE)
setup_bg_and_draw_background (manager);
}
static void
set_accountsservice_background (const gchar *background)
{
GDBusConnection *bus;
GVariant *variant;
GError *error = NULL;
gchar *object_path = NULL;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (bus == NULL) {
g_warning ("Failed to get system bus: %s", error->message);
g_error_free (error);
return;
}
variant = g_dbus_connection_call_sync (bus,
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts",
"FindUserByName",
g_variant_new ("(s)", g_get_user_name ()),
G_VARIANT_TYPE ("(o)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (variant == NULL) {
g_warning ("Could not contact accounts service to look up '%s': %s",
g_get_user_name (), error->message);
g_error_free (error);
g_object_unref (bus);
return;
}
g_variant_get (variant, "(o)", &object_path);
g_variant_unref (variant);
variant = g_dbus_connection_call_sync (bus,
"org.freedesktop.Accounts",
object_path,
"org.freedesktop.DBus.Properties",
"Set",
g_variant_new ("(ssv)",
"org.freedesktop.DisplayManager.AccountsService",
"BackgroundFile",
g_variant_new_string (background ? background : "")),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (variant != NULL)
g_variant_unref (variant);
else {
g_warning ("Failed to set the background '%s': %s", background, error->message);
g_clear_error (&error);
}
/* Also attempt the old method (patch not upstreamed into AccountsService */
variant = g_dbus_connection_call_sync (bus,
"org.freedesktop.Accounts",
object_path,
"org.freedesktop.Accounts.User",
"SetBackgroundFile",
g_variant_new ("(s)", background ? background : ""),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (variant != NULL)
g_variant_unref (variant);
else {
g_warning ("Failed to set the background '%s': %s", background, error->message);
g_clear_error (&error);
}
g_object_unref (bus);
}
static void
picture_uri_changed (GSettings *settings,
const char *key,
GsdBackgroundManager *manager)
{
const char *picture_uri = g_settings_get_string (settings, key);
GFile *picture_file = g_file_new_for_uri (picture_uri);
char *picture_path = g_file_get_path (picture_file);
set_accountsservice_background (picture_path);
g_free (picture_path);
g_object_unref (picture_file);
}
gboolean
gsd_background_manager_start (GsdBackgroundManager *manager,
GError **error)
{
gboolean show_desktop_icons;
g_debug ("Starting background manager");
gnome_settings_profile_start (NULL);
manager->priv->settings = g_settings_new ("org.gnome.desktop.background");
g_signal_connect (manager->priv->settings, "changed::draw-background",
G_CALLBACK (draw_background_changed), manager);
g_signal_connect (manager->priv->settings, "changed::picture-uri",
G_CALLBACK (picture_uri_changed), manager);
/* If this is set, nautilus will draw the background and is
* almost definitely in our session. however, it may not be
* running yet (so is_nautilus_running() will fail). so, on
* startup, just don't do anything if this key is set so we
* don't waste time setting the background only to have
* nautilus overwrite it.
*/
show_desktop_icons = g_settings_get_boolean (manager->priv->settings,
"show-desktop-icons");
if (!show_desktop_icons) {
setup_bg (manager);
} else {
draw_background_after_session_loads (manager);
}
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_background_manager_stop (GsdBackgroundManager *manager)
{
GsdBackgroundManagerPrivate *p = manager->priv;
g_debug ("Stopping background manager");
disconnect_screen_signals (manager);
if (manager->priv->proxy) {
disconnect_session_manager_listener (manager);
g_clear_object (&manager->priv->proxy);
}
g_signal_handlers_disconnect_by_func (manager->priv->settings,
settings_change_event_cb,
manager);
if (p->settings != NULL) {
g_object_unref (p->settings);
p->settings = NULL;
}
if (p->bg != NULL) {
g_object_unref (p->bg);
p->bg = NULL;
}
}
static GObject *
gsd_background_manager_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GsdBackgroundManager *background_manager;
background_manager = GSD_BACKGROUND_MANAGER (G_OBJECT_CLASS (gsd_background_manager_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (background_manager);
}
static void
gsd_background_manager_class_init (GsdBackgroundManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = gsd_background_manager_constructor;
object_class->finalize = gsd_background_manager_finalize;
g_type_class_add_private (klass, sizeof (GsdBackgroundManagerPrivate));
}
static void
gsd_background_manager_init (GsdBackgroundManager *manager)
{
manager->priv = GSD_BACKGROUND_MANAGER_GET_PRIVATE (manager);
}
static void
gsd_background_manager_finalize (GObject *object)
{
GsdBackgroundManager *background_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_BACKGROUND_MANAGER (object));
background_manager = GSD_BACKGROUND_MANAGER (object);
g_return_if_fail (background_manager->priv != NULL);
G_OBJECT_CLASS (gsd_background_manager_parent_class)->finalize (object);
}
GsdBackgroundManager *
gsd_background_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_BACKGROUND_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return GSD_BACKGROUND_MANAGER (manager_object);
}
./plugins/background/Makefile.am 0000644 0000041 0000041 00000003105 13264221014 017071 0 ustar www-data www-data NULL =
plugin_name = background
libexec_PROGRAMS = usd-test-background
usd_test_background_SOURCES = \
test-background.c \
gsd-background-manager.h \
gsd-background-manager.c \
$(NULL)
usd_test_background_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
usd_test_background_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(BACKGROUND_CFLAGS) \
$(AM_CFLAGS)
usd_test_background_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(SETTINGS_PLUGIN_LIBS) \
$(BACKGROUND_LIBS) \
$(NULL)
plugin_LTLIBRARIES = \
libbackground.la \
$(NULL)
libbackground_la_SOURCES = \
gsd-background-plugin.c \
gsd-background-manager.h \
gsd-background-manager.c \
$(NULL)
libbackground_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/background/libbackground \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libbackground_la_CFLAGS = \
$(SETTINGS_PLUGIN_CFLAGS) \
$(BACKGROUND_CFLAGS) \
$(AM_CFLAGS)
libbackground_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS) \
$(NULL)
libbackground_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS) \
$(BACKGROUND_LIBS) \
$(NULL)
plugin_in_files = \
background.gnome-settings-plugin.in \
$(NULL)
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = \
$(plugin_in_files) \
$(NULL)
CLEANFILES = \
$(plugin_DATA) \
$(NULL)
DISTCLEANFILES = \
$(plugin_DATA) \
$(NULL)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/dummy/ 0000755 0000041 0000041 00000000000 13264221014 014052 5 ustar www-data www-data ./plugins/dummy/gsd-dummy-manager.h 0000644 0000041 0000041 00000004370 13264221014 017545 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_DUMMY_MANAGER_H
#define __GSD_DUMMY_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_DUMMY_MANAGER (gsd_dummy_manager_get_type ())
#define GSD_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManager))
#define GSD_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass))
#define GSD_IS_DUMMY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DUMMY_MANAGER))
#define GSD_IS_DUMMY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DUMMY_MANAGER))
#define GSD_DUMMY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerClass))
typedef struct GsdDummyManagerPrivate GsdDummyManagerPrivate;
typedef struct
{
GObject parent;
GsdDummyManagerPrivate *priv;
} GsdDummyManager;
typedef struct
{
GObjectClass parent_class;
} GsdDummyManagerClass;
GType gsd_dummy_manager_get_type (void);
GsdDummyManager * gsd_dummy_manager_new (void);
gboolean gsd_dummy_manager_start (GsdDummyManager *manager,
GError **error);
void gsd_dummy_manager_stop (GsdDummyManager *manager);
G_END_DECLS
#endif /* __GSD_DUMMY_MANAGER_H */
./plugins/dummy/gsd-dummy-manager.c 0000644 0000041 0000041 00000012213 13264221014 017533 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gnome-settings-profile.h"
#include "gsd-dummy-manager.h"
#define GSD_DUMMY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_DUMMY_MANAGER, GsdDummyManagerPrivate))
struct GsdDummyManagerPrivate
{
gboolean padding;
};
enum {
PROP_0,
};
static void gsd_dummy_manager_class_init (GsdDummyManagerClass *klass);
static void gsd_dummy_manager_init (GsdDummyManager *dummy_manager);
static void gsd_dummy_manager_finalize (GObject *object);
G_DEFINE_TYPE (GsdDummyManager, gsd_dummy_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
gboolean
gsd_dummy_manager_start (GsdDummyManager *manager,
GError **error)
{
g_debug ("Starting dummy manager");
gnome_settings_profile_start (NULL);
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_dummy_manager_stop (GsdDummyManager *manager)
{
g_debug ("Stopping dummy manager");
}
static void
gsd_dummy_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gsd_dummy_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObject *
gsd_dummy_manager_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GsdDummyManager *dummy_manager;
dummy_manager = GSD_DUMMY_MANAGER (G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (dummy_manager);
}
static void
gsd_dummy_manager_dispose (GObject *object)
{
G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->dispose (object);
}
static void
gsd_dummy_manager_class_init (GsdDummyManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gsd_dummy_manager_get_property;
object_class->set_property = gsd_dummy_manager_set_property;
object_class->constructor = gsd_dummy_manager_constructor;
object_class->dispose = gsd_dummy_manager_dispose;
object_class->finalize = gsd_dummy_manager_finalize;
g_type_class_add_private (klass, sizeof (GsdDummyManagerPrivate));
}
static void
gsd_dummy_manager_init (GsdDummyManager *manager)
{
manager->priv = GSD_DUMMY_MANAGER_GET_PRIVATE (manager);
}
static void
gsd_dummy_manager_finalize (GObject *object)
{
GsdDummyManager *dummy_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_DUMMY_MANAGER (object));
dummy_manager = GSD_DUMMY_MANAGER (object);
g_return_if_fail (dummy_manager->priv != NULL);
G_OBJECT_CLASS (gsd_dummy_manager_parent_class)->finalize (object);
}
GsdDummyManager *
gsd_dummy_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_DUMMY_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return GSD_DUMMY_MANAGER (manager_object);
}
./plugins/dummy/gsd-dummy-plugin.c 0000644 0000041 0000041 00000002015 13264221014 017416 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-dummy-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdDummy, gsd_dummy)
./plugins/dummy/Makefile.am 0000644 0000041 0000041 00000001556 13264221014 016115 0 ustar www-data www-data plugin_name = dummy
plugin_LTLIBRARIES = \
libdummy.la
libdummy_la_SOURCES = \
gsd-dummy-manager.c \
gsd-dummy-manager.h \
gsd-dummy-plugin.c
libdummy_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libdummy_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
libdummy_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libdummy_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS)
plugin_in_files = \
dummy.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = \
$(plugin_in_files)
CLEANFILES = \
$(plugin_DATA)
DISTCLEANFILES = \
$(plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
# override to _not_ install the test plugin
# do not copy into your plugin
install-pluginDATA:
install-pluginLTLIBRARIES:
./plugins/dummy/dummy.gnome-settings-plugin.in 0000644 0000041 0000041 00000000275 13264221014 021777 0 ustar www-data www-data [GNOME Settings Plugin]
Module=dummy
IAge=0
# 100 is the default load Priority
Priority=100
_Name=Dummy
_Description=Dummy plugin
Authors=AUTHOR
Copyright=Copyright © 2007 AUTHOR
Website=
./plugins/screensaver-proxy/ 0000755 0000041 0000041 00000000000 13264221014 016416 5 ustar www-data www-data ./plugins/screensaver-proxy/test-screensaver-proxy.c 0000644 0000041 0000041 00000000400 13264221014 023230 0 ustar www-data www-data #define NEW gsd_screensaver_proxy_manager_new
#define START gsd_screensaver_proxy_manager_start
#define STOP gsd_screensaver_proxy_manager_stop
#define MANAGER GsdScreensaverProxyManager
#include "gsd-screensaver-proxy-manager.h"
#include "test-plugin.h"
./plugins/screensaver-proxy/gsd-screensaver-proxy-manager.c 0000644 0000041 0000041 00000045327 13264221014 024457 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "gnome-settings-bus.h"
#include "gnome-settings-profile.h"
#include "gsd-screensaver-proxy-manager.h"
#include "gsd-idle-monitor.h"
#define GSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerPrivate))
/* As available in:
* https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/ksmserver/screenlocker/dbus/org.freedesktop.ScreenSaver.xml
* and documented in:
* https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/ksmserver/screenlocker/interface.h */
static const gchar introspection_xml[] =
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
"";
static const gchar introspection_xml2[] =
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
""
"";
#define GSD_SCREENSAVER_PROXY_DBUS_SERVICE "org.freedesktop.ScreenSaver"
#define GSD_SCREENSAVER_PROXY_DBUS_PATH "/org/freedesktop/ScreenSaver"
#define GSD_SCREENSAVER_PROXY_DBUS_PATH2 "/ScreenSaver"
#define GSD_SCREENSAVER_PROXY_DBUS_INTERFACE "org.freedesktop.ScreenSaver"
#define GSM_INHIBITOR_FLAG_IDLE 1 << 3
struct GsdScreensaverProxyManagerPrivate
{
GsdSessionManager *session;
GsdScreenSaver *screensaver;
GDBusConnection *connection;
GCancellable *bus_cancellable;
GDBusNodeInfo *introspection_data;
GDBusNodeInfo *introspection_data2;
guint name_id;
GHashTable *watch_ht; /* key = sender, value = name watch id */
GHashTable *cookie_ht; /* key = cookie, value = sender */
};
static void gsd_screensaver_proxy_manager_class_init (GsdScreensaverProxyManagerClass *klass);
static void gsd_screensaver_proxy_manager_init (GsdScreensaverProxyManager *screensaver_proxy_manager);
static void gsd_screensaver_proxy_manager_finalize (GObject *object);
G_DEFINE_TYPE (GsdScreensaverProxyManager, gsd_screensaver_proxy_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static void
name_vanished_cb (GDBusConnection *connection,
const gchar *name,
GsdScreensaverProxyManager *manager)
{
GHashTableIter iter;
gpointer cookie_ptr;
const char *sender;
/* Look for all the cookies under that name,
* and call uninhibit for them */
g_hash_table_iter_init (&iter, manager->priv->cookie_ht);
while (g_hash_table_iter_next (&iter, &cookie_ptr, (gpointer *) &sender)) {
if (g_strcmp0 (sender, name) == 0) {
guint cookie = GPOINTER_TO_UINT (cookie_ptr);
g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session),
"Uninhibit",
g_variant_new ("(u)", cookie),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
g_debug ("Removing cookie %u for sender %s",
cookie, sender);
g_hash_table_iter_remove (&iter);
}
}
g_hash_table_remove (manager->priv->watch_ht, name);
}
static void
handle_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GsdScreensaverProxyManager *manager = GSD_SCREENSAVER_PROXY_MANAGER (user_data);
GError *error = NULL;
GVariant *ret = NULL;
/* Check session pointer as a proxy for whether the manager is in the
start or stop state */
if (manager->priv->session == NULL || manager->priv->screensaver == NULL) {
goto unimplemented;
}
g_debug ("Calling method '%s.%s' for ScreenSaver Proxy",
interface_name, method_name);
if (g_strcmp0 (method_name, "Inhibit") == 0) {
const char *app_id;
const char *reason;
guint cookie;
g_variant_get (parameters,
"(ss)", &app_id, &reason);
ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session),
"Inhibit",
g_variant_new ("(susu)",
app_id, 0, reason, GSM_INHIBITOR_FLAG_IDLE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
g_variant_get (ret, "(u)", &cookie);
g_hash_table_insert (manager->priv->cookie_ht,
GUINT_TO_POINTER (cookie),
g_strdup (sender));
if (g_hash_table_lookup (manager->priv->watch_ht, sender) == NULL) {
guint watch_id;
watch_id = g_bus_watch_name_on_connection (manager->priv->connection,
sender,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL,
(GBusNameVanishedCallback) name_vanished_cb,
manager,
NULL);
g_hash_table_insert (manager->priv->watch_ht,
g_strdup (sender),
GUINT_TO_POINTER (watch_id));
}
} else if (g_strcmp0 (method_name, "UnInhibit") == 0) {
guint cookie;
g_variant_get (parameters, "(u)", &cookie);
g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->session),
"Uninhibit",
parameters,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
g_debug ("Removing cookie %u from the list for %s", cookie, sender);
g_hash_table_remove (manager->priv->cookie_ht, GUINT_TO_POINTER (cookie));
} else if (g_strcmp0 (method_name, "Lock") == 0 ||
g_strcmp0 (method_name, "SimulateUserActivity") == 0 ||
g_strcmp0 (method_name, "GetActive") == 0 ||
g_strcmp0 (method_name, "GetActiveTime") == 0 ||
g_strcmp0 (method_name, "SetActive") == 0) {
ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->priv->screensaver),
method_name,
parameters,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (error == NULL && g_strcmp0 (method_name, "SetActive") == 0) {
g_variant_unref (ret);
/* Returning the actual Activate state here is not possible,
* as calling GetActive at this point might return an invalid
* value if the activation process is still ongoing. */
ret = g_variant_ref (parameters);
}
} else if (g_strcmp0 (method_name, "GetSessionIdleTime") == 0) {
GsdIdleMonitor *idle_monitor = gsd_idle_monitor_get_core ();
gint64 idle_time_ms = gsd_idle_monitor_get_idletime (idle_monitor);
ret = g_variant_new ("(u)", idle_time_ms / 1000);
} else {
goto unimplemented;
}
if (error != NULL) {
g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
return;
}
g_dbus_method_invocation_return_value (invocation, ret);
return;
unimplemented:
g_dbus_method_invocation_return_dbus_error (invocation,
"org.freedesktop.DBus.Error.NotSupported",
"This method is not implemented");
}
static const GDBusInterfaceVTable interface_vtable =
{
handle_method_call,
NULL, /* GetProperty */
NULL, /* SetProperty */
};
static void
on_bus_gotten (GObject *source_object,
GAsyncResult *res,
GsdScreensaverProxyManager *manager)
{
GDBusConnection *connection;
GDBusInterfaceInfo **infos;
GError *error = NULL;
if (manager->priv->bus_cancellable == NULL ||
g_cancellable_is_cancelled (manager->priv->bus_cancellable)) {
g_warning ("Operation has been cancelled, so not retrieving session bus");
return;
}
connection = g_bus_get_finish (res, &error);
if (connection == NULL) {
g_warning ("Could not get session bus: %s", error->message);
g_error_free (error);
return;
}
manager->priv->connection = connection;
infos = manager->priv->introspection_data->interfaces;
g_dbus_connection_register_object (connection,
GSD_SCREENSAVER_PROXY_DBUS_PATH,
infos[0],
&interface_vtable,
manager,
NULL,
NULL);
infos = manager->priv->introspection_data2->interfaces;
g_dbus_connection_register_object (connection,
GSD_SCREENSAVER_PROXY_DBUS_PATH2,
infos[0],
&interface_vtable,
manager,
NULL,
NULL);
manager->priv->name_id = g_bus_own_name_on_connection (manager->priv->connection,
GSD_SCREENSAVER_PROXY_DBUS_SERVICE,
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
NULL,
NULL,
NULL);
}
static void
register_manager_dbus (GsdScreensaverProxyManager *manager)
{
manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
manager->priv->introspection_data2 = g_dbus_node_info_new_for_xml (introspection_xml2, NULL);
manager->priv->bus_cancellable = g_cancellable_new ();
g_assert (manager->priv->introspection_data != NULL);
g_assert (manager->priv->introspection_data2 != NULL);
g_bus_get (G_BUS_TYPE_SESSION,
manager->priv->bus_cancellable,
(GAsyncReadyCallback) on_bus_gotten,
manager);
}
gboolean
gsd_screensaver_proxy_manager_start (GsdScreensaverProxyManager *manager,
GError **error)
{
g_debug ("Starting screensaver-proxy manager");
gnome_settings_profile_start (NULL);
manager->priv->session =
gnome_settings_bus_get_session_proxy ();
manager->priv->screensaver =
gnome_settings_bus_get_screen_saver_proxy ();
manager->priv->watch_ht = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_bus_unwatch_name);
manager->priv->cookie_ht = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) g_free);
gnome_settings_profile_end (NULL);
return TRUE;
}
void
gsd_screensaver_proxy_manager_stop (GsdScreensaverProxyManager *manager)
{
g_debug ("Stopping screensaver_proxy manager");
g_clear_object (&manager->priv->session);
g_clear_object (&manager->priv->screensaver);
g_clear_pointer (&manager->priv->watch_ht, g_hash_table_destroy);
g_clear_pointer (&manager->priv->cookie_ht, g_hash_table_destroy);
}
static void
gsd_screensaver_proxy_manager_class_init (GsdScreensaverProxyManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_screensaver_proxy_manager_finalize;
g_type_class_add_private (klass, sizeof (GsdScreensaverProxyManagerPrivate));
}
static void
gsd_screensaver_proxy_manager_init (GsdScreensaverProxyManager *manager)
{
manager->priv = GSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE (manager);
}
static void
gsd_screensaver_proxy_manager_finalize (GObject *object)
{
GsdScreensaverProxyManager *manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_SCREENSAVER_PROXY_MANAGER (object));
manager = GSD_SCREENSAVER_PROXY_MANAGER (object);
g_return_if_fail (manager->priv != NULL);
gsd_screensaver_proxy_manager_stop (manager);
if (manager->priv->name_id != 0) {
g_bus_unown_name (manager->priv->name_id);
manager->priv->name_id = 0;
}
g_clear_object (&manager->priv->connection);
g_clear_object (&manager->priv->bus_cancellable);
g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref);
g_clear_pointer (&manager->priv->introspection_data2, g_dbus_node_info_unref);
G_OBJECT_CLASS (gsd_screensaver_proxy_manager_parent_class)->finalize (object);
}
GsdScreensaverProxyManager *
gsd_screensaver_proxy_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (GSD_TYPE_SCREENSAVER_PROXY_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
register_manager_dbus (manager_object);
}
return GSD_SCREENSAVER_PROXY_MANAGER (manager_object);
}
./plugins/screensaver-proxy/gsd-screensaver-proxy-plugin.c 0000644 0000041 0000041 00000002057 13264221014 024334 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include
#include
#include "gnome-settings-plugin.h"
#include "gsd-screensaver-proxy-manager.h"
GNOME_SETTINGS_PLUGIN_REGISTER (GsdScreensaverProxy, gsd_screensaver_proxy)
./plugins/screensaver-proxy/screensaver-proxy.gnome-settings-plugin.in 0000644 0000041 0000041 00000000355 13264221014 026706 0 ustar www-data www-data [GNOME Settings Plugin]
Module=screensaver-proxy
IAge=0
Priority=8
_Name=Screensaver Proxy
_Description=Proxy FreeDesktop screensaver inhibition to gnome-session
Authors=Bastien Nocera
Copyright=Copyright © 2012 Bastien Nocera
Website=
./plugins/screensaver-proxy/gsd-screensaver-proxy-manager.h 0000644 0000041 0000041 00000005167 13264221014 024462 0 ustar www-data www-data /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Bastien Nocera
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_SCREENSAVER_PROXY_MANAGER_H
#define __GSD_SCREENSAVER_PROXY_MANAGER_H
#include
G_BEGIN_DECLS
#define GSD_TYPE_SCREENSAVER_PROXY_MANAGER (gsd_screensaver_proxy_manager_get_type ())
#define GSD_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManager))
#define GSD_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerClass))
#define GSD_IS_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER))
#define GSD_IS_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SCREENSAVER_PROXY_MANAGER))
#define GSD_SCREENSAVER_PROXY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SCREENSAVER_PROXY_MANAGER, GsdScreensaverProxyManagerClass))
typedef struct GsdScreensaverProxyManagerPrivate GsdScreensaverProxyManagerPrivate;
typedef struct
{
GObject parent;
GsdScreensaverProxyManagerPrivate *priv;
} GsdScreensaverProxyManager;
typedef struct
{
GObjectClass parent_class;
} GsdScreensaverProxyManagerClass;
GType gsd_screensaver_proxy_manager_get_type (void);
GsdScreensaverProxyManager *gsd_screensaver_proxy_manager_new (void);
gboolean gsd_screensaver_proxy_manager_start (GsdScreensaverProxyManager *manager,
GError **error);
void gsd_screensaver_proxy_manager_stop (GsdScreensaverProxyManager *manager);
G_END_DECLS
#endif /* __GSD_SCREENSAVER_PROXY_MANAGER_H */
./plugins/screensaver-proxy/Makefile.am 0000644 0000041 0000041 00000003106 13264221014 020452 0 ustar www-data www-data plugin_name = screensaver-proxy
plugin_LTLIBRARIES = libscreensaver-proxy.la
libscreensaver_proxy_la_SOURCES = \
gsd-screensaver-proxy-manager.c \
gsd-screensaver-proxy-manager.h \
gsd-screensaver-proxy-plugin.c
libscreensaver_proxy_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
libscreensaver_proxy_la_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
libscreensaver_proxy_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
libscreensaver_proxy_la_LIBADD = $(SETTINGS_PLUGIN_LIBS)
libexec_PROGRAMS = usd-test-screensaver-proxy
usd_test_screensaver_proxy_SOURCES = \
test-screensaver-proxy.c \
gsd-screensaver-proxy-manager.c \
gsd-screensaver-proxy-manager.h
usd_test_screensaver_proxy_CPPFLAGS = \
-I$(top_srcdir)/data/ \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
$(AM_CPPFLAGS)
usd_test_screensaver_proxy_CFLAGS = \
$(PLUGIN_CFLAGS) \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
usd_test_screensaver_proxy_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd.la \
$(top_builddir)/plugins/common/libcommon.la \
$(SETTINGS_DAEMON_LIBS) \
$(SETTINGS_PLUGIN_LIBS)
plugin_in_files = screensaver-proxy.gnome-settings-plugin.in
plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
EXTRA_DIST = $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
@GSD_INTLTOOL_PLUGIN_RULE@
./plugins/automount/ 0000755 0000041 0000041 00000000000 13264221014 014752 5 ustar www-data www-data ./plugins/automount/gsd-automount-manager.c 0000644 0000041 0000041 00000052144 13264221014 021342 0 ustar www-data www-data /* -*- 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Tomas Bzatek
*/
#include "config.h"
#include