cinnamon-settings-daemon-5.2.0/ 0000775 0001750 0001750 00000000000 14144454032 015344 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/ 0000775 0001750 0001750 00000000000 14144454032 017025 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/ 0000775 0001750 0001750 00000000000 14144454032 021376 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/csd-a11y-preferences-dialog.ui 0000664 0001750 0001750 00000026117 14144454032 027022 0 ustar fabio fabio
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/meson.build 0000664 0001750 0001750 00000002327 14144454032 023544 0 ustar fabio fabio plugin_name = 'a11y-keyboard'
a11y_keyboard_sources = [
'csd-a11y-keyboard-manager.c',
'csd-a11y-preferences-dialog.c',
'main.c',
]
a11y_keyboard_deps = [
common_dep,
csd_dep,
libnotify,
]
executable(
'csd-a11y-keyboard',
a11y_keyboard_sources,
include_directories: [include_dirs, common_inc],
dependencies: a11y_keyboard_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-a11y-keyboard')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-a11y-keyboard')
endif
test_a11y_prefs_dialog_sources = [
'csd-a11y-preferences-dialog.c',
'test-a11y-preferences-dialog.c',
]
executable(
'test-a11y-preferences-dialog',
test_a11y_prefs_dialog_sources,
dependencies: a11y_keyboard_deps,
install: false,
)
configure_file(
input: 'cinnamon-settings-daemon-a11y-keyboard.desktop.in',
output: 'cinnamon-settings-daemon-a11y-keyboard.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
install_data(
'csd-a11y-preferences-dialog.ui',
install_dir: pkgdatadir,
)
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/test-a11y-preferences-dialog.c 0000664 0001750 0001750 00000003175 14144454032 027034 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA
* 02110-1335, USA.
*
*
*/
#include "config.h"
#include
#include
#include
#include "csd-a11y-preferences-dialog.h"
static void
test_window (void)
{
GtkWidget *window;
window = csd_a11y_preferences_dialog_new ();
gtk_dialog_run (GTK_DIALOG (window));
}
int
main (int argc,
char **argv)
{
GError *error = NULL;
bindtextdomain (GETTEXT_PACKAGE, CINNAMON_SETTINGS_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
fprintf (stderr, "%s", error->message);
g_error_free (error);
exit (1);
}
test_window ();
return 0;
}
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/csd-a11y-keyboard-manager.h 0000664 0001750 0001750 00000004750 14144454032 026305 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_A11Y_KEYBOARD_MANAGER_H
#define __CSD_A11Y_KEYBOARD_MANAGER_H
#include
G_BEGIN_DECLS
#define CSD_TYPE_A11Y_KEYBOARD_MANAGER (csd_a11y_keyboard_manager_get_type ())
#define CSD_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_A11Y_KEYBOARD_MANAGER, CsdA11yKeyboardManager))
#define CSD_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_A11Y_KEYBOARD_MANAGER, CsdA11yKeyboardManagerClass))
#define CSD_IS_A11Y_KEYBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_A11Y_KEYBOARD_MANAGER))
#define CSD_IS_A11Y_KEYBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_A11Y_KEYBOARD_MANAGER))
#define CSD_A11Y_KEYBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_A11Y_KEYBOARD_MANAGER, CsdA11yKeyboardManagerClass))
typedef struct CsdA11yKeyboardManagerPrivate CsdA11yKeyboardManagerPrivate;
typedef struct
{
GObject parent;
CsdA11yKeyboardManagerPrivate *priv;
} CsdA11yKeyboardManager;
typedef struct
{
GObjectClass parent_class;
} CsdA11yKeyboardManagerClass;
GType csd_a11y_keyboard_manager_get_type (void);
CsdA11yKeyboardManager *csd_a11y_keyboard_manager_new (void);
gboolean csd_a11y_keyboard_manager_start (CsdA11yKeyboardManager *manager,
GError **error);
void csd_a11y_keyboard_manager_stop (CsdA11yKeyboardManager *manager);
G_END_DECLS
#endif /* __CSD_A11Y_KEYBOARD_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/main.c 0000664 0001750 0001750 00000001054 14144454032 022466 0 ustar fabio fabio #define NEW csd_a11y_keyboard_manager_new
#define START csd_a11y_keyboard_manager_start
#define STOP csd_a11y_keyboard_manager_stop
#define MANAGER CsdA11yKeyboardManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING TRUE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE TRUE
#include "csd-a11y-keyboard-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/csd-a11y-keyboard-manager.c 0000664 0001750 0001750 00000132661 14144454032 026303 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright © 2001 Ximian, Inc.
* 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cinnamon-settings-profile.h"
#include "csd-a11y-keyboard-manager.h"
#include "csd-a11y-preferences-dialog.h"
#define KEYBOARD_A11Y_SCHEMA "org.cinnamon.desktop.a11y.keyboard"
#define NOTIFICATION_TIMEOUT 30
#define CSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_A11Y_KEYBOARD_MANAGER, CsdA11yKeyboardManagerPrivate))
struct CsdA11yKeyboardManagerPrivate
{
guint start_idle_id;
int xkbEventBase;
GdkDeviceManager *device_manager;
guint device_added_id;
gboolean stickykeys_shortcut_val;
gboolean slowkeys_shortcut_val;
GtkWidget *stickykeys_alert;
GtkWidget *slowkeys_alert;
GtkWidget *preferences_dialog;
GtkStatusIcon *status_icon;
GSettings *settings;
NotifyNotification *notification;
};
static void csd_a11y_keyboard_manager_finalize (GObject *object);
static void csd_a11y_keyboard_manager_ensure_status_icon (CsdA11yKeyboardManager *manager);
static void set_server_from_gsettings (CsdA11yKeyboardManager *manager);
G_DEFINE_TYPE (CsdA11yKeyboardManager, csd_a11y_keyboard_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static void
device_added_cb (GdkDeviceManager *device_manager,
GdkDevice *device,
CsdA11yKeyboardManager *manager)
{
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
set_server_from_gsettings (manager);
}
static void
set_devicepresence_handler (CsdA11yKeyboardManager *manager)
{
GdkDeviceManager *device_manager;
device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
if (device_manager == NULL)
return;
manager->priv->device_manager = device_manager;
manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added",
G_CALLBACK (device_added_cb), manager);
}
static gboolean
xkb_enabled (CsdA11yKeyboardManager *manager)
{
int opcode, errorBase, major, minor;
if (!XkbQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
&opcode,
&manager->priv->xkbEventBase,
&errorBase,
&major,
&minor))
return FALSE;
if (!XkbUseExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor))
return FALSE;
return TRUE;
}
static XkbDescRec *
get_xkb_desc_rec (CsdA11yKeyboardManager *manager)
{
XkbDescRec *desc;
Status status = Success;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
desc = XkbGetMap (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbAllMapComponentsMask, XkbUseCoreKbd);
if (desc != NULL) {
desc->ctrls = NULL;
status = XkbGetControls (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbAllControlsMask, desc);
}
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
g_return_val_if_fail (desc != NULL, NULL);
g_return_val_if_fail (desc->ctrls != NULL, NULL);
g_return_val_if_fail (status == Success, NULL);
return desc;
}
static int
get_int (GSettings *settings,
char const *key)
{
int res = g_settings_get_int (settings, key);
if (res <= 0) {
res = 1;
}
return res;
}
static gboolean
set_int (GSettings *settings,
char const *key,
int val)
{
int prev_val;
prev_val = g_settings_get_int (settings, key);
g_settings_set_int (settings, key, val);
if (val != prev_val) {
g_debug ("%s changed", key);
}
return val != prev_val;
}
static gboolean
set_bool (GSettings *settings,
char const *key,
int val)
{
gboolean bval = (val != 0);
gboolean prev_val;
prev_val = g_settings_get_boolean (settings, key);
g_settings_set_boolean (settings, key, bval ? TRUE : FALSE);
if (bval != prev_val) {
g_debug ("%s changed", key);
return TRUE;
}
return (bval != prev_val);
}
static unsigned long
set_clear (gboolean flag,
unsigned long value,
unsigned long mask)
{
if (flag) {
return value | mask;
}
return value & ~mask;
}
static gboolean
set_ctrl_from_gsettings (XkbDescRec *desc,
GSettings *settings,
char const *key,
unsigned long mask)
{
gboolean result = g_settings_get_boolean (settings, key);
desc->ctrls->enabled_ctrls = set_clear (result, desc->ctrls->enabled_ctrls, mask);
return result;
}
static void
set_server_from_gsettings (CsdA11yKeyboardManager *manager)
{
XkbDescRec *desc;
gboolean enable_accessX;
GSettings *settings;
cinnamon_settings_profile_start (NULL);
desc = get_xkb_desc_rec (manager);
if (!desc) {
return;
}
settings = manager->priv->settings;
/* general */
enable_accessX = g_settings_get_boolean (settings, "enable");
desc->ctrls->enabled_ctrls = set_clear (enable_accessX,
desc->ctrls->enabled_ctrls,
XkbAccessXKeysMask);
if (set_ctrl_from_gsettings (desc, settings, "timeout-enable",
XkbAccessXTimeoutMask)) {
desc->ctrls->ax_timeout = get_int (settings, "disable-timeout");
/* disable only the master flag via the server we will disable
* the rest on the rebound without affecting GSettings state
* don't change the option flags at all.
*/
desc->ctrls->axt_ctrls_mask = XkbAccessXKeysMask | XkbAccessXFeedbackMask;
desc->ctrls->axt_ctrls_values = 0;
desc->ctrls->axt_opts_mask = 0;
}
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "feature-state-change-beep"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask);
/* bounce keys */
if (set_ctrl_from_gsettings (desc, settings, "bouncekeys-enable", XkbBounceKeysMask)) {
desc->ctrls->debounce_delay = get_int (settings, "bouncekeys-delay");
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "bouncekeys-beep-reject"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask);
}
/* mouse keys */
if (set_ctrl_from_gsettings (desc, settings, "mousekeys-enable", XkbMouseKeysMask | XkbMouseKeysAccelMask)) {
desc->ctrls->mk_interval = 100; /* msec between mousekey events */
desc->ctrls->mk_curve = 50;
/* We store pixels / sec, XKB wants pixels / event */
desc->ctrls->mk_max_speed = get_int (settings, "mousekeys-max-speed") / (1000 / desc->ctrls->mk_interval);
if (desc->ctrls->mk_max_speed <= 0)
desc->ctrls->mk_max_speed = 1;
desc->ctrls->mk_time_to_max = get_int (settings, /* events before max */
"mousekeys-accel-time") / desc->ctrls->mk_interval;
if (desc->ctrls->mk_time_to_max <= 0)
desc->ctrls->mk_time_to_max = 1;
desc->ctrls->mk_delay = get_int (settings, /* ms before 1st event */
"mousekeys-init-delay");
}
/* slow keys */
if (set_ctrl_from_gsettings (desc, settings, "slowkeys-enable", XkbSlowKeysMask)) {
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-press"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_SKPressFBMask);
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-accept"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask);
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "slowkeys-beep-reject"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask);
desc->ctrls->slow_keys_delay = get_int (settings, "slowkeys-delay");
/* anything larger than 500 seems to loose all keyboard input */
if (desc->ctrls->slow_keys_delay > 500)
desc->ctrls->slow_keys_delay = 500;
}
/* sticky keys */
if (set_ctrl_from_gsettings (desc, settings, "stickykeys-enable", XkbStickyKeysMask)) {
desc->ctrls->ax_options |= XkbAX_LatchToLockMask;
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "stickykeys-two-key-off"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_TwoKeysMask);
desc->ctrls->ax_options = set_clear (g_settings_get_boolean (settings, "stickykeys-modifier-beep"),
desc->ctrls->ax_options,
XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask);
}
/*
g_debug ("CHANGE to : 0x%x", desc->ctrls->enabled_ctrls);
g_debug ("CHANGE to : 0x%x (2)", desc->ctrls->ax_options);
*/
gdk_x11_display_error_trap_push (gdk_display_get_default ());
XkbSetControls (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
XkbSlowKeysMask |
XkbBounceKeysMask |
XkbStickyKeysMask |
XkbMouseKeysMask |
XkbMouseKeysAccelMask |
XkbAccessXKeysMask |
XkbAccessXTimeoutMask |
XkbAccessXFeedbackMask |
XkbControlsEnabledMask,
desc);
XkbFreeKeyboard (desc, XkbAllComponentsMask, True);
XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
cinnamon_settings_profile_end (NULL);
}
static gboolean
ax_response_callback (CsdA11yKeyboardManager *manager,
GtkWindow *parent,
gint response_id,
guint revert_controls_mask,
gboolean enabled)
{
GSettings *settings;
GdkScreen *screen;
GError *err;
settings = manager->priv->settings;
switch (response_id) {
case GTK_RESPONSE_DELETE_EVENT:
case GTK_RESPONSE_REJECT:
case GTK_RESPONSE_CANCEL:
/* we're reverting, so we invert sense of 'enabled' flag */
g_debug ("cancelling AccessX request");
if (revert_controls_mask == XkbStickyKeysMask) {
g_settings_set_boolean (settings,
"stickykeys-enable",
!enabled);
} else if (revert_controls_mask == XkbSlowKeysMask) {
g_settings_set_boolean (settings,
"slowkeys-enable",
!enabled);
}
set_server_from_gsettings (manager);
break;
case GTK_RESPONSE_HELP:
if (!parent)
screen = gdk_screen_get_default ();
else
screen = gtk_widget_get_screen (GTK_WIDGET (parent));
err = NULL;
if (!gtk_show_uri (screen,
"help:gnome-help/a11y",
gtk_get_current_event_time(),
&err)) {
GtkWidget *error_dialog = gtk_message_dialog_new (parent,
0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("There was an error displaying help: %s"),
err->message);
g_signal_connect (error_dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE);
gtk_widget_show (error_dialog);
g_error_free (err);
}
return FALSE;
default:
break;
}
return TRUE;
}
static void
ax_stickykeys_response (GtkDialog *dialog,
gint response_id,
CsdA11yKeyboardManager *manager)
{
if (ax_response_callback (manager, GTK_WINDOW (dialog),
response_id, XkbStickyKeysMask,
manager->priv->stickykeys_shortcut_val)) {
gtk_widget_destroy (GTK_WIDGET (dialog));
}
}
static void
ax_slowkeys_response (GtkDialog *dialog,
gint response_id,
CsdA11yKeyboardManager *manager)
{
if (ax_response_callback (manager, GTK_WINDOW (dialog),
response_id, XkbSlowKeysMask,
manager->priv->slowkeys_shortcut_val)) {
gtk_widget_destroy (GTK_WIDGET (dialog));
}
}
static void
maybe_show_status_icon (CsdA11yKeyboardManager *manager)
{
gboolean show;
/* for now, show if accessx is enabled */
show = g_settings_get_boolean (manager->priv->settings, "enable");
if (!show && manager->priv->status_icon == NULL)
return;
csd_a11y_keyboard_manager_ensure_status_icon (manager);
gtk_status_icon_set_visible (manager->priv->status_icon, show);
}
static void
on_notification_closed (NotifyNotification *notification,
CsdA11yKeyboardManager *manager)
{
g_object_unref (manager->priv->notification);
manager->priv->notification = NULL;
}
static void
on_slow_keys_action (NotifyNotification *notification,
const char *action,
CsdA11yKeyboardManager *manager)
{
gboolean res;
int response_id;
g_assert (action != NULL);
if (strcmp (action, "accept") == 0) {
response_id = GTK_RESPONSE_ACCEPT;
} else if (strcmp (action, "reject") == 0) {
response_id = GTK_RESPONSE_REJECT;
} else {
return;
}
res = ax_response_callback (manager, NULL,
response_id, XkbSlowKeysMask,
manager->priv->slowkeys_shortcut_val);
if (res) {
notify_notification_close (manager->priv->notification, NULL);
}
}
static void
on_sticky_keys_action (NotifyNotification *notification,
const char *action,
CsdA11yKeyboardManager *manager)
{
gboolean res;
int response_id;
g_assert (action != NULL);
if (strcmp (action, "accept") == 0) {
response_id = GTK_RESPONSE_ACCEPT;
} else if (strcmp (action, "reject") == 0) {
response_id = GTK_RESPONSE_REJECT;
} else {
return;
}
res = ax_response_callback (manager, NULL,
response_id, XkbStickyKeysMask,
manager->priv->stickykeys_shortcut_val);
if (res) {
notify_notification_close (manager->priv->notification, NULL);
}
}
static gboolean
ax_slowkeys_warning_post_bubble (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
gboolean res;
const char *title;
const char *message;
GError *error;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
message = _("You just held down the Shift key for 8 seconds. This is the shortcut "
"for the Slow Keys feature, which affects the way your keyboard works.");
if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
return FALSE;
}
if (manager->priv->slowkeys_alert != NULL) {
gtk_widget_destroy (manager->priv->slowkeys_alert);
}
if (manager->priv->notification != NULL) {
notify_notification_close (manager->priv->notification, NULL);
}
csd_a11y_keyboard_manager_ensure_status_icon (manager);
manager->priv->notification = notify_notification_new (title,
message,
"preferences-desktop-accessibility-symbolic");
notify_notification_set_app_name (manager->priv->notification, _("Universal Access"));
notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
notify_notification_set_hint (manager->priv->notification, "transient", g_variant_new_boolean (TRUE));
notify_notification_add_action (manager->priv->notification,
"reject",
enabled ? _("Turn Off") : _("Turn On"),
(NotifyActionCallback) on_slow_keys_action,
manager,
NULL);
notify_notification_add_action (manager->priv->notification,
"accept",
enabled ? _("Leave On") : _("Leave Off"),
(NotifyActionCallback) on_slow_keys_action,
manager,
NULL);
g_signal_connect (manager->priv->notification,
"closed",
G_CALLBACK (on_notification_closed),
manager);
error = NULL;
res = notify_notification_show (manager->priv->notification, &error);
if (! res) {
g_warning ("CsdA11yKeyboardManager: unable to show notification: %s", error->message);
g_error_free (error);
notify_notification_close (manager->priv->notification, NULL);
}
return res;
}
static void
ax_slowkeys_warning_post_dialog (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
const char *title;
const char *message;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
message = _("You just held down the Shift key for 8 seconds. This is the shortcut "
"for the Slow Keys feature, which affects the way your keyboard works.");
if (manager->priv->slowkeys_alert != NULL) {
gtk_widget_show (manager->priv->slowkeys_alert);
return;
}
manager->priv->slowkeys_alert = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
"%s", title);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (manager->priv->slowkeys_alert),
"%s", message);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
GTK_STOCK_HELP,
GTK_RESPONSE_HELP);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
enabled ? _("_Turn Off") : _("_Turn On"),
GTK_RESPONSE_REJECT);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->slowkeys_alert),
enabled ? _("_Leave On") : _("_Leave Off"),
GTK_RESPONSE_ACCEPT);
gtk_window_set_title (GTK_WINDOW (manager->priv->slowkeys_alert), "");
gtk_window_set_icon_name (GTK_WINDOW (manager->priv->slowkeys_alert),
"preferences-desktop-accessibility");
gtk_dialog_set_default_response (GTK_DIALOG (manager->priv->slowkeys_alert),
GTK_RESPONSE_ACCEPT);
g_signal_connect (manager->priv->slowkeys_alert,
"response",
G_CALLBACK (ax_slowkeys_response),
manager);
gtk_widget_show (manager->priv->slowkeys_alert);
g_object_add_weak_pointer (G_OBJECT (manager->priv->slowkeys_alert),
(gpointer*) &manager->priv->slowkeys_alert);
}
static void
ax_slowkeys_warning_post (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
manager->priv->slowkeys_shortcut_val = enabled;
/* alway try to show something */
if (! ax_slowkeys_warning_post_bubble (manager, enabled)) {
ax_slowkeys_warning_post_dialog (manager, enabled);
}
}
static gboolean
ax_stickykeys_warning_post_bubble (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
#if 1
gboolean res;
const char *title;
const char *message;
GError *error;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");
message = enabled ?
_("You just pressed the Shift key 5 times in a row. This is the shortcut "
"for the Sticky Keys feature, which affects the way your keyboard works.") :
_("You just pressed two keys at once, or pressed the Shift key 5 times in a row. "
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
return FALSE;
}
if (manager->priv->slowkeys_alert != NULL) {
gtk_widget_destroy (manager->priv->slowkeys_alert);
}
if (manager->priv->notification != NULL) {
notify_notification_close (manager->priv->notification, NULL);
}
csd_a11y_keyboard_manager_ensure_status_icon (manager);
manager->priv->notification = notify_notification_new (title,
message,
"preferences-desktop-accessibility-symbolic");
notify_notification_set_app_name (manager->priv->notification, _("Universal Access"));
notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
notify_notification_set_hint (manager->priv->notification, "transient", g_variant_new_boolean (TRUE));
notify_notification_add_action (manager->priv->notification,
"reject",
enabled ? _("Turn Off") : _("Turn On"),
(NotifyActionCallback) on_sticky_keys_action,
manager,
NULL);
notify_notification_add_action (manager->priv->notification,
"accept",
enabled ? _("Leave On") : _("Leave Off"),
(NotifyActionCallback) on_sticky_keys_action,
manager,
NULL);
g_signal_connect (manager->priv->notification,
"closed",
G_CALLBACK (on_notification_closed),
manager);
error = NULL;
res = notify_notification_show (manager->priv->notification, &error);
if (! res) {
g_warning ("CsdA11yKeyboardManager: unable to show notification: %s", error->message);
g_error_free (error);
notify_notification_close (manager->priv->notification, NULL);
}
return res;
#endif /* 1 */
}
static void
ax_stickykeys_warning_post_dialog (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
const char *title;
const char *message;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");
message = enabled ?
_("You just pressed the Shift key 5 times in a row. This is the shortcut "
"for the Sticky Keys feature, which affects the way your keyboard works.") :
_("You just pressed two keys at once, or pressed the Shift key 5 times in a row. "
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
if (manager->priv->stickykeys_alert != NULL) {
gtk_widget_show (manager->priv->stickykeys_alert);
return;
}
manager->priv->stickykeys_alert = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
"%s", title);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (manager->priv->stickykeys_alert),
"%s", message);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
GTK_STOCK_HELP,
GTK_RESPONSE_HELP);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
enabled ? _("_Turn Off") : _("_Turn On"),
GTK_RESPONSE_REJECT);
gtk_dialog_add_button (GTK_DIALOG (manager->priv->stickykeys_alert),
enabled ? _("_Leave On") : _("_Leave Off"),
GTK_RESPONSE_ACCEPT);
gtk_window_set_title (GTK_WINDOW (manager->priv->stickykeys_alert), "");
gtk_window_set_icon_name (GTK_WINDOW (manager->priv->stickykeys_alert),
"preferences-desktop-accessibility");
gtk_dialog_set_default_response (GTK_DIALOG (manager->priv->stickykeys_alert),
GTK_RESPONSE_ACCEPT);
g_signal_connect (manager->priv->stickykeys_alert,
"response",
G_CALLBACK (ax_stickykeys_response),
manager);
gtk_widget_show (manager->priv->stickykeys_alert);
g_object_add_weak_pointer (G_OBJECT (manager->priv->stickykeys_alert),
(gpointer*) &manager->priv->stickykeys_alert);
}
static void
ax_stickykeys_warning_post (CsdA11yKeyboardManager *manager,
gboolean enabled)
{
manager->priv->stickykeys_shortcut_val = enabled;
/* alway try to show something */
if (! ax_stickykeys_warning_post_bubble (manager, enabled)) {
ax_stickykeys_warning_post_dialog (manager, enabled);
}
}
static void
set_gsettings_from_server (CsdA11yKeyboardManager *manager)
{
XkbDescRec *desc;
gboolean changed = FALSE;
gboolean slowkeys_changed;
gboolean stickykeys_changed;
GSettings *settings;
desc = get_xkb_desc_rec (manager);
if (! desc) {
return;
}
/* Create a new one, so that only those settings
* are delayed */
settings = g_settings_new (KEYBOARD_A11Y_SCHEMA);
g_settings_delay (settings);
/*
fprintf (stderr, "changed to : 0x%x\n", desc->ctrls->enabled_ctrls);
fprintf (stderr, "changed to : 0x%x (2)\n", desc->ctrls->ax_options);
*/
changed |= set_bool (settings,
"enable",
desc->ctrls->enabled_ctrls & XkbAccessXKeysMask);
changed |= set_bool (settings,
"feature-state-change-beep",
desc->ctrls->ax_options & (XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask));
changed |= set_bool (settings,
"timeout-enable",
desc->ctrls->enabled_ctrls & XkbAccessXTimeoutMask);
changed |= set_int (settings,
"disable-timeout",
desc->ctrls->ax_timeout);
changed |= set_bool (settings,
"bouncekeys-enable",
desc->ctrls->enabled_ctrls & XkbBounceKeysMask);
changed |= set_int (settings,
"bouncekeys-delay",
desc->ctrls->debounce_delay);
changed |= set_bool (settings,
"bouncekeys-beep-reject",
desc->ctrls->ax_options & XkbAX_BKRejectFBMask);
changed |= set_bool (settings,
"mousekeys-enable",
desc->ctrls->enabled_ctrls & XkbMouseKeysMask);
changed |= set_int (settings,
"mousekeys-max-speed",
desc->ctrls->mk_max_speed * (1000 / desc->ctrls->mk_interval));
/* NOTE : mk_time_to_max is measured in events not time */
changed |= set_int (settings,
"mousekeys-accel-time",
desc->ctrls->mk_time_to_max * desc->ctrls->mk_interval);
changed |= set_int (settings,
"mousekeys-init-delay",
desc->ctrls->mk_delay);
slowkeys_changed = set_bool (settings,
"slowkeys-enable",
desc->ctrls->enabled_ctrls & XkbSlowKeysMask);
changed |= set_bool (settings,
"slowkeys-beep-press",
desc->ctrls->ax_options & XkbAX_SKPressFBMask);
changed |= set_bool (settings,
"slowkeys-beep-accept",
desc->ctrls->ax_options & XkbAX_SKAcceptFBMask);
changed |= set_bool (settings,
"slowkeys-beep-reject",
desc->ctrls->ax_options & XkbAX_SKRejectFBMask);
changed |= set_int (settings,
"slowkeys-delay",
desc->ctrls->slow_keys_delay);
stickykeys_changed = set_bool (settings,
"stickykeys-enable",
desc->ctrls->enabled_ctrls & XkbStickyKeysMask);
changed |= set_bool (settings,
"stickykeys-two-key-off",
desc->ctrls->ax_options & XkbAX_TwoKeysMask);
changed |= set_bool (settings,
"stickykeys-modifier-beep",
desc->ctrls->ax_options & XkbAX_StickyKeysFBMask);
if (!changed && stickykeys_changed ^ slowkeys_changed) {
/*
* sticky or slowkeys has changed, singly, without our intervention.
* 99% chance this is due to a keyboard shortcut being used.
* we need to detect via this hack until we get
* XkbAXN_AXKWarning notifications working (probable XKB bug),
* at which time we can directly intercept such shortcuts instead.
* See cb_xkb_event_filter () below.
*/
/* sanity check: are keyboard shortcuts available? */
if (desc->ctrls->enabled_ctrls & XkbAccessXKeysMask) {
if (slowkeys_changed) {
ax_slowkeys_warning_post (manager,
desc->ctrls->enabled_ctrls & XkbSlowKeysMask);
} else {
ax_stickykeys_warning_post (manager,
desc->ctrls->enabled_ctrls & XkbStickyKeysMask);
}
}
}
XkbFreeKeyboard (desc, XkbAllComponentsMask, True);
g_settings_apply (settings);
g_object_unref (settings);
}
static GdkFilterReturn
cb_xkb_event_filter (GdkXEvent *xevent,
GdkEvent *ignored1,
CsdA11yKeyboardManager *manager)
{
XEvent *xev = (XEvent *) xevent;
XkbEvent *xkbEv = (XkbEvent *) xevent;
/* 'event_type' is set to zero on notifying us of updates in
* response to client requests (including our own) and non-zero
* to notify us of key/mouse events causing changes (like
* pressing shift 5 times to enable sticky keys).
*
* We only want to update GSettings when it's in response to an
* explicit user input event, so require a non-zero event_type.
*/
if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) &&
xkbEv->any.xkb_type == XkbControlsNotify &&
xkbEv->ctrls.event_type != 0) {
g_debug ("XKB state changed");
set_gsettings_from_server (manager);
} else if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) &&
xkbEv->any.xkb_type == XkbAccessXNotify) {
if (xkbEv->accessx.detail == XkbAXN_AXKWarning) {
g_debug ("About to turn on an AccessX feature from the keyboard!");
/*
* TODO: when XkbAXN_AXKWarnings start working, we need to
* invoke ax_keys_warning_dialog_run here instead of in
* set_gsettings_from_server().
*/
}
}
return GDK_FILTER_CONTINUE;
}
static void
keyboard_callback (GSettings *settings,
const char *key,
CsdA11yKeyboardManager *manager)
{
set_server_from_gsettings (manager);
maybe_show_status_icon (manager);
}
static gboolean
start_a11y_keyboard_idle_cb (CsdA11yKeyboardManager *manager)
{
guint event_mask;
g_debug ("Starting a11y_keyboard manager");
cinnamon_settings_profile_start (NULL);
if (!xkb_enabled (manager))
goto out;
manager->priv->settings = g_settings_new (KEYBOARD_A11Y_SCHEMA);
g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
G_CALLBACK (keyboard_callback), manager);
set_devicepresence_handler (manager);
event_mask = XkbControlsNotifyMask;
event_mask |= XkbAccessXNotifyMask; /* make default when AXN_AXKWarning works */
/* be sure to init before starting to monitor the server */
set_server_from_gsettings (manager);
XkbSelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
XkbUseCoreKbd,
event_mask,
event_mask);
gdk_window_add_filter (NULL,
(GdkFilterFunc) cb_xkb_event_filter,
manager);
maybe_show_status_icon (manager);
out:
cinnamon_settings_profile_end (NULL);
manager->priv->start_idle_id = 0;
return FALSE;
}
gboolean
csd_a11y_keyboard_manager_start (CsdA11yKeyboardManager *manager,
GError **error)
{
cinnamon_settings_profile_start (NULL);
manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_a11y_keyboard_idle_cb, manager);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
csd_a11y_keyboard_manager_stop (CsdA11yKeyboardManager *manager)
{
CsdA11yKeyboardManagerPrivate *p = manager->priv;
g_debug ("Stopping a11y_keyboard manager");
if (p->start_idle_id != 0) {
g_source_remove (p->start_idle_id);
p->start_idle_id = 0;
}
if (p->device_manager != NULL) {
g_signal_handler_disconnect (p->device_manager, p->device_added_id);
p->device_manager = NULL;
}
if (p->status_icon) {
gtk_status_icon_set_visible (p->status_icon, FALSE);
p->status_icon = NULL;
}
if (p->settings != NULL) {
g_signal_handlers_disconnect_by_func (p->settings, keyboard_callback, manager);
g_object_unref (p->settings);
p->settings = NULL;
}
gdk_window_remove_filter (NULL,
(GdkFilterFunc) cb_xkb_event_filter,
manager);
if (p->slowkeys_alert != NULL) {
gtk_widget_destroy (p->slowkeys_alert);
p->slowkeys_alert = NULL;
}
if (p->stickykeys_alert != NULL) {
gtk_widget_destroy (p->stickykeys_alert);
p->stickykeys_alert = NULL;
}
p->slowkeys_shortcut_val = FALSE;
p->stickykeys_shortcut_val = FALSE;
}
static GObject *
csd_a11y_keyboard_manager_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
CsdA11yKeyboardManager *a11y_keyboard_manager;
a11y_keyboard_manager = CSD_A11Y_KEYBOARD_MANAGER (G_OBJECT_CLASS (csd_a11y_keyboard_manager_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (a11y_keyboard_manager);
}
static void
csd_a11y_keyboard_manager_class_init (CsdA11yKeyboardManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = csd_a11y_keyboard_manager_constructor;
object_class->finalize = csd_a11y_keyboard_manager_finalize;
g_type_class_add_private (klass, sizeof (CsdA11yKeyboardManagerPrivate));
}
static void
on_preferences_dialog_response (GtkDialog *dialog,
int response,
CsdA11yKeyboardManager *manager)
{
g_signal_handlers_disconnect_by_func (dialog,
on_preferences_dialog_response,
manager);
gtk_widget_destroy (GTK_WIDGET (dialog));
manager->priv->preferences_dialog = NULL;
}
static void
on_status_icon_activate (GtkStatusIcon *status_icon,
CsdA11yKeyboardManager *manager)
{
if (manager->priv->preferences_dialog == NULL) {
manager->priv->preferences_dialog = csd_a11y_preferences_dialog_new ();
g_signal_connect (manager->priv->preferences_dialog,
"response",
G_CALLBACK (on_preferences_dialog_response),
manager);
gtk_window_present (GTK_WINDOW (manager->priv->preferences_dialog));
} else {
g_signal_handlers_disconnect_by_func (manager->priv->preferences_dialog,
on_preferences_dialog_response,
manager);
gtk_widget_destroy (GTK_WIDGET (manager->priv->preferences_dialog));
manager->priv->preferences_dialog = NULL;
}
}
static void
on_status_icon_popup_menu (GtkStatusIcon *status_icon,
guint button,
guint activate_time,
CsdA11yKeyboardManager *manager)
{
on_status_icon_activate (status_icon, manager);
}
static void
csd_a11y_keyboard_manager_ensure_status_icon (CsdA11yKeyboardManager *manager)
{
cinnamon_settings_profile_start (NULL);
if (!manager->priv->status_icon) {
manager->priv->status_icon = gtk_status_icon_new_from_icon_name ("preferences-desktop-accessibility");
gtk_status_icon_set_name (manager->priv->status_icon, "a11y-keyboard");
g_signal_connect (manager->priv->status_icon,
"activate",
G_CALLBACK (on_status_icon_activate),
manager);
g_signal_connect (manager->priv->status_icon,
"popup-menu",
G_CALLBACK (on_status_icon_popup_menu),
manager);
}
cinnamon_settings_profile_end (NULL);
}
static void
csd_a11y_keyboard_manager_init (CsdA11yKeyboardManager *manager)
{
manager->priv = CSD_A11Y_KEYBOARD_MANAGER_GET_PRIVATE (manager);
}
static void
csd_a11y_keyboard_manager_finalize (GObject *object)
{
CsdA11yKeyboardManager *a11y_keyboard_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_A11Y_KEYBOARD_MANAGER (object));
a11y_keyboard_manager = CSD_A11Y_KEYBOARD_MANAGER (object);
g_return_if_fail (a11y_keyboard_manager->priv != NULL);
if (a11y_keyboard_manager->priv->start_idle_id != 0) {
g_source_remove (a11y_keyboard_manager->priv->start_idle_id);
a11y_keyboard_manager->priv->start_idle_id = 0;
}
G_OBJECT_CLASS (csd_a11y_keyboard_manager_parent_class)->finalize (object);
}
CsdA11yKeyboardManager *
csd_a11y_keyboard_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (CSD_TYPE_A11Y_KEYBOARD_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return CSD_A11Y_KEYBOARD_MANAGER (manager_object);
}
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/csd-a11y-preferences-dialog.h 0000664 0001750 0001750 00000004416 14144454032 026632 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_A11Y_PREFERENCES_DIALOG_H
#define __CSD_A11Y_PREFERENCES_DIALOG_H
#include
#include
G_BEGIN_DECLS
#define CSD_TYPE_A11Y_PREFERENCES_DIALOG (csd_a11y_preferences_dialog_get_type ())
#define CSD_A11Y_PREFERENCES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_A11Y_PREFERENCES_DIALOG, CsdA11yPreferencesDialog))
#define CSD_A11Y_PREFERENCES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_A11Y_PREFERENCES_DIALOG, CsdA11yPreferencesDialogClass))
#define CSD_IS_A11Y_PREFERENCES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_A11Y_PREFERENCES_DIALOG))
#define CSD_IS_A11Y_PREFERENCES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_A11Y_PREFERENCES_DIALOG))
#define CSD_A11Y_PREFERENCES_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_A11Y_PREFERENCES_DIALOG, CsdA11yPreferencesDialogClass))
typedef struct CsdA11yPreferencesDialogPrivate CsdA11yPreferencesDialogPrivate;
typedef struct
{
GtkDialog parent;
CsdA11yPreferencesDialogPrivate *priv;
} CsdA11yPreferencesDialog;
typedef struct
{
GtkDialogClass parent_class;
} CsdA11yPreferencesDialogClass;
GType csd_a11y_preferences_dialog_get_type (void);
GtkWidget * csd_a11y_preferences_dialog_new (void);
G_END_DECLS
#endif /* __CSD_A11Y_PREFERENCES_DIALOG_H */
././@LongLink 0000644 0000000 0000000 00000000147 00000000000 011605 L ustar root root cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/cinnamon-settings-daemon-a11y-keyboard.desktop.in cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/cinnamon-settings-daemon-a11y-keyboard.desktop.0000664 0001750 0001750 00000000352 14144454032 032317 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - a11y-keyboard
Exec=csd-a11y-keyboard
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/a11y-keyboard/csd-a11y-preferences-dialog.c 0000664 0001750 0001750 00000042154 14144454032 026626 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "csd-a11y-preferences-dialog.h"
#define SM_DBUS_NAME "org.gnome.SessionManager"
#define SM_DBUS_PATH "/org/gnome/SessionManager"
#define SM_DBUS_INTERFACE "org.gnome.SessionManager"
#define CSD_A11Y_PREFERENCES_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_A11Y_PREFERENCES_DIALOG, CsdA11yPreferencesDialogPrivate))
#define GTKBUILDER_UI_FILE "csd-a11y-preferences-dialog.ui"
#define INTERFACE_SCHEMA "org.cinnamon.desktop.interface"
#define KEY_TEXT_SCALING_FACTOR "text-scaling-factor"
#define KEYBOARD_A11Y_SCHEMA "org.cinnamon.desktop.a11y.keyboard"
#define KEY_STICKY_KEYS_ENABLED "stickykeys-enable"
#define KEY_BOUNCE_KEYS_ENABLED "bouncekeys-enable"
#define KEY_SLOW_KEYS_ENABLED "slowkeys-enable"
#define KEY_AT_SCHEMA "org.cinnamon.desktop.a11y.applications"
#define KEY_AT_SCREEN_KEYBOARD_ENABLED "screen-keyboard-enabled"
#define KEY_AT_SCREEN_MAGNIFIER_ENABLED "screen-magnifier-enabled"
#define KEY_AT_SCREEN_READER_ENABLED "screen-reader-enabled"
#define DPI_FACTOR_LARGE 1.25
#define DPI_FACTOR_LARGER 1.5
#define DPI_FACTOR_LARGEST 2.0
#define KEY_GTK_THEME "gtk-theme"
#define KEY_ICON_THEME "icon-theme"
#define KEY_METACITY_THEME "theme"
#define HIGH_CONTRAST_THEME "HighContrast"
struct CsdA11yPreferencesDialogPrivate
{
GtkWidget *large_print_checkbutton;
GtkWidget *high_contrast_checkbutton;
GSettings *a11y_settings;
GSettings *interface_settings;
GSettings *apps_settings;
};
enum {
PROP_0,
};
static void csd_a11y_preferences_dialog_finalize (GObject *object);
G_DEFINE_TYPE (CsdA11yPreferencesDialog, csd_a11y_preferences_dialog, GTK_TYPE_DIALOG)
static GObject *
csd_a11y_preferences_dialog_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
CsdA11yPreferencesDialog *a11y_preferences_dialog;
a11y_preferences_dialog = CSD_A11Y_PREFERENCES_DIALOG (G_OBJECT_CLASS (csd_a11y_preferences_dialog_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (a11y_preferences_dialog);
}
static void
csd_a11y_preferences_dialog_class_init (CsdA11yPreferencesDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = csd_a11y_preferences_dialog_constructor;
object_class->finalize = csd_a11y_preferences_dialog_finalize;
g_type_class_add_private (klass, sizeof (CsdA11yPreferencesDialogPrivate));
}
static void
on_response (CsdA11yPreferencesDialog *dialog,
gint response_id)
{
switch (response_id) {
default:
break;
}
}
static gboolean
config_get_large_print (CsdA11yPreferencesDialog *dialog,
gboolean *is_writable)
{
gboolean ret;
gdouble factor;
factor = g_settings_get_double (dialog->priv->interface_settings, KEY_TEXT_SCALING_FACTOR);
ret = (factor > 1.0);
*is_writable = g_settings_is_writable (dialog->priv->interface_settings, KEY_TEXT_SCALING_FACTOR);
return ret;
}
static void
config_set_large_print (CsdA11yPreferencesDialog *dialog,
gboolean enabled)
{
if (enabled)
g_settings_set_double (dialog->priv->interface_settings, KEY_TEXT_SCALING_FACTOR, DPI_FACTOR_LARGER);
else
g_settings_reset (dialog->priv->interface_settings, KEY_TEXT_SCALING_FACTOR);
}
static gboolean
config_get_high_contrast (CsdA11yPreferencesDialog *dialog)
{
gboolean ret;
char *gtk_theme;
ret = FALSE;
gtk_theme = g_settings_get_string (dialog->priv->interface_settings, KEY_GTK_THEME);
if (gtk_theme != NULL && g_str_equal (gtk_theme, HIGH_CONTRAST_THEME)) {
ret = TRUE;
}
g_free (gtk_theme);
return ret;
}
static void
config_set_high_contrast (gboolean enabled)
{
GSettings *settings;
GSettings *wm_settings;
settings = g_settings_new ("org.cinnamon.desktop.interface");
wm_settings = g_settings_new ("org.cinnamon.desktop.wm.preferences");
if (enabled) {
g_settings_set_string (settings, KEY_GTK_THEME, HIGH_CONTRAST_THEME);
g_settings_set_string (settings, KEY_ICON_THEME, HIGH_CONTRAST_THEME);
/* there isn't a high contrast metacity theme afaik */
} else {
g_settings_reset (settings, KEY_GTK_THEME);
g_settings_reset (settings, KEY_ICON_THEME);
g_settings_reset (wm_settings, KEY_METACITY_THEME);
}
g_object_unref (settings);
g_object_unref (wm_settings);
}
static gboolean
config_have_at_gsettings_condition (const char *condition)
{
GDBusProxy *sm_proxy;
GDBusConnection *connection;
GError *error;
GVariant *res;
gboolean is_handled;
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_warning ("Unable to connect to session bus: %s", error->message);
g_error_free (error);
return FALSE;
}
sm_proxy = g_dbus_proxy_new_sync (connection,
0, NULL,
SM_DBUS_NAME,
SM_DBUS_PATH,
SM_DBUS_INTERFACE,
NULL,
&error);
if (sm_proxy == NULL) {
g_warning ("Unable to get proxy for %s: %s", SM_DBUS_NAME, error->message);
g_error_free (error);
return FALSE;
}
is_handled = FALSE;
res = g_dbus_proxy_call_sync (sm_proxy,
"IsAutostartConditionHandled",
g_variant_new ("(s)", condition),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (! res) {
g_warning ("Unable to call IsAutostartConditionHandled (%s): %s",
condition,
error->message);
}
if (g_variant_is_of_type (res, G_VARIANT_TYPE_BOOLEAN)) {
is_handled = g_variant_get_boolean (res);
}
g_object_unref (sm_proxy);
g_variant_unref (res);
return is_handled;
}
static void
on_high_contrast_checkbutton_toggled (GtkToggleButton *button,
CsdA11yPreferencesDialog *dialog)
{
config_set_high_contrast (gtk_toggle_button_get_active (button));
}
static void
on_large_print_checkbutton_toggled (GtkToggleButton *button,
CsdA11yPreferencesDialog *dialog)
{
config_set_large_print (dialog, gtk_toggle_button_get_active (button));
}
static void
ui_set_high_contrast (CsdA11yPreferencesDialog *dialog,
gboolean enabled)
{
gboolean active;
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->high_contrast_checkbutton));
if (active != enabled) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->high_contrast_checkbutton), enabled);
}
}
static void
ui_set_large_print (CsdA11yPreferencesDialog *dialog,
gboolean enabled)
{
gboolean active;
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->large_print_checkbutton));
if (active != enabled) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->large_print_checkbutton), enabled);
}
}
static void
setup_dialog (CsdA11yPreferencesDialog *dialog,
GtkBuilder *builder)
{
GtkWidget *widget;
gboolean enabled;
gboolean is_writable;
GSettings *settings;
dialog->priv->a11y_settings = g_settings_new (KEYBOARD_A11Y_SCHEMA);
settings = dialog->priv->a11y_settings;
dialog->priv->interface_settings = g_settings_new (INTERFACE_SCHEMA);
dialog->priv->apps_settings = g_settings_new (KEY_AT_SCHEMA);
/* Sticky keys */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "sticky_keys_checkbutton"));
g_settings_bind (settings, KEY_STICKY_KEYS_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (settings, KEY_STICKY_KEYS_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
/* Bounce keys */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "bounce_keys_checkbutton"));
g_settings_bind (settings, KEY_BOUNCE_KEYS_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (settings, KEY_BOUNCE_KEYS_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
/* Slow keys */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "slow_keys_checkbutton"));
g_settings_bind (settings, KEY_SLOW_KEYS_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (settings, KEY_SLOW_KEYS_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
/* High contrast */
widget = GTK_WIDGET (gtk_builder_get_object (builder,
"high_contrast_checkbutton"));
g_settings_bind_writable (dialog->priv->interface_settings, KEY_GTK_THEME,
G_OBJECT (widget), "sensitive", TRUE);
dialog->priv->high_contrast_checkbutton = widget;
g_signal_connect (widget,
"toggled",
G_CALLBACK (on_high_contrast_checkbutton_toggled),
dialog);
enabled = config_get_high_contrast (dialog);
ui_set_high_contrast (dialog, enabled);
/* On-screen keyboard */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "at_screen_keyboard_checkbutton"));
g_settings_bind (dialog->priv->apps_settings, KEY_AT_SCREEN_KEYBOARD_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (dialog->priv->apps_settings, KEY_AT_SCREEN_KEYBOARD_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
gtk_widget_set_no_show_all (widget, TRUE);
if (config_have_at_gsettings_condition ("GSettings " KEYBOARD_A11Y_SCHEMA " " KEY_AT_SCREEN_KEYBOARD_ENABLED)) {
gtk_widget_show_all (widget);
} else {
gtk_widget_hide (widget);
}
/* Screen reader */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "at_screen_reader_checkbutton"));
g_settings_bind (dialog->priv->apps_settings, KEY_AT_SCREEN_READER_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (dialog->priv->apps_settings, KEY_AT_SCREEN_READER_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
gtk_widget_set_no_show_all (widget, TRUE);
if (config_have_at_gsettings_condition ("GSettings " KEYBOARD_A11Y_SCHEMA " " KEY_AT_SCREEN_READER_ENABLED)) {
gtk_widget_show_all (widget);
} else {
gtk_widget_hide (widget);
}
/* Screen magnifier */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "at_screen_magnifier_checkbutton"));
g_settings_bind (dialog->priv->apps_settings, KEY_AT_SCREEN_MAGNIFIER_ENABLED,
G_OBJECT (widget), "active", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_writable (dialog->priv->apps_settings, KEY_AT_SCREEN_MAGNIFIER_ENABLED,
G_OBJECT (widget), "sensitive", TRUE);
gtk_widget_set_no_show_all (widget, TRUE);
if (config_have_at_gsettings_condition ("GSettings " KEYBOARD_A11Y_SCHEMA " " KEY_AT_SCREEN_MAGNIFIER_ENABLED)) {
gtk_widget_show_all (widget);
} else {
gtk_widget_hide (widget);
}
/* Large print */
widget = GTK_WIDGET (gtk_builder_get_object (builder,
"large_print_checkbutton"));
dialog->priv->large_print_checkbutton = widget;
g_signal_connect (widget,
"toggled",
G_CALLBACK (on_large_print_checkbutton_toggled),
dialog);
enabled = config_get_large_print (dialog, &is_writable);
ui_set_large_print (dialog, enabled);
if (! is_writable) {
gtk_widget_set_sensitive (widget, FALSE);
}
}
static void
csd_a11y_preferences_dialog_init (CsdA11yPreferencesDialog *dialog)
{
static const gchar *ui_file_path = GTKBUILDERDIR "/" GTKBUILDER_UI_FILE;
gchar *objects[] = {"main_box", NULL};
GError *error = NULL;
GtkBuilder *builder;
dialog->priv = CSD_A11Y_PREFERENCES_DIALOG_GET_PRIVATE (dialog);
builder = gtk_builder_new ();
gtk_builder_set_translation_domain (builder, PACKAGE);
if (gtk_builder_add_objects_from_file (builder, ui_file_path, objects,
&error) == 0) {
g_warning ("Could not load A11Y-UI: %s", error->message);
g_error_free (error);
} else {
GtkWidget *widget;
widget = GTK_WIDGET (gtk_builder_get_object (builder,
"main_box"));
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
widget);
gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
setup_dialog (dialog, builder);
}
g_object_unref (builder);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
gtk_window_set_title (GTK_WINDOW (dialog), _("Universal Access Preferences"));
gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-desktop-accessibility");
g_object_set (dialog,
"resizable", FALSE,
NULL);
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
NULL);
g_signal_connect (dialog,
"response",
G_CALLBACK (on_response),
dialog);
gtk_widget_show_all (GTK_WIDGET (dialog));
}
static void
csd_a11y_preferences_dialog_finalize (GObject *object)
{
CsdA11yPreferencesDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_A11Y_PREFERENCES_DIALOG (object));
dialog = CSD_A11Y_PREFERENCES_DIALOG (object);
g_return_if_fail (dialog->priv != NULL);
g_object_unref (dialog->priv->a11y_settings);
g_object_unref (dialog->priv->interface_settings);
g_object_unref (dialog->priv->apps_settings);
G_OBJECT_CLASS (csd_a11y_preferences_dialog_parent_class)->finalize (object);
}
GtkWidget *
csd_a11y_preferences_dialog_new (void)
{
GObject *object;
object = g_object_new (CSD_TYPE_A11Y_PREFERENCES_DIALOG,
NULL);
return GTK_WIDGET (object);
}
cinnamon-settings-daemon-5.2.0/plugins/meson.build 0000664 0001750 0001750 00000001366 14144454032 021175 0 ustar fabio fabio desktop_conf = configuration_data()
desktop_conf.set('libexecdir', join_paths(prefix, libexecdir))
ln_script = join_paths(meson.source_root(), 'install-scripts', 'meson_mk_symlink.py')
# subdir('dummy')
subdir('common')
subdir('a11y-keyboard')
subdir('a11y-settings')
subdir('automount')
subdir('background')
subdir('clipboard')
subdir('cursor')
subdir('datetime')
subdir('housekeeping')
subdir('keyboard')
subdir('media-keys')
subdir('mouse')
subdir('orientation')
subdir('power')
subdir('screensaver-proxy')
subdir('sound')
subdir('xrandr')
subdir('xsettings')
if colord.found()
subdir('color')
endif
if cups.found()
subdir('print-notifications')
endif
if nss.found()
subdir('smartcard')
endif
if wacom.found()
subdir('wacom')
endif
cinnamon-settings-daemon-5.2.0/plugins/datetime/ 0000775 0001750 0001750 00000000000 14144454032 020621 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-fedora.h 0000664 0001750 0001750 00000002572 14144454032 026543 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include
#include
gboolean _get_using_ntp_fedora (DBusGMethodInvocation *context);
gboolean _set_using_ntp_fedora (DBusGMethodInvocation *context,
gboolean using_ntp);
gboolean _update_etc_sysconfig_clock_fedora
(DBusGMethodInvocation *context,
const char *key,
const char *value);
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism.h 0000664 0001750 0001750 00000013213 14144454032 025277 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
*
* 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 - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef CSD_DATETIME_MECHANISM_H
#define CSD_DATETIME_MECHANISM_H
#include
#include
G_BEGIN_DECLS
#define CSD_DATETIME_TYPE_MECHANISM (csd_datetime_mechanism_get_type ())
#define CSD_DATETIME_MECHANISM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_DATETIME_TYPE_MECHANISM, CsdDatetimeMechanism))
#define CSD_DATETIME_MECHANISM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_DATETIME_TYPE_MECHANISM, CsdDatetimeMechanismClass))
#define CSD_DATETIME_IS_MECHANISM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_DATETIME_TYPE_MECHANISM))
#define CSD_DATETIME_IS_MECHANISM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_DATETIME_TYPE_MECHANISM))
#define CSD_DATETIME_MECHANISM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_DATETIME_TYPE_MECHANISM, CsdDatetimeMechanismClass))
typedef struct CsdDatetimeMechanismPrivate CsdDatetimeMechanismPrivate;
typedef struct
{
GObject parent;
CsdDatetimeMechanismPrivate *priv;
} CsdDatetimeMechanism;
typedef struct
{
GObjectClass parent_class;
} CsdDatetimeMechanismClass;
typedef enum
{
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
CSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
CSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE,
CSD_DATETIME_MECHANISM_NUM_ERRORS
} CsdDatetimeMechanismError;
#define CSD_DATETIME_MECHANISM_ERROR csd_datetime_mechanism_error_quark ()
GType csd_datetime_mechanism_error_get_type (void);
#define CSD_DATETIME_MECHANISM_TYPE_ERROR (csd_datetime_mechanism_error_get_type ())
GQuark csd_datetime_mechanism_error_quark (void);
GType csd_datetime_mechanism_get_type (void);
CsdDatetimeMechanism *csd_datetime_mechanism_new (void);
/* exported methods */
gboolean csd_datetime_mechanism_get_timezone (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_set_timezone (CsdDatetimeMechanism *mechanism,
const char *zone_file,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_can_set_timezone (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_set_time (CsdDatetimeMechanism *mechanism,
gint64 seconds_since_epoch,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_set_date (CsdDatetimeMechanism *mechanism,
guint day,
guint month,
guint year,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_can_set_time (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_adjust_time (CsdDatetimeMechanism *mechanism,
gint64 seconds_to_add,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_get_hardware_clock_using_utc (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_set_hardware_clock_using_utc (CsdDatetimeMechanism *mechanism,
gboolean using_utc,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_get_using_ntp (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_set_using_ntp (CsdDatetimeMechanism *mechanism,
gboolean using_ntp,
DBusGMethodInvocation *context);
gboolean csd_datetime_mechanism_can_set_using_ntp (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context);
G_END_DECLS
#endif /* CSD_DATETIME_MECHANISM_H */
cinnamon-settings-daemon-5.2.0/plugins/datetime/meson.build 0000664 0001750 0001750 00000004326 14144454032 022770 0 ustar fabio fabio plugin_name = 'datetime'
datetime_dbus = custom_target(
'datetime-dbus',
input: 'csd-datetime-mechanism.xml',
output: 'csd-datetime-mechanism-glue.h',
command: [
dbus_binding_tool,
'--prefix=csd_datetime_mechanism',
'--mode=glib-server',
'--output=@OUTPUT@',
'@INPUT@',
],
)
datetime_common_sources = [
'system-timezone.c',
'system-timezone.h',
]
datetime_sources = [
'csd-datetime-mechanism.c',
'csd-datetime-mechanism.h',
'csd-datetime-mechanism-fedora.c',
'csd-datetime-mechanism-fedora.h',
'csd-datetime-mechanism-debian.c',
'csd-datetime-mechanism-debian.h',
'csd-datetime-mechanism-suse.c',
'csd-datetime-mechanism-suse.h',
'csd-datetime-mechanism-main.c',
datetime_dbus,
datetime_common_sources,
]
test_timezone_sources = [
'test-system-timezone.c',
datetime_common_sources,
]
datetime_deps = [
common_dep,
csd_dep,
dbus,
dbus_glib,
libnotify,
polkit,
xfixes,
]
if polkit.found()
executable(
'csd-datetime-mechanism',
datetime_sources,
include_directories: [include_dirs, common_inc],
dependencies: datetime_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-datetime-mechanism')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-datetime-mechanism')
endif
executable(
'test-datetime',
test_timezone_sources,
dependencies: datetime_deps,
install: false,
)
endif
datetime_conf = configuration_data()
datetime_conf.set('LIBEXECDIR', join_paths(prefix, libexecdir))
configure_file(
input: 'org.cinnamon.SettingsDaemon.DateTimeMechanism.service.in',
output: 'org.cinnamon.SettingsDaemon.DateTimeMechanism.service',
configuration: datetime_conf,
install_dir: dbusservicedir,
)
install_data(
'org.cinnamon.settingsdaemon.datetimemechanism.policy',
install_dir: polkitdir,
)
install_data(
'org.cinnamon.SettingsDaemon.DateTimeMechanism.conf',
install_dir: dbussystemdir,
)
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-fedora.c 0000664 0001750 0001750 00000017113 14144454032 026533 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "csd-datetime-mechanism-fedora.h"
#include "csd-datetime-mechanism.h"
/* Return the name of the installed NTP client, prefer chrony if both chrony
* and ntp are installed */
static const char *
get_ntp_client ()
{
if (g_file_test ("/etc/chrony.conf", G_FILE_TEST_EXISTS))
return "chronyd";
else if (g_file_test ("/etc/ntp.conf", G_FILE_TEST_EXISTS))
return "ntpd";
return NULL;
}
gboolean
_get_using_ntp_fedora (DBusGMethodInvocation *context)
{
int exit_status;
GError *error = NULL;
gboolean can_use_ntp;
gboolean is_using_ntp;
const char *ntp_client;
char *cmd;
ntp_client = get_ntp_client ();
if (ntp_client) {
can_use_ntp = TRUE;
cmd = g_strconcat ("/sbin/service ", ntp_client, " status", NULL);
if (!g_spawn_command_line_sync (cmd,
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /sbin/service: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
if (exit_status == 0)
is_using_ntp = TRUE;
else
is_using_ntp = FALSE;
}
else {
can_use_ntp = FALSE;
is_using_ntp = FALSE;
}
dbus_g_method_return (context, can_use_ntp, is_using_ntp);
return TRUE;
}
gboolean
_set_using_ntp_fedora (DBusGMethodInvocation *context,
gboolean using_ntp)
{
GError *error;
int exit_status;
const char *ntp_client;
char *cmd;
error = NULL;
ntp_client = get_ntp_client ();
/* We omit --level 2345 so that systemd doesn't try to use the
* SysV init scripts */
cmd = g_strconcat ("/sbin/chkconfig ", ntp_client, " ", using_ntp ? "on" : "off", NULL);
if (!g_spawn_command_line_sync (cmd,
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s", cmd, error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
cmd = g_strconcat ("/sbin/service ", ntp_client, " ", using_ntp ? "restart" : "stop", NULL);;
if (!g_spawn_command_line_sync (cmd,
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s", cmd, error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
dbus_g_method_return (context);
return TRUE;
}
gboolean
_update_etc_sysconfig_clock_fedora (DBusGMethodInvocation *context, const char *key, const char *value)
{
char **lines;
int n;
gboolean replaced;
char *data;
gsize len;
GError *error;
/* On Red Hat / Fedora, the /etc/sysconfig/clock file needs to be kept in sync */
if (!g_file_test ("/etc/sysconfig/clock", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error reading /etc/sysconfig/clock file: %s", "No such file");
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
error = NULL;
if (!g_file_get_contents ("/etc/sysconfig/clock", &data, &len, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error reading /etc/sysconfig/clock file: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
replaced = FALSE;
lines = g_strsplit (data, "\n", 0);
g_free (data);
for (n = 0; lines[n] != NULL; n++) {
if (g_str_has_prefix (lines[n], key)) {
g_free (lines[n]);
lines[n] = g_strdup_printf ("%s%s", key, value);
replaced = TRUE;
}
}
if (replaced) {
GString *str;
str = g_string_new (NULL);
for (n = 0; lines[n] != NULL; n++) {
g_string_append (str, lines[n]);
if (lines[n + 1] != NULL)
g_string_append_c (str, '\n');
}
data = g_string_free (str, FALSE);
len = strlen (data);
if (!g_file_set_contents ("/etc/sysconfig/clock", data, len, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error updating /etc/sysconfig/clock: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (data);
return FALSE;
}
g_free (data);
}
g_strfreev (lines);
return TRUE;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-debian.c 0000664 0001750 0001750 00000016317 14144454032 026522 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "csd-datetime-mechanism-debian.h"
#include "csd-datetime-mechanism.h"
static void
_get_using_ntpdate (gboolean *can_use, gboolean *is_using, GError ** error)
{
if (!g_file_test ("/usr/sbin/ntpdate-debian", G_FILE_TEST_EXISTS))
return;
*can_use = TRUE;
if (g_file_test ("/etc/network/if-up.d/ntpdate", G_FILE_TEST_EXISTS))
*is_using = TRUE;
}
static void
_get_using_ntpd (gboolean *can_use, gboolean *is_using, GError ** error)
{
int exit_status;
GError *tmp_error = NULL;
if (!g_file_test ("/usr/sbin/ntpd", G_FILE_TEST_EXISTS))
return;
*can_use = TRUE;
if (!g_spawn_command_line_sync ("/usr/sbin/service ntp status",
NULL, NULL, &exit_status, &tmp_error)) {
if (error != NULL && *error == NULL) {
*error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /usr/sbin/service: %s",
tmp_error->message);
}
g_error_free (tmp_error);
return;
}
if (exit_status == 0)
*is_using = TRUE;
}
gboolean
_get_using_ntp_debian (DBusGMethodInvocation *context)
{
gboolean can_use_ntp = FALSE;
gboolean is_using_ntp = FALSE;
GError *error = NULL;
/* In Debian, ntpdate is used whenever the network comes up. So if
either ntpdate or ntpd is installed and available, can_use is true.
If either is active, is_using is true. */
_get_using_ntpdate (&can_use_ntp, &is_using_ntp, &error);
_get_using_ntpd (&can_use_ntp, &is_using_ntp, &error);
if (error == NULL) {
dbus_g_method_return (context, can_use_ntp, is_using_ntp);
return TRUE;
} else {
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
}
static void
_set_using_ntpdate (gboolean using_ntp, GError **error)
{
const gchar *cmd = NULL;
GError *tmp_error = NULL;
/* Debian uses an if-up.d script to sync network time when an interface
comes up. This is a separate mechanism from ntpd altogether. */
#define NTPDATE_ENABLED "/etc/network/if-up.d/ntpdate"
#define NTPDATE_DISABLED "/etc/network/if-up.d/ntpdate.disabled"
if (using_ntp && g_file_test (NTPDATE_DISABLED, G_FILE_TEST_EXISTS))
cmd = "/bin/mv -f "NTPDATE_DISABLED" "NTPDATE_ENABLED;
else if (!using_ntp && g_file_test (NTPDATE_ENABLED, G_FILE_TEST_EXISTS))
cmd = "/bin/mv -f "NTPDATE_ENABLED" "NTPDATE_DISABLED;
else
return;
if (!g_spawn_command_line_sync (cmd, NULL, NULL, NULL, &tmp_error)) {
if (error != NULL && *error == NULL) {
*error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /bin/mv: %s",
tmp_error->message);
}
g_error_free (tmp_error);
return;
}
/* Kick start ntpdate to sync time immediately */
if (using_ntp &&
!g_spawn_command_line_sync ("/etc/network/if-up.d/ntpdate",
NULL, NULL, NULL, &tmp_error)) {
if (error != NULL && *error == NULL) {
*error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /etc/network/if-up.d/ntpdate: %s",
tmp_error->message);
}
g_error_free (tmp_error);
return;
}
}
static void
_set_using_ntpd (gboolean using_ntp, GError **error)
{
GError *tmp_error = NULL;
int exit_status;
char *cmd;
if (!g_file_test ("/usr/sbin/ntpd", G_FILE_TEST_EXISTS))
return;
cmd = g_strconcat ("/usr/sbin/update-rc.d ntp ", using_ntp ? "enable" : "disable", NULL);
if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &tmp_error)) {
if (error != NULL && *error == NULL) {
*error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s",
cmd, tmp_error->message);
}
g_error_free (tmp_error);
g_free (cmd);
return;
}
g_free (cmd);
cmd = g_strconcat ("/usr/sbin/service ntp ", using_ntp ? "restart" : "stop", NULL);;
if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &tmp_error)) {
if (error != NULL && *error == NULL) {
*error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s",
cmd, tmp_error->message);
}
g_error_free (tmp_error);
g_free (cmd);
return;
}
g_free (cmd);
}
gboolean
_set_using_ntp_debian (DBusGMethodInvocation *context,
gboolean using_ntp)
{
GError *error = NULL;
/* In Debian, ntpdate and ntpd may be installed separately, so don't
assume both are valid. */
_set_using_ntpdate (using_ntp, &error);
_set_using_ntpd (using_ntp, &error);
if (error == NULL) {
dbus_g_method_return (context);
return TRUE;
} else {
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
}
././@LongLink 0000644 0000000 0000000 00000000151 00000000000 011600 L ustar root root cinnamon-settings-daemon-5.2.0/plugins/datetime/org.cinnamon.SettingsDaemon.DateTimeMechanism.service.in cinnamon-settings-daemon-5.2.0/plugins/datetime/org.cinnamon.SettingsDaemon.DateTimeMechanism.servic0000664 0001750 0001750 00000000166 14144454032 032674 0 ustar fabio fabio [D-BUS Service]
Name=org.cinnamon.SettingsDaemon.DateTimeMechanism
Exec=@LIBEXECDIR@/csd-datetime-mechanism
User=root
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism.c 0000664 0001750 0001750 00000064454 14144454032 025307 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
*
* 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 - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "system-timezone.h"
#include "csd-datetime-mechanism.h"
#include "csd-datetime-mechanism-glue.h"
/* NTP helper functions for various distributions */
#include "csd-datetime-mechanism-fedora.h"
#include "csd-datetime-mechanism-debian.h"
#include "csd-datetime-mechanism-suse.h"
static gboolean
do_exit (gpointer user_data)
{
g_debug ("Exiting due to inactivity");
exit (1);
return FALSE;
}
static void
reset_killtimer (void)
{
static guint timer_id = 0;
if (timer_id > 0) {
g_source_remove (timer_id);
timer_id = 0;
}
g_debug ("Setting killtimer to 30 seconds...");
timer_id = g_timeout_add_seconds (30, do_exit, NULL);
}
struct CsdDatetimeMechanismPrivate
{
DBusGConnection *system_bus_connection;
DBusGProxy *system_bus_proxy;
PolkitAuthority *auth;
};
static void csd_datetime_mechanism_finalize (GObject *object);
G_DEFINE_TYPE (CsdDatetimeMechanism, csd_datetime_mechanism, G_TYPE_OBJECT)
#define CSD_DATETIME_MECHANISM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_DATETIME_TYPE_MECHANISM, CsdDatetimeMechanismPrivate))
GQuark
csd_datetime_mechanism_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("csd_datetime_mechanism_error");
}
return ret;
}
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
csd_datetime_mechanism_error_get_type (void)
{
static GType etype = 0;
if (etype == 0)
{
static const GEnumValue values[] =
{
ENUM_ENTRY (CSD_DATETIME_MECHANISM_ERROR_GENERAL, "GeneralError"),
ENUM_ENTRY (CSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
ENUM_ENTRY (CSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE, "InvalidTimezoneFile"),
{ 0, 0, 0 }
};
g_assert (CSD_DATETIME_MECHANISM_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
etype = g_enum_register_static ("CsdDatetimeMechanismError", values);
}
return etype;
}
static GObject *
csd_datetime_mechanism_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
CsdDatetimeMechanism *mechanism;
mechanism = CSD_DATETIME_MECHANISM (G_OBJECT_CLASS (csd_datetime_mechanism_parent_class)->constructor (
type,
n_construct_properties,
construct_properties));
return G_OBJECT (mechanism);
}
static void
csd_datetime_mechanism_class_init (CsdDatetimeMechanismClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = csd_datetime_mechanism_constructor;
object_class->finalize = csd_datetime_mechanism_finalize;
g_type_class_add_private (klass, sizeof (CsdDatetimeMechanismPrivate));
dbus_g_object_type_install_info (CSD_DATETIME_TYPE_MECHANISM, &dbus_glib_csd_datetime_mechanism_object_info);
dbus_g_error_domain_register (CSD_DATETIME_MECHANISM_ERROR, NULL, CSD_DATETIME_MECHANISM_TYPE_ERROR);
}
static void
csd_datetime_mechanism_init (CsdDatetimeMechanism *mechanism)
{
mechanism->priv = CSD_DATETIME_MECHANISM_GET_PRIVATE (mechanism);
}
static void
csd_datetime_mechanism_finalize (GObject *object)
{
CsdDatetimeMechanism *mechanism;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_DATETIME_IS_MECHANISM (object));
mechanism = CSD_DATETIME_MECHANISM (object);
g_return_if_fail (mechanism->priv != NULL);
g_object_unref (mechanism->priv->system_bus_proxy);
G_OBJECT_CLASS (csd_datetime_mechanism_parent_class)->finalize (object);
}
static gboolean
register_mechanism (CsdDatetimeMechanism *mechanism)
{
GError *error = NULL;
mechanism->priv->auth = polkit_authority_get_sync (NULL, &error);
if (mechanism->priv->auth == NULL) {
if (error != NULL) {
g_critical ("error getting system bus: %s", error->message);
g_error_free (error);
}
goto error;
}
mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (mechanism->priv->system_bus_connection == NULL) {
if (error != NULL) {
g_critical ("error getting system bus: %s", error->message);
g_error_free (error);
}
goto error;
}
dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
G_OBJECT (mechanism));
mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
reset_killtimer ();
return TRUE;
error:
return FALSE;
}
CsdDatetimeMechanism *
csd_datetime_mechanism_new (void)
{
GObject *object;
gboolean res;
object = g_object_new (CSD_DATETIME_TYPE_MECHANISM, NULL);
res = register_mechanism (CSD_DATETIME_MECHANISM (object));
if (! res) {
g_object_unref (object);
return NULL;
}
return CSD_DATETIME_MECHANISM (object);
}
static gboolean
_check_polkit_for_action (CsdDatetimeMechanism *mechanism, DBusGMethodInvocation *context)
{
const char *action = "org.cinnamon.settingsdaemon.datetimemechanism.configure";
const char *sender;
GError *error;
PolkitSubject *subject;
PolkitAuthorizationResult *result;
error = NULL;
/* Check that caller is privileged */
sender = dbus_g_method_get_sender (context);
subject = polkit_system_bus_name_new (sender);
result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
subject,
action,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
NULL, &error);
g_object_unref (subject);
if (error) {
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
if (!polkit_authorization_result_get_is_authorized (result)) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED,
"Not Authorized for action %s", action);
dbus_g_method_return_error (context, error);
g_error_free (error);
g_object_unref (result);
return FALSE;
}
g_object_unref (result);
return TRUE;
}
static gboolean
_sync_hwclock (DBusGMethodInvocation *context)
{
GError *error;
error = NULL;
if (g_file_test ("/sbin/hwclock",
G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
int exit_status;
if (!g_spawn_command_line_sync ("/sbin/hwclock --systohc", NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /sbin/hwclock: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
if (WEXITSTATUS (exit_status) != 0) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"/sbin/hwclock returned %d", exit_status);
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
}
return TRUE;
}
static gboolean
_set_time (CsdDatetimeMechanism *mechanism,
const struct timeval *tv,
DBusGMethodInvocation *context)
{
GError *error;
if (!_check_polkit_for_action (mechanism, context))
return FALSE;
if (settimeofday (tv, NULL) != 0) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error calling settimeofday({%ld,%ld}): %s",
(gint64) tv->tv_sec, (gint64) tv->tv_usec,
strerror (errno));
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
if (!_sync_hwclock (context))
return FALSE;
dbus_g_method_return (context);
return TRUE;
}
static gboolean
_set_date (CsdDatetimeMechanism *mechanism,
guint day,
guint month,
guint year,
DBusGMethodInvocation *context)
{
GDateTime *time;
char *date_str, *time_str;
char *date_cmd;
int exit_status;
GError *error;
if (!_check_polkit_for_action (mechanism, context))
return FALSE;
date_str = g_strdup_printf ("%02d/%02d/%d", month, day, year);
error = NULL;
time = g_date_time_new_now_local ();
time_str = g_date_time_format (time, "%R:%S");
g_date_time_unref (time);
date_cmd = g_strdup_printf ("/bin/date -s \"%s %s\" +\"%%D %%R:%%S\"", date_str, time_str);
g_free (date_str);
g_free (time_str);
if (!g_spawn_command_line_sync (date_cmd, NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /bin/date: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (date_cmd);
return FALSE;
}
g_free (date_cmd);
if (WEXITSTATUS (exit_status) != 0) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"/bin/date returned %d", exit_status);
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
if (!_sync_hwclock (context))
return FALSE;
return TRUE;
}
/* exported methods */
gboolean
csd_datetime_mechanism_set_time (CsdDatetimeMechanism *mechanism,
gint64 seconds_since_epoch,
DBusGMethodInvocation *context)
{
struct timeval tv;
reset_killtimer ();
g_debug ("SetTime(%" G_GINT64_FORMAT ") called", seconds_since_epoch);
tv.tv_sec = (time_t) seconds_since_epoch;
tv.tv_usec = 0;
return _set_time (mechanism, &tv, context);
}
gboolean
csd_datetime_mechanism_set_date (CsdDatetimeMechanism *mechanism,
guint day,
guint month,
guint year,
DBusGMethodInvocation *context)
{
reset_killtimer ();
g_debug ("SetDate(%d, %d, %d) called", day, month, year);
return _set_date (mechanism, day, month, year, context);
}
gboolean
csd_datetime_mechanism_adjust_time (CsdDatetimeMechanism *mechanism,
gint64 seconds_to_add,
DBusGMethodInvocation *context)
{
struct timeval tv;
reset_killtimer ();
g_debug ("AdjustTime(%" G_GINT64_FORMAT " ) called", seconds_to_add);
if (gettimeofday (&tv, NULL) != 0) {
GError *error;
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error calling gettimeofday(): %s", strerror (errno));
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
tv.tv_sec += (time_t) seconds_to_add;
return _set_time (mechanism, &tv, context);
}
static gboolean
csd_datetime_check_tz_name (const char *tz,
GError **error)
{
GFile *file;
char *tz_path, *actual_path;
gboolean retval;
retval = TRUE;
tz_path = g_build_filename (SYSTEM_ZONEINFODIR, tz, NULL);
/* Get the actual resolved path */
file = g_file_new_for_path (tz_path);
actual_path = g_file_get_path (file);
g_object_unref (file);
/* The tz name passed had relative paths in it */
if (g_strcmp0 (tz_path, actual_path) != 0) {
g_set_error (error, CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE,
"Timezone file '%s' was invalid.",
tz);
retval = FALSE;
}
g_free (tz_path);
g_free (actual_path);
return retval;
}
gboolean
csd_datetime_mechanism_set_timezone (CsdDatetimeMechanism *mechanism,
const char *tz,
DBusGMethodInvocation *context)
{
GError *error;
reset_killtimer ();
g_debug ("SetTimezone('%s') called", tz);
if (!_check_polkit_for_action (mechanism, context))
return FALSE;
error = NULL;
if (!csd_datetime_check_tz_name (tz, &error))
return FALSE;
if (!system_timezone_set (tz, &error)) {
GError *error2;
int code;
if (error->code == SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE)
code = CSD_DATETIME_MECHANISM_ERROR_INVALID_TIMEZONE_FILE;
else
code = CSD_DATETIME_MECHANISM_ERROR_GENERAL;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
code, "%s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
dbus_g_method_return (context);
return TRUE;
}
gboolean
csd_datetime_mechanism_get_timezone (CsdDatetimeMechanism *mechism,
DBusGMethodInvocation *context)
{
gchar *timezone;
reset_killtimer ();
timezone = system_timezone_find ();
dbus_g_method_return (context, timezone);
return TRUE;
}
gboolean
csd_datetime_mechanism_get_hardware_clock_using_utc (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context)
{
char **lines;
char *data;
gsize len;
GError *error;
gboolean is_utc;
error = NULL;
if (!g_file_get_contents ("/etc/adjtime", &data, &len, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error reading /etc/adjtime file: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
lines = g_strsplit (data, "\n", 0);
g_free (data);
if (g_strv_length (lines) < 3) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Cannot parse /etc/adjtime");
dbus_g_method_return_error (context, error);
g_error_free (error);
g_strfreev (lines);
return FALSE;
}
if (strcmp (lines[2], "UTC") == 0) {
is_utc = TRUE;
} else if (strcmp (lines[2], "LOCAL") == 0) {
is_utc = FALSE;
} else {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Expected UTC or LOCAL at line 3 of /etc/adjtime; found '%s'", lines[2]);
dbus_g_method_return_error (context, error);
g_error_free (error);
g_strfreev (lines);
return FALSE;
}
g_strfreev (lines);
dbus_g_method_return (context, is_utc);
return TRUE;
}
gboolean
csd_datetime_mechanism_set_hardware_clock_using_utc (CsdDatetimeMechanism *mechanism,
gboolean using_utc,
DBusGMethodInvocation *context)
{
GError *error;
error = NULL;
if (!_check_polkit_for_action (mechanism, context))
return FALSE;
if (g_file_test ("/sbin/hwclock",
G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE)) {
int exit_status;
char *cmd;
cmd = g_strdup_printf ("/sbin/hwclock %s --systohc", using_utc ? "--utc" : "--localtime");
if (!g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /sbin/hwclock: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
if (WEXITSTATUS (exit_status) != 0) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"/sbin/hwclock returned %d", exit_status);
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
if (g_file_test ("/etc/redhat-release", G_FILE_TEST_EXISTS)) { /* Fedora */
if (!_update_etc_sysconfig_clock_fedora (context, "UTC=", using_utc ? "true" : "false"))
return FALSE;
} else if (g_file_test ("/etc/SuSE-release", G_FILE_TEST_EXISTS)) { /* SUSE variant */
if (!_update_etc_sysconfig_clock_suse (context, "HWCLOCK=", using_utc ? "-u" : "--localtime"))
return FALSE;
}
}
dbus_g_method_return (context);
return TRUE;
}
gboolean
csd_datetime_mechanism_get_using_ntp (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context)
{
GError *error = NULL;
gboolean ret;
if (g_file_test ("/etc/redhat-release", G_FILE_TEST_EXISTS)) /* Fedora */
ret = _get_using_ntp_fedora (context);
else if (g_file_test ("/usr/sbin/update-rc.d", G_FILE_TEST_EXISTS)) /* Debian */
ret = _get_using_ntp_debian (context);
else if (g_file_test ("/etc/SuSE-release", G_FILE_TEST_EXISTS)) /* SUSE variant */
ret = _get_using_ntp_suse (context);
else {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error enabling NTP: OS variant not supported");
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
return ret;
}
gboolean
csd_datetime_mechanism_set_using_ntp (CsdDatetimeMechanism *mechanism,
gboolean using_ntp,
DBusGMethodInvocation *context)
{
GError *error;
gboolean ret;
error = NULL;
if (!_check_polkit_for_action (mechanism, context))
return FALSE;
if (g_file_test ("/etc/redhat-release", G_FILE_TEST_EXISTS)) /* Fedora */
ret = _set_using_ntp_fedora (context, using_ntp);
else if (g_file_test ("/usr/sbin/update-rc.d", G_FILE_TEST_EXISTS)) /* Debian */
ret = _set_using_ntp_debian (context, using_ntp);
else if (g_file_test ("/etc/SuSE-release", G_FILE_TEST_EXISTS)) /* SUSE variant */
ret = _set_using_ntp_suse (context, using_ntp);
else {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error enabling NTP: OS variant not supported");
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
return ret;
}
static void
check_can_do (CsdDatetimeMechanism *mechanism,
const char *action,
DBusGMethodInvocation *context)
{
const char *sender;
PolkitSubject *subject;
PolkitAuthorizationResult *result;
GError *error;
/* Check that caller is privileged */
sender = dbus_g_method_get_sender (context);
subject = polkit_system_bus_name_new (sender);
error = NULL;
result = polkit_authority_check_authorization_sync (mechanism->priv->auth,
subject,
action,
NULL,
0,
NULL,
&error);
g_object_unref (subject);
if (error) {
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
if (polkit_authorization_result_get_is_authorized (result)) {
dbus_g_method_return (context, 2);
}
else if (polkit_authorization_result_get_is_challenge (result)) {
dbus_g_method_return (context, 1);
}
else {
dbus_g_method_return (context, 0);
}
g_object_unref (result);
}
gboolean
csd_datetime_mechanism_can_set_time (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context)
{
check_can_do (mechanism,
"org.cinnamon.settingsdaemon.datetimemechanism.configure",
context);
return TRUE;
}
gboolean
csd_datetime_mechanism_can_set_timezone (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context)
{
check_can_do (mechanism,
"org.cinnamon.settingsdaemon.datetimemechanism.configure",
context);
return TRUE;
}
gboolean
csd_datetime_mechanism_can_set_using_ntp (CsdDatetimeMechanism *mechanism,
DBusGMethodInvocation *context)
{
check_can_do (mechanism,
"org.cinnamon.settingsdaemon.datetimemechanism.configure",
context);
return TRUE;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-suse.h 0000664 0001750 0001750 00000002647 14144454032 026265 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 Bastien Nocera
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include
#include
gboolean _get_using_ntp_suse (DBusGMethodInvocation *context);
gboolean _set_using_ntp_suse (DBusGMethodInvocation *context,
gboolean using_ntp);
gboolean _update_etc_sysconfig_clock_suse
(DBusGMethodInvocation *context,
const char *key,
const char *value);
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-suse.c 0000664 0001750 0001750 00000015747 14144454032 026265 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 Bastien Nocera
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "csd-datetime-mechanism-suse.h"
#include "csd-datetime-mechanism.h"
gboolean
_get_using_ntp_suse (DBusGMethodInvocation *context)
{
int exit_status;
GError *error = NULL;
gboolean can_use_ntp;
gboolean is_using_ntp;
if (g_file_test ("/etc/ntp.conf", G_FILE_TEST_EXISTS)) {
can_use_ntp = TRUE;
if (!g_spawn_command_line_sync ("/sbin/service ntp status",
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning /sbin/service: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
if (exit_status == 0)
is_using_ntp = TRUE;
else
is_using_ntp = FALSE;
}
else {
can_use_ntp = FALSE;
is_using_ntp = FALSE;
}
dbus_g_method_return (context, can_use_ntp, is_using_ntp);
return TRUE;
}
gboolean
_set_using_ntp_suse (DBusGMethodInvocation *context,
gboolean using_ntp)
{
GError *error;
int exit_status;
char *cmd;
error = NULL;
/* We omit --level 2345 so that systemd doesn't try to use the
* SysV init scripts */
cmd = g_strconcat ("/sbin/chkconfig ntp ", using_ntp ? "on" : "off", NULL);
if (!g_spawn_command_line_sync (cmd,
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s", cmd, error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
cmd = g_strconcat ("/sbin/service ntp ", using_ntp ? "restart" : "stop", NULL);;
if (!g_spawn_command_line_sync (cmd,
NULL, NULL, &exit_status, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error spawning '%s': %s", cmd, error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (cmd);
return FALSE;
}
g_free (cmd);
dbus_g_method_return (context);
return TRUE;
}
gboolean
_update_etc_sysconfig_clock_suse (DBusGMethodInvocation *context, const char *key, const char *value)
{
char **lines;
int n;
gboolean replaced;
char *data;
gsize len;
GError *error;
/* On SUSE variants, the /etc/sysconfig/clock file needs to be kept in sync */
if (!g_file_test ("/etc/sysconfig/clock", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
error = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error reading /etc/sysconfig/clock file: %s", "No such file");
dbus_g_method_return_error (context, error);
g_error_free (error);
return FALSE;
}
error = NULL;
if (!g_file_get_contents ("/etc/sysconfig/clock", &data, &len, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error reading /etc/sysconfig/clock file: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
return FALSE;
}
replaced = FALSE;
lines = g_strsplit (data, "\n", 0);
g_free (data);
for (n = 0; lines[n] != NULL; n++) {
if (g_str_has_prefix (lines[n], key)) {
g_free (lines[n]);
lines[n] = g_strdup_printf ("%s%s", key, value);
replaced = TRUE;
}
}
if (replaced) {
GString *str;
str = g_string_new (NULL);
for (n = 0; lines[n] != NULL; n++) {
g_string_append (str, lines[n]);
if (lines[n + 1] != NULL)
g_string_append_c (str, '\n');
}
data = g_string_free (str, FALSE);
len = strlen (data);
if (!g_file_set_contents ("/etc/sysconfig/clock", data, len, &error)) {
GError *error2;
error2 = g_error_new (CSD_DATETIME_MECHANISM_ERROR,
CSD_DATETIME_MECHANISM_ERROR_GENERAL,
"Error updating /etc/sysconfig/clock: %s", error->message);
g_error_free (error);
dbus_g_method_return_error (context, error2);
g_error_free (error2);
g_free (data);
return FALSE;
}
g_free (data);
}
g_strfreev (lines);
return TRUE;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-main.c 0000664 0001750 0001750 00000010743 14144454032 026221 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
*
* 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 - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "csd-datetime-mechanism.h"
static DBusGProxy *
get_bus_proxy (DBusGConnection *connection)
{
DBusGProxy *bus_proxy;
bus_proxy = dbus_g_proxy_new_for_name (connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
return bus_proxy;
}
#define BUS_NAME "org.cinnamon.SettingsDaemon.DateTimeMechanism"
static gboolean
acquire_name_on_proxy (DBusGProxy *bus_proxy)
{
GError *error;
guint result;
gboolean res;
gboolean ret;
ret = FALSE;
if (bus_proxy == NULL) {
goto out;
}
error = NULL;
res = dbus_g_proxy_call (bus_proxy,
"RequestName",
&error,
G_TYPE_STRING, BUS_NAME,
G_TYPE_UINT, 0,
G_TYPE_INVALID,
G_TYPE_UINT, &result,
G_TYPE_INVALID);
if (! res) {
if (error != NULL) {
g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
g_error_free (error);
} else {
g_warning ("Failed to acquire %s", BUS_NAME);
}
goto out;
}
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
if (error != NULL) {
g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
g_error_free (error);
} else {
g_warning ("Failed to acquire %s", BUS_NAME);
}
goto out;
}
ret = TRUE;
out:
return ret;
}
static DBusGConnection *
get_system_bus (void)
{
GError *error;
DBusGConnection *bus;
error = NULL;
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s", error->message);
g_error_free (error);
}
return bus;
}
int
main (int argc, char **argv)
{
GMainLoop *loop;
CsdDatetimeMechanism *mechanism;
DBusGProxy *bus_proxy;
DBusGConnection *connection;
int ret;
ret = 1;
dbus_g_thread_init ();
connection = get_system_bus ();
if (connection == NULL) {
goto out;
}
bus_proxy = get_bus_proxy (connection);
if (bus_proxy == NULL) {
g_warning ("Could not construct bus_proxy object; bailing out");
goto out;
}
if (!acquire_name_on_proxy (bus_proxy) ) {
g_warning ("Could not acquire name; bailing out");
goto out;
}
mechanism = csd_datetime_mechanism_new ();
if (mechanism == NULL) {
goto out;
}
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
g_object_unref (mechanism);
g_main_loop_unref (loop);
ret = 0;
out:
return ret;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/org.cinnamon.SettingsDaemon.DateTimeMechanism.conf 0000664 0001750 0001750 00000001171 14144454032 032323 0 ustar fabio fabio
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism.xml 0000664 0001750 0001750 00000012365 14144454032 025657 0 ustar fabio fabio
Whether the caller can set the timezone
The return value is not a boolean, but an integer with the following meaning:
0
the caller cannot set the timezone
1
the caller will be challenged before being able to set the timezone
2
the caller is authorized to set the timezone
Whether the caller can set the time
The return value is not a boolean, but an integer with the following meaning:
0
the caller cannot set the time
1
the caller will be challenged before being able to set the time
2
the caller is authorized to set the time
Whether the caller can set the "use NTP" setting
The return value is not a boolean, but an integer with the following meaning:
0
the caller cannot change the "use NTP" setting
1
the caller will be challenged before being able to change "use NTP" setting
2
the caller is authorized to change the "use NTP" setting
cinnamon-settings-daemon-5.2.0/plugins/datetime/test-system-timezone.c 0000664 0001750 0001750 00000004453 14144454032 025124 0 ustar fabio fabio /* Test for system timezone handling
*
* Copyright (C) 2008-2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/
#include
#include "system-timezone.h"
static void
timezone_print (void)
{
SystemTimezone *systz;
systz = system_timezone_new ();
g_print ("Current timezone: %s\n", system_timezone_get (systz));
g_object_unref (systz);
}
static int
timezone_set (const char *new_tz)
{
GError *error;
error = NULL;
if (!system_timezone_set (new_tz, &error)) {
g_printerr ("%s\n", error->message);
g_error_free (error);
return 1;
}
return 0;
}
int
main (int argc,
char **argv)
{
int retval;
gboolean get = FALSE;
char *tz_set = NULL;
GError *error;
GOptionContext *context;
GOptionEntry options[] = {
{ "get", 'g', 0, G_OPTION_ARG_NONE, &get, "Get the current timezone", NULL },
{ "set", 's', 0, G_OPTION_ARG_STRING, &tz_set, "Set the timezone to TIMEZONE", "TIMEZONE" },
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
retval = 0;
context = g_option_context_new ("");
g_option_context_add_main_entries (context, options, NULL);
error = NULL;
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_printerr ("%s\n", error->message);
g_error_free (error);
g_option_context_free (context);
return 1;
}
g_option_context_free (context);
if (get || (!tz_set))
timezone_print ();
else if (tz_set)
retval = timezone_set (tz_set);
else
g_assert_not_reached ();
return retval;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/csd-datetime-mechanism-debian.h 0000664 0001750 0001750 00000002217 14144454032 026521 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include
#include
gboolean _get_using_ntp_debian (DBusGMethodInvocation *context);
gboolean _set_using_ntp_debian (DBusGMethodInvocation *context,
gboolean using_ntp);
cinnamon-settings-daemon-5.2.0/plugins/datetime/system-timezone.c 0000664 0001750 0001750 00000071417 14144454032 024153 0 ustar fabio fabio /* System timezone handling
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* Some code is based on previous code in clock-location.c and on code from
* tz.c (shipped with version <= 2.22.0). Those files were under the same
* license, with those authors and copyrights:
*
* clock-location.c:
* ================
* No header, but most of the work was done (AFAIK) by
* Federico Mena Quintero
* Matthias Clasen
*
* tz.c:
* ====
* Copyright (C) 2000-2001 Ximian, Inc.
* Copyright (C) 2004 Sun Microsystems, Inc.
*
* Authors: Hans Petter Jansson
* additional functions by Erwann Chenede
* reworked by Vincent Untz
*
* Largely based on Michael Fulbright's work on Anaconda.
*/
/* FIXME: it'd be nice to filter out the timezones that we might get when
* parsing config files that are not in zone.tab. Note that it's also wrong
* in some cases: eg, in tzdata2008b, Asia/Calcutta got renamed to
* Asia/Kolkata and the old name is not in zone.tab. */
#include
#include
#include
#include
#include
#include "system-timezone.h"
/* Files that we look at */
#define ETC_TIMEZONE "/etc/timezone"
#define ETC_TIMEZONE_MAJ "/etc/TIMEZONE"
#define ETC_RC_CONF "/etc/rc.conf"
#define ETC_SYSCONFIG_CLOCK "/etc/sysconfig/clock"
#define ETC_CONF_D_CLOCK "/etc/conf.d/clock"
#define ETC_LOCALTIME "/etc/localtime"
/* The first 4 characters in a timezone file, from tzfile.h */
#define TZ_MAGIC "TZif"
static GObject *systz_singleton = NULL;
G_DEFINE_TYPE (SystemTimezone, system_timezone, G_TYPE_OBJECT)
typedef struct {
char *tz;
char *env_tz;
} SystemTimezonePrivate;
static GObject *system_timezone_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties);
static void system_timezone_finalize (GObject *obj);
#define PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezonePrivate))
SystemTimezone *
system_timezone_new (void)
{
return g_object_new (SYSTEM_TIMEZONE_TYPE, NULL);
}
const char *
system_timezone_get (SystemTimezone *systz)
{
SystemTimezonePrivate *priv;
g_return_val_if_fail (IS_SYSTEM_TIMEZONE (systz), NULL);
priv = PRIVATE (systz);
return priv->tz;
}
const char *
system_timezone_get_env (SystemTimezone *systz)
{
SystemTimezonePrivate *priv;
g_return_val_if_fail (IS_SYSTEM_TIMEZONE (systz), NULL);
priv = PRIVATE (systz);
return priv->env_tz;
}
static void
system_timezone_class_init (SystemTimezoneClass *class)
{
GObjectClass *g_obj_class = G_OBJECT_CLASS (class);
g_obj_class->constructor = system_timezone_constructor;
g_obj_class->finalize = system_timezone_finalize;
g_type_class_add_private (class, sizeof (SystemTimezonePrivate));
}
static void
system_timezone_init (SystemTimezone *systz)
{
SystemTimezonePrivate *priv = PRIVATE (systz);
priv->tz = NULL;
priv->env_tz = NULL;
}
static GObject *
system_timezone_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
SystemTimezonePrivate *priv;
/* This is a singleton, we don't need to have it per-applet */
if (systz_singleton)
return g_object_ref (systz_singleton);
obj = G_OBJECT_CLASS (system_timezone_parent_class)->constructor (
type,
n_construct_properties,
construct_properties);
priv = PRIVATE (obj);
priv->tz = system_timezone_find ();
priv->env_tz = g_strdup (g_getenv ("TZ"));
systz_singleton = obj;
return systz_singleton;
}
static void
system_timezone_finalize (GObject *obj)
{
SystemTimezonePrivate *priv = PRIVATE (obj);
if (priv->tz) {
g_free (priv->tz);
priv->tz = NULL;
}
if (priv->env_tz) {
g_free (priv->env_tz);
priv->env_tz = NULL;
}
G_OBJECT_CLASS (system_timezone_parent_class)->finalize (obj);
g_assert (obj == systz_singleton);
systz_singleton = NULL;
}
/*
* Code to deal with the system timezone on all distros.
* There's no dependency on the SystemTimezone GObject here.
*
* Here's what we know:
*
* + /etc/localtime contains the binary data of the timezone.
* It can be a symlink to the actual data file, a hard link to the data
* file, or just a copy. So we can determine the timezone with this
* (reading the symlink, comparing inodes, or comparing content).
*
* + However, most distributions also have the timezone setting
* configured somewhere else. This might be better to read it from there.
*
* Debian/Ubuntu/Gentoo (new): content of /etc/timezone
* Fedora/Mandriva: the ZONE key in /etc/sysconfig/clock
* openSUSE: the TIMEZONE key in /etc/sysconfig/clock
* Solaris/OpenSolaris: the TZ key in /etc/TIMEZONE
* Arch Linux: the TIMEZONE key in /etc/rc.conf
* Gentoo (old): the ZONE key in /etc/conf.d/clock
*
* FIXME: reading the system-tools-backends, it seems there's this too:
* Solaris: the TZ key in /etc/default/init
* /etc/TIMEZONE seems to be a link to /etc/default/init
*
* First, some functions to handle those system config files.
*
*/
/* This works for Debian and derivatives (including Ubuntu), and new Gentoo */
static char *
system_timezone_read_etc_timezone (void)
{
FILE *etc_timezone;
GString *reading;
int c;
etc_timezone = g_fopen (ETC_TIMEZONE, "r");
if (!etc_timezone)
return NULL;
reading = g_string_new ("");
c = fgetc (etc_timezone);
/* only get the first line, we'll validate the value later */
while (c != EOF && !g_ascii_isspace (c)) {
reading = g_string_append_c (reading, c);
c = fgetc (etc_timezone);
}
fclose (etc_timezone);
if (reading->str && reading->str[0] != '\0')
return g_string_free (reading, FALSE);
else
g_string_free (reading, TRUE);
return NULL;
}
static gboolean
system_timezone_write_etc_timezone (const char *tz,
GError **error)
{
char *content;
GError *our_error;
gboolean retval;
if (!g_file_test (ETC_TIMEZONE, G_FILE_TEST_IS_REGULAR))
return TRUE;
content = g_strdup_printf ("%s\n", tz);
our_error = NULL;
retval = g_file_set_contents (ETC_TIMEZONE, content, -1, &our_error);
g_free (content);
if (!retval) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_GENERAL,
ETC_TIMEZONE" cannot be overwritten: %s",
our_error->message);
g_error_free (our_error);
}
return retval;
}
/* Read a file that looks like a key-file (but there's no need for groups)
* and get the last value for a specific key */
static char *
system_timezone_read_key_file (const char *filename,
const char *key)
{
GIOChannel *channel;
char *key_eq;
char *line;
char *retval;
if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
return NULL;
channel = g_io_channel_new_file (filename, "r", NULL);
if (!channel)
return NULL;
key_eq = g_strdup_printf ("%s=", key);
retval = NULL;
while (g_io_channel_read_line (channel, &line, NULL,
NULL, NULL) == G_IO_STATUS_NORMAL) {
if (g_str_has_prefix (line, key_eq)) {
char *value;
int len;
value = line + strlen (key_eq);
g_strstrip (value);
len = strlen (value);
if (value[0] == '\"') {
if (value[len - 1] == '\"') {
if (retval)
g_free (retval);
retval = g_strndup (value + 1,
len - 2);
}
} else {
if (retval)
g_free (retval);
retval = g_strdup (line + strlen (key_eq));
}
g_strstrip (retval);
}
g_free (line);
}
g_free (key_eq);
g_io_channel_unref (channel);
return retval;
}
static gboolean
system_timezone_write_key_file (const char *filename,
const char *key,
const char *value,
GError **error)
{
GError *our_error;
char *content;
gsize len;
char *key_eq;
char **lines;
gboolean replaced;
gboolean retval;
int n;
if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
return TRUE;
our_error = NULL;
if (!g_file_get_contents (filename, &content, &len, &our_error)) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_GENERAL,
"%s cannot be read: %s",
filename, our_error->message);
g_error_free (our_error);
return FALSE;
}
lines = g_strsplit (content, "\n", 0);
g_free (content);
key_eq = g_strdup_printf ("%s=", key);
replaced = FALSE;
for (n = 0; lines[n] != NULL; n++) {
if (g_str_has_prefix (lines[n], key_eq)) {
char *old_value;
gboolean use_quotes;
old_value = lines[n] + strlen (key_eq);
g_strstrip (old_value);
use_quotes = old_value[0] == '\"';
g_free (lines[n]);
if (use_quotes)
lines[n] = g_strdup_printf ("%s\"%s\"",
key_eq, value);
else
lines[n] = g_strdup_printf ("%s%s",
key_eq, value);
replaced = TRUE;
}
}
g_free (key_eq);
if (!replaced) {
g_strfreev (lines);
return TRUE;
}
content = g_strjoinv ("\n", lines);
g_strfreev (lines);
retval = g_file_set_contents (filename, content, -1, &our_error);
g_free (content);
if (!retval) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_GENERAL,
"%s cannot be overwritten: %s",
filename, our_error->message);
g_error_free (our_error);
}
return retval;
}
/* This works for Solaris/OpenSolaris */
static char *
system_timezone_read_etc_TIMEZONE (void)
{
return system_timezone_read_key_file (ETC_TIMEZONE_MAJ,
"TZ");
}
static gboolean
system_timezone_write_etc_TIMEZONE (const char *tz,
GError **error)
{
return system_timezone_write_key_file (ETC_TIMEZONE_MAJ,
"TZ", tz, error);
}
/* This works for Fedora and Mandriva */
static char *
system_timezone_read_etc_sysconfig_clock (void)
{
return system_timezone_read_key_file (ETC_SYSCONFIG_CLOCK,
"ZONE");
}
static gboolean
system_timezone_write_etc_sysconfig_clock (const char *tz,
GError **error)
{
return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
"ZONE", tz, error);
}
/* This works for openSUSE */
static char *
system_timezone_read_etc_sysconfig_clock_alt (void)
{
return system_timezone_read_key_file (ETC_SYSCONFIG_CLOCK,
"TIMEZONE");
}
static gboolean
system_timezone_write_etc_sysconfig_clock_alt (const char *tz,
GError **error)
{
return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
"TIMEZONE", tz, error);
}
/* This works for old Gentoo */
static char *
system_timezone_read_etc_conf_d_clock (void)
{
return system_timezone_read_key_file (ETC_CONF_D_CLOCK,
"TIMEZONE");
}
static gboolean
system_timezone_write_etc_conf_d_clock (const char *tz,
GError **error)
{
return system_timezone_write_key_file (ETC_CONF_D_CLOCK,
"TIMEZONE", tz, error);
}
/* This works for Arch Linux */
static char *
system_timezone_read_etc_rc_conf (void)
{
return system_timezone_read_key_file (ETC_RC_CONF,
"TIMEZONE");
}
static gboolean
system_timezone_write_etc_rc_conf (const char *tz,
GError **error)
{
return system_timezone_write_key_file (ETC_RC_CONF,
"TIMEZONE", tz, error);
}
/*
*
* First, getting the timezone.
*
*/
static char *
system_timezone_strip_path_if_valid (const char *filename)
{
int skip;
if (!filename || !g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/"))
return NULL;
/* Timezone data files also live under posix/ and right/ for some
* reason.
* FIXME: make sure accepting those files is valid. I think "posix" is
* okay, not sure about "right" */
if (g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/posix/"))
skip = strlen (SYSTEM_ZONEINFODIR"/posix/");
else if (g_str_has_prefix (filename, SYSTEM_ZONEINFODIR"/right/"))
skip = strlen (SYSTEM_ZONEINFODIR"/right/");
else
skip = strlen (SYSTEM_ZONEINFODIR"/");
return g_strdup (filename + skip);
}
/* Read the soft symlink from /etc/localtime */
static char *
system_timezone_read_etc_localtime_softlink (void)
{
char *file;
char *tz;
if (!g_file_test (ETC_LOCALTIME, G_FILE_TEST_IS_SYMLINK))
return NULL;
file = g_file_read_link (ETC_LOCALTIME, NULL);
tz = system_timezone_strip_path_if_valid (file);
g_free (file);
return tz;
}
typedef gboolean (*CompareFiles) (struct stat *a_stat,
struct stat *b_stat,
const char *a_content,
gsize a_content_len,
const char *b_filename);
static char *
recursive_compare (struct stat *localtime_stat,
const char *localtime_content,
gsize localtime_content_len,
char *file,
CompareFiles compare_func)
{
struct stat file_stat;
if (g_stat (file, &file_stat) != 0)
return NULL;
if (S_ISREG (file_stat.st_mode)) {
if (compare_func (localtime_stat,
&file_stat,
localtime_content,
localtime_content_len,
file))
return system_timezone_strip_path_if_valid (file);
else
return NULL;
} else if (S_ISDIR (file_stat.st_mode)) {
GDir *dir = NULL;
char *ret = NULL;
const char *subfile = NULL;
char *subpath = NULL;
dir = g_dir_open (file, 0, NULL);
if (dir == NULL)
return NULL;
while ((subfile = g_dir_read_name (dir)) != NULL) {
subpath = g_build_filename (file, subfile, NULL);
ret = recursive_compare (localtime_stat,
localtime_content,
localtime_content_len,
subpath,
compare_func);
g_free (subpath);
if (ret != NULL)
break;
}
g_dir_close (dir);
return ret;
}
return NULL;
}
static gboolean
files_are_identical_inode (struct stat *a_stat,
struct stat *b_stat,
const char *a_content,
gsize a_content_len,
const char *b_filename)
{
return (a_stat->st_ino == b_stat->st_ino);
}
/* Determine if /etc/localtime is a hard link to some file, by looking at
* the inodes */
static char *
system_timezone_read_etc_localtime_hardlink (void)
{
struct stat stat_localtime;
if (g_stat (ETC_LOCALTIME, &stat_localtime) != 0)
return NULL;
if (!S_ISREG (stat_localtime.st_mode))
return NULL;
return recursive_compare (&stat_localtime,
NULL,
0,
SYSTEM_ZONEINFODIR,
files_are_identical_inode);
}
static gboolean
files_are_identical_content (struct stat *a_stat,
struct stat *b_stat,
const char *a_content,
gsize a_content_len,
const char *b_filename)
{
char *b_content = NULL;
gsize b_content_len = -1;
int cmp;
if (a_stat->st_size != b_stat->st_size)
return FALSE;
if (!g_file_get_contents (b_filename,
&b_content, &b_content_len, NULL))
return FALSE;
if (a_content_len != b_content_len) {
g_free (b_content);
return FALSE;
}
cmp = memcmp (a_content, b_content, a_content_len);
g_free (b_content);
return (cmp == 0);
}
/* Determine if /etc/localtime is a copy of a timezone file */
static char *
system_timezone_read_etc_localtime_content (void)
{
struct stat stat_localtime;
char *localtime_content = NULL;
gsize localtime_content_len = -1;
char *retval;
if (g_stat (ETC_LOCALTIME, &stat_localtime) != 0)
return NULL;
if (!S_ISREG (stat_localtime.st_mode))
return NULL;
if (!g_file_get_contents (ETC_LOCALTIME,
&localtime_content,
&localtime_content_len,
NULL))
return NULL;
retval = recursive_compare (&stat_localtime,
localtime_content,
localtime_content_len,
SYSTEM_ZONEINFODIR,
files_are_identical_content);
g_free (localtime_content);
return retval;
}
typedef char * (*GetSystemTimezone) (void);
/* The order of the functions here define the priority of the methods used
* to find the timezone. First method has higher priority. */
static GetSystemTimezone get_system_timezone_methods[] = {
/* cheap and "more correct" than data from a config file */
system_timezone_read_etc_localtime_softlink,
/* reading various config files */
system_timezone_read_etc_timezone,
system_timezone_read_etc_sysconfig_clock,
system_timezone_read_etc_sysconfig_clock_alt,
system_timezone_read_etc_TIMEZONE,
system_timezone_read_etc_rc_conf,
/* reading deprecated config files */
system_timezone_read_etc_conf_d_clock,
/* reading /etc/timezone directly. Expensive since we have to stat
* many files */
system_timezone_read_etc_localtime_hardlink,
system_timezone_read_etc_localtime_content,
NULL
};
static gboolean
system_timezone_is_valid (const char *tz)
{
const char *c;
if (!tz)
return FALSE;
for (c = tz; *c != '\0'; c++) {
if (!(g_ascii_isalnum (*c) ||
*c == '/' || *c == '-' || *c == '_'))
return FALSE;
}
return TRUE;
}
char *
system_timezone_find (void)
{
char *tz;
int i;
for (i = 0; get_system_timezone_methods[i] != NULL; i++) {
tz = get_system_timezone_methods[i] ();
if (system_timezone_is_valid (tz))
return tz;
g_free (tz);
}
return g_strdup ("UTC");
}
/*
*
* Now, setting the timezone.
*
*/
static gboolean
system_timezone_is_zone_file_valid (const char *zone_file,
GError **error)
{
GError *our_error;
GIOChannel *channel;
char buffer[strlen (TZ_MAGIC)];
gsize read;
/* First, check the zone_file is properly rooted */
if (!g_str_has_prefix (zone_file, SYSTEM_ZONEINFODIR"/")) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
"Timezone file needs to be under "SYSTEM_ZONEINFODIR);
return FALSE;
}
/* Second, check it's a regular file that exists */
if (!g_file_test (zone_file, G_FILE_TEST_IS_REGULAR)) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
"No such timezone file %s", zone_file);
return FALSE;
}
/* Third, check that it's a tzfile (see tzfile(5)). The file has a 4
* bytes header which is TZ_MAGIC.
*
* TODO: is there glibc API for this? */
our_error = NULL;
channel = g_io_channel_new_file (zone_file, "r", &our_error);
if (!our_error)
g_io_channel_read_chars (channel,
buffer, strlen (TZ_MAGIC),
&read, &our_error);
if (channel)
g_io_channel_unref (channel);
if (our_error) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
"Timezone file %s cannot be read: %s",
zone_file, our_error->message);
g_error_free (our_error);
return FALSE;
}
if (read != strlen (TZ_MAGIC) || strncmp (buffer, TZ_MAGIC, strlen (TZ_MAGIC)) != 0) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
"%s is not a timezone file",
zone_file);
return FALSE;
}
return TRUE;
}
static gboolean
system_timezone_set_etc_timezone (const char *zone_file,
GError **error)
{
GError *our_error;
char *content;
gsize len;
if (!system_timezone_is_zone_file_valid (zone_file, error))
return FALSE;
/* If /etc/localtime is a symlink, write a symlink */
if (g_file_test (ETC_LOCALTIME, G_FILE_TEST_IS_SYMLINK)) {
if (g_unlink (ETC_LOCALTIME) == 0 &&
symlink (zone_file, ETC_LOCALTIME) == 0)
return TRUE;
/* If we couldn't symlink the file, we'll just fallback on
* copying it */
}
/* Else copy the file to /etc/localtime. We explicitly avoid doing
* hard links since they break with different partitions */
our_error = NULL;
if (!g_file_get_contents (zone_file, &content, &len, &our_error)) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_GENERAL,
"Timezone file %s cannot be read: %s",
zone_file, our_error->message);
g_error_free (our_error);
return FALSE;
}
if (!g_file_set_contents (ETC_LOCALTIME, content, len, &our_error)) {
g_set_error (error, SYSTEM_TIMEZONE_ERROR,
SYSTEM_TIMEZONE_ERROR_GENERAL,
ETC_LOCALTIME" cannot be overwritten: %s",
our_error->message);
g_error_free (our_error);
g_free (content);
return FALSE;
}
g_free (content);
return TRUE;
}
typedef gboolean (*SetSystemTimezone) (const char *tz,
GError **error);
/* The order here does not matter too much: we'll try to change all files
* that already have a timezone configured. It matters in case of error,
* since the process will be stopped and the last methods won't be called.
* So we use the same order as in get_system_timezone_methods */
static SetSystemTimezone set_system_timezone_methods[] = {
/* writing various config files if they exist and have the
* setting already present */
system_timezone_write_etc_timezone,
system_timezone_write_etc_sysconfig_clock,
system_timezone_write_etc_sysconfig_clock_alt,
system_timezone_write_etc_TIMEZONE,
system_timezone_write_etc_rc_conf,
/* writing deprecated config files if they exist and have the
* setting already present */
system_timezone_write_etc_conf_d_clock,
NULL
};
static gboolean
system_timezone_update_config (const char *tz,
GError **error)
{
int i;
for (i = 0; set_system_timezone_methods[i] != NULL; i++) {
if (!set_system_timezone_methods[i] (tz, error))
return FALSE;
/* FIXME: maybe continue to change all config files if
* possible? */
}
return TRUE;
}
gboolean
system_timezone_set (const char *tz,
GError **error)
{
char *zone_file;
gboolean retval;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
zone_file = g_build_filename (SYSTEM_ZONEINFODIR, tz, NULL);
/* FIXME: is it right to return FALSE even when /etc/localtime was
* changed but not the config files? */
retval = system_timezone_set_etc_timezone (zone_file, error) &&
system_timezone_update_config (tz, error);
g_free (zone_file);
return retval;
}
GQuark
system_timezone_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("system-timezone-error");
}
return ret;
}
cinnamon-settings-daemon-5.2.0/plugins/datetime/org.cinnamon.settingsdaemon.datetimemechanism.policy0000664 0001750 0001750 00000001376 14144454032 033144 0 ustar fabio fabio
Cinnamon
https://projects.linuxmint.com/cinnamon/
gnome-panel-clock
Change system time and date settings
To change time or date settings, you need to authenticate.
no
no
auth_admin_keep
cinnamon-settings-daemon-5.2.0/plugins/datetime/system-timezone.h 0000664 0001750 0001750 00000005045 14144454032 024152 0 ustar fabio fabio /* System timezone handling
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/
#ifndef __SYSTEM_TIMEZONE_H__
#define __SYSTEM_TIMEZONE_H__
#include
#include
G_BEGIN_DECLS
#ifdef HAVE_SOLARIS
#define SYSTEM_ZONEINFODIR "/usr/share/lib/zoneinfo/tab"
#else
#define SYSTEM_ZONEINFODIR "/usr/share/zoneinfo"
#endif
#define SYSTEM_TIMEZONE_TYPE (system_timezone_get_type ())
#define SYSTEM_TIMEZONE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezone))
#define SYSTEM_TIMEZONE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), SYSTEM_TIMEZONE_TYPE, SystemTimezoneClass))
#define IS_SYSTEM_TIMEZONE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYSTEM_TIMEZONE_TYPE))
#define IS_SYSTEM_TIMEZONE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), SYSTEM_TIMEZONE_TYPE))
#define SYSTEM_TIMEZONE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYSTEM_TIMEZONE_TYPE, SystemTimezoneClass))
typedef struct
{
GObject g_object;
} SystemTimezone;
typedef struct
{
GObjectClass g_object_class;
} SystemTimezoneClass;
GType system_timezone_get_type (void);
SystemTimezone *system_timezone_new (void);
const char *system_timezone_get (SystemTimezone *systz);
const char *system_timezone_get_env (SystemTimezone *systz);
/* Functions to set the timezone. They won't be used by the applet, but
* by a program with more privileges */
#define SYSTEM_TIMEZONE_ERROR system_timezone_error_quark ()
GQuark system_timezone_error_quark (void);
typedef enum
{
SYSTEM_TIMEZONE_ERROR_GENERAL,
SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
SYSTEM_TIMEZONE_NUM_ERRORS
} SystemTimezoneError;
char *system_timezone_find (void);
gboolean system_timezone_set (const char *tz,
GError **error);
G_END_DECLS
#endif /* __SYSTEM_TIMEZONE_H__ */
cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/ 0000775 0001750 0001750 00000000000 14144454032 022524 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/meson.build 0000664 0001750 0001750 00000001610 14144454032 024664 0 ustar fabio fabio plugin_name = 'screensaver-proxy'
screensaver_proxy_sources = [
'csd-screensaver-proxy-manager.c',
'main.c',
]
screensaver_proxy_deps = [
common_dep,
csd_dep,
libnotify,
]
executable(
'csd-screensaver-proxy',
screensaver_proxy_sources,
include_directories: [include_dirs, common_inc],
dependencies: screensaver_proxy_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-screensaver-proxy')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-screensaver-proxy')
endif
configure_file(
input: 'cinnamon-settings-daemon-screensaver-proxy.desktop.in',
output: 'cinnamon-settings-daemon-screensaver-proxy.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/csd-screensaver-proxy-manager.h 0000664 0001750 0001750 00000005172 14144454032 030560 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_SCREENSAVER_PROXY_MANAGER_H
#define __CSD_SCREENSAVER_PROXY_MANAGER_H
#include
G_BEGIN_DECLS
#define CSD_TYPE_SCREENSAVER_PROXY_MANAGER (csd_screensaver_proxy_manager_get_type ())
#define CSD_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_SCREENSAVER_PROXY_MANAGER, CsdScreensaverProxyManager))
#define CSD_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_SCREENSAVER_PROXY_MANAGER, CsdScreensaverProxyManagerClass))
#define CSD_IS_SCREENSAVER_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_SCREENSAVER_PROXY_MANAGER))
#define CSD_IS_SCREENSAVER_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_SCREENSAVER_PROXY_MANAGER))
#define CSD_SCREENSAVER_PROXY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_SCREENSAVER_PROXY_MANAGER, CsdScreensaverProxyManagerClass))
typedef struct CsdScreensaverProxyManagerPrivate CsdScreensaverProxyManagerPrivate;
typedef struct
{
GObject parent;
CsdScreensaverProxyManagerPrivate *priv;
} CsdScreensaverProxyManager;
typedef struct
{
GObjectClass parent_class;
} CsdScreensaverProxyManagerClass;
GType csd_screensaver_proxy_manager_get_type (void);
CsdScreensaverProxyManager *csd_screensaver_proxy_manager_new (void);
gboolean csd_screensaver_proxy_manager_start (CsdScreensaverProxyManager *manager,
GError **error);
void csd_screensaver_proxy_manager_stop (CsdScreensaverProxyManager *manager);
G_END_DECLS
#endif /* __CSD_SCREENSAVER_PROXY_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/main.c 0000664 0001750 0001750 00000001100 14144454032 023604 0 ustar fabio fabio #define NEW csd_screensaver_proxy_manager_new
#define START csd_screensaver_proxy_manager_start
#define STOP csd_screensaver_proxy_manager_stop
#define MANAGER CsdScreensaverProxyManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING TRUE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE TRUE
#include "csd-screensaver-proxy-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/csd-screensaver-proxy-manager.c 0000664 0001750 0001750 00000047042 14144454032 030555 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cinnamon-settings-session.h"
#include "cinnamon-settings-profile.h"
#include "csd-screensaver-proxy-manager.h"
#define CSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_SCREENSAVER_PROXY_MANAGER, CsdScreensaverProxyManagerPrivate))
/* 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 CSD_SCREENSAVER_PROXY_DBUS_SERVICE "org.freedesktop.ScreenSaver"
#define CSD_SCREENSAVER_PROXY_DBUS_PATH "/org/freedesktop/ScreenSaver"
#define CSD_SCREENSAVER_PROXY_DBUS_PATH2 "/ScreenSaver"
#define CSD_SCREENSAVER_PROXY_DBUS_INTERFACE "org.freedesktop.ScreenSaver"
#define GSM_INHIBITOR_FLAG_IDLE 1 << 3
struct CsdScreensaverProxyManagerPrivate
{
GDBusProxy *session;
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 csd_screensaver_proxy_manager_finalize (GObject *object);
G_DEFINE_TYPE (CsdScreensaverProxyManager, csd_screensaver_proxy_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
#define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager"
#define GNOME_SESSION_DBUS_OBJECT "/org/gnome/SessionManager"
#define GNOME_SESSION_DBUS_INTERFACE "org.gnome.SessionManager"
static GDBusProxy *
cinnamon_settings_session_get_session_proxy (void)
{
static GDBusProxy *session_proxy;
GError *error = NULL;
if (session_proxy != NULL) {
g_object_ref (session_proxy);
} else {
session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
GNOME_SESSION_DBUS_NAME,
GNOME_SESSION_DBUS_OBJECT,
GNOME_SESSION_DBUS_INTERFACE,
NULL,
&error);
if (error) {
g_warning ("Failed to connect to the session manager: %s", error->message);
g_error_free (error);
} else {
g_object_add_weak_pointer (G_OBJECT (session_proxy), (gpointer*)&session_proxy);
}
}
return session_proxy;
}
static void
name_vanished_cb (GDBusConnection *connection,
const gchar *name,
CsdScreensaverProxyManager *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 (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, sender);
}
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)
{
CsdScreensaverProxyManager *manager = CSD_SCREENSAVER_PROXY_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 ScreenSaver Proxy",
interface_name, method_name);
if (g_strcmp0 (method_name, "Inhibit") == 0) {
GVariant *ret;
const char *app_id;
const char *reason;
guint cookie;
g_variant_get (parameters,
"(ss)", &app_id, &reason);
ret = g_dbus_proxy_call_sync (manager->priv->session,
"Inhibit",
g_variant_new ("(susu)",
app_id, 0, reason, GSM_INHIBITOR_FLAG_IDLE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
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));
}
g_dbus_method_invocation_return_value (invocation, ret);
} else if (g_strcmp0 (method_name, "UnInhibit") == 0) {
guint cookie;
g_variant_get (parameters, "(u)", &cookie);
g_dbus_proxy_call_sync (manager->priv->session,
"Uninhibit",
parameters,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "Throttle") == 0) {
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "UnThrottle") == 0) {
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "Lock") == 0) {
goto unimplemented;
} else if (g_strcmp0 (method_name, "SimulateUserActivity") == 0) {
goto unimplemented;
} else if (g_strcmp0 (method_name, "GetActive") == 0) {
goto unimplemented;
} else if (g_strcmp0 (method_name, "GetActiveTime") == 0) {
goto unimplemented;
} else if (g_strcmp0 (method_name, "GetSessionIdleTime") == 0) {
goto unimplemented;
} else if (g_strcmp0 (method_name, "SetActive") == 0) {
goto unimplemented;
}
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,
CsdScreensaverProxyManager *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,
CSD_SCREENSAVER_PROXY_DBUS_PATH,
infos[0],
&interface_vtable,
manager,
NULL,
NULL);
infos = manager->priv->introspection_data2->interfaces;
g_dbus_connection_register_object (connection,
CSD_SCREENSAVER_PROXY_DBUS_PATH2,
infos[0],
&interface_vtable,
manager,
NULL,
NULL);
manager->priv->name_id = g_bus_own_name_on_connection (manager->priv->connection,
CSD_SCREENSAVER_PROXY_DBUS_SERVICE,
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
NULL,
NULL,
NULL);
}
static void
register_manager_dbus (CsdScreensaverProxyManager *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
csd_screensaver_proxy_manager_start (CsdScreensaverProxyManager *manager,
GError **error)
{
g_debug ("Starting screensaver-proxy manager");
cinnamon_settings_profile_start (NULL);
manager->priv->session =
cinnamon_settings_session_get_session_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);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
csd_screensaver_proxy_manager_stop (CsdScreensaverProxyManager *manager)
{
g_debug ("Stopping screensaver_proxy manager");
if (manager->priv->session != NULL) {
g_object_unref (manager->priv->session);
manager->priv->session = NULL;
}
if (manager->priv->watch_ht != NULL) {
g_hash_table_destroy (manager->priv->watch_ht);
manager->priv->watch_ht = NULL;
}
if (manager->priv->cookie_ht != NULL) {
g_hash_table_destroy (manager->priv->cookie_ht);
manager->priv->cookie_ht = NULL;
}
}
static void
csd_screensaver_proxy_manager_class_init (CsdScreensaverProxyManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = csd_screensaver_proxy_manager_finalize;
g_type_class_add_private (klass, sizeof (CsdScreensaverProxyManagerPrivate));
}
static void
csd_screensaver_proxy_manager_init (CsdScreensaverProxyManager *manager)
{
manager->priv = CSD_SCREENSAVER_PROXY_MANAGER_GET_PRIVATE (manager);
}
static void
csd_screensaver_proxy_manager_finalize (GObject *object)
{
CsdScreensaverProxyManager *manager;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_SCREENSAVER_PROXY_MANAGER (object));
manager = CSD_SCREENSAVER_PROXY_MANAGER (object);
g_return_if_fail (manager->priv != NULL);
if (manager->priv->name_id != 0) {
g_bus_unown_name (manager->priv->name_id);
manager->priv->name_id = 0;
}
if (manager->priv->connection != NULL) {
g_object_unref (manager->priv->connection);
manager->priv->connection = NULL;
}
if (manager->priv->bus_cancellable != NULL) {
g_object_unref (manager->priv->bus_cancellable);
manager->priv->bus_cancellable = NULL;
}
if (manager->priv->introspection_data != NULL) {
g_dbus_node_info_unref (manager->priv->introspection_data);
manager->priv->introspection_data = NULL;
}
if (manager->priv->introspection_data2 != NULL) {
g_dbus_node_info_unref (manager->priv->introspection_data2);
manager->priv->introspection_data2 = NULL;
}
G_OBJECT_CLASS (csd_screensaver_proxy_manager_parent_class)->finalize (object);
}
CsdScreensaverProxyManager *
csd_screensaver_proxy_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (CSD_TYPE_SCREENSAVER_PROXY_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
register_manager_dbus (manager_object);
}
return CSD_SCREENSAVER_PROXY_MANAGER (manager_object);
}
././@LongLink 0000644 0000000 0000000 00000000157 00000000000 011606 L ustar root root cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/cinnamon-settings-daemon-screensaver-proxy.desktop.in cinnamon-settings-daemon-5.2.0/plugins/screensaver-proxy/cinnamon-settings-daemon-screensaver-proxy.0000664 0001750 0001750 00000000362 14144454032 033124 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - screensaver-proxy
Exec=csd-screensaver-proxy
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/common/ 0000775 0001750 0001750 00000000000 14144454032 020315 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/common/csd-power-helper.h 0000664 0001750 0001750 00000002174 14144454032 023652 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*/
#ifndef __CSD_POWER_HELPER_H
#define __CSD_POWER_HELPER_H
#include
G_BEGIN_DECLS
void csd_power_suspend (gboolean try_hybrid, gboolean suspend_then_hibernate);
void csd_power_hibernate (void);
void csd_power_poweroff (void);
G_END_DECLS
#endif /* __CSD_POWER_HELPER_H */
cinnamon-settings-daemon-5.2.0/plugins/common/csd-power-helper.c 0000664 0001750 0001750 00000027454 14144454032 023655 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include
#include "config.h"
#include "csd-power-helper.h"
#define LOGIND_DBUS_NAME "org.freedesktop.login1"
#define LOGIND_DBUS_PATH "/org/freedesktop/login1"
#define LOGIND_DBUS_INTERFACE "org.freedesktop.login1.Manager"
#define CONSOLEKIT_DBUS_NAME "org.freedesktop.ConsoleKit"
#define CONSOLEKIT_DBUS_PATH_MANAGER "/org/freedesktop/ConsoleKit/Manager"
#define CONSOLEKIT_DBUS_INTERFACE_MANAGER "org.freedesktop.ConsoleKit.Manager"
#ifdef HAVE_LOGIND
static gboolean
use_logind (void)
{
static gboolean should_use_logind = FALSE;
static gsize once_init_value = 0;
if (g_once_init_enter (&once_init_value)) {
should_use_logind = access("/run/systemd/seats/", F_OK) == 0; // sd_booted ()
g_once_init_leave (&once_init_value, 1);
}
return should_use_logind;
}
#else /* HAVE_LOGIND */
static gboolean
use_logind (void)
{
return FALSE;
}
#endif /* HAVE_LOGIND */
static void
logind_stop (void)
{
GDBusConnection *bus;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_connection_call (bus,
LOGIND_DBUS_NAME,
LOGIND_DBUS_PATH,
LOGIND_DBUS_INTERFACE,
"PowerOff",
g_variant_new ("(b)", FALSE),
NULL, 0, G_MAXINT, NULL, NULL, NULL);
g_object_unref (bus);
}
static gboolean
can_power_action (gchar *method_name)
{
GDBusConnection *bus;
GVariant *res;
gchar *rv;
gboolean can_action;
GError *error = NULL;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
res = g_dbus_connection_call_sync (bus,
LOGIND_DBUS_NAME,
LOGIND_DBUS_PATH,
LOGIND_DBUS_INTERFACE,
method_name,
NULL,
G_VARIANT_TYPE_TUPLE,
0, G_MAXINT, NULL, &error);
g_object_unref (bus);
if (error) {
g_warning ("Calling %s failed: %s", method_name, error->message);
g_clear_error (&error);
return FALSE;
}
g_variant_get (res, "(s)", &rv);
g_variant_unref (res);
can_action = g_strcmp0 (rv, "yes") == 0 ||
g_strcmp0 (rv, "challenge") == 0;
if (!can_action) {
g_warning ("logind does not support method %s", method_name);
}
g_free (rv);
return can_action;
}
static void
logind_suspend (gboolean suspend_then_hibernate)
{
gchar *method_name = "Suspend";
if (suspend_then_hibernate && can_power_action("CanHibernate")) {
method_name = "SuspendThenHibernate";
}
GDBusConnection *bus;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_connection_call (bus,
LOGIND_DBUS_NAME,
LOGIND_DBUS_PATH,
LOGIND_DBUS_INTERFACE,
method_name,
g_variant_new ("(b)", TRUE),
NULL, 0, G_MAXINT, NULL, NULL, NULL);
g_object_unref (bus);
}
static void
logind_hybrid_suspend (void)
{
GDBusConnection *bus;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_connection_call (bus,
LOGIND_DBUS_NAME,
LOGIND_DBUS_PATH,
LOGIND_DBUS_INTERFACE,
"HybridSleep",
g_variant_new ("(b)", TRUE),
NULL, 0, G_MAXINT, NULL, NULL, NULL);
g_object_unref (bus);
}
static void
logind_hibernate (void)
{
GDBusConnection *bus;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_connection_call (bus,
LOGIND_DBUS_NAME,
LOGIND_DBUS_PATH,
LOGIND_DBUS_INTERFACE,
"Hibernate",
g_variant_new ("(b)", TRUE),
NULL, 0, G_MAXINT, NULL, NULL, NULL);
g_object_unref (bus);
}
static void
consolekit_stop_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 stop using ConsoleKit: %s",
error->message);
g_error_free (error);
} else {
g_variant_unref (result);
}
}
static void
consolekit_stop (void)
{
GError *error = NULL;
GDBusProxy *proxy;
/* power down the machine in a safe way */
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
CONSOLEKIT_DBUS_NAME,
CONSOLEKIT_DBUS_PATH_MANAGER,
CONSOLEKIT_DBUS_INTERFACE_MANAGER,
NULL, &error);
if (proxy == NULL) {
g_warning ("cannot connect to ConsoleKit: %s",
error->message);
g_error_free (error);
return;
}
g_dbus_proxy_call (proxy,
"Stop",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
consolekit_stop_cb, NULL);
g_object_unref (proxy);
}
static void
consolekit_sleep_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 sleep using ConsoleKit: %s",
error->message);
g_error_free (error);
} else {
g_variant_unref (result);
}
}
static void
consolekit_suspend (gboolean suspend_then_hibernate)
{
GError *error = NULL;
GDBusProxy *proxy;
gchar *method_name = "Suspend";
if (suspend_then_hibernate && can_power_action("CanHibernate")) {
method_name = "SuspendThenHibernate";
}
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
CONSOLEKIT_DBUS_NAME,
CONSOLEKIT_DBUS_PATH_MANAGER,
CONSOLEKIT_DBUS_INTERFACE_MANAGER,
NULL, &error);
if (proxy == NULL) {
g_warning ("cannot connect to ConsoleKit: %s",
error->message);
g_error_free (error);
return;
}
g_dbus_proxy_call (proxy,
method_name,
g_variant_new("(b)", TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
consolekit_sleep_cb, NULL);
g_object_unref (proxy);
}
static void
consolekit_hibernate (void)
{
GError *error = NULL;
GDBusProxy *proxy;
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
CONSOLEKIT_DBUS_NAME,
CONSOLEKIT_DBUS_PATH_MANAGER,
CONSOLEKIT_DBUS_INTERFACE_MANAGER,
NULL, &error);
if (proxy == NULL) {
g_warning ("cannot connect to ConsoleKit: %s",
error->message);
g_error_free (error);
return;
}
g_dbus_proxy_call (proxy,
"Hibernate",
g_variant_new("(b)", TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
consolekit_sleep_cb, NULL);
g_object_unref (proxy);
}
static void
consolekit_hybrid_suspend (void)
{
GError *error = NULL;
GDBusProxy *proxy;
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
CONSOLEKIT_DBUS_NAME,
CONSOLEKIT_DBUS_PATH_MANAGER,
CONSOLEKIT_DBUS_INTERFACE_MANAGER,
NULL, &error);
if (proxy == NULL) {
g_warning ("cannot connect to ConsoleKit: %s",
error->message);
g_error_free (error);
return;
}
g_dbus_proxy_call (proxy,
"HybridSleep",
g_variant_new("(b)", TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL,
consolekit_sleep_cb, NULL);
g_object_unref (proxy);
}
void
csd_power_suspend (gboolean try_hybrid, gboolean suspend_then_hibernate)
{
if (use_logind ()) {
if (try_hybrid && can_power_action ("CanHybridSleep")) {
logind_hybrid_suspend ();
}
else {
logind_suspend (suspend_then_hibernate);
}
}
else {
if (try_hybrid && can_power_action ("CanHybridSleep")) {
consolekit_hybrid_suspend ();
}
else {
consolekit_suspend (suspend_then_hibernate);
}
}
}
void
csd_power_poweroff (void)
{
if (use_logind ()) {
logind_stop ();
}
else {
consolekit_stop ();
}
}
void
csd_power_hibernate (void)
{
if (use_logind ()) {
logind_hibernate ();
}
else {
consolekit_hibernate ();
}
}
cinnamon-settings-daemon-5.2.0/plugins/common/meson.build 0000664 0001750 0001750 00000001754 14144454032 022466 0 ustar fabio fabio common_sources = [
'csd-keygrab.c',
'csd-input-helper.c',
'csd-power-helper.c',
]
common_deps = [
config_h,
gtk,
x11,
xi,
]
common_inc = include_directories('.')
common_lib = static_library(
'common_lib',
common_sources,
include_directories: [include_dirs, common_inc],
dependencies: common_deps,
)
common_dep = declare_dependency(
include_directories: include_dirs,
link_with: common_lib,
dependencies: common_deps,
)
helper_sources = [
'test-input-helper.c',
common_sources,
]
executable(
'csd-input-helper',
helper_sources,
dependencies: common_dep,
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-input-helper')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-input-helper')
endif
install_data(
'input-device-example.sh',
install_dir: join_paths(datadir, '@0@-@1@'.format(pkgname, api_version)),
)
cinnamon-settings-daemon-5.2.0/plugins/common/csd-keygrab.h 0000664 0001750 0001750 00000003734 14144454032 022670 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Jens Granseuer
*
* 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 - Suite 500, Boston, MA 02110-1335, USA.
*/
#ifndef __CSD_COMMON_KEYGRAB_H
#define __CSD_COMMON_KEYGRAB_H
G_BEGIN_DECLS
#include
#include
#include
typedef struct {
guint keysym;
guint state;
guint *keycodes;
} Key;
typedef enum {
CSD_KEYGRAB_NORMAL = 0,
CSD_KEYGRAB_ALLOW_UNMODIFIED = 1 << 0,
CSD_KEYGRAB_SYNCHRONOUS = 1 << 1
} CsdKeygrabFlags;
void grab_key_unsafe (Key *key,
CsdKeygrabFlags flags,
GSList *screens);
void ungrab_key_unsafe (Key *key,
GSList *screens);
gboolean match_xi2_key (Key *key,
XIDeviceEvent *event);
gboolean key_uses_keycode (const Key *key,
guint keycode);
Key * parse_key (const char *str);
void free_key (Key *key);
void grab_button (int deviceid,
gboolean grab,
GSList *screens);
G_END_DECLS
#endif /* __CSD_COMMON_KEYGRAB_H */
cinnamon-settings-daemon-5.2.0/plugins/common/daemon-skeleton.h 0000664 0001750 0001750 00000016345 14144454032 023564 0 ustar fabio fabio /**
* Create a test app for your plugin quickly.
*
* #define NEW csd_media_keys_manager_new
* #define START csd_media_keys_manager_start
* #define MANAGER CsdMediaKeysManager
* #include "csd-media-keys-manager.h"
*
* #include "daemon-skeleton.h"
*/
#include "config.h"
#include
#include
#include
#include
#ifndef PLUGIN_NAME
#error Include PLUGIN_CFLAGS in the daemon s CFLAGS
#endif /* !PLUGIN_NAME */
#define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager"
#define GNOME_SESSION_DBUS_PATH "/org/gnome/SessionManager"
#define GNOME_SESSION_CLIENT_PRIVATE_NAME "org.gnome.SessionManager.ClientPrivate"
static MANAGER *manager = NULL;
static int timeout = -1;
static gboolean verbose = FALSE;
static GOptionEntry entries[] = {
{ "exit-time", 0, 0, G_OPTION_ARG_INT, &timeout, "Exit after n seconds time", NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose", NULL },
{NULL}
};
static void
respond_to_end_session (GDBusProxy *proxy)
{
/* we must answer with "EndSessionResponse" */
g_dbus_proxy_call (proxy, "EndSessionResponse",
g_variant_new ("(bs)", TRUE, ""),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
}
static void
client_proxy_signal_cb (GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
if (g_strcmp0 (signal_name, "QueryEndSession") == 0) {
g_debug ("Got QueryEndSession signal");
respond_to_end_session (proxy);
} else if (g_strcmp0 (signal_name, "EndSession") == 0) {
g_debug ("Got EndSession signal");
respond_to_end_session (proxy);
} else if (g_strcmp0 (signal_name, "Stop") == 0) {
g_debug ("Got Stop signal");
/* Ideally, we would call gtk_main_quit (); here.
Instead, do nothing.
cinnamon-session-manager doesn't wait in this STOP PHASE.
so we're not delaying the logout/shutdown sequence.
Also, if another process is lagging and delaying previous
phases, we don't want to lose CSD in the background.
We want CSD plugins to run until the very very end of the session.
*/
}
}
static void
on_client_registered (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GVariant *variant;
GDBusProxy *client_proxy;
GError *error = NULL;
gchar *object_path = NULL;
variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
if (!variant) {
if (error != NULL) {
g_warning ("Unable to register client: %s", error->message);
g_error_free (error);
}
return;
}
g_variant_get (variant, "(o)", &object_path);
g_debug ("Registered client at path %s", object_path);
client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, NULL,
GNOME_SESSION_DBUS_NAME,
object_path,
GNOME_SESSION_CLIENT_PRIVATE_NAME,
NULL,
&error);
if (!client_proxy) {
if (error != NULL) {
g_warning ("Unable to get the session client proxy: %s", error->message);
g_error_free (error);
}
return;
}
g_signal_connect (client_proxy, "g-signal",
G_CALLBACK (client_proxy_signal_cb), NULL);
g_free (object_path);
g_variant_unref (variant);
}
static void
register_with_cinnamon_session (void)
{
const char *startup_id;
GError *error = NULL;
GDBusProxy *proxy;
GDBusConnection *bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
if (!bus) {
g_debug ("Could not connect to the dbus session bus");
return;
}
proxy = g_dbus_proxy_new_sync (bus,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
GNOME_SESSION_DBUS_NAME,
GNOME_SESSION_DBUS_PATH,
GNOME_SESSION_DBUS_NAME,
NULL,
&error);
g_object_unref (bus);
if (proxy == NULL) {
if (error != NULL) {
g_debug ("Could not connect to the Session manager: %s", error->message);
g_error_free (error);
}
return;
}
startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
g_dbus_proxy_call (proxy,
"RegisterClient",
g_variant_new ("(ss)", PLUGIN_NAME, startup_id ? startup_id : ""),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) on_client_registered,
NULL);
}
int
main (int argc, char **argv)
{
GError *error;
gboolean started;
bindtextdomain (GETTEXT_PACKAGE, CINNAMON_SETTINGS_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* Work around https://bugzilla.gnome.org/show_bug.cgi?id=674885 */
g_type_ensure (G_TYPE_DBUS_CONNECTION);
g_type_ensure (G_TYPE_DBUS_PROXY);
gdk_set_allowed_backends ("x11");
notify_init ("cinnamon-settings-daemon");
if (FORCE_GDK_SCALE) {
g_setenv ("GDK_SCALE", "1", TRUE);
}
error = NULL;
if (! gtk_init_with_args (&argc, &argv, PLUGIN_NAME, entries, NULL, &error)) {
if (error != NULL) {
fprintf (stderr, "%s\n", error->message);
g_error_free (error);
}
exit (1);
}
if (FORCE_GDK_SCALE) {
g_unsetenv ("GDK_SCALE");
}
if (verbose)
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
if (timeout > 0) {
guint id;
id = g_timeout_add_seconds (timeout, (GSourceFunc) gtk_main_quit, NULL);
g_source_set_name_by_id (id, "[cinnamon-settings-daemon] gtk_main_quit");
}
manager = NEW ();
error = NULL;
if (REGISTER_BEFORE_STARTING) {
register_with_cinnamon_session ();
started = START (manager, &error);
}
else {
started = START (manager, &error);
register_with_cinnamon_session ();
}
if (!started) {
if (error != NULL) {
fprintf (stderr, "[cinnamon-settings-daemon-%s] Failed to start: %s\n", PLUGIN_NAME, error->message);
g_error_free (error);
}
exit (1);
}
gtk_main ();
STOP (manager);
g_object_unref (manager);
return 0;
}
cinnamon-settings-daemon-5.2.0/plugins/common/csd-input-helper.c 0000664 0001750 0001750 00000043545 14144454032 023657 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include "csd-input-helper.h"
#define INPUT_DEVICES_SCHEMA "org.cinnamon.settings-daemon.peripherals.input-devices"
#define KEY_HOTPLUG_COMMAND "hotplug-command"
typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info);
typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice);
gboolean
device_set_property (XDevice *xdevice,
const char *device_name,
PropertyHelper *property)
{
int rc;
unsigned long i;
Atom prop;
Atom realtype;
int realformat;
unsigned long nitems, bytes_after;
unsigned char *data;
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
property->name, False);
if (!prop)
return FALSE;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
xdevice, prop, 0, property->nitems, False,
AnyPropertyType, &realtype, &realformat, &nitems,
&bytes_after, &data);
if (rc != Success ||
realtype != (Atom)property->type ||
realformat != property->format ||
nitems < (unsigned long)property->nitems) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
g_warning ("Error reading property \"%s\" for \"%s\"", property->name, device_name);
return FALSE;
}
for (i = 0; i < nitems; i++) {
switch (property->format) {
case 8:
data[i] = property->data.c[i];
break;
case 32:
((long*)data)[i] = property->data.i[i];
break;
default:
g_warning("device_set_property: default case");
break;
}
}
XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
xdevice, prop, realtype, realformat,
PropModeReplace, data, nitems);
XFree (data);
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ())) {
g_warning ("Error in setting \"%s\" for \"%s\"", property->name, device_name);
return FALSE;
}
return TRUE;
}
static gboolean
supports_xinput_devices_with_opcode (int *opcode)
{
gint op_code, event, error;
gboolean retval;
retval = XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
"XInputExtension",
&op_code,
&event,
&error);
if (opcode)
*opcode = op_code;
return retval;
}
gboolean
supports_xinput_devices (void)
{
return supports_xinput_devices_with_opcode (NULL);
}
gboolean
supports_xtest (void)
{
gint op_code, event, error;
gboolean retval;
retval = XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
"XTEST",
&op_code,
&event,
&error);
return retval;
}
gboolean
supports_xinput2_devices (int *opcode)
{
int major, minor;
if (supports_xinput_devices_with_opcode (opcode) == FALSE)
return FALSE;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
major = 2;
#ifdef XI_23
minor = 3;
#else
minor = 0;
#endif
if (XIQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor) != Success) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
#ifndef XI_23
/* try for 2.2, maybe gtk has already announced 2.2 support */
gdk_x11_display_error_trap_push (gdk_display_get_default ());
major = 2;
minor = 2;
if (XIQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor) != Success) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
return FALSE;
}
#else
return FALSE;
#endif
}
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
if ((major * 1000 + minor) < (2000))
return FALSE;
return TRUE;
}
gboolean
device_is_touchpad (XDevice *xdevice)
{
Atom realtype, prop;
int realformat;
unsigned long nitems, bytes_after;
unsigned char *data;
const char *names[] = {
"libinput Tapping Enabled",
/* we don't check on the type being XI_TOUCHPAD here,
* but having a "Synaptics Off" property should be enough */
"Synaptics Off",
NULL,
};
const char **name = names;
do {
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *name, True);
if (prop) {
gdk_x11_display_error_trap_push (gdk_display_get_default ());
if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
xdevice, prop, 0, 1, False,
XA_INTEGER, &realtype, &realformat, &nitems,
&bytes_after, &data) == Success) && (realtype != None)) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
XFree (data);
return TRUE;
}
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
}
name++;
} while (*name);
return FALSE;
}
gboolean
device_info_is_touchpad (XDeviceInfo *device_info)
{
return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHPAD, False));
}
gboolean
device_info_is_touchscreen (XDeviceInfo *device_info)
{
return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHSCREEN, False));
}
gboolean
device_info_is_tablet (XDeviceInfo *device_info)
{
/* Note that this doesn't match Wacom tablets */
return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TABLET, False));
}
gboolean
device_info_is_mouse (XDeviceInfo *device_info)
{
return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_MOUSE, False));
}
gboolean
device_info_is_trackball (XDeviceInfo *device_info)
{
gboolean retval;
retval = (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TRACKBALL, False));
if (retval == FALSE &&
device_info->name != NULL) {
char *lowercase;
lowercase = g_ascii_strdown (device_info->name, -1);
retval = strstr (lowercase, "trackball") != NULL;
g_free (lowercase);
}
return retval;
}
static gboolean
device_type_is_present (InfoIdentifyFunc info_func,
DeviceIdentifyFunc device_func)
{
XDeviceInfo *device_info;
gint n_devices,i;
gboolean retval;
if (supports_xinput_devices () == FALSE)
return TRUE;
retval = FALSE;
device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
if (device_info == NULL)
return FALSE;
for (i = 0; i < n_devices; i++) {
XDevice *device;
/* Check with the device info first */
retval = (info_func) (&device_info[i]);
if (retval == FALSE)
continue;
/* If we only have an info func, we're done checking */
if (device_func == NULL)
break;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id);
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()) || (device == NULL))
continue;
retval = (device_func) (device);
if (retval) {
xdevice_close (device);
break;
}
xdevice_close (device);
}
XFreeDeviceList (device_info);
return retval;
}
gboolean
touchscreen_is_present (void)
{
return device_type_is_present (device_info_is_touchscreen,
NULL);
}
gboolean
touchpad_is_present (void)
{
return device_type_is_present (device_info_is_touchpad,
device_is_touchpad);
}
gboolean
mouse_is_present (void)
{
return device_type_is_present (device_info_is_mouse,
NULL);
}
gboolean
trackball_is_present (void)
{
return device_type_is_present (device_info_is_trackball,
NULL);
}
char *
xdevice_get_device_node (int deviceid)
{
Atom prop;
Atom act_type;
int act_format;
unsigned long nitems, bytes_after;
unsigned char *data;
char *ret;
gdk_display_sync (gdk_display_get_default ());
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Node", False);
if (!prop)
return NULL;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
if (!XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
deviceid, prop, 0, 1000, False,
AnyPropertyType, &act_type, &act_format,
&nitems, &bytes_after, &data) == Success) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
return NULL;
}
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()))
goto out;
if (nitems == 0)
goto out;
if (act_type != XA_STRING)
goto out;
/* Unknown string format */
if (act_format != 8)
goto out;
ret = g_strdup ((char *) data);
XFree (data);
return ret;
out:
XFree (data);
return NULL;
}
#define TOOL_ID_FORMAT_SIZE 32
static int
get_id_for_index (guchar *data,
guint idx)
{
guchar *ptr;
int id;
ptr = data;
ptr += TOOL_ID_FORMAT_SIZE / 8 * idx;
id = *((int32_t*)ptr);
id = id & 0xfffff;
return id;
}
#define STYLUS_DEVICE_ID 0x02
#define ERASER_DEVICE_ID 0x0A
int
xdevice_get_last_tool_id (int deviceid)
{
Atom prop;
Atom act_type;
int act_format;
unsigned long nitems, bytes_after;
unsigned char *data;
int id;
id = -1;
gdk_display_sync (gdk_display_get_default ());
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), WACOM_SERIAL_IDS_PROP, False);
if (!prop)
return -1;
data = NULL;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
if (XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
deviceid, prop, 0, 1000, False,
AnyPropertyType, &act_type, &act_format,
&nitems, &bytes_after, &data) != Success) {
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
goto out;
}
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()))
goto out;
if (nitems != 4 && nitems != 5)
goto out;
if (act_type != XA_INTEGER)
goto out;
if (act_format != TOOL_ID_FORMAT_SIZE)
goto out;
/* item 0 = tablet ID
* item 1 = old device serial number (== last tool in proximity)
* item 2 = old hardware serial number (including tool ID)
* item 3 = current serial number (0 if no tool in proximity)
* item 4 = current tool ID (since Feb 2012)
*
* Get the current tool ID first, if available, then the old one */
id = 0x0;
if (nitems == 5)
id = get_id_for_index (data, 4);
if (id == 0x0)
id = get_id_for_index (data, 2);
/* That means that no tool was set down yet */
if (id == STYLUS_DEVICE_ID ||
id == ERASER_DEVICE_ID)
id = 0x0;
out:
if (data != NULL)
XFree (data);
return id;
}
gboolean
set_device_enabled (int device_id,
gboolean enabled)
{
Atom prop;
guchar value;
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Enabled", False);
if (!prop)
return FALSE;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
value = enabled ? 1 : 0;
XIChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
device_id, prop, XA_INTEGER, 8, PropModeReplace, &value, 1);
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()))
return FALSE;
return TRUE;
}
static const char *
custom_command_to_string (CustomCommand command)
{
switch (command) {
case COMMAND_DEVICE_ADDED:
return "added";
case COMMAND_DEVICE_REMOVED:
return "removed";
case COMMAND_DEVICE_PRESENT:
return "present";
default:
g_assert_not_reached ();
}
}
/* Run a custom command on device presence events. Parameters passed into
* the custom command are:
* command -t [added|removed|present] -i
* Type 'added' and 'removed' signal 'device added' and 'device removed',
* respectively. Type 'present' signals 'device present at
* cinnamon-settings-daemon init'.
*
* The script is expected to run synchronously, and an exit value
* of "1" means that no other settings will be applied to this
* particular device.
*
* More options may be added in the future.
*
* This function returns TRUE if we should not apply any more settings
* to the device.
*/
gboolean
run_custom_command (GdkDevice *device,
CustomCommand command)
{
GSettings *settings;
char *cmd;
char *argv[7];
int exit_status;
gboolean rc;
int id;
settings = g_settings_new (INPUT_DEVICES_SCHEMA);
cmd = g_settings_get_string (settings, KEY_HOTPLUG_COMMAND);
g_object_unref (settings);
if (!cmd || cmd[0] == '\0') {
g_free (cmd);
return FALSE;
}
/* Easter egg! */
g_object_get (device, "device-id", &id, NULL);
argv[0] = cmd;
argv[1] = (char *)"-t";
argv[2] = (char *) custom_command_to_string (command);
argv[3] = (char *)"-i";
argv[4] = g_strdup_printf ("%d", id);
argv[5] = g_strdup_printf ("%s", gdk_device_get_name (device));
argv[6] = NULL;
rc = g_spawn_sync (g_get_home_dir (), argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, NULL, &exit_status, NULL);
if (rc == FALSE)
g_warning ("Couldn't execute command '%s', verify that this is a valid command.", cmd);
g_free (argv[0]);
g_free (argv[4]);
g_free (argv[5]);
return (exit_status == 0);
}
GList *
get_disabled_devices (GdkDeviceManager *manager)
{
XDeviceInfo *device_info;
gint n_devices;
gint i;
GList *ret;
ret = NULL;
device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
if (device_info == NULL)
return ret;
for (i = 0; i < n_devices; i++) {
GdkDevice *device;
/* Ignore core devices */
if (device_info[i].use == IsXKeyboard ||
device_info[i].use == IsXPointer)
continue;
/* Check whether the device is actually available */
device = gdk_x11_device_manager_lookup (manager, device_info[i].id);
if (device != NULL)
continue;
ret = g_list_prepend (ret, GINT_TO_POINTER (device_info[i].id));
}
XFreeDeviceList (device_info);
return ret;
}
void
xdevice_close (XDevice *xdevice)
{
gdk_x11_display_error_trap_push (gdk_display_get_default ());
XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default ());
}
cinnamon-settings-daemon-5.2.0/plugins/common/input-device-example.sh 0000664 0001750 0001750 00000003014 14144454032 024674 0 ustar fabio fabio #!/bin/sh
#
# This script is an example hotplug script for use with the various
# input devices plugins.
#
# The script is called with the arguments:
# -t [added|present|removed]
# added ... device was just plugged in
# present.. device was present at cinnamon-settings-daemon startup
# removed.. device was just removed
# -i
# device ID being the XInput device ID
# The name of the device
#
# The script should return 0 if the device is to be
# ignored from future configuration.
#
# Set the script to be used with:
# gsettings set org.cinnamon.settings-daemon.peripherals.input-devices hotplug-command /path/to/script/input-devices.sh
#
args=`getopt "t:i:" $*`
set -- $args
while [ $# -gt 0 ]
do
case $1 in
-t)
shift;
type="$1"
;;
-i)
shift;
id="$1"
;;
--)
shift;
device="$@"
break;
;;
*)
echo "Unknown option $1";
exit 1
;;
esac
shift
done
retval=0
case $type in
added)
echo "Device '$device' (ID=$id) was added"
;;
present)
echo "Device '$device' (ID=$id) was already present at startup"
;;
removed)
echo "Device '$device' (ID=$id) was removed"
;;
*)
echo "Unknown operation"
retval=1
;;
esac
# All further processing will be disabled if $retval == 0
exit $retval
cinnamon-settings-daemon-5.2.0/plugins/common/test-input-helper.c 0000664 0001750 0001750 00000007070 14144454032 024056 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2011 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include "csd-input-helper.h"
static void
print_disabled_devices (void)
{
GList *devices, *l;
GdkDeviceManager *manager;
manager = gdk_display_get_device_manager (gdk_display_get_default ());
devices = get_disabled_devices (manager);
g_print ("Disabled devices:\t\t\t");
if (devices == NULL) {
g_print ("no\n");
return;
}
for (l = devices; l != NULL; l = l->next) {
g_print ("%d ", GPOINTER_TO_INT (l->data));
}
g_list_free (devices);
g_print ("\n");
}
int main (int argc, char **argv)
{
gboolean supports_xinput;
gboolean has_touchpad, has_touchscreen;
XDeviceInfo *device_info;
gint n_devices, opcode, i;
gtk_init (&argc, &argv);
supports_xinput = supports_xinput_devices ();
if (supports_xinput) {
g_print ("Supports XInput:\t\t\tyes\n");
} else {
g_print ("Supports XInput:\t\t\tno\n");
return 0;
}
supports_xinput = supports_xinput2_devices (&opcode);
if (supports_xinput) {
g_print ("Supports XInput2:\t\t\tyes (opcode: %d)\n", opcode);
} else {
g_print ("Supports XInput2:\t\t\tno\n");
return 0;
}
has_touchpad = touchpad_is_present ();
g_print ("Has touchpad:\t\t\t\t%s\n", has_touchpad ? "yes" : "no");
has_touchscreen = touchscreen_is_present ();
g_print ("Has touchscreen:\t\t\t%s\n", has_touchscreen ? "yes" : "no");
device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
if (device_info == NULL) {
g_warning ("Has no input devices");
return 1;
}
print_disabled_devices ();
for (i = 0; i < n_devices; i++) {
XDevice *device;
if (device_info_is_touchscreen (&device_info[i])) {
g_print ("Device %d is touchscreen:\t\t%s\n", (int) device_info[i].id, "yes");
continue;
}
gdk_x11_display_error_trap_push (gdk_display_get_default ());
device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id);
if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()) || (device == NULL))
continue;
if (device_is_touchpad (device))
g_print ("Device %d is touchpad:\t\t%s\n", (int) device_info[i].id, "yes");
else {
int tool_id;
tool_id = xdevice_get_last_tool_id (device_info[i].id);
if (tool_id >= 0x0)
g_print ("Device %d is touchpad/touchscreen:\t%s (tool ID: 0x%x)\n", (int) device_info[i].id, "no", tool_id);
else
g_print ("Device %d is touchpad/touchscreen:\t%s\n", (int) device_info[i].id, "no");
}
xdevice_close (device);
}
XFreeDeviceList (device_info);
return 0;
}
cinnamon-settings-daemon-5.2.0/plugins/common/csd-keygrab.c 0000664 0001750 0001750 00000032647 14144454032 022670 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2001-2003 Bastien Nocera
* Copyright (C) 2006-2007 William Jon McCann
* Copyright (C) 2008 Jens Granseuer
*
* 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 - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "csd-keygrab.h"
/* these are the mods whose combinations are ignored by the keygrabbing code */
static GdkModifierType csd_ignored_mods = 0;
/* these are the ones we actually use for global keys, we always only check
* for these set */
static GdkModifierType csd_used_mods = 0;
/* Taken from a comment in XF86keysym.h */
#define XF86KEYS_RANGE_MIN 0x10080001
#define XF86KEYS_RANGE_MAX 0x1008FFFF
#define FKEYS_RANGE_MIN GDK_KEY_F1
#define FKEYS_RANGE_MAX GDK_KEY_R15
#define IN_RANGE(x, min, max) (x >= min && x <= max)
static void
setup_modifiers (void)
{
if (csd_used_mods == 0 || csd_ignored_mods == 0) {
GdkModifierType dynmods;
/* default modifiers */
csd_ignored_mods = \
0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | GDK_HYPER_MASK;
csd_used_mods = \
GDK_SHIFT_MASK | GDK_CONTROL_MASK |\
GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |\
GDK_MOD5_MASK | GDK_SUPER_MASK | GDK_META_MASK;
/* NumLock can be assigned to varying keys so we need to
* resolve and ignore it specially */
dynmods = XkbKeysymToModifiers (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Num_Lock);
csd_ignored_mods |= dynmods;
csd_used_mods &= ~dynmods;
}
}
static void
grab_key_real (guint keycode,
GdkWindow *root,
gboolean grab,
gboolean synchronous,
XIGrabModifiers *mods,
int num_mods)
{
XIEventMask evmask;
unsigned char mask[(XI_LASTEVENT + 7)/8];
memset (mask, 0, sizeof (mask));
XISetMask (mask, XI_KeyPress);
XISetMask (mask, XI_KeyRelease);
evmask.deviceid = XIAllMasterDevices;
evmask.mask_len = sizeof (mask);
evmask.mask = mask;
if (grab) {
XIGrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
XIAllMasterDevices,
keycode,
GDK_WINDOW_XID (root),
GrabModeAsync,
synchronous ? GrabModeSync : GrabModeAsync,
False,
&evmask,
num_mods,
mods);
} else {
XIUngrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
XIAllMasterDevices,
keycode,
GDK_WINDOW_XID (root),
num_mods,
mods);
}
}
/* Grab the key. In order to ignore CSD_IGNORED_MODS we need to grab
* all combinations of the ignored modifiers and those actually used
* for the binding (if any).
*
* inspired by all_combinations from gnome-panel/gnome-panel/global-keys.c
*
* This may generate X errors. The correct way to use this is like:
*
* gdk_x11_display_error_trap_push (gdk_display_get_default ());
*
* grab_key_unsafe (key, grab, screens);
*
* gdk_flush ();
* if (gdk_x11_display_error_trap_pop (gdk_display_get_default ()))
* g_warning ("Grab failed, another application may already have access to key '%u'",
* key->keycode);
*
* This is not done in the function itself, to allow doing multiple grab_key
* operations with one flush only.
*/
#define N_BITS 32
static void
grab_key_internal (Key *key,
gboolean grab,
CsdKeygrabFlags flags,
GSList *screens)
{
int indexes[N_BITS]; /* indexes of bits we need to flip */
int i;
int bit;
int bits_set_cnt;
int uppervalue;
guint mask, modifiers;
GArray *all_mods;
GSList *l;
setup_modifiers ();
mask = csd_ignored_mods & ~key->state & GDK_MODIFIER_MASK;
/* XGrabKey requires real modifiers, not virtual ones */
modifiers = key->state;
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &modifiers);
modifiers &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
/* If key doesn't have a usable modifier, we don't want
* to grab it, since the user might lose a useful key.
*
* The exception is the XFree86 keys and the Function keys
* (which are useful to grab without a modifier).
*/
if (!(flags & CSD_KEYGRAB_ALLOW_UNMODIFIED) &&
(modifiers & csd_used_mods) == 0 &&
!IN_RANGE(key->keysym, XF86KEYS_RANGE_MIN, XF86KEYS_RANGE_MAX) &&
!IN_RANGE(key->keysym, FKEYS_RANGE_MIN, FKEYS_RANGE_MAX) &&
key->keysym != GDK_KEY_Pause &&
key->keysym != GDK_KEY_Print &&
key->keysym != GDK_KEY_Scroll_Lock &&
key->keysym != GDK_KEY_Break &&
key->keysym != GDK_KEY_Menu) {
GString *keycodes;
keycodes = g_string_new ("");
if (key->keycodes != NULL) {
guint *c;
for (c = key->keycodes; *c; ++c) {
g_string_printf (keycodes, " %u", *c);
}
}
g_warning ("Key 0x%x (keycodes: %s) with state 0x%x (resolved to 0x%x) "
" has no usable modifiers (usable modifiers are 0x%x)",
key->keysym, keycodes->str, key->state, modifiers, csd_used_mods);
g_string_free (keycodes, TRUE);
return;
}
bit = 0;
/* store the indexes of all set bits in mask in the array */
for (i = 0; mask; ++i, mask >>= 1) {
if (mask & 0x1) {
indexes[bit++] = i;
}
}
bits_set_cnt = bit;
all_mods = g_array_new (FALSE, TRUE, sizeof(XIGrabModifiers));
uppervalue = 1 << bits_set_cnt;
/* store all possible modifier combinations for our mask into all_mods */
for (i = 0; i < uppervalue; ++i) {
int j;
int result = 0;
XIGrabModifiers *mod;
/* map bits in the counter to those in the mask */
for (j = 0; j < bits_set_cnt; ++j) {
if (i & (1 << j)) {
result |= (1 << indexes[j]);
}
}
/* Grow the array by one, to fit our new XIGrabModifiers item */
g_array_set_size (all_mods, all_mods->len + 1);
mod = &g_array_index (all_mods, XIGrabModifiers, all_mods->len - 1);
mod->modifiers = result | modifiers;
}
/* Capture the actual keycodes with the modifier array */
for (l = screens; l; l = l->next) {
GdkScreen *screen = l->data;
guint *code;
for (code = key->keycodes; *code; ++code) {
grab_key_real (*code,
gdk_screen_get_root_window (screen),
grab,
flags & CSD_KEYGRAB_SYNCHRONOUS,
(XIGrabModifiers *) all_mods->data,
all_mods->len);
}
}
g_array_free (all_mods, TRUE);
}
void
grab_key_unsafe (Key *key,
CsdKeygrabFlags flags,
GSList *screens)
{
grab_key_internal (key, TRUE, flags, screens);
}
void
ungrab_key_unsafe (Key *key,
GSList *screens)
{
grab_key_internal (key, FALSE, 0, screens);
}
static gboolean
have_xkb (Display *dpy)
{
static int have_xkb = -1;
if (have_xkb == -1) {
int opcode, error_base, major, minor, xkb_event_base;
have_xkb = XkbQueryExtension (dpy,
&opcode,
&xkb_event_base,
&error_base,
&major,
&minor)
&& XkbUseExtension (dpy, &major, &minor);
}
return have_xkb;
}
gboolean
key_uses_keycode (const Key *key, guint keycode)
{
if (key->keycodes != NULL) {
guint *c;
for (c = key->keycodes; *c; ++c) {
if (*c == keycode)
return TRUE;
}
}
return FALSE;
}
/* Adapted from _gdk_x11_device_xi2_translate_state()
* in gtk+/gdk/x11/gdkdevice-xi2.c */
static guint
device_xi2_translate_state (XIModifierState *mods_state,
XIGroupState *group_state)
{
guint state;
gint group;
state = (guint) mods_state->base | mods_state->latched | mods_state->locked;
group = group_state->base | group_state->latched | group_state->locked;
/* FIXME: do we need the XKB complications for this ? */
group = CLAMP(group, 0, 3);
state |= group << 13;
return state;
}
gboolean
match_xi2_key (Key *key, XIDeviceEvent *event)
{
guint keyval;
GdkModifierType consumed;
gint group;
guint keycode, state;
if (key == NULL)
return FALSE;
setup_modifiers ();
state = device_xi2_translate_state (&event->mods, &event->group);
if (have_xkb (event->display))
group = XkbGroupForCoreState (state);
else
group = (state & GDK_KEY_Mode_switch) ? 1 : 0;
keycode = event->detail;
/* Check if we find a keysym that matches our current state */
if (gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), keycode,
state, group,
&keyval, NULL, NULL, &consumed)) {
guint lower, upper;
guint mask;
/* HACK: we don't want to use SysRq as a keybinding, so we avoid
* its translation from Alt+Print. */
if (keyval == GDK_KEY_Sys_Req &&
(state & GDK_MOD1_MASK) != 0) {
consumed = 0;
keyval = GDK_KEY_Print;
}
/* The Key structure contains virtual modifiers, whereas
* the XEvent will be using the real modifier, so translate those */
mask = key->state;
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &mask);
mask &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
gdk_keyval_convert_case (keyval, &lower, &upper);
/* If we are checking against the lower version of the
* keysym, we might need the Shift state for matching,
* so remove it from the consumed modifiers */
if (lower == key->keysym)
consumed &= ~GDK_SHIFT_MASK;
return ((lower == key->keysym || upper == key->keysym)
&& (state & ~consumed & csd_used_mods) == mask);
}
/* The key we passed doesn't have a keysym, so try with just the keycode */
return (key != NULL
&& key->state == (state & csd_used_mods)
&& key_uses_keycode (key, keycode));
}
Key *
parse_key (const char *str)
{
Key *key;
if (str == NULL ||
*str == '\0' ||
g_str_equal (str, "disabled")) {
return NULL;
}
key = g_new0 (Key, 1);
gtk_accelerator_parse_with_keycode (str, &key->keysym, &key->keycodes, &key->state);
if (key->keysym == 0 &&
key->keycodes == NULL &&
key->state == 0) {
g_free (key);
return NULL;
}
return key;
}
void
free_key (Key *key)
{
if (key == NULL)
return;
g_free (key->keycodes);
g_free (key);
}
static void
grab_button_real (int deviceid,
gboolean grab,
GdkWindow *root)
{
XIGrabModifiers mods;
mods.modifiers = XIAnyModifier;
if (grab) {
XIEventMask evmask;
unsigned char mask[(XI_LASTEVENT + 7)/8];
memset (mask, 0, sizeof (mask));
XISetMask (mask, XI_ButtonRelease);
XISetMask (mask, XI_ButtonPress);
evmask.deviceid = deviceid;
evmask.mask_len = sizeof (mask);
evmask.mask = mask;
XIGrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
deviceid,
XIAnyButton,
GDK_WINDOW_XID (root),
None,
GrabModeAsync,
GrabModeAsync,
False,
&evmask,
1,
&mods);
} else {
XIUngrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
deviceid,
XIAnyButton,
GDK_WINDOW_XID (root),
1, &mods);
}
}
void
grab_button (int deviceid,
gboolean grab,
GSList *screens)
{
GSList *l;
for (l = screens; l; l = l->next) {
GdkScreen *screen = l->data;
grab_button_real (deviceid,
grab,
gdk_screen_get_root_window (screen));
}
}
cinnamon-settings-daemon-5.2.0/plugins/common/csd-input-helper.h 0000664 0001750 0001750 00000006524 14144454032 023660 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*/
#ifndef __CSD_INPUT_HELPER_H
#define __CSD_INPUT_HELPER_H
G_BEGIN_DECLS
#include
#include
#include
#define WACOM_SERIAL_IDS_PROP "Wacom Serial IDs"
typedef enum {
COMMAND_DEVICE_ADDED,
COMMAND_DEVICE_REMOVED,
COMMAND_DEVICE_PRESENT
} CustomCommand;
/* Generic property setting code. Fill up the struct property with the property
* data and pass it into device_set_property together with the device to be
* changed. Note: doesn't cater for non-zero offsets yet, but we don't have
* any settings that require that.
*/
typedef struct {
const char *name; /* property name */
gint nitems; /* number of items in data */
gint format; /* CARD8 or CARD32 sized-items */
gint type; /* Atom representing data type */
union {
const gchar *c; /* 8 bit data */
const gint *i; /* 32 bit data */
} data;
} PropertyHelper;
gboolean supports_xinput_devices (void);
gboolean supports_xinput2_devices (int *opcode);
gboolean supports_xtest (void);
gboolean set_device_enabled (int device_id,
gboolean enabled);
gboolean device_is_touchpad (XDevice *xdevice);
gboolean device_info_is_touchpad (XDeviceInfo *device_info);
gboolean device_info_is_touchscreen (XDeviceInfo *device_info);
gboolean device_info_is_tablet (XDeviceInfo *device_info);
gboolean device_info_is_mouse (XDeviceInfo *device_info);
gboolean device_info_is_trackball (XDeviceInfo *device_info);
gboolean touchpad_is_present (void);
gboolean touchscreen_is_present (void);
gboolean mouse_is_present (void);
gboolean trackball_is_present (void);
gboolean device_set_property (XDevice *xdevice,
const char *device_name,
PropertyHelper *property);
gboolean run_custom_command (GdkDevice *device,
CustomCommand command);
GList * get_disabled_devices (GdkDeviceManager *manager);
char * xdevice_get_device_node (int deviceid);
int xdevice_get_last_tool_id (int deviceid);
void xdevice_close (XDevice *xdevice);
G_END_DECLS
#endif /* __CSD_INPUT_HELPER_H */
cinnamon-settings-daemon-5.2.0/plugins/sound/ 0000775 0001750 0001750 00000000000 14144454032 020155 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/sound/meson.build 0000664 0001750 0001750 00000001470 14144454032 022321 0 ustar fabio fabio plugin_name = 'sound'
sound_sources = [
'csd-sound-manager.c',
'main.c',
]
sound_deps = [
canberra,
common_dep,
csd_dep,
gudev,
libnotify,
pulse_glib,
pulse,
]
executable(
'csd-sound',
sound_sources,
include_directories: [include_dirs, common_inc],
dependencies: sound_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-sound')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-sound')
endif
configure_file(
input: 'cinnamon-settings-daemon-sound.desktop.in',
output: 'cinnamon-settings-daemon-sound.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
cinnamon-settings-daemon-5.2.0/plugins/sound/csd-sound-manager.c 0000664 0001750 0001750 00000051203 14144454032 023631 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "csd-sound-manager.h"
#include "cinnamon-settings-profile.h"
#define CSD_SOUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_SOUND_MANAGER, CsdSoundManagerPrivate))
#define SOUND_HANDLER_DBUS_PATH "/org/cinnamon/SettingsDaemon/Sound"
#define SOUND_HANDLER_DBUS_NAME "org.cinnamon.SettingsDaemon.Sound"
#define PLAY_ONCE_FLAG 8675309
static const gchar introspection_xml[] =
""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
"";
struct CsdSoundManagerPrivate
{
GSettings *settings;
guint name_id;
GList *monitors;
guint timeout;
GDBusNodeInfo *idata;
ca_context *ca;
GCancellable *bus_cancellable;
GDBusConnection *connection;
/* DBus users pass an ID with the sound string
* We can use this as a flag also to denote a sound
* that we only ever want played once (i.e. initial desktop
* welcome sound)
*/
GList *onetime_sounds;
};
static void csd_sound_manager_finalize (GObject *object);
G_DEFINE_TYPE (CsdSoundManager, csd_sound_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static gboolean
should_play (CsdSoundManager *manager, guint id, const gchar *str)
{
if (id != PLAY_ONCE_FLAG)
return TRUE;
GList *l;
gboolean already_ran = FALSE;
for (l = manager->priv->onetime_sounds; l; l = l->next) {
if (g_strcmp0 (l->data, str) == 0) {
already_ran = TRUE;
break;
}
}
if (!already_ran) {
manager->priv->onetime_sounds = g_list_prepend (manager->priv->onetime_sounds,
g_strdup (str));
}
return !already_ran;
}
static void
handle_sound_request (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
CsdSoundManager *manager = (CsdSoundManager *) user_data;
g_debug ("Calling method '%s' for sound", method_name);
if (g_strcmp0 (method_name, "PlaySound") == 0) {
const char *sound_name;
guint id;
g_variant_get (parameters, "(u&s)", &id, &sound_name);
if (should_play (manager, id, sound_name)) {
ca_context_play (manager->priv->ca,
id == PLAY_ONCE_FLAG ? 0 : id,
CA_PROP_EVENT_ID,
sound_name,
CA_PROP_CANBERRA_CACHE_CONTROL,
id == PLAY_ONCE_FLAG ? "never" : "volatile",
NULL);
}
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "PlaySoundWithChannel") == 0) {
const char *sound_name;
const char *channel_name;
guint id;
g_variant_get (parameters, "(u&s&s)", &id, &sound_name, &channel_name);
if (should_play (manager, id, sound_name)) {
ca_context_play (manager->priv->ca,
id == PLAY_ONCE_FLAG ? 0 : id,
CA_PROP_EVENT_ID, sound_name,
CA_PROP_MEDIA_ROLE, "test",
CA_PROP_CANBERRA_FORCE_CHANNEL, channel_name,
NULL);
}
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "PlaySoundFile") == 0) {
const char *sound_file;
guint id;
g_variant_get (parameters, "(u&s)", &id, &sound_file);
if (should_play (manager, id, sound_file)) {
ca_context_play (manager->priv->ca,
id == PLAY_ONCE_FLAG ? 0 : id,
CA_PROP_MEDIA_FILENAME,
sound_file,
CA_PROP_CANBERRA_CACHE_CONTROL,
id == PLAY_ONCE_FLAG ? "never" : "volatile",
NULL);
}
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "PlaySoundFileVolume") == 0) {
const char *sound_file;
guint id;
const char *volume;
g_variant_get (parameters, "(u&s&s)", &id, &sound_file, &volume);
if (should_play (manager, id, sound_file)) {
ca_context_play (manager->priv->ca,
id == PLAY_ONCE_FLAG ? 0 : id,
CA_PROP_MEDIA_FILENAME,
sound_file,
CA_PROP_CANBERRA_VOLUME,
volume,
CA_PROP_CANBERRA_CACHE_CONTROL,
id == PLAY_ONCE_FLAG ? "never" : "volatile",
NULL);
}
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "CancelSound") == 0) {
guint id;
g_variant_get (parameters, "(u)", &id);
ca_context_cancel (manager->priv->ca, id);
g_dbus_method_invocation_return_value (invocation, NULL);
}
}
static const GDBusInterfaceVTable interface_vtable =
{
handle_sound_request,
NULL, /* Get Property */
NULL, /* Set Property */
};
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.cinnamon.SettingsDaemon.Sound");
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 (CsdSoundManager *manager)
{
flush_cache ();
manager->priv->timeout = 0;
return FALSE;
}
static void
trigger_flush (CsdSoundManager *manager)
{
if (manager->priv->timeout) {
g_source_remove (manager->priv->timeout);
manager->priv->timeout = 0;
}
/* 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,
CsdSoundManager *manager)
{
trigger_flush (manager);
}
static void
register_config_callback (CsdSoundManager *manager)
{
manager->priv->settings = g_settings_new ("org.cinnamon.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,
CsdSoundManager *manager)
{
g_debug ("Theme dir changed");
trigger_flush (manager);
}
static gboolean
register_directory_callback (CsdSoundManager *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;
}
static void
on_bus_gotten (GObject *source_object,
GAsyncResult *res,
CsdSoundManager *manager)
{
GDBusConnection *connection;
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;
g_dbus_connection_register_object (connection,
SOUND_HANDLER_DBUS_PATH,
manager->priv->idata->interfaces[0],
&interface_vtable,
manager,
NULL,
NULL);
manager->priv->name_id = g_bus_own_name_on_connection (connection,
SOUND_HANDLER_DBUS_NAME,
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
NULL,
NULL,
NULL);
}
gboolean
csd_sound_manager_start (CsdSoundManager *manager,
GError **error)
{
char *p, **ps, **k;
const char *env, *dd;
g_debug ("Starting sound manager");
cinnamon_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 ...*/
if ((env = g_getenv ("XDG_DATA_HOME")) && *env == '/')
p = g_build_filename (env, "sounds", NULL);
else if (((env = g_getenv ("HOME")) && *env == '/') || (env = g_get_home_dir ()))
p = g_build_filename (env, ".local", "share", "sounds", NULL);
else
p = NULL;
if (p) {
register_directory_callback (manager, p, NULL);
g_free (p);
}
/* ... and globally. */
if (!(dd = g_getenv ("XDG_DATA_DIRS")) || *dd == 0)
dd = "/usr/local/share:/usr/share";
ps = g_strsplit (dd, ":", 0);
for (k = ps; *k; ++k)
register_directory_callback (manager, *k, NULL);
g_strfreev (ps);
manager->priv->onetime_sounds = NULL;
/* Sound events */
ca_context_create (&manager->priv->ca);
ca_context_set_driver (manager->priv->ca, "pulse");
ca_context_change_props (manager->priv->ca, 0,
CA_PROP_APPLICATION_ID, "org.Cinnamon.Sound",
NULL);
manager->priv->idata = g_dbus_node_info_new_for_xml (introspection_xml,
NULL);
manager->priv->bus_cancellable = g_cancellable_new ();
g_assert (manager->priv->idata != NULL);
g_bus_get (G_BUS_TYPE_SESSION,
manager->priv->bus_cancellable,
(GAsyncReadyCallback) on_bus_gotten,
manager);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
csd_sound_manager_stop (CsdSoundManager *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;
}
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->idata) {
g_dbus_node_info_unref (manager->priv->idata);
manager->priv->idata = NULL;
}
if (manager->priv->ca) {
ca_context_destroy (manager->priv->ca);
manager->priv->ca = NULL;
}
if (manager->priv->connection != NULL) {
g_object_unref (manager->priv->connection);
manager->priv->connection = NULL;
}
if (manager->priv->onetime_sounds != NULL) {
g_list_free_full (manager->priv->onetime_sounds, g_free);
manager->priv->onetime_sounds = NULL;
}
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 void
csd_sound_manager_dispose (GObject *object)
{
CsdSoundManager *manager;
manager = CSD_SOUND_MANAGER (object);
csd_sound_manager_stop (manager);
G_OBJECT_CLASS (csd_sound_manager_parent_class)->dispose (object);
}
static void
csd_sound_manager_class_init (CsdSoundManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = csd_sound_manager_dispose;
object_class->finalize = csd_sound_manager_finalize;
g_type_class_add_private (klass, sizeof (CsdSoundManagerPrivate));
}
static void
csd_sound_manager_init (CsdSoundManager *manager)
{
manager->priv = CSD_SOUND_MANAGER_GET_PRIVATE (manager);
}
static void
csd_sound_manager_finalize (GObject *object)
{
CsdSoundManager *sound_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_SOUND_MANAGER (object));
sound_manager = CSD_SOUND_MANAGER (object);
g_return_if_fail (sound_manager->priv);
if (sound_manager->priv->name_id != 0)
g_bus_unown_name (sound_manager->priv->name_id);
G_OBJECT_CLASS (csd_sound_manager_parent_class)->finalize (object);
}
CsdSoundManager *
csd_sound_manager_new (void)
{
if (manager_object) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (CSD_TYPE_SOUND_MANAGER, NULL);
g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object);
}
return CSD_SOUND_MANAGER (manager_object);
}
cinnamon-settings-daemon-5.2.0/plugins/sound/main.c 0000664 0001750 0001750 00000001005 14144454032 021241 0 ustar fabio fabio #define NEW csd_sound_manager_new
#define START csd_sound_manager_start
#define STOP csd_sound_manager_stop
#define MANAGER CsdSoundManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING TRUE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE TRUE
#include "csd-sound-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/sound/csd-sound-manager.h 0000664 0001750 0001750 00000004123 14144454032 023635 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_SOUND_MANAGER_H
#define __CSD_SOUND_MANAGER_H
#include
#include
G_BEGIN_DECLS
#define CSD_TYPE_SOUND_MANAGER (csd_sound_manager_get_type ())
#define CSD_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_SOUND_MANAGER, CsdSoundManager))
#define CSD_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CSD_TYPE_SOUND_MANAGER, CsdSoundManagerClass))
#define CSD_IS_SOUND_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_SOUND_MANAGER))
#define CSD_IS_SOUND_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_SOUND_MANAGER))
#define CSD_SOUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_SOUND_MANAGER, CsdSoundManagerClass))
typedef struct CsdSoundManagerPrivate CsdSoundManagerPrivate;
typedef struct
{
GObject parent;
CsdSoundManagerPrivate *priv;
} CsdSoundManager;
typedef struct
{
GObjectClass parent_class;
} CsdSoundManagerClass;
GType csd_sound_manager_get_type (void) G_GNUC_CONST;
CsdSoundManager *csd_sound_manager_new (void);
gboolean csd_sound_manager_start (CsdSoundManager *manager, GError **error);
void csd_sound_manager_stop (CsdSoundManager *manager);
G_END_DECLS
#endif /* __CSD_SOUND_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/sound/cinnamon-settings-daemon-sound.desktop.in 0000664 0001750 0001750 00000000332 14144454032 030202 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - sound
Exec=csd-sound
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/automount/ 0000775 0001750 0001750 00000000000 14144454032 021060 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/automount/cinnamon-settings-daemon-automount.desktop.in 0000664 0001750 0001750 00000000342 14144454032 032011 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - automount
Exec=csd-automount
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/automount/meson.build 0000664 0001750 0001750 00000002362 14144454032 023225 0 ustar fabio fabio plugin_name = 'automount'
automount_sources = [
'csd-automount-manager.c',
'csd-autorun.c',
'main.c',
]
automount_deps = [
common_dep,
csd_dep,
libnotify,
]
executable(
'csd-automount',
automount_sources,
include_directories: [include_dirs, common_inc],
dependencies: automount_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install_rpath: join_paths(prefix, apilibdir),
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-automount')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-automount')
endif
test_automount_dialog_sources = [
'test-automount-dialog.c',
'csd-autorun.c',
]
executable(
'test-automount-dialog',
test_automount_dialog_sources,
dependencies: automount_deps,
install: false,
)
configure_file(
input: 'cinnamon-settings-daemon-automount.desktop.in',
output: 'cinnamon-settings-daemon-automount.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
configure_file(
input: 'csd-automount.desktop.in',
output: 'csd-automount.desktop',
configuration: desktop_conf,
install_dir: desktopdir,
)
cinnamon-settings-daemon-5.2.0/plugins/automount/main.c 0000664 0001750 0001750 00000001032 14144454032 022144 0 ustar fabio fabio #define NEW csd_automount_manager_new
#define START csd_automount_manager_start
#define STOP csd_automount_manager_stop
#define MANAGER CsdAutomountManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING TRUE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE FALSE
#include "csd-automount-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/automount/csd-automount.desktop.in 0000664 0001750 0001750 00000001047 14144454032 025664 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Files
Name[am]=ፋይሎች
Name[bg]=Файлове
Name[ca]=Arxius
Name[cs]=Soubory
Name[da]=Filer
Name[de]=Dateien
Name[es]=Archivos
Name[eu]=Fitxategiak
Name[fr]=Fichiers
Name[hr]=Nemo
Name[hu]=Fájlok
Name[ko]=파일
Name[lt]=Failai
Name[nl]=Bestanden
Name[pl]=Pliki
Name[pt]=Ficheiros
Name[pt_BR]=Arquivos
Name[pt_PT]=Ficheiros
Name[ru]=Файлы
Name[sv]=Filer
Name[tr]=Dosyalar
Name[uk]=Файли
Name[zh_CN]=文件
Name[zh_HK]=檔案
Icon=folder
Exec=csd-automount
OnlyShowIn=X-Cinnamon;
NoDisplay=true
cinnamon-settings-daemon-5.2.0/plugins/automount/csd-automount-manager.h 0000664 0001750 0001750 00000004616 14144454032 025452 0 ustar fabio fabio /* -*- 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*
* Author: Tomas Bzatek
*/
#ifndef __CSD_AUTOMOUNT_MANAGER_H
#define __CSD_AUTOMOUNT_MANAGER_H
#include
G_BEGIN_DECLS
#define CSD_TYPE_AUTOMOUNT_MANAGER (csd_automount_manager_get_type ())
#define CSD_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_AUTOMOUNT_MANAGER, CsdAutomountManager))
#define CSD_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_AUTOMOUNT_MANAGER, CsdAutomountManagerClass))
#define CSD_IS_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_AUTOMOUNT_MANAGER))
#define CSD_IS_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_AUTOMOUNT_MANAGER))
#define CSD_AUTOMOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_AUTOMOUNT_MANAGER, CsdAutomountManagerClass))
typedef struct CsdAutomountManagerPrivate CsdAutomountManagerPrivate;
typedef struct
{
GObject parent;
CsdAutomountManagerPrivate *priv;
} CsdAutomountManager;
typedef struct
{
GObjectClass parent_class;
} CsdAutomountManagerClass;
GType csd_automount_manager_get_type (void);
CsdAutomountManager * csd_automount_manager_new (void);
gboolean csd_automount_manager_start (CsdAutomountManager *manager,
GError **error);
void csd_automount_manager_stop (CsdAutomountManager *manager);
G_END_DECLS
#endif /* __CSD_AUTOMOUNT_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/automount/csd-automount-manager.c 0000664 0001750 0001750 00000042703 14144454032 025444 0 ustar fabio fabio /* -*- 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*
* Author: Tomas Bzatek
*/
#include "config.h"
#include
#include
#include
#include
#include
#include "cinnamon-settings-profile.h"
#include "cinnamon-settings-session.h"
#include "csd-automount-manager.h"
#include "csd-autorun.h"
#define CSD_AUTOMOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_AUTOMOUNT_MANAGER, CsdAutomountManagerPrivate))
struct CsdAutomountManagerPrivate
{
GSettings *settings;
GSettings *settings_screensaver;
GVolumeMonitor *volume_monitor;
unsigned int automount_idle_id;
CinnamonSettingsSession *session;
gboolean session_is_active;
gboolean screensaver_active;
guint ss_watch_id;
GDBusProxy *ss_proxy;
GList *volume_queue;
};
G_DEFINE_TYPE (CsdAutomountManager, csd_automount_manager, G_TYPE_OBJECT)
static GtkDialog *
show_error_dialog (const char *primary_text,
const char *secondary_text)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s", "");
g_object_set (dialog,
"text", primary_text,
"secondary-text", secondary_text,
NULL);
gtk_widget_show (GTK_WIDGET (dialog));
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
return GTK_DIALOG (dialog);
}
static void
startup_volume_mount_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_volume_mount_finish (G_VOLUME (source_object), res, NULL);
}
static void
automount_all_volumes (CsdAutomountManager *manager)
{
GList *volumes, *l;
GMount *mount;
GVolume *volume;
if (g_settings_get_boolean (manager->priv->settings, "automount")) {
/* automount all mountable volumes at start-up */
volumes = g_volume_monitor_get_volumes (manager->priv->volume_monitor);
for (l = volumes; l != NULL; l = l->next) {
volume = l->data;
if (!g_volume_should_automount (volume) ||
!g_volume_can_mount (volume)) {
continue;
}
mount = g_volume_get_mount (volume);
if (mount != NULL) {
g_object_unref (mount);
continue;
}
/* pass NULL as GMountOperation to avoid user interaction */
g_volume_mount (volume, 0, NULL, NULL, startup_volume_mount_cb, NULL);
}
g_list_free_full (volumes, g_object_unref);
}
}
static gboolean
automount_all_volumes_idle_cb (gpointer data)
{
CsdAutomountManager *manager = CSD_AUTOMOUNT_MANAGER (data);
automount_all_volumes (manager);
manager->priv->automount_idle_id = 0;
return FALSE;
}
static void
volume_mount_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GMountOperation *mount_op = user_data;
GError *error;
char *primary;
char *name;
error = NULL;
csd_allow_autorun_for_volume_finish (G_VOLUME (source_object));
if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
if (error->code != G_IO_ERROR_FAILED_HANDLED && error->code != G_IO_ERROR_ALREADY_MOUNTED) {
name = g_volume_get_name (G_VOLUME (source_object));
primary = g_strdup_printf (_("Unable to mount %s"), name);
g_free (name);
show_error_dialog (primary,
error->message);
g_free (primary);
}
g_error_free (error);
}
g_object_unref (mount_op);
}
static void
do_mount_volume (GVolume *volume)
{
GMountOperation *mount_op;
mount_op = gtk_mount_operation_new (NULL);
g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
csd_allow_autorun_for_volume (volume);
g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op);
}
static void
check_volume_queue (CsdAutomountManager *manager)
{
GList *l;
GVolume *volume;
if (manager->priv->screensaver_active)
return;
l = manager->priv->volume_queue;
while (l != NULL) {
volume = l->data;
do_mount_volume (volume);
manager->priv->volume_queue =
g_list_remove (manager->priv->volume_queue, volume);
g_object_unref (volume);
l = l->next;
}
manager->priv->volume_queue = NULL;
}
static void
check_screen_lock_and_mount (CsdAutomountManager *manager,
GVolume *volume)
{
if (!manager->priv->session_is_active)
return;
if (manager->priv->screensaver_active) {
/* queue the volume, to mount it after the screensaver state changed */
g_debug ("Queuing volume %p", volume);
manager->priv->volume_queue = g_list_prepend (manager->priv->volume_queue,
g_object_ref (volume));
} else {
/* mount it immediately */
do_mount_volume (volume);
}
}
static void
volume_removed_callback (GVolumeMonitor *monitor,
GVolume *volume,
CsdAutomountManager *manager)
{
g_debug ("Volume %p removed, removing from the queue", volume);
/* clear it from the queue, if present */
manager->priv->volume_queue =
g_list_remove (manager->priv->volume_queue, volume);
}
static void
volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
CsdAutomountManager *manager)
{
if (g_settings_get_boolean (manager->priv->settings, "automount") &&
g_volume_should_automount (volume) &&
g_volume_can_mount (volume)) {
check_screen_lock_and_mount (manager, volume);
} else {
/* Allow csd_autorun() to run. When the mount is later
* added programmatically (i.e. for a blank CD),
* csd_autorun() will be called by mount_added_callback(). */
csd_allow_autorun_for_volume (volume);
csd_allow_autorun_for_volume_finish (volume);
}
}
static void
autorun_show_window (GMount *mount, gpointer user_data)
{
GFile *location;
char *uri;
GError *error;
char *primary;
char *name;
location = g_mount_get_root (mount);
uri = g_file_get_uri (location);
error = NULL;
/* use default folder handler */
g_debug("Opening %s", uri);
if (g_str_has_prefix (uri, "afc://")) {
// AFC (Apple File Conduit, which runs on iPhone and other Apple devices) doesn't always work well
// Observed on an iOS 4 device it would work the first time the device was connected, and then indefinitely hang after that
// Even a simple 'ls /run/user/$USER/gvfs' would hang forever
// It is unacceptable for CSD to hang, so we're treating AFC differently (asynchronously)
g_debug("AFC protocol detected, opening asynchronously!");
char * command = g_strdup_printf("timeout 10s xdg-open %s", uri);
g_debug("Executing command '%s'", command);
system(command);
g_debug("Command was executed, moving on..");
g_free(command);
}
else {
if (! gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error)) {
name = g_mount_get_name (mount);
primary = g_strdup_printf (_("Unable to open a folder for %s"), name);
g_free (name);
show_error_dialog (primary, error->message);
g_free (primary);
g_error_free (error);
}
}
g_free (uri);
g_object_unref (location);
}
static void
mount_added_callback (GVolumeMonitor *monitor,
GMount *mount,
CsdAutomountManager *manager)
{
/* don't autorun if the session is not active */
if (!manager->priv->session_is_active) {
return;
}
csd_autorun (mount, manager->priv->settings, autorun_show_window, manager);
}
static void
session_state_changed (CinnamonSettingsSession *session, GParamSpec *pspec, gpointer user_data)
{
CsdAutomountManager *manager = user_data;
CsdAutomountManagerPrivate *p = manager->priv;
if (cinnamon_settings_session_get_state (session) == CINNAMON_SETTINGS_SESSION_STATE_ACTIVE) {
p->session_is_active = TRUE;
}
else {
p->session_is_active = FALSE;
}
if (!p->session_is_active) {
if (p->volume_queue != NULL) {
g_list_free_full (p->volume_queue, g_object_unref);
p->volume_queue = NULL;
}
}
}
static void
do_initialize_session (CsdAutomountManager *manager)
{
manager->priv->session = cinnamon_settings_session_new ();
g_signal_connect (manager->priv->session, "notify::state",
G_CALLBACK (session_state_changed), manager);
session_state_changed (manager->priv->session, NULL, manager);
}
#define SCREENSAVER_NAME "org.cinnamon.ScreenSaver"
#define SCREENSAVER_PATH "/org/cinnamon/ScreenSaver"
#define SCREENSAVER_INTERFACE "org.cinnamon.ScreenSaver"
static void
screensaver_signal_callback (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
CsdAutomountManager *manager = user_data;
if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
g_variant_get (parameters, "(b)", &manager->priv->screensaver_active);
g_debug ("Screensaver active changed to %d", manager->priv->screensaver_active);
check_volume_queue (manager);
}
}
static void
screensaver_get_active_ready_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
CsdAutomountManager *manager = user_data;
GDBusProxy *proxy = manager->priv->ss_proxy;
GVariant *result;
GError *error = NULL;
result = g_dbus_proxy_call_finish (proxy,
res,
&error);
if (error != NULL) {
g_warning ("Can't call GetActive() on the ScreenSaver object: %s",
error->message);
g_error_free (error);
return;
}
g_variant_get (result, "(b)", &manager->priv->screensaver_active);
g_variant_unref (result);
g_debug ("Screensaver GetActive() returned %d", manager->priv->screensaver_active);
}
static void
screensaver_proxy_ready_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
CsdAutomountManager *manager = user_data;
GError *error = NULL;
GDBusProxy *ss_proxy;
ss_proxy = g_dbus_proxy_new_finish (res, &error);
if (error != NULL) {
g_warning ("Can't get proxy for the ScreenSaver object: %s",
error->message);
g_error_free (error);
return;
}
g_debug ("ScreenSaver proxy ready");
manager->priv->ss_proxy = ss_proxy;
g_signal_connect (ss_proxy, "g-signal",
G_CALLBACK (screensaver_signal_callback), manager);
g_dbus_proxy_call (ss_proxy,
"GetActive",
NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
screensaver_get_active_ready_cb,
manager);
}
static void
screensaver_appeared_callback (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
CsdAutomountManager *manager = user_data;
g_debug ("ScreenSaver name appeared");
manager->priv->screensaver_active = FALSE;
g_dbus_proxy_new (connection,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
name,
SCREENSAVER_PATH,
SCREENSAVER_INTERFACE,
NULL,
screensaver_proxy_ready_cb,
manager);
}
static void
screensaver_vanished_callback (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
CsdAutomountManager *manager = user_data;
g_debug ("ScreenSaver name vanished");
manager->priv->screensaver_active = FALSE;
if (manager->priv->ss_proxy != NULL) {
g_object_unref (manager->priv->ss_proxy);
manager->priv->ss_proxy = NULL;
}
/* in this case force a clear of the volume queue, without
* mounting them.
*/
if (manager->priv->volume_queue != NULL) {
g_list_free_full (manager->priv->volume_queue, g_object_unref);
manager->priv->volume_queue = NULL;
}
}
static void
do_initialize_screensaver (CsdAutomountManager *manager)
{
CsdAutomountManagerPrivate *p = manager->priv;
p->ss_watch_id =
g_bus_watch_name (G_BUS_TYPE_SESSION,
SCREENSAVER_NAME,
G_BUS_NAME_WATCHER_FLAGS_NONE,
screensaver_appeared_callback,
screensaver_vanished_callback,
manager,
NULL);
}
static void
setup_automounter (CsdAutomountManager *manager)
{
do_initialize_session (manager);
gchar *custom_saver = g_settings_get_string (manager->priv->settings_screensaver,
"custom-screensaver-command");
/* if we fail to get the gsettings entry, or if the user did not select
* a custom screen saver, default to cinnamon-screensaver */
if (NULL == custom_saver || g_strcmp0 (custom_saver, "") == 0)
do_initialize_screensaver (manager);
g_free (custom_saver);
manager->priv->volume_monitor = g_volume_monitor_get ();
g_signal_connect_object (manager->priv->volume_monitor, "mount-added",
G_CALLBACK (mount_added_callback), manager, 0);
g_signal_connect_object (manager->priv->volume_monitor, "volume-added",
G_CALLBACK (volume_added_callback), manager, 0);
g_signal_connect_object (manager->priv->volume_monitor, "volume-removed",
G_CALLBACK (volume_removed_callback), manager, 0);
manager->priv->automount_idle_id =
g_idle_add_full (G_PRIORITY_LOW,
automount_all_volumes_idle_cb,
manager, NULL);
}
gboolean
csd_automount_manager_start (CsdAutomountManager *manager,
GError **error)
{
g_debug ("Starting automounting manager");
cinnamon_settings_profile_start (NULL);
manager->priv->settings = g_settings_new ("org.cinnamon.desktop.media-handling");
manager->priv->settings_screensaver = g_settings_new ("org.cinnamon.desktop.screensaver");
setup_automounter (manager);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
csd_automount_manager_stop (CsdAutomountManager *manager)
{
CsdAutomountManagerPrivate *p = manager->priv;
g_debug ("Stopping automounting manager");
if (p->session != NULL) {
g_object_unref (p->session);
p->session = NULL;
}
if (p->volume_monitor != NULL) {
g_object_unref (p->volume_monitor);
p->volume_monitor = NULL;
}
if (p->settings != NULL) {
g_object_unref (p->settings);
p->settings = NULL;
}
if (p->settings_screensaver != NULL) {
g_object_unref (p->settings_screensaver);
p->settings_screensaver = NULL;
}
if (p->ss_proxy != NULL) {
g_object_unref (p->ss_proxy);
p->ss_proxy = NULL;
}
g_bus_unwatch_name (p->ss_watch_id);
if (p->volume_queue != NULL) {
g_list_free_full (p->volume_queue, g_object_unref);
p->volume_queue = NULL;
}
if (p->automount_idle_id != 0) {
g_source_remove (p->automount_idle_id);
p->automount_idle_id = 0;
}
}
static void
csd_automount_manager_class_init (CsdAutomountManagerClass *klass)
{
g_type_class_add_private (klass, sizeof (CsdAutomountManagerPrivate));
}
static void
csd_automount_manager_init (CsdAutomountManager *manager)
{
manager->priv = CSD_AUTOMOUNT_MANAGER_GET_PRIVATE (manager);
}
CsdAutomountManager *
csd_automount_manager_new (void)
{
return CSD_AUTOMOUNT_MANAGER (g_object_new (CSD_TYPE_AUTOMOUNT_MANAGER, NULL));
}
cinnamon-settings-daemon-5.2.0/plugins/automount/csd-autorun.c 0000664 0001750 0001750 00000071752 14144454032 023504 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* csd-automount.c: helpers for automounting hotplugged volumes
*
* Copyright (C) 2008, 2010 Red Hat, Inc.
*
* Nautilus 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, Suite 500, Boston, MA 02110-1335 USA
*
* Authors: David Zeuthen
* Cosimo Cecchi
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "csd-autorun.h"
static gboolean should_autorun_mount (GMount *mount);
#define CUSTOM_ITEM_ASK "csd-item-ask"
#define CUSTOM_ITEM_DO_NOTHING "csd-item-do-nothing"
#define CUSTOM_ITEM_OPEN_FOLDER "csd-item-open-folder"
typedef struct
{
GtkWidget *dialog;
GMount *mount;
gboolean should_eject;
gboolean selected_ignore;
gboolean selected_open_folder;
GAppInfo *selected_app;
gboolean remember;
char *x_content_type;
CsdAutorunOpenWindow open_window_func;
gpointer user_data;
} AutorunDialogData;
static int
csd_autorun_g_strv_find (char **strv, const char *find_me)
{
guint index;
g_return_val_if_fail (find_me != NULL, -1);
for (index = 0; strv[index] != NULL; ++index) {
if (strcmp (strv[index], find_me) == 0) {
return index;
}
}
return -1;
}
#define ICON_SIZE_STANDARD 48
static gint
get_icon_size_for_stock_size (GtkIconSize size)
{
gint w, h;
if (gtk_icon_size_lookup (size, &w, &h)) {
return MAX (w, h);
}
return ICON_SIZE_STANDARD;
}
static GdkPixbuf *
render_icon (GIcon *icon, gint icon_size)
{
GdkPixbuf *pixbuf;
GtkIconInfo *info;
pixbuf = NULL;
if (G_IS_THEMED_ICON (icon)) {
gchar const * const *names;
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
icon,
icon_size,
0);
if (info) {
pixbuf = gtk_icon_info_load_icon (info, NULL);
g_object_unref (info);
}
if (pixbuf == NULL) {
names = g_themed_icon_get_names (G_THEMED_ICON (icon));
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
*names,
icon_size,
0, NULL);
}
}
else
if (G_IS_FILE_ICON (icon)) {
GFile *icon_file;
gchar *path;
icon_file = g_file_icon_get_file (G_FILE_ICON (icon));
path = g_file_get_path (icon_file);
pixbuf = gdk_pixbuf_new_from_file_at_size (path,
icon_size, icon_size,
NULL);
g_free (path);
g_object_unref (G_OBJECT (icon_file));
}
return pixbuf;
}
static void
csd_autorun_get_preferences (const char *x_content_type,
gboolean *pref_start_app,
gboolean *pref_ignore,
gboolean *pref_open_folder)
{
GSettings *settings;
char **x_content_start_app;
char **x_content_ignore;
char **x_content_open_folder;
g_return_if_fail (pref_start_app != NULL);
g_return_if_fail (pref_ignore != NULL);
g_return_if_fail (pref_open_folder != NULL);
settings = g_settings_new ("org.cinnamon.desktop.media-handling");
*pref_start_app = FALSE;
*pref_ignore = FALSE;
*pref_open_folder = FALSE;
x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app");
x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore");
x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder");
if (x_content_start_app != NULL) {
*pref_start_app = csd_autorun_g_strv_find (x_content_start_app, x_content_type) != -1;
}
if (x_content_ignore != NULL) {
*pref_ignore = csd_autorun_g_strv_find (x_content_ignore, x_content_type) != -1;
}
if (x_content_open_folder != NULL) {
*pref_open_folder = csd_autorun_g_strv_find (x_content_open_folder, x_content_type) != -1;
}
g_strfreev (x_content_ignore);
g_strfreev (x_content_start_app);
g_strfreev (x_content_open_folder);
g_object_unref (settings);
}
static char **
remove_elem_from_str_array (char **v,
const char *s)
{
GPtrArray *array;
guint idx;
array = g_ptr_array_new ();
for (idx = 0; v[idx] != NULL; idx++) {
if (g_strcmp0 (v[idx], s) == 0) {
continue;
}
g_ptr_array_add (array, v[idx]);
}
g_ptr_array_add (array, NULL);
g_free (v);
return (char **) g_ptr_array_free (array, FALSE);
}
static char **
add_elem_to_str_array (char **v,
const char *s)
{
GPtrArray *array;
guint idx;
array = g_ptr_array_new ();
for (idx = 0; v[idx] != NULL; idx++) {
g_ptr_array_add (array, v[idx]);
}
g_ptr_array_add (array, g_strdup (s));
g_ptr_array_add (array, NULL);
g_free (v);
return (char **) g_ptr_array_free (array, FALSE);
}
static void
csd_autorun_set_preferences (const char *x_content_type,
gboolean pref_start_app,
gboolean pref_ignore,
gboolean pref_open_folder)
{
GSettings *settings;
char **x_content_start_app;
char **x_content_ignore;
char **x_content_open_folder;
g_assert (x_content_type != NULL);
settings = g_settings_new ("org.cinnamon.desktop.media-handling");
x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app");
x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore");
x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder");
x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type);
if (pref_start_app) {
x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type);
}
g_settings_set_strv (settings, "autorun-x-content-start-app", (const gchar * const*) x_content_start_app);
x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type);
if (pref_ignore) {
x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type);
}
g_settings_set_strv (settings, "autorun-x-content-ignore", (const gchar * const*) x_content_ignore);
x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type);
if (pref_open_folder) {
x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
}
g_settings_set_strv (settings, "autorun-x-content-open-folder", (const gchar * const*) x_content_open_folder);
g_strfreev (x_content_open_folder);
g_strfreev (x_content_ignore);
g_strfreev (x_content_start_app);
g_object_unref (settings);
}
static void
custom_item_activated_cb (GtkAppChooserButton *button,
const gchar *item,
gpointer user_data)
{
gchar *content_type;
AutorunDialogData *data = user_data;
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button));
if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) {
csd_autorun_set_preferences (content_type,
FALSE, FALSE, FALSE);
data->selected_open_folder = FALSE;
data->selected_ignore = FALSE;
} else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) {
csd_autorun_set_preferences (content_type,
FALSE, FALSE, TRUE);
data->selected_open_folder = TRUE;
data->selected_ignore = FALSE;
} else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) {
csd_autorun_set_preferences (content_type,
FALSE, TRUE, FALSE);
data->selected_open_folder = FALSE;
data->selected_ignore = TRUE;
}
g_free (content_type);
}
static void
combo_box_changed_cb (GtkComboBox *combo_box,
gpointer user_data)
{
GAppInfo *info;
AutorunDialogData *data = user_data;
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
if (info == NULL)
return;
if (data->selected_app != NULL) {
g_object_unref (data->selected_app);
data->selected_app = NULL;
}
data->selected_app = info;
}
static void
prepare_combo_box (GtkWidget *combo_box,
AutorunDialogData *data)
{
GtkAppChooserButton *app_chooser = GTK_APP_CHOOSER_BUTTON (combo_box);
GIcon *icon;
gboolean pref_ask;
gboolean pref_start_app;
gboolean pref_ignore;
gboolean pref_open_folder;
GAppInfo *info;
gchar *content_type;
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (app_chooser));
gtk_app_chooser_button_set_show_default_item (GTK_APP_CHOOSER_BUTTON (combo_box), TRUE);
/* fetch preferences for this content type */
csd_autorun_get_preferences (content_type,
&pref_start_app, &pref_ignore, &pref_open_folder);
pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
/* append the separator only if we have >= 1 apps in the chooser */
if (info != NULL) {
gtk_app_chooser_button_append_separator (app_chooser);
g_object_unref (info);
}
icon = g_themed_icon_new ("dialog-question");
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_ASK,
_("Ask what to do"),
icon);
g_object_unref (icon);
icon = g_themed_icon_new ("window-close");
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING,
_("Do Nothing"),
icon);
g_object_unref (icon);
icon = g_themed_icon_new ("folder-open");
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER,
_("Open Folder"),
icon);
g_object_unref (icon);
gtk_app_chooser_button_set_show_dialog_item (app_chooser, TRUE);
if (pref_ask) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_ASK);
} else if (pref_ignore) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING);
} else if (pref_open_folder) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER);
}
g_signal_connect (app_chooser, "changed",
G_CALLBACK (combo_box_changed_cb), data);
g_signal_connect (app_chooser, "custom-item-activated",
G_CALLBACK (custom_item_activated_cb), data);
g_free (content_type);
}
static gboolean
is_shift_pressed (void)
{
gboolean ret;
XkbStateRec state;
Bool status;
ret = FALSE;
gdk_x11_display_error_trap_push (gdk_display_get_default ());
status = XkbGetState (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
XkbUseCoreKbd, &state);
gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default ());
if (status == Success) {
ret = state.mods & ShiftMask;
}
return ret;
}
enum {
AUTORUN_DIALOG_RESPONSE_EJECT = 0
};
static void
csd_autorun_launch_for_mount (GMount *mount, GAppInfo *app_info)
{
GFile *root;
GdkAppLaunchContext *launch_context;
GError *error;
gboolean result;
GList *list;
gchar *uri_scheme;
gchar *uri;
root = g_mount_get_root (mount);
list = g_list_append (NULL, root);
launch_context = gdk_app_launch_context_new ();
error = NULL;
result = g_app_info_launch (app_info,
list,
G_APP_LAUNCH_CONTEXT (launch_context),
&error);
g_object_unref (launch_context);
if (!result) {
if (error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_NOT_SUPPORTED) {
uri = g_file_get_uri (root);
uri_scheme = g_uri_parse_scheme (uri);
/* FIXME: Present user a dialog to choose another app when the last one failed to handle a file */
g_warning ("Cannot open location: %s\n", error->message);
g_free (uri_scheme);
g_free (uri);
} else {
g_warning ("Cannot open app: %s\n", error->message);
}
g_error_free (error);
}
g_list_free (list);
g_object_unref (root);
}
static void autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data);
static void
autorun_dialog_destroy (AutorunDialogData *data)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount),
G_CALLBACK (autorun_dialog_mount_unmounted),
data);
gtk_widget_destroy (GTK_WIDGET (data->dialog));
if (data->selected_app != NULL) {
g_object_unref (data->selected_app);
}
g_object_unref (data->mount);
g_free (data->x_content_type);
g_free (data);
}
static void
autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data)
{
/* remove the dialog if the media is unmounted */
autorun_dialog_destroy (data);
}
static void
unmount_mount_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error;
char *primary;
gboolean unmounted;
gboolean should_eject;
GtkWidget *dialog;
should_eject = user_data != NULL;
error = NULL;
if (should_eject) {
unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object),
res, &error);
} else {
unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object),
res, &error);
}
if (! unmounted) {
if (error->code != G_IO_ERROR_FAILED_HANDLED) {
if (should_eject) {
primary = g_strdup_printf (_("Unable to eject %p"), source_object);
} else {
primary = g_strdup_printf (_("Unable to unmount %p"), source_object);
}
dialog = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s",
primary);
gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
"%s",
error->message);
gtk_widget_show (GTK_WIDGET (dialog));
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
g_free (primary);
}
}
if (error != NULL) {
g_error_free (error);
}
}
static void
do_unmount (GMount *mount, gboolean should_eject, GtkWindow *window)
{
GMountOperation *mount_op;
mount_op = gtk_mount_operation_new (window);
if (should_eject) {
g_mount_eject_with_operation (mount,
0,
mount_op,
NULL,
unmount_mount_callback,
(gpointer) 1);
} else {
g_mount_unmount_with_operation (mount,
0,
mount_op,
NULL,
unmount_mount_callback,
(gpointer) 0);
}
g_object_unref (mount_op);
}
static void
autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *data)
{
switch (response) {
case AUTORUN_DIALOG_RESPONSE_EJECT:
do_unmount (data->mount, data->should_eject, GTK_WINDOW (dialog));
break;
case GTK_RESPONSE_NONE:
/* window was closed */
break;
case GTK_RESPONSE_CANCEL:
break;
case GTK_RESPONSE_OK:
/* do the selected action */
if (data->remember) {
/* make sure we don't ask again */
csd_autorun_set_preferences (data->x_content_type, TRUE, data->selected_ignore, data->selected_open_folder);
if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) {
g_app_info_set_as_default_for_type (data->selected_app,
data->x_content_type,
NULL);
}
} else {
/* make sure we do ask again */
csd_autorun_set_preferences (data->x_content_type, FALSE, FALSE, FALSE);
}
if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) {
csd_autorun_launch_for_mount (data->mount, data->selected_app);
} else if (!data->selected_ignore && data->selected_open_folder) {
if (data->open_window_func != NULL)
data->open_window_func (data->mount, data->user_data);
}
break;
}
autorun_dialog_destroy (data);
}
static void
autorun_always_toggled (GtkToggleButton *togglebutton, AutorunDialogData *data)
{
data->remember = gtk_toggle_button_get_active (togglebutton);
}
static gboolean
combo_box_enter_ok (GtkWidget *togglebutton, GdkEventKey *event, GtkDialog *dialog)
{
if (event->keyval == GDK_KEY_KP_Enter || event->keyval == GDK_KEY_Return) {
gtk_dialog_response (dialog, GTK_RESPONSE_OK);
return TRUE;
}
return FALSE;
}
/* returns TRUE if a folder window should be opened */
static gboolean
do_autorun_for_content_type (GMount *mount,
const char *x_content_type,
CsdAutorunOpenWindow open_window_func,
gpointer user_data)
{
AutorunDialogData *data;
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *combo_box;
GtkWidget *always_check_button;
GtkWidget *eject_button;
GtkWidget *image;
char *markup;
char *content_description;
char *mount_name;
GIcon *icon;
GdkPixbuf *pixbuf;
int icon_size;
gboolean user_forced_dialog;
gboolean pref_ask;
gboolean pref_start_app;
gboolean pref_ignore;
gboolean pref_open_folder;
char *media_greeting;
gboolean ret;
ret = FALSE;
mount_name = NULL;
if (g_content_type_is_a (x_content_type, "x-content/win32-software")) {
/* don't pop up the dialog anyway if the content type says
* windows software.
*/
goto out;
}
user_forced_dialog = is_shift_pressed ();
csd_autorun_get_preferences (x_content_type, &pref_start_app, &pref_ignore, &pref_open_folder);
pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
if (user_forced_dialog) {
goto show_dialog;
}
if (!pref_ask && !pref_ignore && !pref_open_folder) {
GAppInfo *app_info;
app_info = g_app_info_get_default_for_type (x_content_type, FALSE);
if (app_info != NULL) {
csd_autorun_launch_for_mount (mount, app_info);
}
goto out;
}
if (pref_open_folder) {
ret = TRUE;
goto out;
}
if (pref_ignore) {
goto out;
}
show_dialog:
mount_name = g_mount_get_name (mount);
dialog = gtk_dialog_new ();
gtk_window_set_default_size (GTK_WINDOW (dialog), 450, -1);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
icon = g_mount_get_icon (mount);
icon_size = get_icon_size_for_stock_size (GTK_ICON_SIZE_DIALOG);
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
pixbuf = render_icon (icon, icon_size);
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_START);
gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0);
/* also use the icon on the dialog */
gtk_window_set_title (GTK_WINDOW (dialog), mount_name);
gtk_window_set_icon (GTK_WINDOW (dialog), pixbuf);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
g_object_unref (icon);
if (pixbuf) {
g_object_unref (pixbuf);
}
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
label = gtk_label_new (NULL);
/* Customize greeting for well-known x-content types */
if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
media_greeting = _("You have just inserted an Audio CD.");
} else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
media_greeting = _("You have just inserted an Audio DVD.");
} else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
media_greeting = _("You have just inserted a Video DVD.");
} else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
media_greeting = _("You have just inserted a Video CD.");
} else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
media_greeting = _("You have just inserted a Super Video CD.");
} else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
media_greeting = _("You have just inserted a blank CD.");
} else if (strcmp (x_content_type, "x-content/blank-dvd") == 0) {
media_greeting = _("You have just inserted a blank DVD.");
} else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
media_greeting = _("You have just inserted a blank Blu-Ray disc.");
} else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
media_greeting = _("You have just inserted a blank HD DVD.");
} else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
media_greeting = _("You have just inserted a Photo CD.");
} else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
media_greeting = _("You have just inserted a Picture CD.");
} else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
media_greeting = _("You have just inserted a medium with digital photos.");
} else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
media_greeting = _("You have just inserted a digital audio player.");
} else if (g_content_type_is_a (x_content_type, "x-content/software")) {
media_greeting = _("You have just inserted a medium with software intended to be automatically started.");
} else {
/* fallback to generic greeting */
media_greeting = _("You have just inserted a medium.");
}
markup = g_strdup_printf ("%s %s", media_greeting, _("Choose what application to launch."));
gtk_label_set_markup (GTK_LABEL (label), markup);
g_free (markup);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_label_set_yalign (GTK_LABEL (label), 0.5);
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
label = gtk_label_new (NULL);
content_description = g_content_type_get_description (x_content_type);
markup = g_strdup_printf (_("Select how to open \"%s\" and whether to perform this action in the future for other media of type \"%s\"."), mount_name, content_description);
g_free (content_description);
gtk_label_set_markup (GTK_LABEL (label), markup);
g_free (markup);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_label_set_yalign (GTK_LABEL (label), 0.5);
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
data = g_new0 (AutorunDialogData, 1);
data->dialog = dialog;
data->mount = g_object_ref (mount);
data->remember = !pref_ask;
data->selected_ignore = pref_ignore;
data->x_content_type = g_strdup (x_content_type);
data->selected_app = g_app_info_get_default_for_type (x_content_type, FALSE);
data->open_window_func = open_window_func;
data->user_data = user_data;
combo_box = gtk_app_chooser_button_new (x_content_type);
prepare_combo_box (combo_box, data);
g_signal_connect (G_OBJECT (combo_box),
"key-press-event",
G_CALLBACK (combo_box_enter_ok),
dialog);
gtk_box_pack_start (GTK_BOX (vbox), combo_box, TRUE, TRUE, 0);
always_check_button = gtk_check_button_new_with_mnemonic (_("_Always perform this action"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (always_check_button), data->remember);
g_signal_connect (G_OBJECT (always_check_button),
"toggled",
G_CALLBACK (autorun_always_toggled),
data);
gtk_box_pack_start (GTK_BOX (vbox), always_check_button, TRUE, TRUE, 0);
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Ok"), GTK_RESPONSE_OK,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
if (g_mount_can_eject (mount)) {
eject_button = gtk_button_new_with_mnemonic (_("_Eject"));
data->should_eject = TRUE;
} else {
eject_button = gtk_button_new_with_mnemonic (_("_Unmount"));
data->should_eject = FALSE;
}
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), eject_button, AUTORUN_DIALOG_RESPONSE_EJECT);
gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), eject_button, TRUE);
/* show the dialog */
gtk_widget_show_all (dialog);
g_signal_connect (G_OBJECT (dialog),
"response",
G_CALLBACK (autorun_dialog_response),
data);
g_signal_connect (G_OBJECT (data->mount),
"unmounted",
G_CALLBACK (autorun_dialog_mount_unmounted),
data);
out:
g_free (mount_name);
return ret;
}
typedef struct {
GMount *mount;
CsdAutorunOpenWindow open_window_func;
gpointer user_data;
GSettings *settings;
} AutorunData;
static void
autorun_guessed_content_type_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error;
char **guessed_content_type;
AutorunData *data = user_data;
gboolean open_folder;
open_folder = FALSE;
error = NULL;
guessed_content_type = g_mount_guess_content_type_finish (G_MOUNT (source_object), res, &error);
g_object_set_data_full (source_object,
"csd-content-type-cache",
g_strdupv (guessed_content_type),
(GDestroyNotify)g_strfreev);
if (error != NULL) {
g_warning ("Unable to guess content type for mount: %s", error->message);
g_error_free (error);
} else {
if (guessed_content_type != NULL && g_strv_length (guessed_content_type) > 0) {
int n;
for (n = 0; guessed_content_type[n] != NULL; n++) {
if (do_autorun_for_content_type (data->mount, guessed_content_type[n],
data->open_window_func, data->user_data)) {
open_folder = TRUE;
}
}
g_strfreev (guessed_content_type);
} else {
if (g_settings_get_boolean (data->settings, "automount-open")) {
open_folder = TRUE;
}
}
}
/* only open the folder once.. */
if (open_folder && data->open_window_func != NULL) {
data->open_window_func (data->mount, data->user_data);
}
g_object_unref (data->mount);
g_object_unref (data->settings);
g_free (data);
}
void
csd_autorun (GMount *mount,
GSettings *settings,
CsdAutorunOpenWindow open_window_func,
gpointer user_data)
{
AutorunData *data;
if (!should_autorun_mount (mount) ||
g_settings_get_boolean (settings, "autorun-never")) {
return;
}
data = g_new0 (AutorunData, 1);
data->mount = g_object_ref (mount);
data->open_window_func = open_window_func;
data->user_data = user_data;
data->settings = g_object_ref (settings);
g_mount_guess_content_type (mount,
FALSE,
NULL,
autorun_guessed_content_type_callback,
data);
}
static gboolean
remove_allow_volume (gpointer data)
{
GVolume *volume = data;
g_object_set_data (G_OBJECT (volume), "csd-allow-autorun", NULL);
return FALSE;
}
void
csd_allow_autorun_for_volume (GVolume *volume)
{
g_object_set_data (G_OBJECT (volume), "csd-allow-autorun", GINT_TO_POINTER (1));
}
#define INHIBIT_AUTORUN_SECONDS 10
void
csd_allow_autorun_for_volume_finish (GVolume *volume)
{
if (g_object_get_data (G_OBJECT (volume), "csd-allow-autorun") != NULL) {
g_timeout_add_seconds_full (0,
INHIBIT_AUTORUN_SECONDS,
remove_allow_volume,
g_object_ref (volume),
g_object_unref);
}
}
static gboolean
should_skip_native_mount_root (GFile *root)
{
char *path;
gboolean should_skip;
/* skip any mounts in hidden directory hierarchies */
path = g_file_get_path (root);
should_skip = strstr (path, "/.") != NULL;
g_free (path);
return should_skip;
}
static gboolean
should_autorun_mount (GMount *mount)
{
GFile *root;
GVolume *enclosing_volume;
gboolean ignore_autorun;
ignore_autorun = TRUE;
enclosing_volume = g_mount_get_volume (mount);
if (enclosing_volume != NULL) {
if (g_object_get_data (G_OBJECT (enclosing_volume), "csd-allow-autorun") != NULL) {
ignore_autorun = FALSE;
g_object_set_data (G_OBJECT (enclosing_volume), "csd-allow-autorun", NULL);
}
}
if (ignore_autorun) {
if (enclosing_volume != NULL) {
g_object_unref (enclosing_volume);
}
return FALSE;
}
root = g_mount_get_root (mount);
/* only do autorun on local files or files where g_volume_should_automount() returns TRUE */
ignore_autorun = TRUE;
if ((g_file_is_native (root) && !should_skip_native_mount_root (root)) ||
(enclosing_volume != NULL && g_volume_should_automount (enclosing_volume))) {
ignore_autorun = FALSE;
}
if (enclosing_volume != NULL) {
g_object_unref (enclosing_volume);
}
g_object_unref (root);
return !ignore_autorun;
}
void
csd_autorun_for_content_type (GMount *mount,
const gchar *content_type,
CsdAutorunOpenWindow callback,
gpointer user_data)
{
do_autorun_for_content_type (mount, content_type, callback, user_data);
}
cinnamon-settings-daemon-5.2.0/plugins/automount/test-automount-dialog.c 0000664 0001750 0001750 00000004154 14144454032 025475 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
* save-session.c - Small program to talk to session manager.
Copyright (C) 1998 Tom Tromey
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, 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 - Suite 500, Boston, MA
02110-1335, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include "csd-autorun.h"
static void
autorun_show_window (GMount *mount, gpointer user_data)
{
gtk_main_quit ();
}
int
main (int argc, char *argv[])
{
GVolumeMonitor *monitor;
GError *error;
GList *mounts;
error = NULL;
if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
g_warning ("Unable to start: %s", error->message);
g_error_free (error);
exit (1);
}
if (argc != 2)
{
g_print ("Need one argument as content type\n");
exit (1);
}
monitor = g_volume_monitor_get ();
mounts = g_volume_monitor_get_mounts (monitor);
if (mounts)
{
GMount *mount = G_MOUNT (mounts->data);
csd_autorun_for_content_type (mount,
argv[1],
(CsdAutorunOpenWindow) autorun_show_window,
NULL);
}
gtk_main ();
gtk_main_quit ();
return 0;
}
cinnamon-settings-daemon-5.2.0/plugins/automount/csd-autorun.h 0000664 0001750 0001750 00000003605 14144454032 023501 0 ustar fabio fabio /*
* csd-automount.h:helpers for automounting hotplugged volumes
*
* Copyright (C) 2008 Red Hat, Inc.
*
* Nautilus 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, Suite 500, Boston, MA 02110-1335 USA
*
* Authors: David Zeuthen
* Cosimo Cecchi
*/
/* TODO:
*
* - unmount all the media we've automounted on shutdown
* - finish x-content / * types
* - finalize the semi-spec
* - add probing/sniffing code
* - implement missing features
* - "Open Folder when mounted"
* - Autorun spec (e.g. $ROOT/.autostart)
*
*/
#ifndef __CSD_AUTORUN_H__
#define __CSD_AUTORUN_H__
#include
#include
typedef void (*CsdAutorunOpenWindow) (GMount *mount,
gpointer user_data);
void csd_autorun (GMount *mount,
GSettings *settings,
CsdAutorunOpenWindow open_window_func,
gpointer user_data);
void csd_autorun_for_content_type (GMount *mount,
const gchar *content_type,
CsdAutorunOpenWindow callback,
gpointer user_data);
void csd_allow_autorun_for_volume (GVolume *volume);
void csd_allow_autorun_for_volume_finish (GVolume *volume);
#endif /* __CSD_AUTORUN_H__ */
cinnamon-settings-daemon-5.2.0/plugins/orientation/ 0000775 0001750 0001750 00000000000 14144454032 021360 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/orientation/meson.build 0000664 0001750 0001750 00000001534 14144454032 023525 0 ustar fabio fabio plugin_name = 'orientation'
orientation_sources = [
'csd-orientation-manager.c',
'main.c',
]
orientation_deps = [
cinnamon_desktop,
common_dep,
csd_dep,
libnotify,
]
executable(
'csd-orientation',
orientation_sources,
include_directories: [include_dirs, common_inc],
dependencies: orientation_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-orientation')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-orientation')
endif
configure_file(
input: 'cinnamon-settings-daemon-orientation.desktop.in',
output: 'cinnamon-settings-daemon-orientation.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
cinnamon-settings-daemon-5.2.0/plugins/orientation/main.c 0000664 0001750 0001750 00000001043 14144454032 022446 0 ustar fabio fabio #define NEW csd_orientation_manager_new
#define START csd_orientation_manager_start
#define STOP csd_orientation_manager_stop
#define MANAGER CsdOrientationManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING TRUE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE TRUE
#include "csd-orientation-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/orientation/csd-orientation-manager.c 0000664 0001750 0001750 00000041760 14144454032 026246 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
* Copyright (C) 2010,2011 Red Hat, Inc.
*
* Author: 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include
#include "csd-input-helper.h"
#include "cinnamon-settings-profile.h"
#include "csd-orientation-manager.h"
typedef enum {
ORIENTATION_UNDEFINED,
ORIENTATION_NORMAL,
ORIENTATION_BOTTOM_UP,
ORIENTATION_LEFT_UP,
ORIENTATION_RIGHT_UP
} OrientationUp;
#define CSD_ORIENTATION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_ORIENTATION_MANAGER, CsdOrientationManagerPrivate))
struct CsdOrientationManagerPrivate
{
/* Accelerometer */
guint watch_id;
GDBusProxy *iio_proxy;
gboolean has_accel;
OrientationUp prev_orientation;
/* DBus */
GDBusProxy *xrandr_proxy;
GCancellable *cancellable;
/* Notifications */
GSettings *settings;
gboolean orientation_lock;
};
#define CONF_SCHEMA "org.cinnamon.settings-daemon.peripherals.touchscreen"
#define ORIENTATION_LOCK_KEY "orientation-lock"
static void csd_orientation_manager_finalize (GObject *object);
G_DEFINE_TYPE (CsdOrientationManager, csd_orientation_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
#define MPU_THRESHOLD 12000
#define MPU_POLL_INTERVAL 1
static gboolean is_mpu6050 = FALSE;
static char *mpu6050_accel_x = NULL;
static char *mpu6050_accel_y = NULL;
static gboolean mpu_timer(CsdOrientationManager *manager);
static void
csd_orientation_manager_class_init (CsdOrientationManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = csd_orientation_manager_finalize;
g_type_class_add_private (klass, sizeof (CsdOrientationManagerPrivate));
}
static void
csd_orientation_manager_init (CsdOrientationManager *manager)
{
manager->priv = CSD_ORIENTATION_MANAGER_GET_PRIVATE (manager);
manager->priv->prev_orientation = ORIENTATION_UNDEFINED;
}
static GnomeRRRotation
orientation_to_rotation (OrientationUp orientation)
{
switch (orientation) {
case ORIENTATION_NORMAL:
return GNOME_RR_ROTATION_0;
case ORIENTATION_BOTTOM_UP:
return GNOME_RR_ROTATION_180;
case ORIENTATION_LEFT_UP:
return GNOME_RR_ROTATION_90;
case ORIENTATION_RIGHT_UP:
return GNOME_RR_ROTATION_270;
default:
g_assert_not_reached ();
}
}
static OrientationUp
orientation_from_string (const char *orientation)
{
if (g_strcmp0 (orientation, "normal") == 0)
return ORIENTATION_NORMAL;
if (g_strcmp0 (orientation, "bottom-up") == 0)
return ORIENTATION_BOTTOM_UP;
if (g_strcmp0 (orientation, "left-up") == 0)
return ORIENTATION_LEFT_UP;
if (g_strcmp0 (orientation, "right-up") == 0)
return ORIENTATION_RIGHT_UP;
return ORIENTATION_UNDEFINED;
}
static const char *
orientation_to_string (OrientationUp o)
{
switch (o) {
case ORIENTATION_UNDEFINED:
return "undefined";
case ORIENTATION_NORMAL:
return "normal";
case ORIENTATION_BOTTOM_UP:
return "bottom-up";
case ORIENTATION_LEFT_UP:
return "left-up";
case ORIENTATION_RIGHT_UP:
return "right-up";
default:
g_assert_not_reached ();
}
}
static OrientationUp
get_orientation_from_device (CsdOrientationManager *manager)
{
GVariant *v;
OrientationUp o;
v = g_dbus_proxy_get_cached_property (manager->priv->iio_proxy, "AccelerometerOrientation");
if (v == NULL) {
g_debug ("Couldn't find orientation for accelerometer");
return ORIENTATION_UNDEFINED;
}
g_debug ("Found orientation '%s' for accelerometer", g_variant_get_string (v, NULL));
o = orientation_from_string (g_variant_get_string (v, NULL));
g_variant_unref (v);
return o;
}
static void
on_xrandr_action_call_finished (GObject *source_object,
GAsyncResult *res,
CsdOrientationManager *manager)
{
GError *error = NULL;
GVariant *variant;
variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
g_clear_object (&manager->priv->cancellable);
if (variant == NULL) {
g_warning ("Unable to call 'RotateTo': %s", error->message);
g_error_free (error);
} else {
g_variant_unref (variant);
}
}
static void
do_xrandr_action (CsdOrientationManager *manager,
GnomeRRRotation rotation)
{
CsdOrientationManagerPrivate *priv = manager->priv;
GTimeVal tv;
gint64 timestamp;
if (priv->xrandr_proxy == NULL) {
g_warning ("No existing D-Bus connection trying to handle XRANDR keys");
return;
}
if (priv->cancellable != NULL) {
g_debug ("xrandr action already in flight");
return;
}
g_get_current_time (&tv);
timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;
priv->cancellable = g_cancellable_new ();
g_dbus_proxy_call (priv->xrandr_proxy,
"RotateTo",
g_variant_new ("(ix)", rotation, timestamp),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->cancellable,
(GAsyncReadyCallback) on_xrandr_action_call_finished,
manager);
}
static void
do_rotation (CsdOrientationManager *manager)
{
GnomeRRRotation rotation;
if (manager->priv->orientation_lock) {
g_debug ("Orientation changed, but we are locked");
return;
}
if (manager->priv->prev_orientation == ORIENTATION_UNDEFINED) {
g_debug ("Not trying to rotate, orientation is undefined");
return;
}
rotation = orientation_to_rotation (manager->priv->prev_orientation);
do_xrandr_action (manager, rotation);
}
static void
orientation_lock_changed_cb (GSettings *settings,
gchar *key,
CsdOrientationManager *manager)
{
gboolean new;
new = g_settings_get_boolean (settings, ORIENTATION_LOCK_KEY);
if (new == manager->priv->orientation_lock)
return;
manager->priv->orientation_lock = new;
if (new == FALSE) {
if (is_mpu6050) {
g_timeout_add_seconds(MPU_POLL_INTERVAL, (GSourceFunc) mpu_timer, manager);
}
/* Handle the rotations that could have occurred while
* we were locked */
do_rotation (manager);
}
}
static void
properties_changed (GDBusProxy *proxy,
GVariant *changed_properties,
GStrv invalidated_properties,
gpointer user_data)
{
CsdOrientationManager *manager = user_data;
CsdOrientationManagerPrivate *p = manager->priv;
GVariant *v;
GVariantDict dict;
if (manager->priv->xrandr_proxy == NULL)
return;
if (changed_properties)
g_variant_dict_init (&dict, changed_properties);
if (changed_properties == NULL ||
g_variant_dict_contains (&dict, "HasAccelerometer")) {
v = g_dbus_proxy_get_cached_property (p->iio_proxy, "HasAccelerometer");
if (v == NULL) {
g_debug ("Couldn't fetch HasAccelerometer property");
return;
}
p->has_accel = g_variant_get_boolean (v);
if (!p->has_accel)
p->prev_orientation = ORIENTATION_UNDEFINED;
g_variant_unref (v);
}
if (changed_properties == NULL ||
g_variant_dict_contains (&dict, "AccelerometerOrientation")) {
if (p->has_accel) {
OrientationUp orientation;
orientation = get_orientation_from_device (manager);
if (orientation != p->prev_orientation) {
p->prev_orientation = orientation;
g_debug ("Orientation changed to '%s', switching screen rotation",
orientation_to_string (p->prev_orientation));
do_rotation (manager);
}
}
}
}
static void
xrandr_ready_cb (GObject *source_object,
GAsyncResult *res,
CsdOrientationManager *manager)
{
CsdOrientationManagerPrivate *p = manager->priv;
GError *error = NULL;
manager->priv->xrandr_proxy = g_dbus_proxy_new_finish (res, &error);
if (manager->priv->xrandr_proxy == NULL) {
g_warning ("Failed to get proxy for XRandR operations: %s", error->message);
g_error_free (error);
}
if (p->iio_proxy == NULL)
return;
properties_changed (manager->priv->iio_proxy, NULL, NULL, manager);
}
static int read_sysfs_attr_as_int(const char *filename) {
int i, c;
char buf[40];
int fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
c = read(fd, buf, 40);
if (c < 0)
return 0;
close(fd);
sscanf(buf, "%d", &i);
return i;
}
static gboolean mpu_timer(CsdOrientationManager *manager) {
int x, y;
static gboolean first = TRUE;
OrientationUp orientation = manager->priv->prev_orientation;
if (manager->priv->xrandr_proxy == NULL)
return TRUE;
x = read_sysfs_attr_as_int(mpu6050_accel_x);
y = read_sysfs_attr_as_int(mpu6050_accel_y);
if (x > MPU_THRESHOLD)
orientation = ORIENTATION_NORMAL;
if (x < -MPU_THRESHOLD)
orientation = ORIENTATION_BOTTOM_UP;
if (y > MPU_THRESHOLD)
orientation = ORIENTATION_RIGHT_UP;
if (y < -MPU_THRESHOLD)
orientation = ORIENTATION_LEFT_UP;
if (orientation != manager->priv->prev_orientation || first) {
first = FALSE;
manager->priv->prev_orientation = orientation;
g_debug ("Orientation changed to '%s', switching screen rotation",
orientation_to_string (manager->priv->prev_orientation));
do_rotation (manager);
}
return !manager->priv->orientation_lock;
}
static void
iio_sensor_appeared_cb (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
CsdOrientationManager *manager = user_data;
CsdOrientationManagerPrivate *p = manager->priv;
GError *error = NULL;
p->iio_proxy = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"net.hadess.SensorProxy",
"/net/hadess/SensorProxy",
"net.hadess.SensorProxy",
NULL,
&error);
if (p->iio_proxy == NULL) {
g_warning ("Failed to access net.hadess.SensorProxy after it appeared");
return;
}
g_dbus_proxy_call_sync (p->iio_proxy,
"ClaimAccelerometer",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, NULL);
g_signal_connect (G_OBJECT (manager->priv->iio_proxy), "g-properties-changed",
G_CALLBACK (properties_changed), manager);
properties_changed (manager->priv->iio_proxy, NULL, NULL, manager);
}
static void
iio_sensor_vanished_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
CsdOrientationManager *manager = user_data;
g_clear_object (&manager->priv->iio_proxy);
manager->priv->has_accel = FALSE;
manager->priv->prev_orientation = ORIENTATION_UNDEFINED;
}
gboolean
csd_orientation_manager_start (CsdOrientationManager *manager,
GError **error)
{
cinnamon_settings_profile_start (NULL);
manager->priv->settings = g_settings_new (CONF_SCHEMA);
g_signal_connect (G_OBJECT (manager->priv->settings), "changed::" ORIENTATION_LOCK_KEY,
G_CALLBACK (orientation_lock_changed_cb), manager);
manager->priv->orientation_lock = g_settings_get_boolean (manager->priv->settings, ORIENTATION_LOCK_KEY);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.cinnamon.SettingsDaemon.XRANDR_2",
"/org/cinnamon/SettingsDaemon/XRANDR",
"org.cinnamon.SettingsDaemon.XRANDR_2",
NULL,
(GAsyncReadyCallback) xrandr_ready_cb,
manager);
manager->priv->watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
"net.hadess.SensorProxy",
G_BUS_NAME_WATCHER_FLAGS_NONE,
iio_sensor_appeared_cb,
iio_sensor_vanished_cb,
manager,
NULL);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
csd_orientation_manager_stop (CsdOrientationManager *manager)
{
CsdOrientationManagerPrivate *p = manager->priv;
g_debug ("Stopping orientation manager");
if (p->watch_id > 0) {
g_bus_unwatch_name (p->watch_id);
p->watch_id = 0;
}
if (p->iio_proxy) {
g_dbus_proxy_call_sync (p->iio_proxy,
"ReleaseAccelerometer",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, NULL);
g_clear_object (&p->iio_proxy);
}
g_clear_object (&p->xrandr_proxy);
g_clear_object (&p->settings);
p->has_accel = FALSE;
if (p->cancellable) {
g_cancellable_cancel (p->cancellable);
g_clear_object (&p->cancellable);
}
}
static void
csd_orientation_manager_finalize (GObject *object)
{
CsdOrientationManager *orientation_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_ORIENTATION_MANAGER (object));
orientation_manager = CSD_ORIENTATION_MANAGER (object);
g_return_if_fail (orientation_manager->priv != NULL);
csd_orientation_manager_stop (orientation_manager);
G_OBJECT_CLASS (csd_orientation_manager_parent_class)->finalize (object);
}
CsdOrientationManager *
csd_orientation_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (CSD_TYPE_ORIENTATION_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return CSD_ORIENTATION_MANAGER (manager_object);
}
cinnamon-settings-daemon-5.2.0/plugins/orientation/csd-orientation-manager.h 0000664 0001750 0001750 00000004723 14144454032 026251 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann
* 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_ORIENTATION_MANAGER_H
#define __CSD_ORIENTATION_MANAGER_H
#include
G_BEGIN_DECLS
#define CSD_TYPE_ORIENTATION_MANAGER (csd_orientation_manager_get_type ())
#define CSD_ORIENTATION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_ORIENTATION_MANAGER, CsdOrientationManager))
#define CSD_ORIENTATION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_ORIENTATION_MANAGER, CsdOrientationManagerClass))
#define CSD_IS_ORIENTATION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_ORIENTATION_MANAGER))
#define CSD_IS_ORIENTATION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_ORIENTATION_MANAGER))
#define CSD_ORIENTATION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_ORIENTATION_MANAGER, CsdOrientationManagerClass))
typedef struct CsdOrientationManagerPrivate CsdOrientationManagerPrivate;
typedef struct
{
GObject parent;
CsdOrientationManagerPrivate *priv;
} CsdOrientationManager;
typedef struct
{
GObjectClass parent_class;
} CsdOrientationManagerClass;
GType csd_orientation_manager_get_type (void);
CsdOrientationManager * csd_orientation_manager_new (void);
gboolean csd_orientation_manager_start (CsdOrientationManager *manager,
GError **error);
void csd_orientation_manager_stop (CsdOrientationManager *manager);
G_END_DECLS
#endif /* __CSD_ORIENTATION_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/orientation/cinnamon-settings-daemon-orientation.desktop.in 0000664 0001750 0001750 00000000346 14144454032 032615 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - orientation
Exec=csd-orientation
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/xsettings/ 0000775 0001750 0001750 00000000000 14144454032 021055 5 ustar fabio fabio cinnamon-settings-daemon-5.2.0/plugins/xsettings/fontconfig-monitor.h 0000664 0001750 0001750 00000002544 14144454032 025054 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
* Author: Behdad Esfahbod, Red Hat, Inc.
*/
#ifndef __FONTCONFIG_MONITOR_H
#define __FONTCONFIG_MONITOR_H
#include
G_BEGIN_DECLS
void fontconfig_cache_init (void);
gboolean fontconfig_cache_update (void);
typedef struct _fontconfig_monitor_handle fontconfig_monitor_handle_t;
fontconfig_monitor_handle_t *
fontconfig_monitor_start (GFunc notify_callback,
gpointer notify_data);
void fontconfig_monitor_stop (fontconfig_monitor_handle_t *handle);
G_END_DECLS
#endif /* __FONTCONFIG_MONITOR_H */
cinnamon-settings-daemon-5.2.0/plugins/xsettings/csd-xsettings-manager.h 0000664 0001750 0001750 00000005147 14144454032 025444 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CINNAMON_XSETTINGS_MANAGER_H
#define __CINNAMON_XSETTINGS_MANAGER_H
#include
G_BEGIN_DECLS
#define CINNAMON_TYPE_XSETTINGS_MANAGER (cinnamon_xsettings_manager_get_type ())
#define CINNAMON_XSETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CINNAMON_TYPE_XSETTINGS_MANAGER, CinnamonSettingsXSettingsManager))
#define CINNAMON_XSETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CINNAMON_TYPE_XSETTINGS_MANAGER, CinnamonSettingsXSettingsManagerClass))
#define CINNAMON_IS_XSETTINGS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CINNAMON_TYPE_XSETTINGS_MANAGER))
#define CINNAMON_IS_XSETTINGS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CINNAMON_TYPE_XSETTINGS_MANAGER))
#define CINNAMON_XSETTINGS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CINNAMON_TYPE_XSETTINGS_MANAGER, CinnamonSettingsXSettingsManagerClass))
typedef struct CinnamonSettingsXSettingsManagerPrivate CinnamonSettingsXSettingsManagerPrivate;
typedef struct
{
GObject parent;
CinnamonSettingsXSettingsManagerPrivate *priv;
} CinnamonSettingsXSettingsManager;
typedef struct
{
GObjectClass parent_class;
} CinnamonSettingsXSettingsManagerClass;
GType cinnamon_xsettings_manager_get_type (void);
CinnamonSettingsXSettingsManager * cinnamon_xsettings_manager_new (void);
gboolean cinnamon_xsettings_manager_start (CinnamonSettingsXSettingsManager *manager,
GError **error);
void cinnamon_xsettings_manager_stop (CinnamonSettingsXSettingsManager *manager);
G_END_DECLS
#endif /* __CINNAMON_XSETTINGS_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/xsettings/xsettings-common.c 0000664 0001750 0001750 00000005614 14144454032 024545 0 ustar fabio fabio /*
* Copyright © 2001 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor, Red Hat, Inc.
*/
#include
#include "string.h"
#include "stdlib.h"
#include
#include /* For CARD32 */
#include "xsettings-common.h"
XSettingsSetting *
xsettings_setting_new (const gchar *name)
{
XSettingsSetting *result;
result = g_slice_new0 (XSettingsSetting);
result->name = g_strdup (name);
return result;
}
static gboolean
xsettings_variant_equal0 (GVariant *a,
GVariant *b)
{
if (a == b)
return TRUE;
if (!a || !b)
return FALSE;
return g_variant_equal (a, b);
}
GVariant *
xsettings_setting_get (XSettingsSetting *setting)
{
gint i;
for (i = G_N_ELEMENTS (setting->value) - 1; 0 <= i; i--)
if (setting->value[i])
return setting->value[i];
return NULL;
}
void
xsettings_setting_set (XSettingsSetting *setting,
gint tier,
GVariant *value,
guint32 serial)
{
GVariant *old_value;
old_value = xsettings_setting_get (setting);
if (old_value)
g_variant_ref (old_value);
if (setting->value[tier])
g_variant_unref (setting->value[tier]);
setting->value[tier] = value ? g_variant_ref_sink (value) : NULL;
if (!xsettings_variant_equal0 (old_value, xsettings_setting_get (setting)))
setting->last_change_serial = serial;
if (old_value)
g_variant_unref (old_value);
}
void
xsettings_setting_free (XSettingsSetting *setting)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (setting->value); i++)
if (setting->value[i])
g_variant_unref (setting->value[i]);
g_free (setting->name);
g_slice_free (XSettingsSetting, setting);
}
char
xsettings_byte_order (void)
{
CARD32 myint = 0x01020304;
return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
}
cinnamon-settings-daemon-5.2.0/plugins/xsettings/xsettings-common.h 0000664 0001750 0001750 00000004427 14144454032 024553 0 ustar fabio fabio /*
* Copyright © 2001 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor, Red Hat, Inc.
*/
#ifndef XSETTINGS_COMMON_H
#define XSETTINGS_COMMON_H
#include
#define XSETTINGS_N_TIERS 2
typedef struct _XSettingsColor XSettingsColor;
typedef struct _XSettingsSetting XSettingsSetting;
/* Types of settings possible. Enum values correspond to
* protocol values.
*/
typedef enum
{
XSETTINGS_TYPE_INT = 0,
XSETTINGS_TYPE_STRING = 1,
XSETTINGS_TYPE_COLOR = 2
} XSettingsType;
struct _XSettingsColor
{
unsigned short red, green, blue, alpha;
};
struct _XSettingsSetting
{
char *name;
GVariant *value[XSETTINGS_N_TIERS];
unsigned long last_change_serial;
};
XSettingsSetting *xsettings_setting_new (const gchar *name);
GVariant * xsettings_setting_get (XSettingsSetting *setting);
void xsettings_setting_set (XSettingsSetting *setting,
gint tier,
GVariant *value,
guint32 serial);
void xsettings_setting_free (XSettingsSetting *setting);
char xsettings_byte_order (void);
#endif /* XSETTINGS_COMMON_H */
cinnamon-settings-daemon-5.2.0/plugins/xsettings/meson.build 0000664 0001750 0001750 00000003012 14144454032 023213 0 ustar fabio fabio plugin_name = 'xsettings'
xsettings_common_sources = [
'csd-xsettings-gtk.c',
]
xsettings_sources = [
'csd-xsettings-manager.c',
'xsettings-common.c',
'xsettings-manager.c',
'fontconfig-monitor.c',
'main.c',
xsettings_common_sources,
]
test_xsettings_sources = [
'test-gtk-modules.c',
xsettings_common_sources,
]
xsettings_deps = [
cinnamon_desktop,
common_dep,
csd_dep,
fontconfig,
libnotify,
]
executable(
'csd-xsettings',
xsettings_sources,
include_directories: [include_dirs, common_inc, include_enums],
dependencies: xsettings_deps,
c_args: [
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
'-DGTK_MODULES_DIRECTORY="@0@/@1@/cinnamon-settings-daemon-@2@/gtk-modules/"'.format(prefix, libdir, api_version),
],
install: true,
install_dir: libexecdir,
)
meson.add_install_script(ln_script, libexecdir, bindir, 'csd-xsettings')
if libexecdir != pkglibdir
meson.add_install_script(ln_script, libexecdir, pkglibdir, 'csd-xsettings')
endif
executable(
'test-gtk-modules',
test_xsettings_sources,
include_directories: [include_dirs, common_inc],
dependencies: xsettings_deps,
c_args: [
'-DGTK_MODULES_DIRECTORY="@0@/@1@/cinnamon-settings-daemon-@2@/gtk-modules/"'.format(prefix, libdir, api_version),
],
)
configure_file(
input: 'cinnamon-settings-daemon-xsettings.desktop.in',
output: 'cinnamon-settings-daemon-xsettings.desktop',
configuration: desktop_conf,
install_dir: autostartdir,
)
cinnamon-settings-daemon-5.2.0/plugins/xsettings/cinnamon-settings-daemon-xsettings.desktop.in 0000664 0001750 0001750 00000000342 14144454032 032003 0 ustar fabio fabio [Desktop Entry]
Type=Application
Name=Cinnamon Settings Daemon - xsettings
Exec=csd-xsettings
OnlyShowIn=X-Cinnamon;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
cinnamon-settings-daemon-5.2.0/plugins/xsettings/csd-xsettings-manager.c 0000664 0001750 0001750 00000127563 14144454032 025446 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 Rodrigo Moya
* 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cinnamon-settings-profile.h"
#include "csd-enums.h"
#include "csd-xsettings-manager.h"
#include "csd-xsettings-gtk.h"
#include "xsettings-manager.h"
#include "fontconfig-monitor.h"
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include
#define CINNAMON_XSETTINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CINNAMON_TYPE_XSETTINGS_MANAGER, CinnamonSettingsXSettingsManagerPrivate))
#define MOUSE_SETTINGS_SCHEMA "org.cinnamon.settings-daemon.peripherals.mouse"
#define INTERFACE_SETTINGS_SCHEMA "org.cinnamon.desktop.interface"
#define INTERFACE_WM_SETTINGS_SCHEMA "org.cinnamon.desktop.wm.preferences"
#define SOUND_SETTINGS_SCHEMA "org.cinnamon.desktop.sound"
#define PRIVACY_SETTINGS_SCHEMA "org.cinnamon.desktop.privacy"
#define XSETTINGS_PLUGIN_SCHEMA "org.cinnamon.settings-daemon.plugins.xsettings"
#define XSETTINGS_OVERRIDE_KEY "overrides"
#define GTK_MODULES_DISABLED_KEY "disabled-gtk-modules"
#define GTK_MODULES_ENABLED_KEY "enabled-gtk-modules"
#define TEXT_SCALING_FACTOR_KEY "text-scaling-factor"
#define SCALING_FACTOR_KEY "scaling-factor"
#define CURSOR_SIZE_KEY "cursor-size"
#define FONT_ANTIALIASING_KEY "antialiasing"
#define FONT_HINTING_KEY "hinting"
#define FONT_RGBA_ORDER_KEY "rgba-order"
/* As we cannot rely on the X server giving us good DPI information, and
* that we don't want multi-monitor screens to have different DPIs (thus
* different text sizes), we'll hard-code the value of the DPI
*
* See also:
* https://bugzilla.novell.com/show_bug.cgi?id=217790•
* https://bugzilla.gnome.org/show_bug.cgi?id=643704
*
* http://lists.fedoraproject.org/pipermail/devel/2011-October/157671.html
* Why EDID is not trustworthy for DPI
* Adam Jackson ajax at redhat.com
* Tue Oct 4 17:54:57 UTC 2011
*
* Previous message: GNOME 3 - font point sizes now scaled?
* Next message: Why EDID is not trustworthy for DPI
* Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
*
* On Tue, 2011-10-04 at 11:46 -0400, Kaleb S. KEITHLEY wrote:
*
* > Grovelling around in the F15 xorg-server sources and reviewing the Xorg
* > log file on my F15 box, I see, with _modern hardware_ at least, that we
* > do have the monitor geometry available from DDC or EDIC, and obviously
* > it is trivial to compute the actual, correct DPI for each screen.
*
* I am clearly going to have to explain this one more time, forever.
* Let's see if I can't write it authoritatively once and simply answer
* with a URL from here out. (As always, use of the second person "you"
* herein is plural, not singular.)
*
* EDID does not reliably give you the size of the display.
*
* Base EDID has at least two different places where you can give a
* physical size (before considering extensions that aren't widely deployed
* so whatever). The first is a global property, measured in centimeters,
* of the physical size of the glass. The second is attached to your (zero
* or more) detailed timing specifications, and reflects the size of the
* mode, in millimeters.
*
* So, how does this screw you?
*
* a) Glass size is too coarse. On a large display that cm roundoff isn't
* a big deal, but on subnotebooks it's a different game. The 11" MBA is
* 25.68x14.44 cm, so that gives you a range of 52.54-54.64 dpcm horizontal
* and 51.20-54.86 dpcm vertical (133.4-138.8 dpi h and 130.0-139.3 dpi v).
* Which is optimistic, because that's doing the math forward from knowing
* the actual size, and you as the EDID parser can't know which way the
* manufacturer rounded.
*
* b) Glass size need not be non-zero. This is in fact the usual case for
* projectors, which don't have a fixed display size since it's a function
* of how far away the wall is from the lens.
*
* c) Glass size could be partially non-zero. Yes, really. EDID 1.4
* defines a method of using these two bytes to encode aspect ratio, where
* if vertical size is 0 then the aspect ratio is computed as (horizontal
* value + 99) / 100 in portrait mode (and the obvious reverse thing if
* horizontal is zero). Admittedly, unlike every other item in this list,
* I've never seen this in the wild. But it's legal.
*
* d) Glass size could be a direct encoding of the aspect ratio. Base EDID
* doesn't condone this behaviour, but the CEA spec (to which all HDMI
* monitors must conform) does allow-but-not-require it, which means your
* 1920x1080 TV could claim to be 16 "cm" by 9 "cm". So of course that's
* what TV manufacturers do because that way they don't have to modify the
* EDID info when physical construction changes, and that's cheaper.
*
* e) You could use mode size to get size in millimeters, but you might not
* have any detailed timings.
*
* f) You could use mode size, but mode size is explicitly _not_ glass
* size. It's the size that the display chooses to present that mode.
* Sometimes those are the same, and sometimes they're not. You could be
* scaled or {letter,pillar}boxed, and that's not necessarily something you
* can control from the host side.
*
* g) You could use mode size, but it could be an encoded aspect ratio, as
* in case d above, because CEA says that's okay.
*
* h) You could use mode size, but it could be the aspect ratio from case d
* multiplied by 10 in each direction (because, of course, you gave size in
* centimeters and so your authoring tool just multiplied it up).
*
* i) Any or all of the above could be complete and utter garbage, because
* - and I really, really need you to understand this - there is no
* requirements program for any commercial OS or industry standard that
* requires honesty here, as far as I'm aware. There is every incentive
* for there to _never_ be one, because it would make the manufacturing
* process more expensive.
*
* So from this point the suggestion is usually "well come up with some
* heuristic to make a good guess assuming there's some correlation between
* the various numbers you're given". I have in fact written heuristics
* for this, and they're in your kernel and your X server, and they still
* encounter a huge number of cases where we simply _cannot_ know from EDID
* anything like a physical size, because - to pick only one example - the
* consumer electronics industry are cheap bastards, because you the
* consumer demanded that they be cheap.
*
* And then your only recourse is to an external database, and now you're
* up the creek again because the identifying information here is a
* vendor/model/serial tuple, and the vendor can and does change physical
* construction without changing model number. Now you get to play the
* guessing game of how big the serial number range is for each subvariant,
* assuming they bothered to encode a serial number - and they didn't. Or,
* if they bothered to encode week/year of manufacturer correctly - and
* they didn't - which weeks meant which models. And then you still have
* to go out and buy one of every TV at Fry's, and that covers you for one
* market, for three months.
*
* If someone wants to write something better, please, by all means. If
* it's kernel code, send it to dri-devel at lists.freedesktop.org and cc me
* and I will happily review it. Likewise xorg-devel@ for X server
* changes.
*
* I gently suggest that doing so is a waste of time.
*
* But if there's one thing free software has taught me, it's that you can
* not tell people something is a bad idea and have any expectation they
* will believe you.
*
* > Obviously in a multi-screen set-up using Xinerama this has the potential
* > to be a Hard Problem if the monitors differ greatly in their DPI.
* >
* > If the major resistance is over what to do with older hardware that
* > doesn't have this data available, then yes, punt; use a hard-coded
* > default. Likewise, if the two monitors really differ greatly, then punt.
*
* I'm going to limit myself to observing that "greatly" is a matter of
* opinion, and that in order to be really useful you'd need some way of
* communicating "I punted" to the desktop.
*
* Beyond that, sure, pick a heuristic, accept that it's going to be
* insufficient for someone, and then sit back and wait to get
* second-guessed on it over and over.
*
* > And it wouldn't be so hard to to add something like -dpi:0, -dpi:1,
* > -dpi:2 command line options to specify per-screen dpi. I kinda thought I
* > did that a long, long time ago, but maybe I only thought about doing it
* > and never actually got around to it.
*
* The RANDR extension as of version 1.2 does allow you to override
* physical size on a per-output basis at runtime. We even try pretty hard
* to set them as honestly as we can up front. The 96dpi thing people
* complain about is from the per-screen info, which is simply a default
* because of all the tl;dr above; because you have N outputs per screen
* which means a single number is in general useless; and because there is
* no way to refresh the per-screen info at runtime, as it's only ever sent
* in the initial connection handshake.
*
* - ajax
*
*/
#define DPI_FALLBACK 96
typedef struct _TranslationEntry TranslationEntry;
typedef void (* TranslationFunc) (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value);
struct _TranslationEntry {
const char *gsettings_schema;
const char *gsettings_key;
const char *xsetting_name;
TranslationFunc translate;
};
struct CinnamonSettingsXSettingsManagerPrivate
{
guint start_idle_id;
XSettingsManager **managers;
GHashTable *settings;
GSettings *plugin_settings;
fontconfig_monitor_handle_t *fontconfig_handle;
CsdXSettingsGtk *gtk;
guint notify_idle_id;
};
#define CSD_XSETTINGS_ERROR csd_xsettings_error_quark ()
enum {
CSD_XSETTINGS_ERROR_INIT
};
static void cinnamon_xsettings_manager_finalize (GObject *object);
G_DEFINE_TYPE (CinnamonSettingsXSettingsManager, cinnamon_xsettings_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
static GQuark
csd_xsettings_error_quark (void)
{
return g_quark_from_static_string ("csd-xsettings-error-quark");
}
static void
translate_bool_int (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
int i;
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
g_variant_get_boolean (value));
}
}
static void
translate_int_int (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
int i;
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
g_variant_get_int32 (value));
}
}
static void
translate_string_string (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
int i;
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_string (manager->priv->managers [i],
trans->xsetting_name,
g_variant_get_string (value, NULL));
}
}
static void
translate_string_string_toolbar (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
int i;
const char *tmp;
/* This is kind of a workaround since GNOME expects the key value to be
* "both_horiz" and gtk+ wants the XSetting to be "both-horiz".
*/
tmp = g_variant_get_string (value, NULL);
if (tmp && strcmp (tmp, "both_horiz") == 0) {
tmp = "both-horiz";
}
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_string (manager->priv->managers [i],
trans->xsetting_name,
tmp);
}
}
static void
translate_string_string_window_buttons (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
int i;
const char *tmp;
gchar *ptr, *final_str;
/* This is kind of a workaround. "menu" is useless in metacity titlebars
* it duplicates the same features as the right-click menu.
* In CSD windows on the hand it is required to show unique featues.
*/
tmp = g_variant_get_string (value, NULL);
/* Check if menu is in the setting string already */
ptr = g_strstr_len (tmp, -1, "menu");
if (!ptr) {
/* If it wasn't there already, we add it... */
/* Simple cases, :* - all items on right, just prepend menu on left side*/
if (g_str_has_prefix (tmp, ":")) {
final_str = g_strdup_printf ("menu%s", tmp);
}
else
/* All items on left... * (no :), append menu - we want actual window
controls on the outside */
if (!g_strstr_len (tmp, -1, ":")) {
final_str = g_strdup_printf ("%s,menu", tmp);
}
else {
/* Items on both sides, split it, append menu to the lefthand, and re-
* construct the string with the : separator */
gchar **split = g_strsplit (tmp, ":", 2);
final_str = g_strdup_printf ("%s,menu:%s", split[0], split[1]);
g_strfreev (split);
}
} else {
/* If menu was already included, just copy the original string */
final_str = g_strdup (tmp);
}
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_string (manager->priv->managers [i],
trans->xsetting_name,
final_str);
}
g_free (final_str);
}
static TranslationEntry translations [] = {
{ "org.cinnamon.settings-daemon.peripherals.mouse", "double-click", "Net/DoubleClickTime", translate_int_int },
{ "org.cinnamon.settings-daemon.peripherals.mouse", "drag-threshold", "Net/DndDragThreshold", translate_int_int },
{ "org.cinnamon.desktop.interface", "gtk-color-palette", "Gtk/ColorPalette", translate_string_string },
{ "org.cinnamon.desktop.interface", "font-name", "Gtk/FontName", translate_string_string },
{ "org.cinnamon.desktop.interface", "gtk-key-theme", "Gtk/KeyThemeName", translate_string_string },
{ "org.cinnamon.desktop.interface", "toolbar-style", "Gtk/ToolbarStyle", translate_string_string_toolbar },
{ "org.cinnamon.desktop.interface", "toolbar-icons-size", "Gtk/ToolbarIconSize", translate_string_string },
{ "org.cinnamon.desktop.interface", "can-change-accels", "Gtk/CanChangeAccels", translate_bool_int },
{ "org.cinnamon.desktop.interface", "cursor-blink", "Net/CursorBlink", translate_bool_int },
{ "org.cinnamon.desktop.interface", "cursor-blink-time", "Net/CursorBlinkTime", translate_int_int },
{ "org.cinnamon.desktop.interface", "cursor-blink-timeout", "Gtk/CursorBlinkTimeout", translate_int_int },
{ "org.cinnamon.desktop.interface", "gtk-theme", "Net/ThemeName", translate_string_string },
{ "org.cinnamon.desktop.interface", "gtk-timeout-initial", "Gtk/TimeoutInitial", translate_int_int },
{ "org.cinnamon.desktop.interface", "gtk-timeout-repeat", "Gtk/TimeoutRepeat", translate_int_int },
{ "org.cinnamon.desktop.interface", "gtk-color-scheme", "Gtk/ColorScheme", translate_string_string },
{ "org.cinnamon.desktop.interface", "gtk-im-preedit-style", "Gtk/IMPreeditStyle", translate_string_string },
{ "org.cinnamon.desktop.interface", "gtk-im-status-style", "Gtk/IMStatusStyle", translate_string_string },
{ "org.cinnamon.desktop.interface", "gtk-im-module", "Gtk/IMModule", translate_string_string },
{ "org.cinnamon.desktop.interface", "icon-theme", "Net/IconThemeName", translate_string_string },
{ "org.cinnamon.settings-daemon.plugins.xsettings", "menus-have-icons", "Gtk/MenuImages", translate_bool_int },
{ "org.cinnamon.settings-daemon.plugins.xsettings", "buttons-have-icons", "Gtk/ButtonImages", translate_bool_int },
{ "org.cinnamon.desktop.interface", "menubar-accel", "Gtk/MenuBarAccel", translate_string_string },
{ "org.cinnamon.desktop.interface", "enable-animations", "Gtk/EnableAnimations", translate_bool_int },
{ "org.cinnamon.desktop.interface", "cursor-theme", "Gtk/CursorThemeName", translate_string_string },
{ "org.cinnamon.desktop.wm.preferences", "button-layout", "Gtk/DecorationLayout", translate_string_string_window_buttons },
{ "org.cinnamon.desktop.wm.preferences", "action-double-click-titlebar", "Gtk/TitlebarDoubleClick", translate_string_string },
{ "org.cinnamon.desktop.wm.preferences", "action-middle-click-titlebar", "Gtk/TitlebarMiddleClick", translate_string_string },
{ "org.cinnamon.desktop.wm.preferences", "action-right-click-titlebar", "Gtk/TitlebarRightClick", translate_string_string },
{ "org.cinnamon.settings-daemon.plugins.xsettings", "show-input-method-menu", "Gtk/ShowInputMethodMenu", translate_bool_int },
{ "org.cinnamon.settings-daemon.plugins.xsettings", "show-unicode-menu", "Gtk/ShowUnicodeMenu", translate_bool_int },
{ "org.cinnamon.settings-daemon.plugins.xsettings", "automatic-mnemonics", "Gtk/AutoMnemonics", translate_bool_int },
{ "org.cinnamon.desktop.sound", "theme-name", "Net/SoundThemeName", translate_string_string },
{ "org.cinnamon.desktop.sound", "event-sounds", "Net/EnableEventSounds" , translate_bool_int },
{ "org.cinnamon.desktop.sound", "input-feedback-sounds", "Net/EnableInputFeedbackSounds", translate_bool_int },
{ "org.cinnamon.desktop.privacy", "recent-files-max-age", "Gtk/RecentFilesMaxAge", translate_int_int },
{ "org.cinnamon.desktop.privacy", "remember-recent-files", "Gtk/RecentFilesEnabled", translate_bool_int }
};
static gboolean
notify_idle (gpointer data)
{
CinnamonSettingsXSettingsManager *manager = data;
gint i;
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_notify (manager->priv->managers[i]);
}
manager->priv->notify_idle_id = 0;
return G_SOURCE_REMOVE;
}
static void
queue_notify (CinnamonSettingsXSettingsManager *manager)
{
if (manager->priv->notify_idle_id != 0)
return;
manager->priv->notify_idle_id = g_idle_add (notify_idle, manager);
}
static double
get_dpi_from_gsettings (CinnamonSettingsXSettingsManager *manager)
{
GSettings *interface_settings;
double dpi;
double factor;
interface_settings = g_hash_table_lookup (manager->priv->settings, INTERFACE_SETTINGS_SCHEMA);
factor = g_settings_get_double (interface_settings, TEXT_SCALING_FACTOR_KEY);
dpi = DPI_FALLBACK;
return dpi * factor;
}
static int
get_window_scale (CinnamonSettingsXSettingsManager *manager)
{
GSettings *interface_settings;
GError *error = NULL;
int window_scale;
interface_settings = g_hash_table_lookup (manager->priv->settings, INTERFACE_SETTINGS_SCHEMA);
window_scale = g_settings_get_uint (interface_settings, SCALING_FACTOR_KEY);
if (window_scale == 0) {
GnomeRRScreen *screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
if (!error) {
window_scale = gnome_rr_screen_calculate_best_global_scale (screen, -1);
g_object_unref (screen);
} else {
g_warning ("Could not get/create GnomeRRScreen instance: %s", error->message);
g_error_free (error);
}
}
return window_scale;
}
typedef struct {
gboolean antialias;
gboolean hinting;
int scaled_dpi;
int dpi;
int window_scale;
int cursor_size;
const char *rgba;
const char *hintstyle;
} CinnamonSettingsXftSettings;
/* Read GSettings and determine the appropriate Xft settings based on them. */
static void
xft_settings_get (CinnamonSettingsXSettingsManager *manager,
CinnamonSettingsXftSettings *settings)
{
GSettings *interface_settings;
CsdFontAntialiasingMode antialiasing;
CsdFontHinting hinting;
CsdFontRgbaOrder order;
gboolean use_rgba = FALSE;
double dpi;
int cursor_size;
interface_settings = g_hash_table_lookup (manager->priv->settings, INTERFACE_SETTINGS_SCHEMA);
antialiasing = g_settings_get_enum (manager->priv->plugin_settings, FONT_ANTIALIASING_KEY);
hinting = g_settings_get_enum (manager->priv->plugin_settings, FONT_HINTING_KEY);
order = g_settings_get_enum (manager->priv->plugin_settings, FONT_RGBA_ORDER_KEY);
settings->antialias = (antialiasing != CSD_FONT_ANTIALIASING_MODE_NONE);
settings->hinting = (hinting != CSD_FONT_HINTING_NONE);
settings->window_scale = get_window_scale (manager);
dpi = get_dpi_from_gsettings (manager);
settings->dpi = dpi * 1024; /* Xft wants 1/1024ths of an inch */
settings->scaled_dpi = dpi * settings->window_scale * 1024;
cursor_size = g_settings_get_int (interface_settings, CURSOR_SIZE_KEY);
settings->cursor_size = cursor_size * settings->window_scale;
settings->rgba = "rgb";
settings->hintstyle = "hintfull";
switch (hinting) {
case CSD_FONT_HINTING_NONE:
settings->hintstyle = "hintnone";
break;
case CSD_FONT_HINTING_SLIGHT:
settings->hintstyle = "hintslight";
break;
case CSD_FONT_HINTING_MEDIUM:
settings->hintstyle = "hintmedium";
break;
case CSD_FONT_HINTING_FULL:
settings->hintstyle = "hintfull";
break;
}
switch (order) {
case CSD_FONT_RGBA_ORDER_RGBA:
settings->rgba = "rgba";
break;
case CSD_FONT_RGBA_ORDER_RGB:
settings->rgba = "rgb";
break;
case CSD_FONT_RGBA_ORDER_BGR:
settings->rgba = "bgr";
break;
case CSD_FONT_RGBA_ORDER_VRGB:
settings->rgba = "vrgb";
break;
case CSD_FONT_RGBA_ORDER_VBGR:
settings->rgba = "vbgr";
break;
}
switch (antialiasing) {
case CSD_FONT_ANTIALIASING_MODE_NONE:
settings->antialias = 0;
break;
case CSD_FONT_ANTIALIASING_MODE_GRAYSCALE:
settings->antialias = 1;
break;
case CSD_FONT_ANTIALIASING_MODE_RGBA:
settings->antialias = 1;
use_rgba = TRUE;
}
if (!use_rgba) {
settings->rgba = "none";
}
}
static void
xft_settings_set_xsettings (CinnamonSettingsXSettingsManager *manager,
CinnamonSettingsXftSettings *settings)
{
int i;
cinnamon_settings_profile_start (NULL);
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_int (manager->priv->managers [i], "Xft/Antialias", settings->antialias);
xsettings_manager_set_int (manager->priv->managers [i], "Xft/Hinting", settings->hinting);
xsettings_manager_set_string (manager->priv->managers [i], "Xft/HintStyle", settings->hintstyle);
xsettings_manager_set_int (manager->priv->managers [i], "Gdk/WindowScalingFactor", settings->window_scale);
xsettings_manager_set_int (manager->priv->managers [i], "Gdk/UnscaledDPI", settings->dpi);
xsettings_manager_set_int (manager->priv->managers [i], "Xft/DPI", settings->scaled_dpi);
xsettings_manager_set_string (manager->priv->managers [i], "Xft/RGBA", settings->rgba);
xsettings_manager_set_int (manager->priv->managers [i], "Gtk/CursorThemeSize", settings->cursor_size);
}
cinnamon_settings_profile_end (NULL);
}
static void
update_property (GString *props, const gchar* key, const gchar* value)
{
gchar* needle;
size_t needle_len;
gchar* found = NULL;
/* update an existing property */
needle = g_strconcat (key, ":", NULL);
needle_len = strlen (needle);
if (g_str_has_prefix (props->str, needle))
found = props->str;
else
found = strstr (props->str, needle);
if (found) {
size_t value_index;
gchar* end;
end = strchr (found, '\n');
value_index = (found - props->str) + needle_len + 1;
g_string_erase (props, value_index, end ? (end - found - needle_len) : -1);
g_string_insert (props, value_index, "\n");
g_string_insert (props, value_index, value);
} else {
g_string_append_printf (props, "%s:\t%s\n", key, value);
}
g_free (needle);
}
static void
xft_settings_set_xresources (CinnamonSettingsXftSettings *settings)
{
GString *add_string;
char dpibuf[G_ASCII_DTOSTR_BUF_SIZE];
Display *dpy;
cinnamon_settings_profile_start (NULL);
/* get existing properties */
dpy = XOpenDisplay (NULL);
g_return_if_fail (dpy != NULL);
add_string = g_string_new (XResourceManagerString (dpy));
g_debug("xft_settings_set_xresources: orig res '%s'", add_string->str);
update_property (add_string, "Xft.dpi",
g_ascii_dtostr (dpibuf, sizeof (dpibuf), (double) settings->scaled_dpi / 1024.0));
update_property (add_string, "Xft.antialias",
settings->antialias ? "1" : "0");
update_property (add_string, "Xft.hinting",
settings->hinting ? "1" : "0");
update_property (add_string, "Xft.hintstyle",
settings->hintstyle);
update_property (add_string, "Xft.rgba",
settings->rgba);
g_debug("xft_settings_set_xresources: new res '%s'", add_string->str);
/* Set the new X property */
XChangeProperty(dpy, RootWindow (dpy, 0),
XA_RESOURCE_MANAGER, XA_STRING, 8, PropModeReplace, (const unsigned char *) add_string->str, add_string->len);
XCloseDisplay (dpy);
g_string_free (add_string, TRUE);
cinnamon_settings_profile_end (NULL);
}
/* We mirror the Xft properties both through XSETTINGS and through
* X resources
*/
static void
update_xft_settings (CinnamonSettingsXSettingsManager *manager)
{
CinnamonSettingsXftSettings settings;
cinnamon_settings_profile_start (NULL);
xft_settings_get (manager, &settings);
xft_settings_set_xsettings (manager, &settings);
xft_settings_set_xresources (&settings);
cinnamon_settings_profile_end (NULL);
}
static void
xft_callback (GSettings *settings,
const gchar *key,
CinnamonSettingsXSettingsManager *manager)
{
update_xft_settings (manager);
queue_notify (manager);
}
static void
size_changed_callback (GdkScreen *screen, CinnamonSettingsXSettingsManager *manager)
{
update_xft_settings (manager);
queue_notify (manager);
}
static void
override_callback (GSettings *settings,
const gchar *key,
CinnamonSettingsXSettingsManager *manager)
{
GVariant *value;
int i;
value = g_settings_get_value (settings, XSETTINGS_OVERRIDE_KEY);
for (i = 0; manager->priv->managers[i]; i++) {
xsettings_manager_set_overrides (manager->priv->managers[i], value);
}
queue_notify (manager);
g_variant_unref (value);
}
static void
plugin_callback (GSettings *settings,
const char *key,
CinnamonSettingsXSettingsManager *manager)
{
if (g_str_equal (key, GTK_MODULES_DISABLED_KEY) ||
g_str_equal (key, GTK_MODULES_ENABLED_KEY)) {
/* Do nothing, as CsdXsettingsGtk will handle it */
} else if (g_str_equal (key, XSETTINGS_OVERRIDE_KEY)) {
override_callback (settings, key, manager);
} else {
xft_callback (settings, key, manager);
}
}
static void
gtk_modules_callback (CsdXSettingsGtk *gtk,
GParamSpec *spec,
CinnamonSettingsXSettingsManager *manager)
{
const char *modules = csd_xsettings_gtk_get_modules (manager->priv->gtk);
int i;
if (modules == NULL) {
for (i = 0; manager->priv->managers [i]; ++i) {
xsettings_manager_delete_setting (manager->priv->managers [i], "Gtk/Modules");
}
} else {
g_debug ("Setting GTK modules '%s'", modules);
for (i = 0; manager->priv->managers [i]; ++i) {
xsettings_manager_set_string (manager->priv->managers [i],
"Gtk/Modules",
modules);
}
}
queue_notify (manager);
}
static void
fontconfig_callback (fontconfig_monitor_handle_t *handle,
CinnamonSettingsXSettingsManager *manager)
{
int i;
int timestamp = time (NULL);
cinnamon_settings_profile_start (NULL);
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_int (manager->priv->managers [i], "Fontconfig/Timestamp", timestamp);
}
queue_notify (manager);
cinnamon_settings_profile_end (NULL);
}
static gboolean
start_fontconfig_monitor_idle_cb (CinnamonSettingsXSettingsManager *manager)
{
cinnamon_settings_profile_start (NULL);
manager->priv->fontconfig_handle = fontconfig_monitor_start ((GFunc) fontconfig_callback, manager);
cinnamon_settings_profile_end (NULL);
manager->priv->start_idle_id = 0;
return FALSE;
}
static void
start_fontconfig_monitor (CinnamonSettingsXSettingsManager *manager)
{
cinnamon_settings_profile_start (NULL);
fontconfig_cache_init ();
manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_fontconfig_monitor_idle_cb, manager);
cinnamon_settings_profile_end (NULL);
}
static void
stop_fontconfig_monitor (CinnamonSettingsXSettingsManager *manager)
{
if (manager->priv->fontconfig_handle) {
fontconfig_monitor_stop (manager->priv->fontconfig_handle);
manager->priv->fontconfig_handle = NULL;
}
}
static void
process_value (CinnamonSettingsXSettingsManager *manager,
TranslationEntry *trans,
GVariant *value)
{
(* trans->translate) (manager, trans, value);
}
static TranslationEntry *
find_translation_entry (GSettings *settings, const char *key)
{
guint i;
char *schema;
g_object_get (settings, "schema-id", &schema, NULL);
for (i = 0; i < G_N_ELEMENTS (translations); i++) {
if (g_str_equal (schema, translations[i].gsettings_schema) &&
g_str_equal (key, translations[i].gsettings_key)) {
g_free (schema);
return &translations[i];
}
}
g_free (schema);
return NULL;
}
static void
xsettings_callback (GSettings *settings,
const char *key,
CinnamonSettingsXSettingsManager *manager)
{
TranslationEntry *trans;
guint i;
GVariant *value;
if (g_str_equal (key, TEXT_SCALING_FACTOR_KEY) ||
g_str_equal (key, SCALING_FACTOR_KEY) ||
g_str_equal (key, CURSOR_SIZE_KEY)) {
xft_callback (NULL, key, manager);
return;
}
trans = find_translation_entry (settings, key);
if (trans == NULL) {
return;
}
value = g_settings_get_value (settings, key);
process_value (manager, trans, value);
g_variant_unref (value);
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_string (manager->priv->managers [i],
"Net/FallbackIconTheme",
"gnome");
}
queue_notify (manager);
}
static void
terminate_cb (void *data)
{
gboolean *terminated = data;
if (*terminated) {
return;
}
*terminated = TRUE;
g_warning ("X Settings Manager is terminating");
gtk_main_quit ();
}
static gboolean
setup_xsettings_managers (CinnamonSettingsXSettingsManager *manager)
{
GdkDisplay *display;
int i;
int n_screens;
gboolean res;
gboolean terminated;
display = gdk_display_get_default ();
n_screens = gdk_display_get_n_screens (display);
res = xsettings_manager_check_running (gdk_x11_display_get_xdisplay (display),
gdk_screen_get_number (gdk_screen_get_default ()));
if (res) {
g_warning ("You can only run one xsettings manager at a time; exiting");
return FALSE;
}
manager->priv->managers = g_new0 (XSettingsManager *, n_screens + 1);
terminated = FALSE;
for (i = 0; i < n_screens; i++) {
GdkScreen *screen;
screen = gdk_display_get_screen (display, i);
manager->priv->managers [i] = xsettings_manager_new (gdk_x11_display_get_xdisplay (display),
gdk_screen_get_number (screen),
terminate_cb,
&terminated);
if (! manager->priv->managers [i]) {
g_warning ("Could not create xsettings manager for screen %d!", i);
return FALSE;
}
g_signal_connect (screen, "size-changed", G_CALLBACK (size_changed_callback), manager);
}
return TRUE;
}
gboolean
cinnamon_xsettings_manager_start (CinnamonSettingsXSettingsManager *manager,
GError **error)
{
GVariant *overrides;
guint i;
GList *list, *l;
g_debug ("Starting xsettings manager");
cinnamon_settings_profile_start (NULL);
if (!setup_xsettings_managers (manager)) {
g_set_error (error, CSD_XSETTINGS_ERROR,
CSD_XSETTINGS_ERROR_INIT,
"Could not initialize xsettings manager.");
return FALSE;
}
manager->priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) g_object_unref);
g_hash_table_insert (manager->priv->settings,
MOUSE_SETTINGS_SCHEMA, g_settings_new (MOUSE_SETTINGS_SCHEMA));
g_hash_table_insert (manager->priv->settings,
INTERFACE_SETTINGS_SCHEMA, g_settings_new (INTERFACE_SETTINGS_SCHEMA));
g_hash_table_insert (manager->priv->settings,
INTERFACE_WM_SETTINGS_SCHEMA, g_settings_new (INTERFACE_WM_SETTINGS_SCHEMA));
g_hash_table_insert (manager->priv->settings,
SOUND_SETTINGS_SCHEMA, g_settings_new (SOUND_SETTINGS_SCHEMA));
g_hash_table_insert (manager->priv->settings,
XSETTINGS_PLUGIN_SCHEMA, g_settings_new (XSETTINGS_PLUGIN_SCHEMA));
g_hash_table_insert (manager->priv->settings,
PRIVACY_SETTINGS_SCHEMA, g_settings_new (PRIVACY_SETTINGS_SCHEMA));
for (i = 0; i < G_N_ELEMENTS (translations); i++) {
GVariant *val;
GSettings *settings;
settings = g_hash_table_lookup (manager->priv->settings,
translations[i].gsettings_schema);
if (settings == NULL) {
g_warning ("Schemas '%s' has not been setup", translations[i].gsettings_schema);
continue;
}
val = g_settings_get_value (settings, translations[i].gsettings_key);
process_value (manager, &translations[i], val);
g_variant_unref (val);
}
list = g_hash_table_get_values (manager->priv->settings);
for (l = list; l != NULL; l = l->next) {
g_signal_connect_object (G_OBJECT (l->data), "changed", G_CALLBACK (xsettings_callback), manager, 0);
}
g_list_free (list);
/* Plugin settings (GTK modules and Xft) */
manager->priv->plugin_settings = g_settings_new (XSETTINGS_PLUGIN_SCHEMA);
g_signal_connect_object (manager->priv->plugin_settings, "changed", G_CALLBACK (plugin_callback), manager, 0);
manager->priv->gtk = csd_xsettings_gtk_new ();
g_signal_connect (G_OBJECT (manager->priv->gtk), "notify::gtk-modules",
G_CALLBACK (gtk_modules_callback), manager);
gtk_modules_callback (manager->priv->gtk, NULL, manager);
/* Xft settings */
update_xft_settings (manager);
start_fontconfig_monitor (manager);
overrides = g_settings_get_value (manager->priv->plugin_settings, XSETTINGS_OVERRIDE_KEY);
for (i = 0; manager->priv->managers [i]; i++) {
xsettings_manager_set_string (manager->priv->managers [i],
"Net/FallbackIconTheme",
"gnome");
xsettings_manager_set_overrides (manager->priv->managers [i], overrides);
xsettings_manager_set_int (manager->priv->managers [i], "Gtk/ShellShowsAppMenu",
FALSE);
xsettings_manager_set_int (manager->priv->managers [i], "Gtk/ShellShowsMenubar",
FALSE);
}
queue_notify (manager);
g_variant_unref (overrides);
cinnamon_settings_profile_end (NULL);
return TRUE;
}
void
cinnamon_xsettings_manager_stop (CinnamonSettingsXSettingsManager *manager)
{
CinnamonSettingsXSettingsManagerPrivate *p = manager->priv;
int i;
g_debug ("Stopping xsettings manager");
if (p->managers != NULL) {
for (i = 0; p->managers [i]; ++i)
xsettings_manager_destroy (p->managers [i]);
g_free (p->managers);
p->managers = NULL;
}
if (p->plugin_settings != NULL) {
g_object_unref (p->plugin_settings);
p->plugin_settings = NULL;
}
stop_fontconfig_monitor (manager);
if (p->settings != NULL) {
g_hash_table_destroy (p->settings);
p->settings = NULL;
}
if (p->gtk != NULL) {
g_object_unref (p->gtk);
p->gtk = NULL;
}
}
static GObject *
cinnamon_xsettings_manager_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
CinnamonSettingsXSettingsManager *xsettings_manager;
xsettings_manager = CINNAMON_XSETTINGS_MANAGER (G_OBJECT_CLASS (cinnamon_xsettings_manager_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (xsettings_manager);
}
static void
cinnamon_xsettings_manager_class_init (CinnamonSettingsXSettingsManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = cinnamon_xsettings_manager_constructor;
object_class->finalize = cinnamon_xsettings_manager_finalize;
g_type_class_add_private (klass, sizeof (CinnamonSettingsXSettingsManagerPrivate));
}
static void
cinnamon_xsettings_manager_init (CinnamonSettingsXSettingsManager *manager)
{
manager->priv = CINNAMON_XSETTINGS_MANAGER_GET_PRIVATE (manager);
}
static void
cinnamon_xsettings_manager_finalize (GObject *object)
{
CinnamonSettingsXSettingsManager *xsettings_manager;
g_return_if_fail (object != NULL);
g_return_if_fail (CINNAMON_IS_XSETTINGS_MANAGER (object));
xsettings_manager = CINNAMON_XSETTINGS_MANAGER (object);
g_return_if_fail (xsettings_manager->priv != NULL);
if (xsettings_manager->priv->start_idle_id != 0) {
g_source_remove (xsettings_manager->priv->start_idle_id);
xsettings_manager->priv->start_idle_id = 0;
}
G_OBJECT_CLASS (cinnamon_xsettings_manager_parent_class)->finalize (object);
}
CinnamonSettingsXSettingsManager *
cinnamon_xsettings_manager_new (void)
{
if (manager_object != NULL) {
g_object_ref (manager_object);
} else {
manager_object = g_object_new (CINNAMON_TYPE_XSETTINGS_MANAGER, NULL);
g_object_add_weak_pointer (manager_object,
(gpointer *) &manager_object);
}
return CINNAMON_XSETTINGS_MANAGER (manager_object);
}
cinnamon-settings-daemon-5.2.0/plugins/xsettings/main.c 0000664 0001750 0001750 00000001066 14144454032 022150 0 ustar fabio fabio #define NEW cinnamon_xsettings_manager_new
#define START cinnamon_xsettings_manager_start
#define STOP cinnamon_xsettings_manager_stop
#define MANAGER CinnamonSettingsXSettingsManager
// Setting this to TRUE makes the plugin register
// with CSM before starting.
// Setting this to FALSE makes CSM wait for the plugin to be started
// before initializing the next phase.
#define REGISTER_BEFORE_STARTING FALSE
// Setting this to TRUE makes the plugin force GDK_SCALE=1
#define FORCE_GDK_SCALE TRUE
#include "csd-xsettings-manager.h"
#include "daemon-skeleton.h"
cinnamon-settings-daemon-5.2.0/plugins/xsettings/xsettings-manager.h 0000664 0001750 0001750 00000005240 14144454032 024667 0 ustar fabio fabio /*
* Copyright © 2001 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor, Red Hat, Inc.
*/
#ifndef XSETTINGS_MANAGER_H
#define XSETTINGS_MANAGER_H
#include
#include "xsettings-common.h"
typedef struct _XSettingsManager XSettingsManager;
typedef void (*XSettingsTerminateFunc) (void *cb_data);
Bool xsettings_manager_check_running (Display *display,
int screen);
XSettingsManager *xsettings_manager_new (Display *display,
int screen,
XSettingsTerminateFunc terminate,
void *cb_data);
void xsettings_manager_destroy (XSettingsManager *manager);
void xsettings_manager_delete_setting (XSettingsManager *manager,
const char *name);
void xsettings_manager_set_int (XSettingsManager *manager,
const char *name,
int value);
void xsettings_manager_set_string (XSettingsManager *manager,
const char *name,
const char *value);
void xsettings_manager_set_color (XSettingsManager *manager,
const char *name,
XSettingsColor *value);
void xsettings_manager_notify (XSettingsManager *manager);
void xsettings_manager_set_overrides (XSettingsManager *manager,
GVariant *overrides);
#endif /* XSETTINGS_MANAGER_H */
cinnamon-settings-daemon-5.2.0/plugins/xsettings/README.xsettings 0000664 0001750 0001750 00000002600 14144454032 023762 0 ustar fabio fabio This is very simple documentation for the 'override' GSettings key for
cinnamon-setting-daemon's xsettings plugin.
The override is given as a dictionary of overrides to be applied on top
of the usual values that are exported to the X server as XSETTINGS. The
intent of this is to allow users to override values of programmatically
determined settings (such as 'Gtk/ShellShowsAppMenu') and to allow
developers to introduce new XSETTINGS for testing (without having to kill the
cinnamon-settings-daemon running in the session and run their own patched
version).
The type of the overrides is 'a{sv}'.
The key gives the full XSETTINGS setting name to override (for example,
'Gtk/ShellShowsAppMenu'). The value is one of the following:
- a string ('s') for the case of a string XSETTING
- an int32 ('i') for the case of an integer XSETTING
- a 4-tuple of uint16s ('(qqqq)') for the case of a color XSETTING
Dictionary items with a value that is not one of the above types will be
ignored. Specifically note that XSETTINGS does not have a concept of
booleans -- you must use an integer that is either 0 or 1.
An example setting for this key (as expressed in GVariant text format)
might be:
{ 'Gtk/ShellShowsAppMenu': < 0 >, 'Xft/DPI', < 98304 > }
Noting that variants must be specified in the usual way (wrapped in <>).
Note also that DPI in the above example is expressed in 1024ths of an
inch.
cinnamon-settings-daemon-5.2.0/plugins/xsettings/test-gtk-modules.c 0000664 0001750 0001750 00000001275 14144454032 024436 0 ustar fabio fabio
#include "csd-xsettings-gtk.h"
static void
gtk_modules_callback (CsdXSettingsGtk *gtk,
GParamSpec *spec,
gpointer user_data)
{
const char *modules;
modules = csd_xsettings_gtk_get_modules (gtk);
g_message ("GTK+ modules list changed to: %s", modules ? modules : "(empty)");
}
int main (int argc, char **argv)
{
GMainLoop *loop;
CsdXSettingsGtk *gtk;
gtk = csd_xsettings_gtk_new ();
g_signal_connect (G_OBJECT (gtk), "notify::gtk-modules",
G_CALLBACK (gtk_modules_callback), NULL);
gtk_modules_callback (gtk, NULL, NULL);
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}
cinnamon-settings-daemon-5.2.0/plugins/xsettings/csd-xsettings-gtk.h 0000664 0001750 0001750 00000004144 14144454032 024613 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#ifndef __CSD_XSETTINGS_GTK_H__
#define __CSD_XSETTINGS_GTK_H__
#include
#include
#include
G_BEGIN_DECLS
#define CSD_TYPE_XSETTINGS_GTK (csd_xsettings_gtk_get_type ())
#define CSD_XSETTINGS_GTK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CSD_TYPE_XSETTINGS_GTK, CsdXSettingsGtk))
#define CSD_XSETTINGS_GTK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CSD_TYPE_XSETTINGS_GTK, CsdXSettingsGtkClass))
#define CSD_IS_XSETTINGS_GTK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSD_TYPE_XSETTINGS_GTK))
#define CSD_IS_XSETTINGS_GTK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSD_TYPE_XSETTINGS_GTK))
#define CSD_XSETTINGS_GTK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CSD_TYPE_XSETTINGS_GTK, CsdXSettingsGtkClass))
typedef struct CsdXSettingsGtkPrivate CsdXSettingsGtkPrivate;
typedef struct
{
GObject parent;
CsdXSettingsGtkPrivate *priv;
} CsdXSettingsGtk;
typedef struct
{
GObjectClass parent_class;
} CsdXSettingsGtkClass;
GType csd_xsettings_gtk_get_type (void) G_GNUC_CONST;
CsdXSettingsGtk *csd_xsettings_gtk_new (void);
const char * csd_xsettings_gtk_get_modules (CsdXSettingsGtk *gtk);
G_END_DECLS
#endif /* __CSD_XSETTINGS_GTK_H__ */
cinnamon-settings-daemon-5.2.0/plugins/xsettings/fontconfig-monitor.c 0000664 0001750 0001750 00000011423 14144454032 025043 0 ustar fabio fabio /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
* Author: Behdad Esfahbod, Red Hat, Inc.
*/
#include "fontconfig-monitor.h"
#include
#include
#define TIMEOUT_SECONDS 2
static void
stuff_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer handle);
void
fontconfig_cache_init (void)
{
FcInit ();
}
gboolean
fontconfig_cache_update (void)
{
return !FcConfigUptoDate (NULL) && FcInitReinitialize ();
}
static void
monitor_files (GPtrArray *monitors,
FcStrList *list,
gpointer data)
{
const char *str;
while ((str = (const char *) FcStrListNext (list))) {
GFile *file;
GFileMonitor *monitor;
file = g_file_new_for_path (str);
monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
if (!monitor)
continue;
g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), data);
g_ptr_array_add (monitors, monitor);
}
FcStrListDone (list);
}
struct _fontconfig_monitor_handle {
GPtrArray *monitors;
guint timeout;
GFunc notify_callback;
gpointer notify_data;
};
static GPtrArray *
monitors_create (gpointer data)
{
GPtrArray *monitors = g_ptr_array_new ();
monitor_files (monitors, FcConfigGetConfigFiles (NULL), data);
monitor_files (monitors, FcConfigGetFontDirs (NULL) , data);
return monitors;
}
static void
monitors_free (GPtrArray *monitors)
{
if (!monitors)
return;
g_ptr_array_foreach (monitors, (GFunc) g_object_unref, NULL);
g_ptr_array_free (monitors, TRUE);
}
static gboolean
update (gpointer data)
{
fontconfig_monitor_handle_t *handle = data;
gboolean notify = FALSE;
handle->timeout = 0;
if (fontconfig_cache_update ()) {
notify = TRUE;
monitors_free (handle->monitors);
handle->monitors = monitors_create (data);
}
/* we finish modifying handle before calling the notify callback,
* allowing the callback to free the monitor if it decides to. */
if (notify && handle->notify_callback)
handle->notify_callback (data, handle->notify_data);
return FALSE;
}
static void
stuff_changed (GFileMonitor *monitor G_GNUC_UNUSED,
GFile *file G_GNUC_UNUSED,
GFile *other_file G_GNUC_UNUSED,
GFileMonitorEvent event_type G_GNUC_UNUSED,
gpointer data)
{
fontconfig_monitor_handle_t *handle = data;
/* wait for quiescence */
if (handle->timeout) {
g_source_remove (handle->timeout);
handle->timeout = 0;
}
handle->timeout = g_timeout_add_seconds (TIMEOUT_SECONDS, update, data);
}
fontconfig_monitor_handle_t *
fontconfig_monitor_start (GFunc notify_callback,
gpointer notify_data)
{
fontconfig_monitor_handle_t *handle = g_slice_new0 (fontconfig_monitor_handle_t);
handle->notify_callback = notify_callback;
handle->notify_data = notify_data;
handle->monitors = monitors_create (handle);
return handle;
}
void
fontconfig_monitor_stop (fontconfig_monitor_handle_t *handle)
{
if (handle->timeout) {
g_source_remove (handle->timeout);
handle->timeout = 0;
}
monitors_free (handle->monitors);
handle->monitors = NULL;
}
#ifdef FONTCONFIG_MONITOR_TEST
static void
yay (void)
{
g_message ("yay");
}
int
main (void)
{
GMainLoop *loop;
fontconfig_monitor_start ((GFunc) yay, NULL);
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}
#endif
cinnamon-settings-daemon-5.2.0/plugins/xsettings/csd-xsettings-gtk.c 0000664 0001750 0001750 00000030212 14144454032 024601 0 ustar fabio fabio /* -*- 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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA.
*
*/
#include "config.h"
#include
#include
#include "csd-xsettings-gtk.h"
#define XSETTINGS_PLUGIN_SCHEMA "org.cinnamon.settings-daemon.plugins.xsettings"
#define GTK_MODULES_DISABLED_KEY "disabled-gtk-modules"
#define GTK_MODULES_ENABLED_KEY "enabled-gtk-modules"
enum {
PROP_0,
PROP_GTK_MODULES
};
struct CsdXSettingsGtkPrivate {
char *modules;
GHashTable *dir_modules;
GSettings *settings;
guint64 dir_mtime;
GFileMonitor *monitor;
GList *cond_settings;
};
#define CSD_XSETTINGS_GTK_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), CSD_TYPE_XSETTINGS_GTK, CsdXSettingsGtkPrivate))
G_DEFINE_TYPE(CsdXSettingsGtk, csd_xsettings_gtk, G_TYPE_OBJECT)
static void update_gtk_modules (CsdXSettingsGtk *gtk);
static void
empty_cond_settings_list (CsdXSettingsGtk *gtk)
{
if (gtk->priv->cond_settings == NULL)
return;
/* Empty the list of settings */
g_list_foreach (gtk->priv->cond_settings, (GFunc) g_object_unref, NULL);
g_list_free (gtk->priv->cond_settings);
gtk->priv->cond_settings = NULL;
}
static void
cond_setting_changed (GSettings *settings,
const char *key,
CsdXSettingsGtk *gtk)
{
gboolean enabled;
const char *module_name;
module_name = g_object_get_data (G_OBJECT (settings), "module-name");
enabled = g_settings_get_boolean (settings, key);
if (enabled != FALSE) {
if (gtk->priv->dir_modules == NULL)
gtk->priv->dir_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_hash_table_insert (gtk->priv->dir_modules, g_strdup (module_name), NULL);
} else if (gtk->priv->dir_modules != NULL) {
g_hash_table_remove (gtk->priv->dir_modules, module_name);
}
update_gtk_modules (gtk);
}
static char *
process_desktop_file (const char *path,
CsdXSettingsGtk *gtk)
{
GKeyFile *keyfile;
char *retval;
char *module_name;
retval = NULL;
if (g_str_has_suffix (path, ".desktop") == FALSE &&
g_str_has_suffix (path, ".gtk-module") == FALSE)
return retval;
keyfile = g_key_file_new ();
if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL) == FALSE)
goto bail;
if (g_key_file_has_group (keyfile, "GTK Module") == FALSE)
goto bail;
module_name = g_key_file_get_string (keyfile, "GTK Module", "X-GTK-Module-Name", NULL);
if (module_name == NULL)
goto bail;
if (g_key_file_has_key (keyfile, "GTK Module", "X-GTK-Module-Enabled-Schema", NULL) != FALSE) {
char *schema;
char *key;
gboolean enabled;
GSettings *settings;
char *signal;
schema = g_key_file_get_string (keyfile, "GTK Module", "X-GTK-Module-Enabled-Schema", NULL);
key = g_key_file_get_string (keyfile, "GTK Module", "X-GTK-Module-Enabled-Key", NULL);
settings = g_settings_new (schema);
enabled = g_settings_get_boolean (settings, key);
gtk->priv->cond_settings = g_list_prepend (gtk->priv->cond_settings, settings);
g_object_set_data_full (G_OBJECT (settings), "module-name", g_strdup (module_name), (GDestroyNotify) g_free);
signal = g_strdup_printf ("changed::%s", key);
g_signal_connect_object (G_OBJECT (settings), signal, G_CALLBACK (cond_setting_changed), gtk, 0);
g_free (signal);
g_free (schema);
g_free (key);
if (enabled != FALSE)
retval = g_strdup (module_name);
} else {
retval = g_strdup (module_name);
}
g_free (module_name);
bail:
g_key_file_free (keyfile);
return retval;
}
static void
get_gtk_modules_from_dir (CsdXSettingsGtk *gtk)
{
GFile *file;
GFileInfo *info;
GHashTable *ht;
file = g_file_new_for_path (GTK_MODULES_DIRECTORY);
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (info != NULL) {
guint64 dir_mtime;
dir_mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
if (gtk->priv->dir_mtime == 0 ||
dir_mtime > gtk->priv->dir_mtime) {
GDir *dir;
const char *name;
empty_cond_settings_list (gtk);
gtk->priv->dir_mtime = dir_mtime;
if (gtk->priv->dir_modules != NULL) {
g_hash_table_destroy (gtk->priv->dir_modules);
gtk->priv->dir_modules = NULL;
}
dir = g_dir_open (GTK_MODULES_DIRECTORY, 0, NULL);
if (dir == NULL)
goto bail;
ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
while ((name = g_dir_read_name (dir)) != NULL) {
char *path;
char *module;
path = g_build_filename (GTK_MODULES_DIRECTORY, name, NULL);
module = process_desktop_file (path, gtk);
if (module != NULL)
g_hash_table_insert (ht, module, NULL);
g_free (path);
}
g_dir_close (dir);
gtk->priv->dir_modules = ht;
}
} else {
empty_cond_settings_list (gtk);
}
bail:
if (info != NULL)
g_object_unref (info);
g_object_unref (file);
}
static void
stringify_gtk_modules (gpointer key,
gpointer value,
GString *str)
{
if (str->len != 0)
g_string_append_c (str, ':');
g_string_append (str, key);
}
static void
update_gtk_modules (CsdXSettingsGtk *gtk)
{
char **enabled, **disabled;
GHashTable *ht;
guint i;
GString *str;
char *modules;
enabled = g_settings_get_strv (gtk->priv->settings, GTK_MODULES_ENABLED_KEY);
disabled = g_settings_get_strv (gtk->priv->settings, GTK_MODULES_DISABLED_KEY);
ht = g_hash_table_new (g_str_hash, g_str_equal);
if (gtk->priv->dir_modules != NULL) {
GList *list, *l;
list = g_hash_table_get_keys (gtk->priv->dir_modules);
for (l = list; l != NULL; l = l->next) {
g_hash_table_insert (ht, l->data, NULL);
}
g_list_free (list);
}
for (i = 0; enabled[i] != NULL; i++)
g_hash_table_insert (ht, enabled[i], NULL);
for (i = 0; disabled[i] != NULL; i++)
g_hash_table_remove (ht, disabled[i]);
str = g_string_new (NULL);
g_hash_table_foreach (ht, (GHFunc) stringify_gtk_modules, str);
g_hash_table_destroy (ht);
modules = g_string_free (str, FALSE);
if (modules == NULL ||
gtk->priv->modules == NULL ||
g_str_equal (modules, gtk->priv->modules) == FALSE) {
g_free (gtk->priv->modules);
gtk->priv->modules = modules;
g_object_notify (G_OBJECT (gtk), "gtk-modules");
} else {
g_free (modules);
}
g_strfreev (enabled);
g_strfreev (disabled);
}
static void
gtk_modules_dir_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
CsdXSettingsGtk *gtk)
{
get_gtk_modules_from_dir (gtk);
update_gtk_modules (gtk);
}
static void
csd_xsettings_gtk_init (CsdXSettingsGtk *gtk)
{
GFile *file;
gtk->priv = CSD_XSETTINGS_GTK_GET_PRIVATE (gtk);
g_debug ("CsdXSettingsGtk initializing");
gtk->priv->settings = g_settings_new (XSETTINGS_PLUGIN_SCHEMA);
get_gtk_modules_from_dir (gtk);
file = g_file_new_for_path (GTK_MODULES_DIRECTORY);
gtk->priv->monitor = g_file_monitor (file,
G_FILE_MONITOR_NONE,
NULL,
NULL);
g_signal_connect (G_OBJECT (gtk->priv->monitor), "changed",
G_CALLBACK (gtk_modules_dir_changed_cb), gtk);
g_object_unref (file);
update_gtk_modules (gtk);
}
static void
csd_xsettings_gtk_finalize (GObject *object)
{
CsdXSettingsGtk *gtk;
g_return_if_fail (object != NULL);
g_return_if_fail (CSD_IS_XSETTINGS_GTK (object));
g_debug ("CsdXSettingsGtk finalizing");
gtk = CSD_XSETTINGS_GTK (object);
g_return_if_fail (gtk->priv != NULL);
g_free (gtk->priv->modules);
gtk->priv->modules = NULL;
if (gtk->priv->dir_modules != NULL) {
g_hash_table_destroy (gtk->priv->dir_modules);
gtk->priv->dir_modules = NULL;
}
g_object_unref (gtk->priv->settings);
if (gtk->priv->monitor != NULL)
g_object_unref (gtk->priv->monitor);
empty_cond_settings_list (gtk);
G_OBJECT_CLASS (csd_xsettings_gtk_parent_class)->finalize (object);
}
static void
csd_xsettings_gtk_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CsdXSettingsGtk *self;
self = CSD_XSETTINGS_GTK (object);
switch (prop_id) {
case PROP_GTK_MODULES:
g_value_set_string (value, self->priv->modules);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
csd_xsettings_gtk_class_init (CsdXSettingsGtkClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = csd_xsettings_gtk_get_property;
object_class->finalize = csd_xsettings_gtk_finalize;
g_object_class_install_property (object_class, PROP_GTK_MODULES,
g_param_spec_string ("gtk-modules", NULL, NULL,
NULL, G_PARAM_READABLE));
g_type_class_add_private (klass, sizeof (CsdXSettingsGtkPrivate));
}
CsdXSettingsGtk *
csd_xsettings_gtk_new (void)
{
return CSD_XSETTINGS_GTK (g_object_new (CSD_TYPE_XSETTINGS_GTK, NULL));
}
const char *
csd_xsettings_gtk_get_modules (CsdXSettingsGtk *gtk)
{
return gtk->priv->modules;
}
cinnamon-settings-daemon-5.2.0/plugins/xsettings/xsettings-manager.c 0000664 0001750 0001750 00000025607 14144454032 024673 0 ustar fabio fabio /*
* Copyright © 2001 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor, Red Hat, Inc.
*/
#include
#include
#include