Merge branch 'statusmenu'
svn path=/trunk/; revision=183
This commit is contained in:
parent
48e578ddaa
commit
b7a0a5e769
@ -21,6 +21,7 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
|||||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 dbus-glib-1 metacity-plugins gjs-gi-1.0)
|
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 dbus-glib-1 metacity-plugins gjs-gi-1.0)
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-0.8)
|
PKG_CHECK_MODULES(TIDY, clutter-0.8)
|
||||||
PKG_CHECK_MODULES(BIG, clutter-cairo-0.8 gtk+-2.0 librsvg-2.0)
|
PKG_CHECK_MODULES(BIG, clutter-cairo-0.8 gtk+-2.0 librsvg-2.0)
|
||||||
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TASKPANEL, libwnck-1.0 dbus-glib-1)
|
PKG_CHECK_MODULES(TASKPANEL, libwnck-1.0 dbus-glib-1)
|
||||||
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
|
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
|
||||||
|
@ -1,29 +1,21 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Big = imports.gi.Big;
|
||||||
const Tweener = imports.tweener.tweener;
|
const Tweener = imports.tweener.tweener;
|
||||||
|
|
||||||
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
||||||
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddccff);
|
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
||||||
|
|
||||||
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
|
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
|
||||||
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaaff);
|
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
|
||||||
|
|
||||||
// Time for animation making the button darker
|
function Button(widget, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
|
||||||
const ANIMATION_TIME = 0.3;
|
this._init(widget, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight);
|
||||||
|
|
||||||
const NO_OPACITY = 0;
|
|
||||||
|
|
||||||
const PARTIAL_OPACITY = 0.4 * 255;
|
|
||||||
|
|
||||||
const FULL_OPACITY = 255;
|
|
||||||
|
|
||||||
function Button(text, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
|
|
||||||
this._init(text, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button.prototype = {
|
Button.prototype = {
|
||||||
_init : function(text, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
|
_init : function(widgetOrText, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
|
||||||
let me = this;
|
let me = this;
|
||||||
|
|
||||||
this._buttonColor = buttonColor
|
this._buttonColor = buttonColor
|
||||||
@ -47,29 +39,29 @@ Button.prototype = {
|
|||||||
this._isBetweenPressAndRelease = false;
|
this._isBetweenPressAndRelease = false;
|
||||||
this._mouseIsOverButton = false;
|
this._mouseIsOverButton = false;
|
||||||
|
|
||||||
this.button = new Clutter.Group({reactive: true});
|
this.button = new Big.Box({ reactive: true,
|
||||||
this._background = new Clutter.Rectangle({ color: this._buttonColor});
|
corner_radius: 5,
|
||||||
this._pressedBackground = new Clutter.Rectangle({ color: this._pressedButtonColor, opacity: NO_OPACITY});
|
padding_left: 4,
|
||||||
this._label = new Clutter.Label({ font_name: "Sans Bold 16px",
|
padding_right: 4,
|
||||||
text: text});
|
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
this._label.set_position(5, 5);
|
y_align: Big.BoxAlignment.CENTER
|
||||||
let backgroundWidth = Math.max(this._label.get_width()+10, minWidth);
|
});
|
||||||
let backgroundHeight = Math.max(this._label.get_height()+10, minHeight);
|
if (typeof widgetOrText == 'string') {
|
||||||
this._background.set_width(backgroundWidth)
|
this._widget = new Clutter.Label({ font_name: "Sans Bold 16px",
|
||||||
this._background.set_height(backgroundHeight)
|
text: widgetOrText });
|
||||||
this._pressedBackground.set_width(backgroundWidth)
|
} else {
|
||||||
this._pressedBackground.set_height(backgroundHeight)
|
this._widget = widgetOrText;
|
||||||
this.button.add_actor(this._background);
|
}
|
||||||
this.button.add_actor(this._pressedBackground);
|
|
||||||
this.button.add_actor(this._label);
|
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
this._minWidth = minWidth;
|
||||||
|
this._minHeight = minHeight;
|
||||||
|
|
||||||
this.button.connect('button-press-event',
|
this.button.connect('button-press-event',
|
||||||
function(o, event) {
|
function(o, event) {
|
||||||
me._isBetweenPressAndRelease = true;
|
me._isBetweenPressAndRelease = true;
|
||||||
Tweener.addTween(me._pressedBackground,
|
me.button.backgroundColor = me._pressedButtonColor;
|
||||||
{ time: ANIMATION_TIME,
|
|
||||||
opacity: FULL_OPACITY,
|
|
||||||
transition: "linear"
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
this.button.connect('button-release-event',
|
this.button.connect('button-release-event',
|
||||||
@ -86,8 +78,7 @@ Button.prototype = {
|
|||||||
function(o, event) {
|
function(o, event) {
|
||||||
me._mouseIsOverButton = true;
|
me._mouseIsOverButton = true;
|
||||||
if (!me._active) {
|
if (!me._active) {
|
||||||
Tweener.removeTweens(me._pressedBackground);
|
me.button.backgroundColor = me._buttonColor;
|
||||||
me._pressedBackground.set_opacity(PARTIAL_OPACITY);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -96,8 +87,7 @@ Button.prototype = {
|
|||||||
me._isBetweenPressAndRelease = false;
|
me._isBetweenPressAndRelease = false;
|
||||||
me._mouseIsOverButton = false;
|
me._mouseIsOverButton = false;
|
||||||
if (!me._active) {
|
if (!me._active) {
|
||||||
Tweener.removeTweens(me._pressedBackground);
|
me.button.backgroundColor = null;
|
||||||
me._pressedBackground.set_opacity(NO_OPACITY);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -106,11 +96,10 @@ Button.prototype = {
|
|||||||
release : function() {
|
release : function() {
|
||||||
if (!this._isBetweenPressAndRelease) {
|
if (!this._isBetweenPressAndRelease) {
|
||||||
this._active = false;
|
this._active = false;
|
||||||
Tweener.removeTweens(this._pressedBackground);
|
|
||||||
if (this._mouseIsOverButton) {
|
if (this._mouseIsOverButton) {
|
||||||
this._pressedBackground.set_opacity(PARTIAL_OPACITY);
|
this.button.backgroundColor = this._buttonColor;
|
||||||
} else {
|
} else {
|
||||||
this._pressedBackground.set_opacity(NO_OPACITY);
|
this.button.backgroundColor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ const PANEL_HEIGHT = 32;
|
|||||||
const TRAY_HEIGHT = 24;
|
const TRAY_HEIGHT = 24;
|
||||||
const PANEL_BACKGROUND_COLOR = new Clutter.Color();
|
const PANEL_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
PANEL_BACKGROUND_COLOR.from_pixel(0xeeddccff);
|
PANEL_BACKGROUND_COLOR.from_pixel(0xeeddccff);
|
||||||
|
const PANEL_BUTTON_COLOR = new Clutter.Color();
|
||||||
|
PANEL_BUTTON_COLOR.from_pixel(0xccbbaa66);
|
||||||
const PANEL_BORDER_COLOR = new Clutter.Color();
|
const PANEL_BORDER_COLOR = new Clutter.Color();
|
||||||
PANEL_BORDER_COLOR.from_pixel(0x000000ff);
|
PANEL_BORDER_COLOR.from_pixel(0x000000ff);
|
||||||
const PRESSED_BUTTON_BACKGROUND_COLOR = new Clutter.Color();
|
const PRESSED_BUTTON_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
@ -37,10 +39,25 @@ Panel.prototype = {
|
|||||||
border_bottom: 1,
|
border_bottom: 1,
|
||||||
border_color: PANEL_BORDER_COLOR });
|
border_color: PANEL_BORDER_COLOR });
|
||||||
|
|
||||||
this.button = new Button.Button("Activities", PANEL_BACKGROUND_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT);
|
this.button = new Button.Button("Activities", PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT);
|
||||||
|
|
||||||
this._box.append(this.button.button, Big.BoxPackFlags.NONE);
|
this._box.append(this.button.button, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
let statusbox = new Big.Box();
|
||||||
|
this._statusmenu = new Shell.StatusMenu();
|
||||||
|
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
|
||||||
|
let statusbutton = new Button.Button(statusbox, PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||||
|
true, null, PANEL_HEIGHT);
|
||||||
|
statusbutton.button.connect('button-press-event', function (b, e) {
|
||||||
|
me._statusmenu.toggle(e);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
this._box.append(statusbutton.button, Big.BoxPackFlags.END);
|
||||||
|
// We get a deactivated event when the popup disappears
|
||||||
|
this._statusmenu.connect('deactivated', function (sm) {
|
||||||
|
statusbutton.release();
|
||||||
|
});
|
||||||
|
|
||||||
this._clock = new Clutter.Label({ font_name: "Sans Bold 16px",
|
this._clock = new Clutter.Label({ font_name: "Sans Bold 16px",
|
||||||
text: "" });
|
text: "" });
|
||||||
let pad = (PANEL_HEIGHT - this._clock.height) / 2;
|
let pad = (PANEL_HEIGHT - this._clock.height) / 2;
|
||||||
|
@ -7,6 +7,7 @@ noinst_LTLIBRARIES =
|
|||||||
|
|
||||||
include Makefile-tidy.am
|
include Makefile-tidy.am
|
||||||
include Makefile-big.am
|
include Makefile-big.am
|
||||||
|
include Makefile-gdmuser.am
|
||||||
include Makefile-tray.am
|
include Makefile-tray.am
|
||||||
include Makefile-taskpanel.am
|
include Makefile-taskpanel.am
|
||||||
|
|
||||||
@ -42,6 +43,8 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-process.h \
|
shell-process.h \
|
||||||
shell-global.c \
|
shell-global.c \
|
||||||
shell-global.h \
|
shell-global.h \
|
||||||
|
shell-status-menu.c \
|
||||||
|
shell-status-menu.h \
|
||||||
shell-tray-manager.c \
|
shell-tray-manager.c \
|
||||||
shell-tray-manager.h \
|
shell-tray-manager.h \
|
||||||
shell-wm.c \
|
shell-wm.c \
|
||||||
@ -77,6 +80,7 @@ libgnome_shell_la_LIBADD = \
|
|||||||
$(MUTTER_PLUGIN_LIBS) \
|
$(MUTTER_PLUGIN_LIBS) \
|
||||||
$(LIBGNOMEUI_LIBS) \
|
$(LIBGNOMEUI_LIBS) \
|
||||||
libbig-1.0.la \
|
libbig-1.0.la \
|
||||||
|
libgdmuser-1.0.la \
|
||||||
libtidy-1.0.la \
|
libtidy-1.0.la \
|
||||||
libtray.la
|
libtray.la
|
||||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||||
@ -84,13 +88,15 @@ libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
|||||||
typelibdir = $(pkglibdir)
|
typelibdir = $(pkglibdir)
|
||||||
typelib_DATA = Shell-0.1.typelib Tidy-1.0.typelib Big-1.0.typelib
|
typelib_DATA = Shell-0.1.typelib Tidy-1.0.typelib Big-1.0.typelib
|
||||||
|
|
||||||
Shell-0.1.gir: $(metacity) $(G_IR_SCANNER) libgnome-shell.la Makefile
|
Shell-0.1.gir: $(metacity) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
|
||||||
$(G_IR_SCANNER) \
|
$(G_IR_SCANNER) \
|
||||||
--namespace=Shell \
|
--namespace=Shell \
|
||||||
--nsversion=0.1 \
|
--nsversion=0.1 \
|
||||||
--add-include-path=$(libdir)/metacity/ \
|
--add-include-path=$(libdir)/metacity/ \
|
||||||
--include=Clutter-0.8 \
|
--include=Clutter-0.8 \
|
||||||
--include=Meta-2.25 \
|
--include=Meta-2.25 \
|
||||||
|
--add-include-path=$(builddir) \
|
||||||
|
--include=Big-1.0 \
|
||||||
--program=metacity \
|
--program=metacity \
|
||||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||||
$(libgnome_shell_la_gir_sources) \
|
$(libgnome_shell_la_gir_sources) \
|
||||||
@ -101,7 +107,7 @@ CLEANFILES += Shell-1.0.gir
|
|||||||
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
||||||
# (not the fake library, since we've already done the rewriting)
|
# (not the fake library, since we've already done the rewriting)
|
||||||
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir
|
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir
|
||||||
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler --includedir=$(libdir)/metacity/ Shell-0.1.gir -o $@
|
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler --includedir=$(builddir) --includedir=$(libdir)/metacity/ Shell-0.1.gir -o $@
|
||||||
CLEANFILES += Shell-1.0.typelib
|
CLEANFILES += Shell-1.0.typelib
|
||||||
|
|
||||||
Tidy-1.0.gir: $(metacity) $(G_IR_SCANNER) libgnome-shell.la libtidy-1.0.la Makefile
|
Tidy-1.0.gir: $(metacity) $(G_IR_SCANNER) libgnome-shell.la libtidy-1.0.la Makefile
|
||||||
|
208
src/gdmuser/gdm-user-chooser-dialog.c
Normal file
208
src/gdmuser/gdm-user-chooser-dialog.c
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "gdm-user-chooser-widget.h"
|
||||||
|
#include "gdm-user-chooser-dialog.h"
|
||||||
|
|
||||||
|
#define GDM_USER_CHOOSER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogPrivate))
|
||||||
|
|
||||||
|
struct GdmUserChooserDialogPrivate
|
||||||
|
{
|
||||||
|
GtkWidget *chooser_widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass);
|
||||||
|
static void gdm_user_chooser_dialog_init (GdmUserChooserDialog *user_chooser_dialog);
|
||||||
|
static void gdm_user_chooser_dialog_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmUserChooserDialog, gdm_user_chooser_dialog, GTK_TYPE_DIALOG)
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog)
|
||||||
|
{
|
||||||
|
char *user_name;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog), NULL);
|
||||||
|
|
||||||
|
user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget));
|
||||||
|
|
||||||
|
return user_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_dialog_set_show_user_other (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||||
|
|
||||||
|
gdm_user_chooser_widget_set_show_user_other (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||||
|
|
||||||
|
gdm_user_chooser_widget_set_show_user_guest (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
|
||||||
|
|
||||||
|
gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_user_chooser_dialog_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmUserChooserDialog *user_chooser_dialog;
|
||||||
|
|
||||||
|
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
return G_OBJECT (user_chooser_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_user_chooser_dialog_get_property;
|
||||||
|
object_class->set_property = gdm_user_chooser_dialog_set_property;
|
||||||
|
object_class->constructor = gdm_user_chooser_dialog_constructor;
|
||||||
|
object_class->dispose = gdm_user_chooser_dialog_dispose;
|
||||||
|
object_class->finalize = gdm_user_chooser_dialog_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GdmUserChooserDialogPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_response (GdmUserChooserDialog *dialog,
|
||||||
|
gint response_id)
|
||||||
|
{
|
||||||
|
switch (response_id) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_init (GdmUserChooserDialog *dialog)
|
||||||
|
{
|
||||||
|
|
||||||
|
dialog->priv = GDM_USER_CHOOSER_DIALOG_GET_PRIVATE (dialog);
|
||||||
|
|
||||||
|
dialog->priv->chooser_widget = gdm_user_chooser_widget_new ();
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dialog->priv->chooser_widget);
|
||||||
|
|
||||||
|
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||||
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
||||||
|
NULL);
|
||||||
|
g_signal_connect (dialog,
|
||||||
|
"response",
|
||||||
|
G_CALLBACK (on_response),
|
||||||
|
dialog);
|
||||||
|
|
||||||
|
gtk_widget_show_all (GTK_WIDGET (dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_dialog_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmUserChooserDialog *user_chooser_dialog;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (object));
|
||||||
|
|
||||||
|
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (object);
|
||||||
|
|
||||||
|
g_return_if_fail (user_chooser_dialog->priv != NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gdm_user_chooser_dialog_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_USER_CHOOSER_DIALOG,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (object);
|
||||||
|
}
|
62
src/gdmuser/gdm-user-chooser-dialog.h
Normal file
62
src/gdmuser/gdm-user-chooser-dialog.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_USER_CHOOSER_DIALOG_H
|
||||||
|
#define __GDM_USER_CHOOSER_DIALOG_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtkdialog.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_USER_CHOOSER_DIALOG (gdm_user_chooser_dialog_get_type ())
|
||||||
|
#define GDM_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialog))
|
||||||
|
#define GDM_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
|
||||||
|
#define GDM_IS_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_DIALOG))
|
||||||
|
#define GDM_IS_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_DIALOG))
|
||||||
|
#define GDM_USER_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
|
||||||
|
|
||||||
|
typedef struct GdmUserChooserDialogPrivate GdmUserChooserDialogPrivate;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GtkDialog parent;
|
||||||
|
GdmUserChooserDialogPrivate *priv;
|
||||||
|
} GdmUserChooserDialog;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GtkDialogClass parent_class;
|
||||||
|
} GdmUserChooserDialogClass;
|
||||||
|
|
||||||
|
GType gdm_user_chooser_dialog_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget * gdm_user_chooser_dialog_new (void);
|
||||||
|
|
||||||
|
char * gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog);
|
||||||
|
void gdm_user_chooser_dialog_set_show_other_user (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show);
|
||||||
|
void gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show);
|
||||||
|
void gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
|
||||||
|
gboolean show);
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_USER_CHOOSER_DIALOG_H */
|
723
src/gdmuser/gdm-user-chooser-widget.c
Normal file
723
src/gdmuser/gdm-user-chooser-widget.c
Normal file
@ -0,0 +1,723 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
* Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <gconf/gconf-client.h>
|
||||||
|
|
||||||
|
#include "gdm-user-manager.h"
|
||||||
|
#include "gdm-user-chooser-widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define KEY_DISABLE_USER_LIST "/apps/gdm/simple-greeter/disable_user_list"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
USER_NO_DISPLAY = 1 << 0,
|
||||||
|
USER_ACCOUNT_DISABLED = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_USER_ICON "stock_person"
|
||||||
|
|
||||||
|
#define GDM_USER_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetPrivate))
|
||||||
|
|
||||||
|
#define MAX_ICON_SIZE 128
|
||||||
|
|
||||||
|
struct GdmUserChooserWidgetPrivate
|
||||||
|
{
|
||||||
|
GdmUserManager *manager;
|
||||||
|
GtkIconTheme *icon_theme;
|
||||||
|
|
||||||
|
GdkPixbuf *logged_in_pixbuf;
|
||||||
|
GdkPixbuf *stock_person_pixbuf;
|
||||||
|
|
||||||
|
guint loaded : 1;
|
||||||
|
guint show_user_other : 1;
|
||||||
|
guint show_user_guest : 1;
|
||||||
|
guint show_user_auto : 1;
|
||||||
|
guint show_normal_users : 1;
|
||||||
|
|
||||||
|
guint load_idle_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_SHOW_USER_GUEST,
|
||||||
|
PROP_SHOW_USER_AUTO,
|
||||||
|
PROP_SHOW_USER_OTHER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass);
|
||||||
|
static void gdm_user_chooser_widget_init (GdmUserChooserWidget *user_chooser_widget);
|
||||||
|
static void gdm_user_chooser_widget_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmUserChooserWidget, gdm_user_chooser_widget, GDM_TYPE_CHOOSER_WIDGET)
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_font_height_for_widget (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
PangoFontMetrics *metrics;
|
||||||
|
PangoContext *context;
|
||||||
|
int ascent;
|
||||||
|
int descent;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
gtk_widget_ensure_style (widget);
|
||||||
|
context = gtk_widget_get_pango_context (widget);
|
||||||
|
metrics = pango_context_get_metrics (context,
|
||||||
|
widget->style->font_desc,
|
||||||
|
pango_context_get_language (context));
|
||||||
|
|
||||||
|
ascent = pango_font_metrics_get_ascent (metrics);
|
||||||
|
descent = pango_font_metrics_get_descent (metrics);
|
||||||
|
height = PANGO_PIXELS (ascent + descent);
|
||||||
|
pango_font_metrics_unref (metrics);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_icon_height_for_widget (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
int font_height;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
font_height = get_font_height_for_widget (widget);
|
||||||
|
height = 3 * font_height;
|
||||||
|
if (height > MAX_ICON_SIZE) {
|
||||||
|
height = MAX_ICON_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: font height %d; using icon size %d", font_height, height);
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_user_other (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_OTHER,
|
||||||
|
NULL,
|
||||||
|
_("Other..."),
|
||||||
|
_("Choose a different account"),
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_user_guest (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_GUEST,
|
||||||
|
widget->priv->stock_person_pixbuf,
|
||||||
|
_("Guest"),
|
||||||
|
_("Login as a temporary guest"),
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_user_auto (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_AUTO,
|
||||||
|
NULL,
|
||||||
|
_("Automatic Login"),
|
||||||
|
_("Automatically login to the system after selecting options"),
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_user_other (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_user_guest (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_GUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_user_auto (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_USER_CHOOSER_USER_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
if (widget->priv->show_user_other != show_user) {
|
||||||
|
widget->priv->show_user_other = show_user;
|
||||||
|
if (show_user) {
|
||||||
|
add_user_other (widget);
|
||||||
|
} else {
|
||||||
|
remove_user_other (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
if (widget->priv->show_user_guest != show_user) {
|
||||||
|
widget->priv->show_user_guest = show_user;
|
||||||
|
if (show_user) {
|
||||||
|
add_user_guest (widget);
|
||||||
|
} else {
|
||||||
|
remove_user_guest (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show_user)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
if (widget->priv->show_user_auto != show_user) {
|
||||||
|
widget->priv->show_user_auto = show_user;
|
||||||
|
if (show_user) {
|
||||||
|
add_user_auto (widget);
|
||||||
|
} else {
|
||||||
|
remove_user_auto (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL);
|
||||||
|
|
||||||
|
return gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
gdm_chooser_widget_set_active_item (GDM_CHOOSER_WIDGET (widget), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show_only) {
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
gdm_chooser_widget_set_hide_inactive_items (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
show_only);
|
||||||
|
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmUserChooserWidget *self;
|
||||||
|
|
||||||
|
self = GDM_USER_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SHOW_USER_AUTO:
|
||||||
|
gdm_user_chooser_widget_set_show_user_auto (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_USER_GUEST:
|
||||||
|
gdm_user_chooser_widget_set_show_user_guest (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_USER_OTHER:
|
||||||
|
gdm_user_chooser_widget_set_show_user_other (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmUserChooserWidget *self;
|
||||||
|
|
||||||
|
self = GDM_USER_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SHOW_USER_AUTO:
|
||||||
|
g_value_set_boolean (value, self->priv->show_user_auto);
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_USER_GUEST:
|
||||||
|
g_value_set_boolean (value, self->priv->show_user_guest);
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_USER_OTHER:
|
||||||
|
g_value_set_boolean (value, self->priv->show_user_other);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_user_list_disabled (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GConfClient *client;
|
||||||
|
GError *error;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
client = gconf_client_get_default ();
|
||||||
|
error = NULL;
|
||||||
|
result = gconf_client_get_bool (client, KEY_DISABLE_USER_LIST, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GdmUserChooserWidget: unable to get disable-user-list configuration: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
g_object_unref (client);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_user (GdmUserChooserWidget *widget,
|
||||||
|
GdmUser *user)
|
||||||
|
{
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
char *tooltip;
|
||||||
|
gboolean is_logged_in;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (!widget->priv->show_normal_users) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = get_icon_height_for_widget (widget);
|
||||||
|
pixbuf = gdm_user_render_icon (user, size);
|
||||||
|
if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) {
|
||||||
|
pixbuf = g_object_ref (widget->priv->stock_person_pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip = g_strdup_printf (_("Log in as %s"),
|
||||||
|
gdm_user_get_user_name (user));
|
||||||
|
|
||||||
|
is_logged_in = gdm_user_get_num_sessions (user) > 0;
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: User added name:%s logged-in:%d pixbuf:%p",
|
||||||
|
gdm_user_get_user_name (user),
|
||||||
|
is_logged_in,
|
||||||
|
pixbuf);
|
||||||
|
|
||||||
|
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
gdm_user_get_user_name (user),
|
||||||
|
pixbuf,
|
||||||
|
gdm_user_get_real_name (user),
|
||||||
|
tooltip,
|
||||||
|
gdm_user_get_login_frequency (user),
|
||||||
|
is_logged_in,
|
||||||
|
FALSE);
|
||||||
|
g_free (tooltip);
|
||||||
|
|
||||||
|
if (pixbuf != NULL) {
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_added (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
/* wait for all users to be loaded */
|
||||||
|
if (! widget->priv->loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
add_user (widget, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_removed (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
const char *user_name;
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: User removed: %s", gdm_user_get_user_name (user));
|
||||||
|
/* wait for all users to be loaded */
|
||||||
|
if (! widget->priv->loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user_name = gdm_user_get_user_name (user);
|
||||||
|
|
||||||
|
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
user_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_is_logged_in_changed (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
const char *user_name;
|
||||||
|
gboolean is_logged_in;
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: User logged in changed: %s", gdm_user_get_user_name (user));
|
||||||
|
|
||||||
|
user_name = gdm_user_get_user_name (user);
|
||||||
|
is_logged_in = gdm_user_get_num_sessions (user) > 0;
|
||||||
|
|
||||||
|
gdm_chooser_widget_set_item_in_use (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
user_name,
|
||||||
|
is_logged_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_login_frequency_changed (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
const char *user_name;
|
||||||
|
gulong freq;
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: User login frequency changed: %s", gdm_user_get_user_name (user));
|
||||||
|
|
||||||
|
user_name = gdm_user_get_user_name (user);
|
||||||
|
freq = gdm_user_get_login_frequency (user);
|
||||||
|
|
||||||
|
gdm_chooser_widget_set_item_priority (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
user_name,
|
||||||
|
freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_users_loaded (GdmUserManager *manager,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GSList *users;
|
||||||
|
|
||||||
|
widget->priv->loaded = TRUE;
|
||||||
|
|
||||||
|
g_debug ("GdmUserChooserWidget: Users loaded");
|
||||||
|
|
||||||
|
users = gdm_user_manager_list_users (manager);
|
||||||
|
while (users != NULL) {
|
||||||
|
add_user (widget, users->data);
|
||||||
|
users = g_slist_delete_link (users, users);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (widget));
|
||||||
|
|
||||||
|
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
load_users (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (widget->priv->show_normal_users) {
|
||||||
|
widget->priv->manager = gdm_user_manager_ref_default ();
|
||||||
|
g_signal_connect (widget->priv->manager,
|
||||||
|
"user-added",
|
||||||
|
G_CALLBACK (on_user_added),
|
||||||
|
widget);
|
||||||
|
g_signal_connect (widget->priv->manager,
|
||||||
|
"user-removed",
|
||||||
|
G_CALLBACK (on_user_removed),
|
||||||
|
widget);
|
||||||
|
g_signal_connect (widget->priv->manager,
|
||||||
|
"users-loaded",
|
||||||
|
G_CALLBACK (on_users_loaded),
|
||||||
|
widget);
|
||||||
|
g_signal_connect (widget->priv->manager,
|
||||||
|
"user-is-logged-in-changed",
|
||||||
|
G_CALLBACK (on_user_is_logged_in_changed),
|
||||||
|
widget);
|
||||||
|
g_signal_connect (widget->priv->manager,
|
||||||
|
"user-login-frequency-changed",
|
||||||
|
G_CALLBACK (on_user_login_frequency_changed),
|
||||||
|
widget);
|
||||||
|
} else {
|
||||||
|
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->priv->load_idle_id = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_user_chooser_widget_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmUserChooserWidget *widget;
|
||||||
|
|
||||||
|
widget = GDM_USER_CHOOSER_WIDGET (G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
widget->priv->show_normal_users = !is_user_list_disabled (widget);
|
||||||
|
|
||||||
|
widget->priv->load_idle_id = g_idle_add ((GSourceFunc)load_users, widget);
|
||||||
|
|
||||||
|
return G_OBJECT (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GdmUserChooserWidget *widget;
|
||||||
|
|
||||||
|
widget = GDM_USER_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->dispose (object);
|
||||||
|
|
||||||
|
if (widget->priv->load_idle_id > 0) {
|
||||||
|
g_source_remove (widget->priv->load_idle_id);
|
||||||
|
widget->priv->load_idle_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget->priv->logged_in_pixbuf != NULL) {
|
||||||
|
g_object_unref (widget->priv->logged_in_pixbuf);
|
||||||
|
widget->priv->logged_in_pixbuf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget->priv->stock_person_pixbuf != NULL) {
|
||||||
|
g_object_unref (widget->priv->stock_person_pixbuf);
|
||||||
|
widget->priv->stock_person_pixbuf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_user_chooser_widget_get_property;
|
||||||
|
object_class->set_property = gdm_user_chooser_widget_set_property;
|
||||||
|
object_class->constructor = gdm_user_chooser_widget_constructor;
|
||||||
|
object_class->dispose = gdm_user_chooser_widget_dispose;
|
||||||
|
object_class->finalize = gdm_user_chooser_widget_finalize;
|
||||||
|
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_SHOW_USER_AUTO,
|
||||||
|
g_param_spec_boolean ("show-user-auto",
|
||||||
|
"show user auto",
|
||||||
|
"show user auto",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_SHOW_USER_GUEST,
|
||||||
|
g_param_spec_boolean ("show-user-guest",
|
||||||
|
"show user guest",
|
||||||
|
"show user guest",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_SHOW_USER_OTHER,
|
||||||
|
g_param_spec_boolean ("show-user-other",
|
||||||
|
"show user other",
|
||||||
|
"show user other",
|
||||||
|
TRUE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GdmUserChooserWidgetPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *
|
||||||
|
get_stock_person_pixbuf (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = get_icon_height_for_widget (widget);
|
||||||
|
|
||||||
|
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
|
||||||
|
DEFAULT_USER_ICON,
|
||||||
|
size,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *
|
||||||
|
get_logged_in_pixbuf (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = get_icon_height_for_widget (widget);
|
||||||
|
|
||||||
|
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
|
||||||
|
"emblem-default",
|
||||||
|
size / 3,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkPixbuf *old_icon;
|
||||||
|
GdkPixbuf *new_icon;
|
||||||
|
} IconUpdateData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
update_icons (GdmChooserWidget *widget,
|
||||||
|
const char *id,
|
||||||
|
GdkPixbuf **image,
|
||||||
|
char **name,
|
||||||
|
char **comment,
|
||||||
|
gulong *priority,
|
||||||
|
gboolean *is_in_use,
|
||||||
|
gboolean *is_separate,
|
||||||
|
IconUpdateData *data)
|
||||||
|
{
|
||||||
|
if (data->old_icon == *image) {
|
||||||
|
*image = data->new_icon;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_icons (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GdkPixbuf *old_pixbuf;
|
||||||
|
IconUpdateData data;
|
||||||
|
|
||||||
|
if (widget->priv->logged_in_pixbuf != NULL) {
|
||||||
|
g_object_unref (widget->priv->logged_in_pixbuf);
|
||||||
|
}
|
||||||
|
widget->priv->logged_in_pixbuf = get_logged_in_pixbuf (widget);
|
||||||
|
|
||||||
|
old_pixbuf = widget->priv->stock_person_pixbuf;
|
||||||
|
widget->priv->stock_person_pixbuf = get_stock_person_pixbuf (widget);
|
||||||
|
/* update the icons in the model */
|
||||||
|
data.old_icon = old_pixbuf;
|
||||||
|
data.new_icon = widget->priv->stock_person_pixbuf;
|
||||||
|
gdm_chooser_widget_update_foreach_item (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
(GdmChooserUpdateForeachFunc)update_icons,
|
||||||
|
&data);
|
||||||
|
if (old_pixbuf != NULL) {
|
||||||
|
g_object_unref (old_pixbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_icon_theme_changed (GtkIconTheme *icon_theme,
|
||||||
|
GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
g_debug ("GdmUserChooserWidget: icon theme changed");
|
||||||
|
load_icons (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_icons (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
if (gtk_widget_has_screen (GTK_WIDGET (widget))) {
|
||||||
|
widget->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (widget)));
|
||||||
|
} else {
|
||||||
|
widget->priv->icon_theme = gtk_icon_theme_get_default ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget->priv->icon_theme != NULL) {
|
||||||
|
g_signal_connect (widget->priv->icon_theme,
|
||||||
|
"changed",
|
||||||
|
G_CALLBACK (on_icon_theme_changed),
|
||||||
|
widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_icons (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_init (GdmUserChooserWidget *widget)
|
||||||
|
{
|
||||||
|
widget->priv = GDM_USER_CHOOSER_WIDGET_GET_PRIVATE (widget);
|
||||||
|
|
||||||
|
gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
GDM_CHOOSER_WIDGET_POSITION_BOTTOM);
|
||||||
|
gdm_chooser_widget_set_in_use_message (GDM_CHOOSER_WIDGET (widget),
|
||||||
|
_("Currently logged in"));
|
||||||
|
|
||||||
|
setup_icons (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_user_chooser_widget_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmUserChooserWidget *widget;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (object));
|
||||||
|
|
||||||
|
widget = GDM_USER_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
g_return_if_fail (widget->priv != NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gdm_user_chooser_widget_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_USER_CHOOSER_WIDGET,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (object);
|
||||||
|
}
|
70
src/gdmuser/gdm-user-chooser-widget.h
Normal file
70
src/gdmuser/gdm-user-chooser-widget.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_USER_CHOOSER_WIDGET_H
|
||||||
|
#define __GDM_USER_CHOOSER_WIDGET_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-chooser-widget.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_USER_CHOOSER_WIDGET (gdm_user_chooser_widget_get_type ())
|
||||||
|
#define GDM_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidget))
|
||||||
|
#define GDM_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
|
||||||
|
#define GDM_IS_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_WIDGET))
|
||||||
|
#define GDM_IS_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_WIDGET))
|
||||||
|
#define GDM_USER_CHOOSER_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
|
||||||
|
|
||||||
|
typedef struct GdmUserChooserWidgetPrivate GdmUserChooserWidgetPrivate;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GdmChooserWidget parent;
|
||||||
|
GdmUserChooserWidgetPrivate *priv;
|
||||||
|
} GdmUserChooserWidget;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GdmChooserWidgetClass parent_class;
|
||||||
|
} GdmUserChooserWidgetClass;
|
||||||
|
|
||||||
|
#define GDM_USER_CHOOSER_USER_OTHER "__other"
|
||||||
|
#define GDM_USER_CHOOSER_USER_GUEST "__guest"
|
||||||
|
#define GDM_USER_CHOOSER_USER_AUTO "__auto"
|
||||||
|
|
||||||
|
GType gdm_user_chooser_widget_get_type (void);
|
||||||
|
GtkWidget * gdm_user_chooser_widget_new (void);
|
||||||
|
|
||||||
|
char * gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget);
|
||||||
|
void gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
|
||||||
|
const char *user_name);
|
||||||
|
void gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show_only);
|
||||||
|
void gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show);
|
||||||
|
void gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show);
|
||||||
|
void gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
|
||||||
|
gboolean show);
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_USER_CHOOSER_WIDGET_H */
|
1644
src/gdmuser/gdm-user-manager.c
Normal file
1644
src/gdmuser/gdm-user-manager.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/gdmuser/gdm-user-manager.h
Normal file
87
src/gdmuser/gdm-user-manager.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_USER_MANAGER_H
|
||||||
|
#define __GDM_USER_MANAGER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-user.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_USER_MANAGER (gdm_user_manager_get_type ())
|
||||||
|
#define GDM_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_MANAGER, GdmUserManager))
|
||||||
|
#define GDM_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_MANAGER, GdmUserManagerClass))
|
||||||
|
#define GDM_IS_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_MANAGER))
|
||||||
|
#define GDM_IS_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_MANAGER))
|
||||||
|
#define GDM_USER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerClass))
|
||||||
|
|
||||||
|
typedef struct GdmUserManagerPrivate GdmUserManagerPrivate;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
GdmUserManagerPrivate *priv;
|
||||||
|
} GdmUserManager;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* loading_users) (GdmUserManager *user_manager);
|
||||||
|
void (* users_loaded) (GdmUserManager *user_manager);
|
||||||
|
void (* user_added) (GdmUserManager *user_manager,
|
||||||
|
GdmUser *user);
|
||||||
|
void (* user_removed) (GdmUserManager *user_manager,
|
||||||
|
GdmUser *user);
|
||||||
|
void (* user_is_logged_in_changed) (GdmUserManager *user_manager,
|
||||||
|
GdmUser *user);
|
||||||
|
void (* user_login_frequency_changed) (GdmUserManager *user_manager,
|
||||||
|
GdmUser *user);
|
||||||
|
} GdmUserManagerClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_USER_MANAGER_ERROR_GENERAL,
|
||||||
|
GDM_USER_MANAGER_ERROR_KEY_NOT_FOUND
|
||||||
|
} GdmUserManagerError;
|
||||||
|
|
||||||
|
#define GDM_USER_MANAGER_ERROR gdm_user_manager_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_user_manager_error_quark (void);
|
||||||
|
GType gdm_user_manager_get_type (void);
|
||||||
|
|
||||||
|
GdmUserManager * gdm_user_manager_ref_default (void);
|
||||||
|
|
||||||
|
GSList * gdm_user_manager_list_users (GdmUserManager *manager);
|
||||||
|
GdmUser * gdm_user_manager_get_user (GdmUserManager *manager,
|
||||||
|
const char *user_name);
|
||||||
|
GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager,
|
||||||
|
uid_t uid);
|
||||||
|
|
||||||
|
gboolean gdm_user_manager_activate_user_session (GdmUserManager *manager,
|
||||||
|
GdmUser *user);
|
||||||
|
|
||||||
|
gboolean gdm_user_manager_goto_login_session (GdmUserManager *manager);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_USER_MANAGER_H */
|
44
src/gdmuser/gdm-user-private.h
Normal file
44
src/gdmuser/gdm-user-private.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private interfaces to the GdmUser object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_USER_PRIVATE__
|
||||||
|
#define __GDM_USER_PRIVATE__ 1
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include "gdm-user.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void _gdm_user_update (GdmUser *user,
|
||||||
|
const struct passwd *pwent);
|
||||||
|
void _gdm_user_add_session (GdmUser *user,
|
||||||
|
const char *session_id);
|
||||||
|
void _gdm_user_remove_session (GdmUser *user,
|
||||||
|
const char *session_id);
|
||||||
|
|
||||||
|
void _gdm_user_icon_changed (GdmUser *user);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* !__GDM_USER_PRIVATE__ */
|
1171
src/gdmuser/gdm-user.c
Normal file
1171
src/gdmuser/gdm-user.c
Normal file
File diff suppressed because it is too large
Load Diff
59
src/gdmuser/gdm-user.h
Normal file
59
src/gdmuser/gdm-user.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
|
||||||
|
* Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Facade object for user data, owned by GdmUserManager
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_USER__
|
||||||
|
#define __GDM_USER__ 1
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <gtk/gtkwidget.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_USER (gdm_user_get_type ())
|
||||||
|
#define GDM_USER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDM_TYPE_USER, GdmUser))
|
||||||
|
#define GDM_IS_USER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDM_TYPE_USER))
|
||||||
|
|
||||||
|
typedef struct _GdmUser GdmUser;
|
||||||
|
|
||||||
|
GType gdm_user_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
uid_t gdm_user_get_uid (GdmUser *user);
|
||||||
|
G_CONST_RETURN char *gdm_user_get_user_name (GdmUser *user);
|
||||||
|
G_CONST_RETURN char *gdm_user_get_real_name (GdmUser *user);
|
||||||
|
G_CONST_RETURN char *gdm_user_get_home_directory (GdmUser *user);
|
||||||
|
G_CONST_RETURN char *gdm_user_get_shell (GdmUser *user);
|
||||||
|
guint gdm_user_get_num_sessions (GdmUser *user);
|
||||||
|
GList *gdm_user_get_sessions (GdmUser *user);
|
||||||
|
gulong gdm_user_get_login_frequency (GdmUser *user);
|
||||||
|
|
||||||
|
GdkPixbuf *gdm_user_render_icon (GdmUser *user,
|
||||||
|
gint icon_size);
|
||||||
|
|
||||||
|
gint gdm_user_collate (GdmUser *user1,
|
||||||
|
GdmUser *user2);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
632
src/shell-status-menu.c
Normal file
632
src/shell-status-menu.c
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/* Adapted from gdm/gui/user-switch-applet/applet.c */
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
|
||||||
|
* Copyright (C) 2008,2009 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shell-status-menu.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <gconf/gconf.h>
|
||||||
|
#include <gconf/gconf-client.h>
|
||||||
|
|
||||||
|
#include <dbus/dbus-glib.h>
|
||||||
|
|
||||||
|
#define GDMUSER_I_KNOW_THIS_IS_UNSTABLE
|
||||||
|
#include <gdmuser/gdm-user-manager.h>
|
||||||
|
|
||||||
|
#include "shell-global.h"
|
||||||
|
|
||||||
|
#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
|
||||||
|
#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching"
|
||||||
|
|
||||||
|
struct _ShellStatusMenuPrivate {
|
||||||
|
GConfClient *client;
|
||||||
|
GdmUserManager *manager;
|
||||||
|
GdmUser *user;
|
||||||
|
|
||||||
|
ClutterTexture *user_icon;
|
||||||
|
BigBox *name_box;
|
||||||
|
ClutterLabel *name;
|
||||||
|
|
||||||
|
GtkWidget *menu;
|
||||||
|
GtkWidget *account_item;
|
||||||
|
GtkWidget *control_panel_item;
|
||||||
|
GtkWidget *lock_screen_item;
|
||||||
|
GtkWidget *login_screen_item;
|
||||||
|
GtkWidget *quit_session_item;
|
||||||
|
|
||||||
|
guint client_notify_lockdown_id;
|
||||||
|
|
||||||
|
guint current_status_state;
|
||||||
|
|
||||||
|
guint user_icon_changed_id;
|
||||||
|
guint user_notify_id;
|
||||||
|
|
||||||
|
gboolean has_other_users;
|
||||||
|
|
||||||
|
GtkIconSize icon_size;
|
||||||
|
guint pixel_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(ShellStatusMenu, shell_status_menu, BIG_TYPE_BOX);
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEACTIVATED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint shell_status_menu_signals [LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_icon (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
|
||||||
|
if (priv->user == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->user_icon != NULL)
|
||||||
|
{
|
||||||
|
pixbuf = gdm_user_render_icon (priv->user, 24);
|
||||||
|
|
||||||
|
if (pixbuf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shell_clutter_texture_set_from_pixbuf (priv->user_icon, pixbuf);
|
||||||
|
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_label (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
char *markup;
|
||||||
|
|
||||||
|
markup = g_strdup_printf ("<b>%s</b>",
|
||||||
|
gdm_user_get_real_name (GDM_USER (priv->user)));
|
||||||
|
clutter_label_set_use_markup (priv->name, TRUE);
|
||||||
|
clutter_label_set_text (priv->name, markup);
|
||||||
|
g_free (markup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_icon_changed (GdmUser *user,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
g_debug ("User icon changed");
|
||||||
|
reset_icon (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
user_notify_display_name_cb (GObject *object,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
update_label (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_current_user (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
priv->user = gdm_user_manager_get_user_by_uid (priv->manager, getuid ());
|
||||||
|
if (priv->user != NULL)
|
||||||
|
{
|
||||||
|
g_object_ref (priv->user);
|
||||||
|
name = gdm_user_get_real_name (priv->user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = _("Unknown");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
priv->menuitem = gtk_image_menu_item_new_with_label (name);
|
||||||
|
label = GTK_BIN (adata->menuitem)->child;
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (adata->menubar), adata->menuitem);
|
||||||
|
gtk_widget_show (adata->menuitem);
|
||||||
|
*/
|
||||||
|
|
||||||
|
update_label (status);
|
||||||
|
|
||||||
|
if (priv->user != NULL)
|
||||||
|
{
|
||||||
|
reset_icon (status);
|
||||||
|
|
||||||
|
priv->user_icon_changed_id =
|
||||||
|
g_signal_connect (priv->user,
|
||||||
|
"icon-changed",
|
||||||
|
G_CALLBACK (on_user_icon_changed),
|
||||||
|
status);
|
||||||
|
priv->user_notify_id =
|
||||||
|
g_signal_connect (priv->user,
|
||||||
|
"notify::display-name",
|
||||||
|
G_CALLBACK (user_notify_display_name_cb),
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_lock_screen (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
char *args[3];
|
||||||
|
GError *err;
|
||||||
|
GdkScreen *screen;
|
||||||
|
gboolean use_gscreensaver = TRUE;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
g_debug ("Attempting to lock screen");
|
||||||
|
|
||||||
|
args[0] = g_find_program_in_path ("gnome-screensaver-command");
|
||||||
|
if (args[0] == NULL)
|
||||||
|
{
|
||||||
|
args[0] = g_find_program_in_path ("xscreensaver-command");
|
||||||
|
use_gscreensaver = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[0] == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (use_gscreensaver)
|
||||||
|
args[1] = "--lock";
|
||||||
|
else
|
||||||
|
args[1] = "-lock";
|
||||||
|
args[2] = NULL;
|
||||||
|
|
||||||
|
screen = gdk_screen_get_default ();
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
|
||||||
|
NULL, NULL, &err);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
g_warning (_("Can't lock screen: %s"), err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_gscreensaver)
|
||||||
|
args[1] = "--throttle";
|
||||||
|
else
|
||||||
|
args[1] = "-throttle";
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL,
|
||||||
|
(G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL), NULL, NULL,
|
||||||
|
NULL, &err);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
g_warning (_("Can't temporarily set screensaver to blank screen: %s"),
|
||||||
|
err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_lock_screen_activate (GtkMenuItem *item,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
maybe_lock_screen (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_switch (ShellStatusMenu *status,
|
||||||
|
GdmUser *user)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
guint num_sessions;
|
||||||
|
|
||||||
|
g_debug ("Do user switch");
|
||||||
|
|
||||||
|
if (user == NULL)
|
||||||
|
{
|
||||||
|
gdm_user_manager_goto_login_session (priv->manager);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_sessions = gdm_user_get_num_sessions (user);
|
||||||
|
if (num_sessions > 0)
|
||||||
|
gdm_user_manager_activate_user_session (priv->manager, user);
|
||||||
|
else
|
||||||
|
gdm_user_manager_goto_login_session (priv->manager);
|
||||||
|
out:
|
||||||
|
maybe_lock_screen (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_login_screen_activate (GtkMenuItem *item,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
GdmUser *user;
|
||||||
|
|
||||||
|
user = NULL;
|
||||||
|
|
||||||
|
do_switch (status, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spawn_external (ShellStatusMenu *status, const char *program)
|
||||||
|
{
|
||||||
|
char *args[2];
|
||||||
|
GError *error;
|
||||||
|
GdkScreen *screen;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
args[0] = g_find_program_in_path (program);
|
||||||
|
if (args[0] == NULL)
|
||||||
|
return;
|
||||||
|
args[1] = NULL;
|
||||||
|
|
||||||
|
screen = gdk_screen_get_default ();
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
|
||||||
|
NULL, NULL, &error);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to exec %s: %s", program, error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (args[0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_control_panel_activate (GtkMenuItem *item,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
spawn_external (status, "gnome-control-center");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_account_activate (GtkMenuItem *item,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
spawn_external (status, "gnome-about-me");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_quit_session_activate (GtkMenuItem *item,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
char *args[3];
|
||||||
|
GError *error;
|
||||||
|
GdkScreen *screen;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
args[0] = g_find_program_in_path ("gnome-session-save");
|
||||||
|
if (args[0] == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args[1] = "--logout-dialog";
|
||||||
|
args[2] = NULL;
|
||||||
|
|
||||||
|
screen = gdk_screen_get_default ();
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
|
||||||
|
NULL, NULL, &error);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
g_warning (_("Can't logout: %s"), error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_switch_user (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
GSList *users;
|
||||||
|
|
||||||
|
users = gdm_user_manager_list_users (priv->manager);
|
||||||
|
priv->has_other_users = FALSE;
|
||||||
|
if (users != NULL)
|
||||||
|
priv->has_other_users = g_slist_length (users) > 1;
|
||||||
|
g_slist_free (users);
|
||||||
|
|
||||||
|
if (priv->has_other_users)
|
||||||
|
gtk_widget_show (priv->login_screen_item);
|
||||||
|
else
|
||||||
|
gtk_widget_hide (priv->login_screen_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_user_added (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
update_switch_user (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_user_removed (GdmUserManager *manager,
|
||||||
|
GdmUser *user,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
update_switch_user (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_users_loaded (GdmUserManager *manager,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
update_switch_user (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_style_set_cb (GtkWidget *menu, GtkStyle *old_style,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
GtkSettings *settings;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
priv->icon_size = gtk_icon_size_from_name ("panel-menu");
|
||||||
|
if (priv->icon_size == GTK_ICON_SIZE_INVALID)
|
||||||
|
priv->icon_size = gtk_icon_size_register ("panel-menu", 24, 24);
|
||||||
|
|
||||||
|
if (gtk_widget_has_screen (menu))
|
||||||
|
settings = gtk_settings_get_for_screen (gtk_widget_get_screen (menu));
|
||||||
|
else
|
||||||
|
settings = gtk_settings_get_default ();
|
||||||
|
|
||||||
|
if (!gtk_icon_size_lookup_for_settings (settings, priv->icon_size, &width,
|
||||||
|
&height))
|
||||||
|
priv->pixel_size = -1;
|
||||||
|
else
|
||||||
|
priv->pixel_size = MAX(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menuitem_style_set_cb (GtkWidget *menuitem,
|
||||||
|
GtkStyle *old_style,
|
||||||
|
ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
GtkWidget *image;
|
||||||
|
const char *icon_name;
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
|
||||||
|
if (menuitem == priv->login_screen_item)
|
||||||
|
icon_name = "system-users";
|
||||||
|
else if (menuitem == priv->lock_screen_item)
|
||||||
|
icon_name = "system-lock-screen";
|
||||||
|
else if (menuitem == priv->quit_session_item)
|
||||||
|
icon_name = "system-log-out";
|
||||||
|
else if (menuitem == priv->account_item)
|
||||||
|
icon_name = "user-info";
|
||||||
|
else if (menuitem == priv->control_panel_item)
|
||||||
|
icon_name = "preferences-desktop";
|
||||||
|
else
|
||||||
|
icon_name = GTK_STOCK_MISSING_IMAGE;
|
||||||
|
|
||||||
|
image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem));
|
||||||
|
gtk_image_set_pixel_size (GTK_IMAGE (image), priv->pixel_size);
|
||||||
|
gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, priv->icon_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_deactivate (GtkMenuShell *menushell, gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellStatusMenu *shell = SHELL_STATUS_MENU (user_data);
|
||||||
|
g_signal_emit (G_OBJECT (shell), shell_status_menu_signals[DEACTIVATED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_sub_menu (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
GtkWidget *item;
|
||||||
|
|
||||||
|
priv->menu = gtk_menu_new ();
|
||||||
|
g_signal_connect (priv->menu, "style-set", G_CALLBACK (menu_style_set_cb),
|
||||||
|
status);
|
||||||
|
|
||||||
|
g_signal_connect (priv->manager, "users-loaded",
|
||||||
|
G_CALLBACK (on_manager_users_loaded), status);
|
||||||
|
g_signal_connect (priv->manager, "user-added",
|
||||||
|
G_CALLBACK (on_manager_user_added), status);
|
||||||
|
g_signal_connect (priv->manager, "user-removed",
|
||||||
|
G_CALLBACK (on_manager_user_removed), status);
|
||||||
|
|
||||||
|
priv->account_item = gtk_image_menu_item_new_with_label (_("Account Information..."));
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->account_item),
|
||||||
|
gtk_image_new ());
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->account_item);
|
||||||
|
g_signal_connect (priv->account_item, "style-set",
|
||||||
|
G_CALLBACK (menuitem_style_set_cb), status);
|
||||||
|
g_signal_connect (priv->account_item, "activate",
|
||||||
|
G_CALLBACK (on_account_activate), status);
|
||||||
|
gtk_widget_show (priv->account_item);
|
||||||
|
|
||||||
|
priv->control_panel_item = gtk_image_menu_item_new_with_label (_(
|
||||||
|
"System Preferences..."));
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->control_panel_item),
|
||||||
|
gtk_image_new ());
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->control_panel_item);
|
||||||
|
g_signal_connect (priv->control_panel_item, "style-set",
|
||||||
|
G_CALLBACK (menuitem_style_set_cb), status);
|
||||||
|
g_signal_connect (priv->control_panel_item, "activate",
|
||||||
|
G_CALLBACK (on_control_panel_activate), status);
|
||||||
|
gtk_widget_show (priv->control_panel_item);
|
||||||
|
|
||||||
|
item = gtk_separator_menu_item_new ();
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item);
|
||||||
|
gtk_widget_show (item);
|
||||||
|
|
||||||
|
priv->lock_screen_item
|
||||||
|
= gtk_image_menu_item_new_with_label (_("Lock Screen"));
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->lock_screen_item),
|
||||||
|
gtk_image_new ());
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->lock_screen_item);
|
||||||
|
g_signal_connect (priv->lock_screen_item, "style-set",
|
||||||
|
G_CALLBACK (menuitem_style_set_cb), status);
|
||||||
|
g_signal_connect (priv->lock_screen_item, "activate",
|
||||||
|
G_CALLBACK (on_lock_screen_activate), status);
|
||||||
|
gtk_widget_show (priv->lock_screen_item);
|
||||||
|
|
||||||
|
priv->login_screen_item = gtk_image_menu_item_new_with_label (_("Switch User"));
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->login_screen_item),
|
||||||
|
gtk_image_new ());
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->login_screen_item);
|
||||||
|
g_signal_connect (priv->login_screen_item, "style-set",
|
||||||
|
G_CALLBACK (menuitem_style_set_cb), status);
|
||||||
|
g_signal_connect (priv->login_screen_item, "activate",
|
||||||
|
G_CALLBACK (on_login_screen_activate), status);
|
||||||
|
/* Only show switch user if there are other users */
|
||||||
|
|
||||||
|
priv->quit_session_item = gtk_image_menu_item_new_with_label (_("Quit..."));
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->quit_session_item),
|
||||||
|
gtk_image_new ());
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->quit_session_item);
|
||||||
|
g_signal_connect (priv->quit_session_item, "style-set",
|
||||||
|
G_CALLBACK (menuitem_style_set_cb), status);
|
||||||
|
g_signal_connect (priv->quit_session_item, "activate",
|
||||||
|
G_CALLBACK (on_quit_session_activate), status);
|
||||||
|
gtk_widget_show (priv->quit_session_item);
|
||||||
|
|
||||||
|
g_signal_connect (G_OBJECT (priv->menu), "deactivate",
|
||||||
|
G_CALLBACK (on_deactivate), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_status_menu_init (ShellStatusMenu *status)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv;
|
||||||
|
|
||||||
|
status->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (status, SHELL_TYPE_STATUS_MENU,
|
||||||
|
ShellStatusMenuPrivate);
|
||||||
|
|
||||||
|
g_object_set (G_OBJECT (status),
|
||||||
|
"orientation", BIG_BOX_ORIENTATION_HORIZONTAL,
|
||||||
|
NULL);
|
||||||
|
priv->client = gconf_client_get_default ();
|
||||||
|
|
||||||
|
priv->user_icon = CLUTTER_TEXTURE (clutter_texture_new ());
|
||||||
|
big_box_append (BIG_BOX (status), CLUTTER_ACTOR (status->priv->user_icon), 0);
|
||||||
|
|
||||||
|
priv->name_box = BIG_BOX (big_box_new (BIG_BOX_ORIENTATION_VERTICAL));
|
||||||
|
g_object_set (G_OBJECT (priv->name_box), "y-align", BIG_BOX_ALIGNMENT_CENTER, NULL);
|
||||||
|
big_box_append (BIG_BOX (status), CLUTTER_ACTOR (priv->name_box), BIG_BOX_PACK_EXPAND);
|
||||||
|
priv->name = CLUTTER_LABEL (clutter_label_new ());
|
||||||
|
big_box_append (BIG_BOX (priv->name_box), CLUTTER_ACTOR (priv->name), BIG_BOX_PACK_EXPAND);
|
||||||
|
|
||||||
|
priv->manager = gdm_user_manager_ref_default ();
|
||||||
|
setup_current_user (status);
|
||||||
|
|
||||||
|
create_sub_menu (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_status_menu_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ShellStatusMenu *status = SHELL_STATUS_MENU (object);
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
|
||||||
|
gconf_client_notify_remove (priv->client, priv->client_notify_lockdown_id);
|
||||||
|
|
||||||
|
g_signal_handler_disconnect (priv->user, priv->user_notify_id);
|
||||||
|
g_signal_handler_disconnect (priv->user, priv->user_icon_changed_id);
|
||||||
|
|
||||||
|
if (priv->user != NULL) {
|
||||||
|
g_object_unref (priv->user);
|
||||||
|
}
|
||||||
|
g_object_unref (priv->client);
|
||||||
|
g_object_unref (priv->manager);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_status_menu_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_status_menu_class_init (ShellStatusMenuClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (ShellStatusMenuPrivate));
|
||||||
|
|
||||||
|
gobject_class->finalize = shell_status_menu_finalize;
|
||||||
|
|
||||||
|
shell_status_menu_signals[DEACTIVATED] =
|
||||||
|
g_signal_new ("deactivated",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ShellStatusMenuClass, deactivated),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShellStatusMenu *
|
||||||
|
shell_status_menu_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (SHELL_TYPE_STATUS_MENU, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellStatusMenu *status = SHELL_STATUS_MENU (user_data);
|
||||||
|
int src_x, src_y;
|
||||||
|
|
||||||
|
clutter_actor_get_transformed_position (CLUTTER_ACTOR (status), &src_x, &src_y);
|
||||||
|
|
||||||
|
*x = src_x;
|
||||||
|
*y = src_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
|
||||||
|
{
|
||||||
|
ShellStatusMenuPrivate *priv = status->priv;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu)))
|
||||||
|
{
|
||||||
|
gtk_widget_hide (GTK_WIDGET (priv->menu));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_show (GTK_WIDGET (priv->menu));
|
||||||
|
gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, position_menu,
|
||||||
|
status, 1, event->button.time);
|
||||||
|
}
|
||||||
|
}
|
42
src/shell-status-menu.h
Normal file
42
src/shell-status-menu.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#ifndef __SHELL_STATUS_MENU_H__
|
||||||
|
#define __SHELL_STATUS_MENU_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include "big/box.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define SHELL_TYPE_STATUS_MENU (shell_status_menu_get_type ())
|
||||||
|
#define SHELL_STATUS_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_STATUS_MENU, ShellStatusMenu))
|
||||||
|
#define SHELL_STATUS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_STATUS_MENU, ShellStatusMenuClass))
|
||||||
|
#define SHELL_IS_STATUS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_STATUS_MENU))
|
||||||
|
#define SHELL_IS_STATUS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_STATUS_MENU))
|
||||||
|
#define SHELL_STATUS_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_STATUS_MENU, ShellStatusMenuClass))
|
||||||
|
|
||||||
|
typedef struct _ShellStatusMenu ShellStatusMenu;
|
||||||
|
typedef struct _ShellStatusMenuPrivate ShellStatusMenuPrivate;
|
||||||
|
typedef struct _ShellStatusMenuClass ShellStatusMenuClass;
|
||||||
|
|
||||||
|
struct _ShellStatusMenu
|
||||||
|
{
|
||||||
|
BigBox parent_instance;
|
||||||
|
|
||||||
|
ShellStatusMenuPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellStatusMenuClass
|
||||||
|
{
|
||||||
|
BigBoxClass parent_class;
|
||||||
|
|
||||||
|
void (*deactivated) (ShellStatusMenu *status, gpointer user_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType shell_status_menu_get_type (void);
|
||||||
|
|
||||||
|
void shell_status_menu_toggle (ShellStatusMenu *menu, ClutterEvent *event);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __SHELL_STATUS_MENU_H__ */
|
Loading…
Reference in New Issue
Block a user