This commit is contained in:
Dan Williams 2007-02-25 19:27:37 -05:00
commit 0cad068bf4
60 changed files with 614 additions and 1921 deletions

View File

@ -112,12 +112,12 @@ lib/threadframe/Makefile
services/Makefile
services/presence/Makefile
services/presence2/Makefile
services/nm/Makefile
services/clipboard/Makefile
services/datastore/Makefile
shell/Makefile
shell/intro/Makefile
shell/data/Makefile
shell/hardware/Makefile
shell/view/Makefile
shell/view/devices/Makefile
shell/view/frame/Makefile

View File

@ -21,13 +21,6 @@
(gtype-id "SUGAR_TYPE_KEY_GRABBER")
)
(define-object TrayManager
(in-module "Sugar")
(parent "GObject")
(c-name "SugarTrayManager")
(gtype-id "SUGAR_TYPE_TRAY_MANAGER")
)
(define-object PushScroller
(in-module "Sugar")
(parent "GObject")
@ -124,60 +117,6 @@
)
)
;; From sugar-tray-manager.h
(define-function tray_manager_get_type
(c-name "sugar_tray_manager_get_type")
(return-type "GType")
)
(define-function tray_manager_check_running
(c-name "sugar_tray_manager_check_running")
(return-type "gboolean")
(parameters
'("GdkScreen*" "screen")
)
)
(define-function tray_manager_new
(c-name "sugar_tray_manager_new")
(is-constructor-of "SugarTrayManager")
(return-type "SugarTrayManager*")
)
(define-method manage_screen
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_manage_screen")
(return-type "gboolean")
(parameters
'("GdkScreen*" "screen")
)
)
(define-method get_child_title
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_get_child_title")
(return-type "char*")
(parameters
'("SugarTrayManagerChild*" "child")
)
)
(define-method set_orientation
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_set_orientation")
(return-type "none")
(parameters
'("GtkOrientation" "orientation")
)
)
(define-method get_orientation
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_get_orientation")
(return-type "GtkOrientation")
)
;; From sugar-push-scroller.h
(define-function push_scroller_get_type

View File

@ -7,7 +7,6 @@ headers
#include "sugar-browser.h"
#include "sugar-key-grabber.h"
#include "sugar-address-entry.h"
#include "sugar-tray-manager.h"
#include "sugar-push-scroller.h"
#include "sugar-download-manager.h"
#include "sugar-download.h"
@ -22,9 +21,6 @@ extern Pycairo_CAPI_t *Pycairo_CAPI;
%%
modulename gecko
%%
ignore
sugar_tray_manager_new
%%
import gobject.GObject as PyGObject_Type
import gtk.Entry as PyGtkEntry_Type
import gtk.gdk.Screen as PyGdkScreen_Type

View File

@ -44,8 +44,6 @@ libsugarprivate_la_SOURCES = \
sugar-key-grabber.c \
sugar-push-scroller.c \
sugar-push-scroller.h \
sugar-tray-manager.c \
sugar-tray-manager.h \
sugar-utils.c \
sugar-utils.h

View File

@ -1,908 +0,0 @@
/* na-tray-manager.c
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Copyright (C) 2003-2006 Vincent Untz
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Used to be: eggtraymanager.c
*/
#include <config.h>
#include <string.h>
#include <libintl.h>
#include "sugar-tray-manager.h"
#include <gdkconfig.h>
#include <glib/gi18n.h>
#if defined (GDK_WINDOWING_X11)
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#elif defined (GDK_WINDOWING_WIN32)
#include <gdk/gdkwin32.h>
#endif
#include <gtk/gtkinvisible.h>
#include <gtk/gtksocket.h>
#include <gtk/gtkwindow.h>
#include "sugar-marshal.h"
/* Signals */
enum
{
TRAY_ICON_ADDED,
TRAY_ICON_REMOVED,
MESSAGE_SENT,
MESSAGE_CANCELLED,
LOST_SELECTION,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_ORIENTATION
};
typedef struct
{
long id, len;
long remaining_len;
long timeout;
char *str;
#ifdef GDK_WINDOWING_X11
Window window;
#endif
} PendingMessage;
static guint manager_signals[LAST_SIGNAL] = { 0 };
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
#define SYSTEM_TRAY_ORIENTATION_HORZ 0
#define SYSTEM_TRAY_ORIENTATION_VERT 1
#ifdef GDK_WINDOWING_X11
static gboolean sugar_tray_manager_check_running_screen_x11 (GdkScreen *screen);
#endif
static void sugar_tray_manager_finalize (GObject *object);
static void sugar_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void sugar_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void sugar_tray_manager_unmanage (SugarTrayManager *manager);
G_DEFINE_TYPE (SugarTrayManager, sugar_tray_manager, G_TYPE_OBJECT)
static void
sugar_tray_manager_init (SugarTrayManager *manager)
{
manager->invisible = NULL;
manager->socket_table = g_hash_table_new (NULL, NULL);
}
static void
sugar_tray_manager_class_init (SugarTrayManagerClass *klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *)klass;
gobject_class->finalize = sugar_tray_manager_finalize;
gobject_class->set_property = sugar_tray_manager_set_property;
gobject_class->get_property = sugar_tray_manager_get_property;
g_object_class_install_property (gobject_class,
PROP_ORIENTATION,
g_param_spec_enum ("orientation",
_("Orientation"),
_("The orientation of the tray."),
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_HORIZONTAL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
manager_signals[TRAY_ICON_ADDED] =
g_signal_new ("tray_icon_added",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, tray_icon_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[TRAY_ICON_REMOVED] =
g_signal_new ("tray_icon_removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, tray_icon_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[MESSAGE_SENT] =
g_signal_new ("message_sent",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, message_sent),
NULL, NULL,
sugar_marshal_VOID__OBJECT_STRING_LONG_LONG,
G_TYPE_NONE, 4,
GTK_TYPE_SOCKET,
G_TYPE_STRING,
G_TYPE_LONG,
G_TYPE_LONG);
manager_signals[MESSAGE_CANCELLED] =
g_signal_new ("message_cancelled",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, message_cancelled),
NULL, NULL,
sugar_marshal_VOID__OBJECT_LONG,
G_TYPE_NONE, 2,
GTK_TYPE_SOCKET,
G_TYPE_LONG);
manager_signals[LOST_SELECTION] =
g_signal_new ("lost_selection",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, lost_selection),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
#if defined (GDK_WINDOWING_X11)
/* Nothing */
#elif defined (GDK_WINDOWING_WIN32)
g_warning ("Port SugarTrayManager to Win32");
#else
g_warning ("Port SugarTrayManager to this GTK+ backend");
#endif
}
static void
sugar_tray_manager_finalize (GObject *object)
{
SugarTrayManager *manager;
manager = SUGAR_TRAY_MANAGER (object);
sugar_tray_manager_unmanage (manager);
g_list_free (manager->messages);
g_hash_table_destroy (manager->socket_table);
G_OBJECT_CLASS (sugar_tray_manager_parent_class)->finalize (object);
}
static void
sugar_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SugarTrayManager *manager = SUGAR_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
sugar_tray_manager_set_orientation (manager, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
sugar_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SugarTrayManager *manager = SUGAR_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
g_value_set_enum (value, manager->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
SugarTrayManager *
sugar_tray_manager_new (void)
{
SugarTrayManager *manager;
manager = g_object_new (SUGAR_TYPE_TRAY_MANAGER, NULL);
return manager;
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_plug_removed (GtkSocket *socket,
SugarTrayManager *manager)
{
Window *window;
window = g_object_get_data (G_OBJECT (socket), "na-tray-child-window");
g_hash_table_remove (manager->socket_table, GINT_TO_POINTER (*window));
g_object_set_data (G_OBJECT (socket), "na-tray-child-window",
NULL);
g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, socket);
/* This destroys the socket. */
return FALSE;
}
static void
sugar_tray_manager_make_socket_transparent (GtkWidget *widget,
gpointer user_data)
{
if (GTK_WIDGET_NO_WINDOW (widget))
return;
gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
}
static gboolean
sugar_tray_manager_socket_exposed (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
gdk_window_clear_area (widget->window,
event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
static void
sugar_tray_manager_socket_style_set (GtkWidget *widget,
GtkStyle *previous_style,
gpointer user_data)
{
if (widget->window == NULL)
return;
sugar_tray_manager_make_socket_transparent (widget, user_data);
}
static void
sugar_tray_manager_handle_dock_request (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GtkWidget *socket;
Window *window;
GtkRequisition req;
if (g_hash_table_lookup (manager->socket_table, GINT_TO_POINTER (xevent->data.l[2])))
{
/* We already got this notification earlier, ignore this one */
return;
}
socket = gtk_socket_new ();
gtk_widget_set_app_paintable (socket, TRUE);
//FIXME: need to find a theme where this (and expose event) is needed
gtk_widget_set_double_buffered (socket, FALSE);
/* FIXME Disabled this so that I can customize the icons background in theme.
I couldn't find a way to set a specific color for the GtkPlug.
g_signal_connect (socket, "realize",
G_CALLBACK (sugar_tray_manager_make_socket_transparent), NULL);
*/
g_signal_connect (socket, "expose_event",
G_CALLBACK (sugar_tray_manager_socket_exposed), NULL);
g_signal_connect_after (socket, "style_set",
G_CALLBACK (sugar_tray_manager_socket_style_set), NULL);
/* We need to set the child window here
* so that the client can call _get functions
* in the signal handler
*/
window = g_new (Window, 1);
*window = xevent->data.l[2];
g_object_set_data_full (G_OBJECT (socket),
"na-tray-child-window",
window, g_free);
g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
socket);
/* Add the socket only if it's been attached */
if (GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))))
{
g_signal_connect (socket, "plug_removed",
G_CALLBACK (sugar_tray_manager_plug_removed), manager);
gtk_socket_add_id (GTK_SOCKET (socket), *window);
g_hash_table_insert (manager->socket_table, GINT_TO_POINTER (*window), socket);
/*
* Make sure the icons have a meaningfull size ...
*/
req.width = req.height = 1;
gtk_widget_size_request (socket, &req);
/*
if ((req.width < 16) || (req.height < 16))
{
gint nw = MAX (24, req.width);
gint nh = MAX (24, req.height);
g_warning (_("tray icon has requested a size of (%i x %i), resizing to (%i x %i)"),
req.width, req.height, nw, nh);
gtk_widget_set_size_request(icon, nw, nh);
}
*/
gtk_widget_show(socket);
}
else
gtk_widget_destroy (socket);
}
static void
pending_message_free (PendingMessage *message)
{
g_free (message->str);
g_free (message);
}
static GdkFilterReturn
sugar_tray_manager_handle_client_message_message_data (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XClientMessageEvent *xevent;
SugarTrayManager *manager;
GList *p;
int len;
xevent = (XClientMessageEvent *) xev;
manager = data;
/* Try to see if we can find the pending message in the list */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window)
{
/* Append the message */
len = MIN (msg->remaining_len, 20);
memcpy ((msg->str + msg->len - msg->remaining_len),
&xevent->data, len);
msg->remaining_len -= len;
if (msg->remaining_len == 0)
{
GtkSocket *socket;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (msg->window));
if (socket)
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, msg->str, msg->id, msg->timeout);
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
}
break;
}
}
return GDK_FILTER_REMOVE;
}
static void
sugar_tray_manager_handle_begin_message (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GtkSocket *socket;
GList *p;
PendingMessage *msg;
long timeout;
long len;
long id;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
/* we don't know about this tray icon, so ignore the message */
if (!socket)
return;
/* Check if the same message is already in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
xevent->data.l[4] == msg->id)
{
/* Hmm, we found it, now remove it */
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
timeout = xevent->data.l[2];
len = xevent->data.l[3];
id = xevent->data.l[4];
if (len == 0)
{
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, "", id, timeout);
}
else
{
/* Now add the new message to the queue */
msg = g_new0 (PendingMessage, 1);
msg->window = xevent->window;
msg->timeout = timeout;
msg->len = len;
msg->id = id;
msg->remaining_len = msg->len;
msg->str = g_malloc (msg->len + 1);
msg->str[msg->len] = '\0';
manager->messages = g_list_prepend (manager->messages, msg);
}
}
static void
sugar_tray_manager_handle_cancel_message (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GList *p;
GtkSocket *socket;
/* Check if the message is in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
xevent->data.l[4] == msg->id)
{
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
if (socket)
{
g_signal_emit (manager, manager_signals[MESSAGE_CANCELLED], 0,
socket, xevent->data.l[2]);
}
}
static GdkFilterReturn
sugar_tray_manager_handle_client_message_opcode (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XClientMessageEvent *xevent;
SugarTrayManager *manager;
xevent = (XClientMessageEvent *) xev;
manager = data;
switch (xevent->data.l[1])
{
case SYSTEM_TRAY_REQUEST_DOCK:
/* Ignore this one since we don't know on which window this was received
* and so we can't know for which screen this is. It will be handled
* in sugar_tray_manager_window_filter() since we also receive it there */
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
sugar_tray_manager_handle_begin_message (manager, xevent);
return GDK_FILTER_REMOVE;
case SYSTEM_TRAY_CANCEL_MESSAGE:
sugar_tray_manager_handle_cancel_message (manager, xevent);
return GDK_FILTER_REMOVE;
default:
break;
}
return GDK_FILTER_CONTINUE;
}
static GdkFilterReturn
sugar_tray_manager_window_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XEvent *xevent = (GdkXEvent *)xev;
SugarTrayManager *manager = data;
if (xevent->type == ClientMessage)
{
/* We handle this client message here. See comment in
* sugar_tray_manager_handle_client_message_opcode() for details */
if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
{
sugar_tray_manager_handle_dock_request (manager,
(XClientMessageEvent *) xevent);
return GDK_FILTER_REMOVE;
}
}
else if (xevent->type == SelectionClear)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
sugar_tray_manager_unmanage (manager);
}
return GDK_FILTER_CONTINUE;
}
#if 0
//FIXME investigate why this doesn't work
static gboolean
sugar_tray_manager_selection_clear_event (GtkWidget *widget,
GdkEventSelection *event,
SugarTrayManager *manager)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
sugar_tray_manager_unmanage (manager);
return FALSE;
}
#endif
#endif
static void
sugar_tray_manager_unmanage (SugarTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
guint32 timestamp;
GtkWidget *invisible;
if (manager->invisible == NULL)
return;
invisible = manager->invisible;
g_assert (GTK_IS_INVISIBLE (invisible));
g_assert (GTK_WIDGET_REALIZED (invisible));
g_assert (GDK_IS_WINDOW (invisible->window));
display = gtk_widget_get_display (invisible);
if (gdk_selection_owner_get_for_display (display, manager->selection_atom) ==
invisible->window)
{
timestamp = gdk_x11_get_server_time (invisible->window);
gdk_selection_owner_set_for_display (display,
NULL,
manager->selection_atom,
timestamp,
TRUE);
}
//FIXME: we should also use gdk_remove_client_message_filter when it's
//available
// See bug #351254
gdk_window_remove_filter (invisible->window,
sugar_tray_manager_window_filter, manager);
manager->invisible = NULL; /* prior to destroy for reentrancy paranoia */
gtk_widget_destroy (invisible);
g_object_unref (G_OBJECT (invisible));
#endif
}
static void
sugar_tray_manager_set_orientation_property (SugarTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
Atom orientation_atom;
gulong data[1];
if (!manager->invisible || !manager->invisible->window)
return;
display = gtk_widget_get_display (manager->invisible);
orientation_atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_SYSTEM_TRAY_ORIENTATION");
data[0] = manager->orientation == GTK_ORIENTATION_HORIZONTAL ?
SYSTEM_TRAY_ORIENTATION_HORZ :
SYSTEM_TRAY_ORIENTATION_VERT;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XWINDOW (manager->invisible->window),
orientation_atom,
XA_CARDINAL, 32,
PropModeReplace,
(guchar *) &data, 1);
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_manage_screen_x11 (SugarTrayManager *manager,
GdkScreen *screen)
{
GdkDisplay *display;
Screen *xscreen;
GtkWidget *invisible;
char *selection_atom_name;
guint32 timestamp;
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
/* If there's already a manager running on the screen
* we can't create another one.
*/
#if 0
if (sugar_tray_manager_check_running_screen_x11 (screen))
return FALSE;
#endif
display = gdk_screen_get_display (screen);
xscreen = GDK_SCREEN_XSCREEN (screen);
invisible = gtk_invisible_new_for_screen (screen);
gtk_widget_realize (invisible);
gtk_widget_add_events (invisible,
GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE);
g_free (selection_atom_name);
sugar_tray_manager_set_orientation_property (manager);
timestamp = gdk_x11_get_server_time (invisible->window);
/* Check if we could set the selection owner successfully */
if (gdk_selection_owner_set_for_display (display,
invisible->window,
manager->selection_atom,
timestamp,
TRUE))
{
XClientMessageEvent xev;
GdkAtom opcode_atom;
GdkAtom message_data_atom;
xev.type = ClientMessage;
xev.window = RootWindowOfScreen (xscreen);
xev.message_type = gdk_x11_get_xatom_by_name_for_display (display,
"MANAGER");
xev.format = 32;
xev.data.l[0] = timestamp;
xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display,
manager->selection_atom);
xev.data.l[2] = GDK_WINDOW_XWINDOW (invisible->window);
xev.data.l[3] = 0; /* manager specific data */
xev.data.l[4] = 0; /* manager specific data */
XSendEvent (GDK_DISPLAY_XDISPLAY (display),
RootWindowOfScreen (xscreen),
False, StructureNotifyMask, (XEvent *)&xev);
manager->invisible = invisible;
g_object_ref (G_OBJECT (manager->invisible));
opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE);
manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display,
opcode_atom);
message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA",
FALSE);
/* Add a window filter */
#if 0
/* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */
g_signal_connect (invisible, "selection-clear-event",
G_CALLBACK (sugar_tray_manager_selection_clear_event),
manager);
#endif
/* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */
gdk_window_add_filter (invisible->window,
sugar_tray_manager_window_filter, manager);
/* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */
gdk_display_add_client_message_filter (display, opcode_atom,
sugar_tray_manager_handle_client_message_opcode,
manager);
/* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */
gdk_display_add_client_message_filter (display, message_data_atom,
sugar_tray_manager_handle_client_message_message_data,
manager);
return TRUE;
}
else
{
gtk_widget_destroy (invisible);
return FALSE;
}
}
#endif
gboolean
sugar_tray_manager_manage_screen (SugarTrayManager *manager,
GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
#ifdef GDK_WINDOWING_X11
return sugar_tray_manager_manage_screen_x11 (manager, screen);
#else
return FALSE;
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_check_running_screen_x11 (GdkScreen *screen)
{
GdkDisplay *display;
Atom selection_atom;
char *selection_atom_name;
display = gdk_screen_get_display (screen);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
selection_atom = gdk_x11_get_xatom_by_name_for_display (display,
selection_atom_name);
g_free (selection_atom_name);
if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
selection_atom) != None)
return TRUE;
else
return FALSE;
}
#endif
gboolean
sugar_tray_manager_check_running (GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
#ifdef GDK_WINDOWING_X11
return sugar_tray_manager_check_running_screen_x11 (screen);
#else
return FALSE;
#endif
}
char *
sugar_tray_manager_get_child_title (SugarTrayManager *manager,
SugarTrayManagerChild *child)
{
char *retval = NULL;
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
Window *child_window;
Atom utf8_string, atom, type;
int result;
int format;
gulong nitems;
gulong bytes_after;
guchar *val;
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), NULL);
g_return_val_if_fail (GTK_IS_SOCKET (child), NULL);
display = gdk_screen_get_display (manager->screen);
child_window = g_object_get_data (G_OBJECT (child),
"na-tray-child-window");
utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING");
atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME");
gdk_error_trap_push ();
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
*child_window,
atom,
0, G_MAXLONG,
False, utf8_string,
&type, &format, &nitems,
&bytes_after, (guchar **)&val);
if (gdk_error_trap_pop () || result != Success)
return NULL;
if (type != utf8_string ||
format != 8 ||
nitems == 0)
{
if (val)
XFree (val);
return NULL;
}
if (!g_utf8_validate (val, nitems, NULL))
{
XFree (val);
return NULL;
}
retval = g_strndup (val, nitems);
XFree (val);
#endif
return retval;
}
void
sugar_tray_manager_set_orientation (SugarTrayManager *manager,
GtkOrientation orientation)
{
g_return_if_fail (SUGAR_IS_TRAY_MANAGER (manager));
if (manager->orientation != orientation)
{
manager->orientation = orientation;
sugar_tray_manager_set_orientation_property (manager);
g_object_notify (G_OBJECT (manager), "orientation");
}
}
GtkOrientation
sugar_tray_manager_get_orientation (SugarTrayManager *manager)
{
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
return manager->orientation;
}

View File

@ -1,98 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* na-tray-manager.h
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Copyright (C) 2003-2006 Vincent Untz
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Used to be: eggtraymanager.h
*/
#ifndef __SUGAR_TRAY_MANAGER_H__
#define __SUGAR_TRAY_MANAGER_H__
#include <gtk/gtkwidget.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
G_BEGIN_DECLS
#define SUGAR_TYPE_TRAY_MANAGER (sugar_tray_manager_get_type ())
#define SUGAR_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManager))
#define SUGAR_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManagerClass))
#define SUGAR_IS_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SUGAR_TYPE_TRAY_MANAGER))
#define SUGAR_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SUGAR_TYPE_TRAY_MANAGER))
#define SUGAR_TRAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManagerClass))
typedef struct _SugarTrayManager SugarTrayManager;
typedef struct _SugarTrayManagerClass SugarTrayManagerClass;
typedef struct _SugarTrayManagerChild SugarTrayManagerChild;
struct _SugarTrayManager
{
GObject parent_instance;
#ifdef GDK_WINDOWING_X11
GdkAtom selection_atom;
Atom opcode_atom;
#endif
GtkWidget *invisible;
GdkScreen *screen;
GtkOrientation orientation;
GList *messages;
GHashTable *socket_table;
};
struct _SugarTrayManagerClass
{
GObjectClass parent_class;
void (* tray_icon_added) (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void (* tray_icon_removed) (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void (* message_sent) (SugarTrayManager *manager,
SugarTrayManagerChild *child,
const gchar *message,
glong id,
glong timeout);
void (* message_cancelled) (SugarTrayManager *manager,
SugarTrayManagerChild *child,
glong id);
void (* lost_selection) (SugarTrayManager *manager);
};
GType sugar_tray_manager_get_type (void);
gboolean sugar_tray_manager_check_running (GdkScreen *screen);
SugarTrayManager *sugar_tray_manager_new (void);
gboolean sugar_tray_manager_manage_screen (SugarTrayManager *manager,
GdkScreen *screen);
char *sugar_tray_manager_get_child_title (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void sugar_tray_manager_set_orientation (SugarTrayManager *manager,
GtkOrientation orientation);
GtkOrientation sugar_tray_manager_get_orientation (SugarTrayManager *manager);
G_END_DECLS
#endif /* __SUGAR_TRAY_MANAGER_H__ */

View File

@ -1 +1 @@
SUBDIRS = presence presence2 nm clipboard datastore console
SUBDIRS = presence presence2 clipboard datastore console

View File

@ -1,15 +0,0 @@
sugardir = $(pkgdatadir)/services/nm
sugar_PYTHON = \
__init__.py \
nmclient.py \
nminfo.py \
bubble.py \
style.py \
wepkeydialog.py
bin_SCRIPTS = sugar-nm-applet
dbusservicedir = $(sysconfdir)/dbus-1/system.d/
dbusservice_DATA = NetworkManagerInfo.conf
EXTRA_DIST = $(dbusservice_DATA) $(bin_SCRIPTS)

View File

@ -1,26 +0,0 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="org.freedesktop.NetworkManagerInfo"/>
<allow send_destination="org.freedesktop.NetworkManagerInfo"/>
<allow send_interface="org.freedesktop.NetworkManagerInfo"/>
</policy>
<policy at_console="true">
<allow own="org.freedesktop.NetworkManagerInfo"/>
<allow send_destination="org.freedesktop.NetworkManagerInfo"/>
<allow send_interface="org.freedesktop.NetworkManagerInfo"/>
</policy>
<policy context="default">
<deny own="org.freedesktop.NetworkManagerInfo"/>
<deny send_destination="org.freedesktop.NetworkManagerInfo"/>
<deny send_interface="org.freedesktop.NetworkManagerInfo"/>
</policy>
<limit name="max_replies_per_connection">512</limit>
</busconfig>

View File

@ -1,132 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import math
import gobject
import gtk
import hippo
class Bubble(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'NetworkBubble'
__gproperties__ = {
'fill-color': (object, None, None,
gobject.PARAM_READWRITE),
'stroke-color': (object, None, None,
gobject.PARAM_READWRITE),
'progress-color': (object, None, None,
gobject.PARAM_READWRITE),
'percent' : (object, None, None,
gobject.PARAM_READWRITE),
}
def __init__(self, **kwargs):
self._stroke_color = 0xFFFFFFFF
self._fill_color = 0xFFFFFFFF
self._progress_color = 0x000000FF
self._percent = 0
self._radius = 8
hippo.CanvasBox.__init__(self, **kwargs)
def do_set_property(self, pspec, value):
if pspec.name == 'fill-color':
self._fill_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'stroke-color':
self._stroke_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'progress-color':
self._progress_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'percent':
self._percent = value
self.emit_paint_needed(0, 0, -1, -1)
def do_get_property(self, pspec):
if pspec.name == 'fill-color':
return self._fill_color
elif pspec.name == 'stroke-color':
return self._stroke_color
elif pspec.name == 'progress-color':
return self._progress_color
elif pspec.name == 'percent':
return self._percent
def _int_to_rgb(self, int_color):
red = (int_color >> 24) & 0x000000FF
green = (int_color >> 16) & 0x000000FF
blue = (int_color >> 8) & 0x000000FF
alpha = int_color & 0x000000FF
return (red / 255.0, green / 255.0, blue / 255.0)
def do_paint_below_children(self, cr, damaged_box):
[width, height] = self.get_allocation()
line_width = 3.0
x = line_width
y = line_width
width -= line_width * 2
height -= line_width * 2
cr.move_to(x + self._radius, y);
cr.arc(x + width - self._radius, y + self._radius,
self._radius, math.pi * 1.5, math.pi * 2);
cr.arc(x + width - self._radius, x + height - self._radius,
self._radius, 0, math.pi * 0.5);
cr.arc(x + self._radius, y + height - self._radius,
self._radius, math.pi * 0.5, math.pi);
cr.arc(x + self._radius, y + self._radius, self._radius,
math.pi, math.pi * 1.5);
color = self._int_to_rgb(self._fill_color)
cr.set_source_rgb(*color)
cr.fill_preserve();
color = self._int_to_rgb(self._stroke_color)
cr.set_source_rgb(*color)
cr.set_line_width(line_width)
cr.stroke();
if self._percent > 0:
self._paint_progress_bar(cr, x, y, width, height, line_width)
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
prog_x = x + line_width
prog_y = y + line_width
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
prog_height = (height - (line_width * 2))
x = prog_x
y = prog_y
width = prog_width
height = prog_height
cr.move_to(x + self._radius, y);
cr.arc(x + width - self._radius, y + self._radius,
self._radius, math.pi * 1.5, math.pi * 2);
cr.arc(x + width - self._radius, x + height - self._radius,
self._radius, 0, math.pi * 0.5);
cr.arc(x + self._radius, y + height - self._radius,
self._radius, math.pi * 0.5, math.pi);
cr.arc(x + self._radius, y + self._radius, self._radius,
math.pi, math.pi * 1.5);
color = self._int_to_rgb(self._progress_color)
cr.set_source_rgb(*color)
cr.fill_preserve();

View File

@ -1,59 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import logging
import gtk
### Deprecated: we should drop this once we removed stylesheets ###
_styles = {}
screen_factor = gtk.gdk.screen_width() / 1200.0
space_unit = 9 * screen_factor
separator_thickness = 3 * screen_factor
standard_icon_scale = 1.0 * screen_factor
small_icon_scale = 0.5 * screen_factor
medium_icon_scale = 1.5 * screen_factor
large_icon_scale = 2.0 * screen_factor
xlarge_icon_scale = 3.0 * screen_factor
default_font_size = 9.0 * screen_factor
def load_stylesheet(module):
for objname in dir(module):
if not objname.startswith('_'):
obj = getattr(module, objname)
if isinstance(obj, dict):
register_stylesheet(objname.replace('_', '.'), obj)
def register_stylesheet(name, style):
_styles[name] = style
def apply_stylesheet(item, stylesheet_name):
if _styles.has_key(stylesheet_name):
style_sheet = _styles[stylesheet_name]
for name in style_sheet.keys():
item.set_property(name, style_sheet[name])
else:
logging.debug('Stylesheet %s not found.' % stylesheet_name)
def get_font_description(style, relative_size):
base_size = 18 * screen_factor
return '%s %dpx' % (style, int(base_size * relative_size))

View File

@ -1,38 +0,0 @@
#!/usr/bin/env python
# vi: ts=4 ai noet
#
# Copyright (C) 2006, 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 St, Fifth Floor, Boston, MA 02110-1301 USA
import sys
import logging
import pygtk
pygtk.require('2.0')
from sugar import logger
from sugar import env
sys.path.insert(0, env.get_services_dir())
from nm import nmclient
logger.start('nm-applet')
logging.info('Starting network applet')
app = nmclient.NMClientApp()
app.run()

View File

@ -1,4 +1,4 @@
SUBDIRS = data model view intro
SUBDIRS = data hardware model view intro
bin_SCRIPTS = \
sugar-activity \

View File

@ -0,0 +1,7 @@
sugardir = $(pkgdatadir)/shell/hardware
sugar_PYTHON = \
__init__.py \
hardwaremanager.py \
nmclient.py \
nminfo.py \
wepkeydialog.py

View File

@ -18,20 +18,23 @@ import logging
import dbus
HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager'
HARDWARE_MANAGER_OBJECT_PATH = '/org/laptop/HardwareManager'
from hardware.nmclient import NMClient
from _sugar import AudioManager
_HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
_HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager'
_HARDWARE_MANAGER_OBJECT_PATH = '/org/laptop/HardwareManager'
COLOR_MODE = 0
B_AND_W_MODE = 1
class HardwareManager(object):
COLOR_MODE = 0
B_AND_W_MODE = 1
def __init__(self):
try:
bus = dbus.SystemBus()
proxy = bus.get_object(HARDWARE_MANAGER_SERVICE,
HARDWARE_MANAGER_OBJECT_PATH)
self._service = dbus.Interface(proxy, HARDWARE_MANAGER_INTERFACE)
proxy = bus.get_object(_HARDWARE_MANAGER_SERVICE,
_HARDWARE_MANAGER_OBJECT_PATH)
self._service = dbus.Interface(proxy, _HARDWARE_MANAGER_INTERFACE)
except dbus.DBusException:
self._service = None
logging.error('Hardware manager service not found.')
@ -56,3 +59,16 @@ class HardwareManager(object):
self._service.set_keyboard_brightness(False)
else:
self._service.set_keyboard_brightness(True)
def get_hardware_manager():
return _hardware_manager
def get_audio_manager():
return _audio_manager
def get_network_manager():
return _network_manager
_hardware_manager = HardwareManager()
_audio_manager = AudioManager()
_network_manager = NMClient()

View File

@ -1,4 +1,3 @@
# vi: ts=4 ai noet
#
# Copyright (C) 2006, Red Hat, Inc.
#
@ -16,27 +15,21 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import os
import dbus
import dbus.glib
import dbus.decorators
import gobject
import gtk
import logging
import os
from gettext import gettext as _
import hippo
import style
from sugar.graphics.timeline import Timeline
from wepkeydialog import WEPKeyDialog
from bubble import Bubble
import nminfo
from hardware.wepkeydialog import WEPKeyDialog
from hardware import nminfo
IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
IW_AUTH_ALG_SHARED_KEY = 0x00000002
NM_DEVICE_STAGE_STRINGS=("Unknown",
"Prepare",
"Config",
@ -63,10 +56,8 @@ NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001
NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002
NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004
sys_bus = dbus.SystemBus()
NM_802_11_CAP_NONE = 0x00000000
NM_802_11_CAP_PROTO_NONE = 0x00000001
NM_802_11_CAP_PROTO_WEP = 0x00000002
@ -79,10 +70,14 @@ NM_802_11_CAP_CIPHER_WEP104 = 0x00002000
NM_802_11_CAP_CIPHER_TKIP = 0x00004000
NM_802_11_CAP_CIPHER_CCMP = 0x00008000
class Network(gobject.GObject):
__gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
'init-failed' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'ssid-changed' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([]))
}
def __init__(self, op):
@ -115,6 +110,9 @@ class Network(gobject.GObject):
logging.debug("Net(%s): ssid '%s', mode %d, strength %d" % (self._op,
self._ssid, self._mode, self._strength))
self.emit('strength-changed')
self.emit('ssid-changed')
def _update_error_cb(self, err):
logging.debug("Net(%s): failed to update. (%s)" % (self._op, err))
self._valid = False
@ -131,26 +129,27 @@ class Network(gobject.GObject):
def set_strength(self, strength):
self._strength = strength
self.emit('strength-changed')
def is_valid(self):
return self._valid
def add_to_menu(self, menu, callback, dev):
strength = self._strength
if strength > 100:
strength = 100
elif strength < 0:
strength = 0
item = NetworkMenuItem(text=self._ssid, percent=strength)
item.connect('button-press-event', callback, (dev, self))
menu.add_item(item)
class Device(gobject.GObject):
__gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
'init-failed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'activated': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'deactivated': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'network-appeared': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'network-disappeared': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
@ -178,8 +177,6 @@ class Device(gobject.GObject):
self._type = props[2]
self._udi = props[3]
self._active = props[4]
if self._active:
self.emit('activated')
self._link = props[15]
self._caps = props[17]
@ -192,6 +189,11 @@ class Device(gobject.GObject):
self._valid = True
if self._active:
self.emit('activated')
else:
self.emit('deactivated')
def _update_networks(self, net_ops, active_op):
for op in net_ops:
net = Network(op)
@ -213,41 +215,15 @@ class Device(gobject.GObject):
self._active_net = None
del self._networks[net_op]
def _add_to_menu_wired(self, menu, callback):
item = NetworkMenuItem(_("Wired Network"), stylesheet="nm.Bubble.Wired",
hi_stylesheet="nm.Bubble.Wired.Hi",
act_stylesheet="nm.Bubble.Wired.Activated")
item.connect('button-press-event', callback, (self, None))
menu.add_item(item)
def _add_to_menu_wireless(self, menu, callback, active_only):
act_net = None
if self._active_net and self._networks.has_key(self._active_net):
act_net = self._networks[self._active_net]
# Only add the active network if active_only == True
if active_only:
if act_net:
act_net.add_to_menu(menu, callback, self)
return
# Otherwise, add all networks _except_ the active one
for net in self._networks.values():
if not net.is_valid():
continue
if act_net == net:
continue
net.add_to_menu(menu, callback, self)
def add_to_menu(self, menu, callback, active_only=False):
if self._type == DEVICE_TYPE_802_3_ETHERNET:
self._add_to_menu_wired(menu, callback)
elif self._type == DEVICE_TYPE_802_11_WIRELESS:
self._add_to_menu_wireless(menu, callback, active_only)
def get_op(self):
return self._op
def get_networks(self):
return self._networks.values()
def get_active_network(self):
return self.get_network(self._active_net)
def get_network(self, op):
if self._networks.has_key(op):
return self._networks[op]
@ -276,12 +252,16 @@ class Device(gobject.GObject):
net = Network(network)
self._networks[network] = net
net.connect('init-failed', self._net_init_failed)
self.emit('network-appeared', net)
def network_disappeared(self, network):
if not self._networks.has_key(network):
return
if network == self._active_net:
self._active_net = None
self.emit('network-disappeared', self._networks[network])
del self._networks[network]
def get_active(self):
@ -309,171 +289,31 @@ class Device(gobject.GObject):
def get_capabilities(self):
return self._caps
nm_bubble_wireless = {
'fill-color' : 0x646464FF,
'stroke-color' : 0x646464FF,
'progress-color': 0x333333FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wireless_hi = {
'fill-color' : 0x979797FF,
'stroke-color' : 0x979797FF,
'progress-color': 0x666666FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wireless_activated = {
'fill-color' : 0xA7A7A7FF,
'stroke-color' : 0xA7A7A7FF,
'progress-color': 0x777777FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired = {
'fill-color' : 0x000000FF,
'stroke-color' : 0x000000FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired_hi = {
'fill-color' : 0x333333FF,
'stroke-color' : 0x333333FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired_activated = {
'fill-color' : 0x444444FF,
'stroke-color' : 0x444444FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_menu_item_title = {
'xalign': hippo.ALIGNMENT_START,
'padding-left': 5,
'color' : 0xFFFFFFFF,
'font' : style.get_font_description('Bold', 1.2)
}
style.register_stylesheet("nm.Bubble.Wireless", nm_bubble_wireless)
style.register_stylesheet("nm.Bubble.Wireless.Hi", nm_bubble_wireless_hi)
style.register_stylesheet("nm.Bubble.Wireless.Activated", nm_bubble_wireless_activated)
style.register_stylesheet("nm.Bubble.Wired", nm_bubble_wired)
style.register_stylesheet("nm.Bubble.Wired.Hi", nm_bubble_wired_hi)
style.register_stylesheet("nm.Bubble.Wired.Activated", nm_bubble_wired_activated)
style.register_stylesheet("nm.MenuItem.Title", nm_menu_item_title)
class NetworkMenuItem(Bubble):
def __init__(self, text, percent=0, stylesheet="nm.Bubble.Wireless",
hi_stylesheet="nm.Bubble.Wireless.Hi",
act_stylesheet="nm.Bubble.Wireless.Activated"):
Bubble.__init__(self, percent=percent)
self._hover = False
self._default_stylesheet = stylesheet
self._hi_stylesheet = hi_stylesheet
self._act_stylesheet = act_stylesheet
style.apply_stylesheet(self, stylesheet)
text_item = hippo.CanvasText(text=text)
style.apply_stylesheet(text_item, 'nm.MenuItem.Title')
self.append(text_item)
self.connect('motion-notify-event', self._motion_notify_event_cb)
# Disable active hilight for now...
#self.connect('button-press-event', self._button_press_event_cb)
def _motion_notify_event_cb(self, widget, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
if not self._hover:
self._hover = True
style.apply_stylesheet(self, self._hi_stylesheet)
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
if self._hover:
self._hover = False
style.apply_stylesheet(self, self._default_stylesheet)
return True
def _button_press_event_cb(self, widget, event):
style.apply_stylesheet(self, self._act_stylesheet)
return False
class NetworkMenu(gtk.Window):
__gsignals__ = {
'action': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([int])),
}
def __init__(self):
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
canvas = hippo.Canvas()
self.add(canvas)
canvas.show()
self._root = hippo.CanvasBox()
style.apply_stylesheet(self._root, 'menu')
canvas.set_root(self._root)
def add_separator(self):
separator = hippo.CanvasBox()
style.apply_stylesheet(separator, 'menu.Separator')
self._root.append(separator)
def add_item(self, item):
self._root.append(item)
NM_STATE_UNKNOWN = 0
NM_STATE_ASLEEP = 1
NM_STATE_CONNECTING = 2
NM_STATE_CONNECTED = 3
NM_STATE_DISCONNECTED = 4
ICON_WIRED = "stock-net-wired"
ICON_WIRELESS_00 = "stock-net-wireless-00"
ICON_WIRELESS_01_20 = "stock-net-wireless-01-20"
ICON_WIRELESS_21_40 = "stock-net-wireless-21-40"
ICON_WIRELESS_41_60 = "stock-net-wireless-41-60"
ICON_WIRELESS_61_80 = "stock-net-wireless-61-80"
ICON_WIRELESS_81_100 = "stock-net-wireless-81-100"
class NMClient(gobject.GObject):
__gsignals__ = {
'device-activated' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'device-removed' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
class NMClientApp:
def __init__(self):
gobject.GObject.__init__(self)
self.nminfo = None
self._nm_present = False
self._nm_state = NM_STATE_UNKNOWN
self._update_timer = 0
self._active_device = None
self._devices = {}
self._key_dialog = None
self._icon_theme = gtk.icon_theme_get_default()
self._icons = {}
self._cur_icon = None
try:
self._icons = self._load_icons()
except RuntimeError:
logging.debug("Couldn't find required icon resources, will exit.")
os._exit(1)
self._setup_trayicon()
self._menu = None
self._hover_menu = False
self._timeline = Timeline(self)
self._timeline.add_tag('popup', 6, 6)
self._timeline.add_tag('before_popdown', 7, 7)
self._timeline.add_tag('popdown', 8, 8)
try:
self.nminfo = nminfo.NMInfo(self)
@ -484,22 +324,8 @@ class NMClientApp:
self._get_nm_state()
self._get_initial_devices()
def _get_one_icon_pixbuf(self, name):
info = self._icon_theme.lookup_icon(name, 75, 0)
if not info or not info.get_filename():
raise RuntimeError
return gtk.gdk.pixbuf_new_from_file(info.get_filename())
def _load_icons(self):
icons = {}
icons[ICON_WIRED] = self._get_one_icon_pixbuf(ICON_WIRED)
icons[ICON_WIRELESS_00] = self._get_one_icon_pixbuf(ICON_WIRELESS_00)
icons[ICON_WIRELESS_01_20] = self._get_one_icon_pixbuf(ICON_WIRELESS_01_20)
icons[ICON_WIRELESS_21_40] = self._get_one_icon_pixbuf(ICON_WIRELESS_21_40)
icons[ICON_WIRELESS_41_60] = self._get_one_icon_pixbuf(ICON_WIRELESS_41_60)
icons[ICON_WIRELESS_61_80] = self._get_one_icon_pixbuf(ICON_WIRELESS_61_80)
icons[ICON_WIRELESS_81_100] = self._get_one_icon_pixbuf(ICON_WIRELESS_81_100)
return icons
def get_devices(self):
return self._devices
def _get_nm_state(self):
# Grab NM's state
@ -507,163 +333,11 @@ class NMClientApp:
error_handler=self._get_state_error_cb)
def _get_state_reply_cb(self, state):
if self._nm_state != state:
self._schedule_icon_update(immediate=True)
self._nm_state = state
def _get_state_error_cb(self, err):
logging.debug("Failed to get NetworkManager state! %s" % err)
def _get_icon(self):
act_dev = None
if self._active_device and self._devices.has_key(self._active_device):
act_dev = self._devices[self._active_device]
pixbuf = None
if not self._nm_present \
or not act_dev \
or self._nm_state == NM_STATE_UNKNOWN \
or self._nm_state == NM_STATE_ASLEEP \
or self._nm_state == NM_STATE_DISCONNECTED:
pixbuf = self._icons[ICON_WIRELESS_00]
elif act_dev.get_type() == DEVICE_TYPE_802_3_ETHERNET:
pixbuf = self._icons[ICON_WIRED]
elif act_dev.get_type() == DEVICE_TYPE_802_11_WIRELESS:
strength = act_dev.get_strength()
if strength <= 0:
pixbuf = self._icons[ICON_WIRELESS_00]
elif strength >= 1 and strength <= 20:
pixbuf = self._icons[ICON_WIRELESS_01_20]
elif strength >= 21 and strength <= 40:
pixbuf = self._icons[ICON_WIRELESS_21_40]
elif strength >= 41 and strength <= 60:
pixbuf = self._icons[ICON_WIRELESS_41_60]
elif strength >= 61 and strength <= 80:
pixbuf = self._icons[ICON_WIRELESS_61_80]
elif strength >= 81 and strength:
pixbuf = self._icons[ICON_WIRELESS_81_100]
if not pixbuf:
pixbuf = self._icons[ICON_WIRELESS_00]
return pixbuf
def _setup_trayicon(self):
pixbuf = self._get_icon()
self._trayicon = gtk.status_icon_new_from_pixbuf(pixbuf)
self._trayicon.connect("popup_menu", self._status_icon_clicked)
self._trayicon.connect("activate", self._status_icon_clicked)
self._schedule_icon_update()
def _status_icon_clicked(self, button=0, time=None):
self._timeline.play(None, 'popup')
def _get_menu_position(self, menu, item):
(screen, rect, orientation) = item.get_geometry()
[item_x, item_y, item_w, item_h] = rect
[menu_w, menu_h] = menu.size_request()
x = item_x + item_w - menu_w
y = item_y + item_h
x = min(x, screen.get_width() - menu_w)
x = max(0, x)
y = min(y, screen.get_height() - menu_h)
y = max(0, y)
return (x, y)
def do_popup(self, current, n_frames):
if self._menu:
return
self._menu = self._create_menu()
self._menu.connect('enter-notify-event',
self._menu_enter_notify_event_cb)
self._menu.connect('leave-notify-event',
self._menu_leave_notify_event_cb)
(x, y) = self._get_menu_position(self._menu, self._trayicon)
self._menu.move(x, y)
self._menu.show_all()
def do_popdown(self, current, frame):
if self._menu:
self._menu.destroy()
self._menu = None
def _popdown(self):
self._timeline.play('popdown', 'popdown')
def _menu_enter_notify_event_cb(self, widget, event):
self._hover_menu = True
self._timeline.play('popup', 'popup')
def _menu_leave_notify_event_cb(self, widget, event):
self._hover_menu = False
self._popdown()
def _create_menu(self):
menu = NetworkMenu()
# Active device goes above the separator
act_dev = None
if self._active_device and self._devices.has_key(self._active_device):
act_dev = self._devices[self._active_device]
if act_dev:
act_dev.add_to_menu(menu, self._menu_item_clicked_cb, active_only=True)
menu.add_separator()
# Wired devices first, if they don't support carrier detect
for dev in self._devices.values():
if not dev.is_valid():
continue
if dev.get_type() != DEVICE_TYPE_802_3_ETHERNET:
continue
if dev.get_capabilities() & NM_DEVICE_CAP_CARRIER_DETECT:
continue
if dev == act_dev:
continue
dev.add_to_menu(menu, self._menu_item_clicked_cb)
# Wireless devices second
for dev in self._devices.values():
if not dev.is_valid():
continue
if dev.get_type() != DEVICE_TYPE_802_11_WIRELESS:
continue
dev.add_to_menu(menu, self._menu_item_clicked_cb)
return menu
def _update_icon(self):
pixbuf = self._get_icon()
if self._cur_icon != pixbuf:
self._trayicon.set_from_pixbuf(pixbuf)
self._cur_icon = pixbuf
blink = False
if self._nm_state == NM_STATE_CONNECTING:
blink = True
self._trayicon.set_blinking(blink)
self._update_timer = 0
return False
def _schedule_icon_update(self, immediate=False):
if immediate and self._update_timer:
gobject.source_remove(self._update_timer)
self._update_timer = 0
if self._update_timer != 0:
# There is already an update scheduled
return
if immediate:
self._update_timer = gobject.idle_add(self._update_icon)
else:
self._update_timer = gobject.timeout_add(2000, self._update_icon)
def _get_initial_devices_reply_cb(self, ops):
for op in ops:
self._add_device(op)
@ -699,7 +373,8 @@ class NMClientApp:
dev.disconnect('init-failed')
dev.disconnect('strength-changed')
del self._devices[dev_op]
self._schedule_icon_update(immediate=True)
self.emit('device-removed', dev)
def _dev_activated_cb(self, dev):
op = dev.get_op()
@ -708,7 +383,8 @@ class NMClientApp:
if not dev.get_active():
return
self._active_device = op
self._schedule_icon_update(immediate=True)
self.emit('device-activated', dev)
def _dev_strength_changed_cb(self, dev, strength):
op = dev.get_op()
@ -716,7 +392,6 @@ class NMClientApp:
return
if not dev.get_active():
return
self._schedule_icon_update()
def get_device(self, dev_op):
if not self._devices.has_key(dev_op):
@ -760,8 +435,7 @@ class NMClientApp:
except dbus.DBusException:
pass
def _menu_item_clicked_cb(self, widget, event, dev_data):
(device, network) = dev_data
def set_active_device(self, device, network):
net_op = ""
if network:
net_op = network.get_op()
@ -776,8 +450,6 @@ class NMClientApp:
else:
raise dbus.DBusException(e)
self._popdown()
def get_key_for_network(self, net, async_cb, async_err_cb):
# Throw up a dialog asking for the key here, and set
# the authentication algorithm to the given one, if any
@ -832,7 +504,6 @@ class NMClientApp:
def state_change_sig_handler(self, state):
self._nm_state = state
self._schedule_icon_update(immediate=True)
def device_activating_sig_handler(self, device):
self._active_device = device
@ -842,7 +513,6 @@ class NMClientApp:
return
self._active_device = device
self._devices[device].set_active(True, ssid)
self._schedule_icon_update(immediate=True)
def device_no_longer_active_sig_handler(self, device):
if not self._devices.has_key(device):
@ -850,7 +520,6 @@ class NMClientApp:
if self._active_device == device:
self._active_device = None
self._devices[device].set_active(False)
self._schedule_icon_update(immediate=True)
def name_owner_changed_sig_handler(self, name, old, new):
if name != NM_SERVICE:
@ -858,7 +527,6 @@ class NMClientApp:
if (old and len(old)) and (not new and not len(new)):
# NM went away
self._nm_present = False
self._schedule_icon_update(immediate=True)
for op in self._devices.keys():
del self._devices[op]
self._devices = {}
@ -907,11 +575,3 @@ class NMClientApp:
if not self._devices.has_key(device):
return
self._devices[device].set_carrier(False)
def run(self):
loop = gobject.MainLoop()
try:
loop.run()
except KeyboardInterrupt:
pass

View File

@ -20,6 +20,46 @@ from sugar.graphics.xocolor import XoColor
from sugar.presence import PresenceService
from sugar.activity import bundleregistry
from model.BuddyModel import BuddyModel
from hardware import hardwaremanager
class AccessPointModel(gobject.GObject):
__gproperties__ = {
'name' : (str, None, None, None,
gobject.PARAM_READABLE),
'strength' : (int, None, None, 0, 100, 0,
gobject.PARAM_READABLE)
}
def __init__(self, nm_device, nm_network):
gobject.GObject.__init__(self)
self._nm_network = nm_network
self._nm_device = nm_device
self._nm_network.connect('strength-changed',
self._strength_changed_cb)
self._nm_network.connect('ssid-changed',
self._essid_changed_cb)
def _strength_changed_cb(self, nm_network):
self.notify('strength')
def _essid_changed_cb(self, nm_network):
self.notify('name')
def get_id(self):
return self._nm_network.get_op()
def get_nm_device(self):
return self._nm_device
def get_nm_network(self):
return self._nm_network
def do_get_property(self, pspec):
if pspec.name == 'strength':
return self._nm_network.get_strength()
elif pspec.name == 'name':
return self._nm_network.get_ssid()
class ActivityModel:
def __init__(self, activity, bundle, service):
@ -48,9 +88,14 @@ class MeshModel(gobject.GObject):
'buddy-added': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'buddy-moved': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT,
gobject.TYPE_PYOBJECT])),
'buddy-removed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'access-point-added': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'access-point-removed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
}
@ -59,6 +104,7 @@ class MeshModel(gobject.GObject):
self._activities = {}
self._buddies = {}
self._access_points = {}
self._bundle_registry = bundleregistry.get_registry()
self._pservice = PresenceService.get_instance()
@ -78,6 +124,42 @@ class MeshModel(gobject.GObject):
for service in self._pservice.get_services():
self._check_service(service)
network_manager = hardwaremanager.get_network_manager()
for nm_device in network_manager.get_devices():
self._add_network_device(nm_device)
network_manager.connect('device-activated',
self._nm_device_activated_cb)
def _nm_device_activated_cb(self, manager, nm_device):
self._add_network_device(nm_device)
def _nm_network_appeared_cb(self, nm_device, nm_network):
self._add_access_point(nm_device, nm_network)
def _nm_network_disappeared_cb(self, nm_device, nm_network):
self._remove_access_point(nm_device, nm_network)
def _add_network_device(self, nm_device):
for nm_network in nm_device.get_networks():
self._add_access_point(nm_device, nm_network)
nm_device.connect('network-appeared',
self._nm_network_appeared_cb)
nm_device.connect('network-disappeared',
self._nm_network_disappeared_cb)
def _add_access_point(self, nm_device, nm_network):
model = AccessPointModel(nm_device, nm_network)
self._access_points[nm_network.get_op()] = model
self.emit('access-point-added', model)
def _remove_access_point(self, nm_network):
self.emit('access-point-removed',
self._access_points[nm_network.get_op()])
del self._access_points[nm_network.get_op()]
def get_access_points(self):
return self._access_points.values()
def get_activities(self):
return self._activities.values()

View File

@ -4,4 +4,5 @@ sugar_PYTHON = \
device.py \
devicesmodel.py \
battery.py \
network.py
wirednetwork.py \
wirelessnetwork.py

View File

@ -5,7 +5,7 @@ class Device(device.Device):
device.Device.__init__(self)
def get_type(self):
return 'network'
return 'battery'
def get_level(self):
return 0

View File

@ -1,7 +1,10 @@
import gobject
from sugar import util
class Device(object):
class Device(gobject.GObject):
def __init__(self):
gobject.GObject.__init__(self)
self._id = util.unique_id()
def get_type(self):

View File

@ -1,8 +1,11 @@
import gobject
from model.devices import device
from model.devices import network
from model.devices import wirednetwork
from model.devices import wirelessnetwork
from model.devices import battery
from hardware import hardwaremanager
from hardware import nmclient
class DevicesModel(gobject.GObject):
__gsignals__ = {
@ -17,13 +20,56 @@ class DevicesModel(gobject.GObject):
def __init__(self):
gobject.GObject.__init__(self)
self._devices = []
self.add_device(network.Device())
self._devices = {}
self.add_device(battery.Device())
self._observe_network_manager()
def _observe_network_manager(self):
network_manager = hardwaremanager.get_network_manager()
for device in network_manager.get_devices():
self._check_network_device(device)
network_manager.connect('device-activated',
self._network_device_activated_cb)
network_manager.connect('device-removed',
self._network_device_removed_cb)
def _network_device_activated_cb(self, network_manager, nm_device):
self._check_network_device(nm_device)
def _network_device_removed_cb(self, nm_device):
self._remove_network_device(nm_device)
def _network_device_deactivated_cb(self, nm_device):
self._remove_network_device(nm_device)
def _check_network_device(self, nm_device):
if not nm_device.is_valid():
return
if nm_device.get_type() == nmclient.DEVICE_TYPE_802_11_WIRELESS:
self._add_network_device(nm_device)
def _get_network_device(self, nm_device):
return self._devices[nm_device.get_op()]
def _add_network_device(self, nm_device):
self.add_device(wirelessnetwork.Device(nm_device))
nm_device.connect('deactivated',
self._network_device_deactivated_cb)
def _remove_network_device(self, nm_device):
self.remove_device(self._get_network_device(nm_device))
def __iter__(self):
return iter(self._devices)
return iter(self._devices.values())
def add_device(self, device):
self._devices.append(device)
self._devices[device.get_id()] = device
self.emit('device-appeared', device)
def remove_device(self, device):
self.emit('device-disappeared', self._devices[device.get_id()])
del self._devices[device.get_id()]

View File

@ -1,11 +0,0 @@
from model.devices import device
class Device(device.Device):
def __init__(self):
device.Device.__init__(self)
def get_type(self):
return 'network'
def get_level(self):
return 0

View File

@ -0,0 +1,12 @@
from model.devices import device
class Device(device.Device):
def __init__(self, nm_device):
device.Device.__init__(self)
self._nm_device = device
def get_id(self):
return self._nm_device.get_op()
def get_type(self):
return 'wirednetwork'

View File

@ -0,0 +1,37 @@
import gobject
from model.devices import device
class Device(device.Device):
__gproperties__ = {
'name' : (str, None, None, None,
gobject.PARAM_READABLE),
'strength' : (int, None, None, 0, 100, 0,
gobject.PARAM_READABLE)
}
def __init__(self, nm_device):
device.Device.__init__(self)
self._nm_device = nm_device
self._nm_device.connect('strength-changed',
self._strength_changed_cb)
def _strength_changed_cb(self, nm_device, strength):
self.notify('strength')
def _essid_changed_cb(self, nm_device):
self.notify('name')
def do_get_property(self, pspec):
if pspec.name == 'strength':
return self._nm_device.get_strength()
elif pspec.name == 'name':
# FIXME
return None
def get_type(self):
return 'wirelessnetwork'
def get_id(self):
return self._nm_device.get_op()

View File

@ -1,5 +1,7 @@
import dbus
from sugar.activity import bundleregistry
_DBUS_SERVICE = "org.laptop.Shell"
_DBUS_INTERFACE = "org.laptop.Shell"
_DBUS_PATH = "/org/laptop/Shell"
@ -15,5 +17,5 @@ class ShellService(dbus.service.Object):
@dbus.service.method(_DBUS_INTERFACE, in_signature="s", out_signature="b")
def add_bundle(self, bundle_path):
registry = self._shellModel.get_bundle_registry()
registry = bundleregistry.get_registry()
return registry.add_bundle(bundle_path)

View File

@ -64,12 +64,6 @@ model = ShellModel()
service = ShellService(model)
shell = Shell(model)
# Start the NetworkManager applet
# FIXME: do this somewhere else, better planned out
args = ["sugar-nm-applet"]
flags = gobject.SPAWN_SEARCH_PATH
result = gobject.spawn_async(args, flags=flags, standard_output=False)
tbh = TracebackUtils.TracebackHelper()
try:
gtk.main()

View File

@ -35,6 +35,8 @@ class BuddyMenu(Menu):
self._shell = shell
Menu.__init__(self, buddy.get_name())
self.props.border = 0
self.props.padding = units.points_to_pixels(5)
pixbuf = self._get_buddy_icon_pixbuf()
if pixbuf:
icon_item = hippo.CanvasImage()

View File

@ -11,5 +11,4 @@ sugar_PYTHON = \
clipboardmenu.py \
keyhandler.py \
OverlayWindow.py \
Shell.py \
hardwaremanager.py
Shell.py

View File

@ -26,8 +26,6 @@ from view.ActivityHost import ActivityHost
from sugar.activity import activityfactory
from view.frame.frame import Frame
from view.keyhandler import KeyHandler
from view.hardwaremanager import HardwareManager
from _sugar import AudioManager
import sugar
class Shell(gobject.GObject):
@ -40,9 +38,6 @@ class Shell(gobject.GObject):
self._current_host = None
self._screen_rotation = 0
self._hw_manager = HardwareManager()
self._audio_manager = AudioManager()
self._home_window = HomeWindow(self)
self._home_window.show()
self.set_zoom_level(sugar.ZOOM_HOME)
@ -88,12 +83,6 @@ class Shell(gobject.GObject):
if self._current_host:
self._current_host.set_active(True)
def get_hardware_manager(self):
return self._hw_manager
def get_audio_manager(self):
return self._audio_manager
def get_model(self):
return self._model

View File

@ -4,6 +4,7 @@ from sugar.graphics.canvasicon import CanvasIcon
from view.clipboardmenu import ClipboardMenu
from sugar.graphics.xocolor import XoColor
from sugar.graphics import units
from sugar.graphics import color
from sugar.activity import activityfactory
from sugar.clipboard import clipboardservice
from sugar import util
@ -43,9 +44,9 @@ class ClipboardIcon(CanvasIcon):
self._menu.set_state(name, percent, preview, activity)
if activity and percent < 100:
self.set_property('color', XoColor("#000000,#424242"))
self.props.xo_color = XoColor("#000000,#424242")
else:
self.set_property('color', XoColor("#000000,#FFFFFF"))
self.props.xo_color = XoColor("#000000,#FFFFFF")
def _activity_create_success_cb(self, handler, activity):
activity.start(util.unique_id())
@ -81,3 +82,9 @@ class ClipboardIcon(CanvasIcon):
def get_object_id(self):
return self._object_id
def prelight(self, enter):
if enter:
self.props.background_color = color.BLACK.get_int()
else:
self.props.background_color = color.TOOLBAR_BACKGROUND.get_int()

View File

@ -35,6 +35,7 @@ class ClipboardMenu(Menu):
def __init__(self, name, percent, preview, activity):
Menu.__init__(self, name)
self.props.border = 0
if percent < 100:
self._progress_bar = ClipboardProgressBar(percent)

View File

@ -3,4 +3,5 @@ sugar_PYTHON = \
__init__.py \
battery.py \
deviceview.py \
network.py
wirednetwork.py \
wirelessnetwork.py

View File

@ -1,6 +1,6 @@
from view.devices import deviceview
class DeviceView(deviceview.DeviceView)
class DeviceView(deviceview.DeviceView):
def __init__(self, model):
deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close'

View File

@ -3,4 +3,4 @@ from view.devices import deviceview
class DeviceView(deviceview.DeviceView):
def __init__(self, model):
deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close'
self.props.icon_name = 'theme:stock-net-wired'

View File

@ -0,0 +1,34 @@
from view.devices import deviceview
class DeviceView(deviceview.DeviceView):
def __init__(self, model):
deviceview.DeviceView.__init__(self, model)
self._model = model
model.connect('notify::name', self._name_changed_cb)
model.connect('notify::strength', self._strength_changed_cb)
self._update_name()
self._update_icon()
def _strength_changed_cb(self, model, pspec):
self._update_icon()
def _name_changed_cb(self, model, pspec):
self._update_name()
def _update_name(self):
self.props.tooltip = self._model.props.name
def _update_icon(self):
strength = self._model.props.strength
if strength < 21:
self.props.icon_name = 'theme:stock-net-wireless-00'
elif strength < 41:
self.props.icon_name = 'theme:stock-net-wireless-21-40'
elif strength < 61:
self.props.icon_name = 'theme:stock-net-wireless-41-60'
elif strength < 81:
self.props.icon_name = 'theme:stock-net-wireless-61-80'
else:
self.props.icon_name = 'theme:stock-net-wireless-81-100'

View File

@ -17,15 +17,30 @@
import hippo
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import color
from sugar.presence import PresenceService
from view.BuddyIcon import BuddyIcon
from model.BuddyModel import BuddyModel
class FriendIcon(BuddyIcon):
def __init__(self, shell, popup_context, buddy):
BuddyIcon.__init__(self, shell, popup_context, buddy)
self._popup_context = popup_context
def get_popup_context(self):
return self._popup_context
def prelight(self, enter):
if enter:
self.props.background_color = color.BLACK.get_int()
else:
self.props.background_color = color.TOOLBAR_BACKGROUND.get_int()
class FriendsBox(hippo.CanvasBox):
def __init__(self, shell, menu_shell):
def __init__(self, shell, popup_context):
hippo.CanvasBox.__init__(self)
self._shell = shell
self._menu_shell = menu_shell
self._popup_context = popup_context
self._activity_ps = None
self._joined_hid = -1
self._left_hid = -1
@ -48,7 +63,7 @@ class FriendsBox(hippo.CanvasBox):
return
model = BuddyModel(buddy=buddy)
icon = BuddyIcon(self._shell, self._menu_shell, model)
icon = FriendIcon(self._shell, self._popup_context, model)
self.append(icon)
self._buddies[buddy.get_name()] = icon

View File

@ -8,7 +8,6 @@ sugar_PYTHON = \
eventframe.py \
frame.py \
ZoomBox.py \
notificationtray.py \
overlaybox.py \
PanelWindow.py \
framepopupcontext.py

View File

@ -22,6 +22,7 @@ from sugar.graphics import units
class PanelWindow(gtk.Window):
def __init__(self, orientation):
gtk.Window.__init__(self)
self._orientation = orientation
self.set_decorated(False)
self.connect('realize', self._realize_cb)
@ -29,28 +30,16 @@ class PanelWindow(gtk.Window):
self._canvas = hippo.Canvas()
self._bg = hippo.CanvasBox(background_color=0x414141ff,
orientation=orientation)
padding = units.grid_to_pixels(1)
if orientation == hippo.ORIENTATION_HORIZONTAL:
self._bg.props.padding_left = padding
self._bg.props.padding_right = padding
width = gtk.gdk.screen_width()
height = units.grid_to_pixels(1)
else:
self._bg.props.padding_top = padding
self._bg.props.padding_bottom = padding
width = units.grid_to_pixels(1)
height = gtk.gdk.screen_height()
orientation=self._orientation)
self._update_size()
self._canvas.set_root(self._bg)
self.add(self._canvas)
self._canvas.show()
self.resize(width, height)
screen = gtk.gdk.screen_get_default()
screen.connect('size-changed', self._size_changed_cb)
def get_root(self):
return self._bg
@ -58,6 +47,29 @@ class PanelWindow(gtk.Window):
def get_canvas(self):
return self._canvas
def _update_size(self):
padding = units.grid_to_pixels(1)
if self._orientation == hippo.ORIENTATION_HORIZONTAL:
self._bg.props.padding_left = padding
self._bg.props.padding_right = padding
self._bg.props.padding_top = 0
self._bg.props.padding_bottom = 0
width = gtk.gdk.screen_width()
height = units.grid_to_pixels(1)
else:
self._bg.props.padding_left = 0
self._bg.props.padding_right = 0
self._bg.props.padding_top = padding
self._bg.props.padding_bottom = padding
width = units.grid_to_pixels(1)
height = gtk.gdk.screen_height()
self.resize(width, height)
def _realize_cb(self, widget):
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self.window.set_accept_focus(False)
def _size_changed_cb(self, screen):
self._update_size()

View File

@ -26,7 +26,6 @@ from view.frame.overlaybox import OverlayBox
from view.frame.FriendsBox import FriendsBox
from view.frame.PanelWindow import PanelWindow
from view.frame.clipboardpanelwindow import ClipboardPanelWindow
from view.frame.notificationtray import NotificationTray
from view.frame.framepopupcontext import FramePopupContext
from model.ShellModel import ShellModel
from sugar.graphics.timeline import Timeline
@ -50,6 +49,7 @@ class Frame:
self._hover_frame = False
self._shell = shell
self._mode = Frame.INACTIVE
self._current_position = 0
self._timeline = Timeline(self)
self._timeline.add_tag('slide_in', 18, 24)
@ -76,6 +76,9 @@ class Frame:
shell.get_model().connect('notify::state',
self._shell_state_changed_cb)
screen = gtk.gdk.screen_get_default()
screen.connect('size-changed', self._size_changed_cb)
def _create_top_panel(self):
panel = self._create_panel(hippo.ORIENTATION_HORIZONTAL)
root = panel.get_root()
@ -83,16 +86,6 @@ class Frame:
box = ZoomBox(self._shell, self._popup_context)
root.append(box)
tray = NotificationTray()
tray_box = hippo.CanvasBox(box_width=units.grid_to_pixels(1),
box_height=units.grid_to_pixels(1),
xalign=hippo.ALIGNMENT_END)
tray_widget = hippo.CanvasWidget()
tray_widget.props.widget = tray
tray_box.append(tray_widget, gtk.EXPAND)
root.append(tray_box)
box = OverlayBox(self._shell)
root.append(box, hippo.PACK_FIXED)
@ -221,22 +214,26 @@ class Frame:
self._timeline.play('before_slide_out', 'slide_out')
def _move(self, pos):
self._current_position = pos
self._update_position()
def _update_position(self):
screen_h = gtk.gdk.screen_height()
screen_w = gtk.gdk.screen_width()
self._move_panel(self._top_panel, pos,
self._move_panel(self._top_panel, self._current_position,
0, units.grid_to_pixels(-1),
0, 0)
self._move_panel(self._bottom_panel, pos,
self._move_panel(self._bottom_panel, self._current_position,
0, screen_h,
0, screen_h - units.grid_to_pixels(1))
self._move_panel(self._left_panel, pos,
self._move_panel(self._left_panel, self._current_position,
units.grid_to_pixels(-1), 0,
0, 0)
self._move_panel(self._right_panel, pos,
self._move_panel(self._right_panel, self._current_position,
screen_w, 0,
screen_w - units.grid_to_pixels(1), 0)
@ -256,6 +253,9 @@ class Frame:
if not self._event_frame.is_visible():
self._event_frame.show()
def _size_changed_cb(self, screen):
self._update_position()
def is_visible(self):
return self._top_panel.props.visible

View File

@ -36,7 +36,7 @@ class FramePopupContext(PopupContext):
left_x = item_x + item_w
left_y = item_y
right_x = item_x + item_w
right_x = item_x - popup_w
right_y = item_y
top_x = item_x
top_y = item_y + item_h

View File

@ -1,18 +0,0 @@
import gtk
from _sugar import TrayManager
class NotificationTray(gtk.HBox):
def __init__(self):
gtk.HBox.__init__(self)
self._manager = TrayManager()
self._manager.connect('tray-icon-added', self._icon_added_cb)
self._manager.connect('tray-icon-removed', self._icon_removed_cb)
self._manager.manage_screen(gtk.gdk.screen_get_default())
def _icon_added_cb(self, manager, icon):
self.pack_start(icon, False)
def _icon_removed_cb(self, manager, icon):
icon.destroy()

View File

@ -45,14 +45,31 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
shell_model.connect('notify::state',
self._shell_state_changed_cb)
self._device_icons = []
for device in shell_model.get_devices():
self._device_icons = {}
devices_model = shell_model.get_devices()
for device in devices_model:
self._add_device(device)
devices_model.connect('device-appeared',
self._device_appeared_cb)
devices_model.connect('device-disappeared',
self._device_disappeared_cb)
def _add_device(self, device):
view = deviceview.create(device)
self.append(view, hippo.PACK_FIXED)
self._device_icons.append(view)
self._device_icons[device.get_id()] = view
def _remove_device(self, device):
self.remove(self._device_icons[device.get_id()])
del self._device_icons[device.get_id()]
def _device_appeared_cb(self, model, device):
self._add_device(device)
def _device_disappeared_cb(self, model, device):
self._remove_device(device)
def _shell_state_changed_cb(self, model, pspec):
# FIXME handle all possible mode switches
@ -74,7 +91,7 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
(height - icon_height) / 2)
i = 0
for icon in self._device_icons:
for icon in self._device_icons.values():
angle = 2 * math.pi / len(self._device_icons) * i + math.pi / 2
radius = units.grid_to_pixels(5)

View File

@ -22,8 +22,52 @@ import gobject
from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics.snowflakebox import SnowflakeBox
from sugar.graphics.canvasicon import CanvasIcon
from hardware import hardwaremanager
from view.BuddyIcon import BuddyIcon
class AccessPointView(CanvasIcon):
def __init__(self, model):
CanvasIcon.__init__(self)
self._model = model
self.connect('activated', self._activate_cb)
model.connect('notify::strength', self._strength_changed_cb)
model.connect('notify::name', self._name_changed_cb)
self._update_icon()
self._update_name()
def _strength_changed_cb(self, model, pspec):
self._update_icon()
def _name_changed_cb(self, model, pspec):
self._update_name()
def _activate_cb(self, icon):
network_manager = hardwaremanager.get_network_manager()
device = self._model.get_nm_device()
network = self._model.get_nm_network()
network_manager.set_active_device(device, network)
def _update_name(self):
self.props.tooltip = self._model.props.name
def _update_icon(self):
strength = self._model.props.strength
if strength < 21:
self.props.icon_name = 'theme:stock-net-wireless-00'
elif strength < 41:
self.props.icon_name = 'theme:stock-net-wireless-21-40'
elif strength < 61:
self.props.icon_name = 'theme:stock-net-wireless-41-60'
elif strength < 81:
self.props.icon_name = 'theme:stock-net-wireless-61-80'
else:
self.props.icon_name = 'theme:stock-net-wireless-81-100'
class ActivityView(SnowflakeBox):
def __init__(self, shell, menu_shell, model):
SnowflakeBox.__init__(self)
@ -63,6 +107,7 @@ class MeshBox(SpreadBox):
self._model = shell.get_model().get_mesh()
self._buddies = {}
self._activities = {}
self._access_points = {}
self._buddy_to_activity = {}
for buddy_model in self._model.get_buddies():
@ -78,6 +123,14 @@ class MeshBox(SpreadBox):
self._model.connect('activity-added', self._activity_added_cb)
self._model.connect('activity-removed', self._activity_removed_cb)
for ap_model in self._model.get_access_points():
self._add_access_point(ap_model)
self._model.connect('access-point-added',
self._access_point_added_cb)
self._model.connect('access-point-removed',
self._access_point_removed_cb)
def _buddy_added_cb(self, model, buddy_model):
self._add_alone_buddy(buddy_model)
@ -93,6 +146,12 @@ class MeshBox(SpreadBox):
def _activity_removed_cb(self, model, activity_model):
self._remove_activity(activity_model)
def _access_point_added_cb(self, model, ap_model):
self._add_access_point(ap_model)
def _access_point_removed_cb(self, model, ap_model):
self._add_access_point(ap_model)
def _add_alone_buddy(self, buddy_model):
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
self.add_item(icon)
@ -136,3 +195,14 @@ class MeshBox(SpreadBox):
icon = self._activities[activity_model.get_id()]
self.remove_item(icon)
del self._activities[activity_model.get_id()]
def _add_access_point(self, ap_model):
icon = AccessPointView(ap_model)
self.add_item(icon)
self._access_points[ap_model.get_id()] = icon
def _remove_access_point(self, ap_model):
icon = self._access_points[ap_model.get_id()]
self.remove_item(icon)
del self._access_points[ap_model.get_id()]

View File

@ -2,7 +2,7 @@ import dbus
import gobject
from sugar import env
from view.hardwaremanager import HardwareManager
from hardware import hardwaremanager
from model.ShellModel import ShellModel
from _sugar import KeyGrabber
import sugar
@ -40,8 +40,8 @@ _actions_table = {
class KeyHandler(object):
def __init__(self, shell):
self._shell = shell
self._hw_manager = shell.get_hardware_manager()
self._audio_manager = shell.get_audio_manager()
self._hw_manager = hardwaremanager.get_hardware_manager()
self._audio_manager = hardwaremanager.get_audio_manager()
self._screen_rotation = 0
self._key_grabber = KeyGrabber()
@ -90,10 +90,10 @@ class KeyHandler(object):
self._audio_manager.set_volume(100)
def handle_color_mode(self):
self._hw_manager.set_display_mode(HardwareManager.COLOR_MODE)
self._hw_manager.set_display_mode(hardwaremanager.COLOR_MODE)
def handle_b_and_w_mode(self):
self._hw_manager.set_display_mode(HardwareManager.B_AND_W_MODE)
self._hw_manager.set_display_mode(hardwaremanager.B_AND_W_MODE)
def handle_console(self):
gobject.idle_add(self._toggle_console_visibility_cb)

View File

@ -47,8 +47,6 @@ class Activity(gtk.Window):
self._bus = ActivityService(self)
self.present()
def get_service_name(self):
"""Gets the activity service name."""
return os.environ['SUGAR_BUNDLE_SERVICE_NAME']

View File

@ -61,6 +61,7 @@ class ActivityFactoryService(dbus.service.Object):
def create(self, handle):
activity_handle = activityhandle.create_from_dict(handle)
activity = self._constructor(activity_handle)
activity.present()
self._activities.append(activity)
activity.connect('destroy', self._activity_destroy_cb)

View File

@ -143,7 +143,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
'stroke-color' : (object, None, None,
gobject.PARAM_READWRITE),
'scale' : (float, None, None,
0.0, 1024.0, 1.0,
0.0, 1024.0, units.STANDARD_ICON_SCALE,
gobject.PARAM_READWRITE),
'cache' : (bool, None, None, False,
gobject.PARAM_READWRITE),
@ -156,7 +156,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def __init__(self, **kwargs):
self._buffers = {}
self._cur_buffer = None
self._scale = 1.0
self._scale = units.STANDARD_ICON_SCALE
self._fill_color = None
self._stroke_color = None
self._icon_name = None
@ -173,8 +173,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
hippo.CanvasBox.__init__(self, **kwargs)
self.connect('motion-notify-event', self._motion_notify_event_cb)
self.connect('button-press-event', self._button_press_event_cb)
self.connect_after('button-press-event', self._button_press_event_cb)
self.connect_after('motion-notify-event', self._motion_notify_event_cb)
def _clear_buffers(self):
cur_buf_key = self._get_current_buffer_key()
@ -314,17 +314,17 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def _button_press_event_cb(self, item, event):
item.emit_activated()
return False
def get_popup(self):
if self._tooltip:
tooltip_popup = Popup()
canvas_text = hippo.CanvasText(text=self._tooltip)
canvas_text.props.background_color = color.MENU_BACKGROUND.get_int()
canvas_text.props.border_color = color.MENU_BORDER.get_int()
canvas_text.props.border = units.points_to_pixels(1)
canvas_text.props.color = color.LABEL_TEXT.get_int()
canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
tooltip_popup.append(canvas_text)
text = hippo.CanvasText(text=self._tooltip)
text.props.background_color = color.MENU_BACKGROUND.get_int()
text.props.color = color.LABEL_TEXT.get_int()
text.props.font_desc = font.DEFAULT.get_pango_desc()
text.props.padding = units.points_to_pixels(5)
tooltip_popup.append(text)
return tooltip_popup
else:
@ -355,7 +355,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
[x, y] = context.translate_to_screen(self)
# TODO: Any better place to do this?
popup.props.box_width = max(popup.props.box_width,
popup.props.box_width = max(popup.get_width_request(),
self.get_width_request())
[width, height] = self.get_allocation()
@ -364,7 +364,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
popup.popup(x, y)
popup.connect('motion-notify-event',
self._popup_motion_notify_event_cb)
self.popup_motion_notify_event_cb)
popup.connect('action-completed',
self._popup_action_completed_cb)
@ -389,17 +389,29 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def _motion_notify_event_cb(self, button, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self._timeline.play(None, 'popup')
self.prelight(enter=True)
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
if not self._hover_popup:
self._timeline.play('before_popdown', 'popdown')
self.prelight(enter=False)
return False
def _popup_motion_notify_event_cb(self, popup, event):
def popup_motion_notify_event_cb(self, popup, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self._hover_popup = True
self._timeline.play('popup', 'popup')
self.prelight(enter=True)
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self._hover_popup = False
self._timeline.play('popdown', 'popdown')
self.prelight(enter=False)
return False
def _popup_action_completed_cb(self, popup):
self.popdown()
def prelight(self, enter):
"""
Override this method for adding prelighting behavior.
"""
pass

View File

@ -12,7 +12,8 @@ _system_colors = {
'entry-border' : '#D1D1D2',
'label-text' : '#FFFFFF',
'desktop-background' : '#E2E2E3',
'menu-background' : '#414141',
'menu-background' : '#000000',
'menu-background-hover' : '#424242',
'menu-separator' : '#D1D1D2',
'menu-border' : '#D1D1D2',
'button-normal' : '#FFFFFF',
@ -90,6 +91,7 @@ ENTRY_BORDER = SystemColor('entry-border')
LABEL_TEXT = SystemColor('label-text')
DESKTOP_BACKGROUND = SystemColor('desktop-background')
MENU_BACKGROUND = SystemColor('menu-background')
MENU_BACKGROUND_HOVER = SystemColor('menu-background-hover')
MENU_SEPARATOR = SystemColor('menu-separator')
MENU_BORDER = SystemColor('menu-border')
BUTTON_NORMAL = SystemColor('button-normal')

View File

@ -21,8 +21,8 @@ import gobject
import hippo
from canvasicon import CanvasIcon
from xocolor import XoColor
from sugar.graphics import units
from sugar.graphics import color
from sugar import profile
STANDARD_SIZE = 0
@ -44,16 +44,20 @@ class IconButton(CanvasIcon):
CanvasIcon.__init__(self, cache=True, **kwargs)
self._prelight_color = profile.get_color()
self._inactive_color = XoColor('#808080,#424242')
self._normal_color = XoColor('white')
if not self.props.fill_color:
self.props.fill_color = color.BUTTON_BACKGROUND_NORMAL
if not self.props.stroke_color:
self.props.stroke_color = color.BUTTON_NORMAL
self.props.background_color = color.BUTTON_BACKGROUND_NORMAL.get_int()
if not self.props.xo_color:
self.props.xo_color = self._normal_color
self._normal_fill_color = self.props.fill_color
self._normal_stroke_color = self.props.stroke_color
self._normal_background_color = self.props.background_color
self._set_size(STANDARD_SIZE)
self.connect('button-press-event', self._button_press_event_cb)
self.connect('button-press-event',
self._icon_button_button_press_event_cb)
def _set_size(self, size):
if size == SMALL_SIZE:
@ -73,9 +77,13 @@ class IconButton(CanvasIcon):
elif pspec.name == 'active':
self._active = value
if self._active:
self.props.xo_color = self._normal_color
self.props.fill_color = self._normal_fill_color
self.props.stroke_color = self._normal_stroke_color
self.props.background_color = self._normal_background_color
else:
self.props.xo_color = self._inactive_color
self.props.fill_color = color.BUTTON_BACKGROUND_INACTIVE
self.props.stroke_color = color.BUTTON_INACTIVE
self.props.background_color = color.BUTTON_BACKGROUND_INACTIVE.get_int()
else:
CanvasIcon.do_set_property(self, pspec, value)
@ -87,7 +95,17 @@ class IconButton(CanvasIcon):
else:
return CanvasIcon.do_get_property(self, pspec)
def _button_press_event_cb(self, widget, event):
def _icon_button_button_press_event_cb(self, widget, event):
if self._active:
self.emit_activated()
return True
def prelight(self, enter):
if enter:
if self._active:
self.props.fill_color = color.BLACK
self.props.background_color = color.BLACK.get_int()
else:
if self._active:
self.props.fill_color = self._normal_fill_color
self.props.background_color = self._normal_background_color

View File

@ -57,6 +57,14 @@ class MenuItem(hippo.CanvasBox):
self._canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
self.append(self._canvas_text)
self.connect('motion-notify-event', self._motion_notify_event_cb)
def _motion_notify_event_cb(self, menu_item, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self.props.background_color = color.MENU_BACKGROUND_HOVER.get_int()
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self.props.background_color = color.MENU_BACKGROUND.get_int()
def do_set_property(self, pspec, value):
if pspec.name == 'action-id':
self._action_id = value

View File

@ -64,12 +64,14 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
self._round_box = RoundBox()
self._round_box.props.border_color = color.FRAME_BORDER.get_int()
self._round_box.props.spacing = units.points_to_pixels(3)
self._round_box.props.padding = units.points_to_pixels(1)
self.append(self._round_box, hippo.PACK_EXPAND)
self._canvas_text = hippo.CanvasText()
self._canvas_text.props.text = _('No options')
self._canvas_text.props.color = color.LABEL_TEXT.get_int()
self._canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
self._canvas_text = hippo.CanvasText(text=_('No options'),
color=color.LABEL_TEXT.get_int(),
font_desc=font.DEFAULT.get_pango_desc(),
xalign=hippo.ALIGNMENT_START)
self._round_box.append(self._canvas_text, hippo.PACK_EXPAND)
# TODO: Substitute for the right icon.
@ -100,6 +102,16 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
self._menu.add_item(menu_item)
def do_get_width_request(self):
max_width = max(self._canvas_text.do_get_content_width_request(self._canvas_text),
self._menu.do_get_content_width_request(self._menu))
self._canvas_text.props.box_width = max_width
current_width = hippo.CanvasBox.do_get_width_request(self)
self._menu.props.box_width = current_width
return current_width
def add_separator(self):
self._menu.add_separator()
@ -110,12 +122,12 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
context = self._round_box.get_context()
[x, y] = context.translate_to_screen(self._round_box)
# TODO: Any better place to do this?
self._menu.props.box_width = self.get_width_request()
[width, height] = self._round_box.get_allocation()
self._menu.popup(x, y + height)
# Grab the pointer so the menu will popdown on mouse click.
self._menu.grab_pointer()
def _menu_action_cb(self, menu, menu_item):
action_id = menu_item.props.action_id
label = menu_item.props.label

View File

@ -46,5 +46,13 @@ class Popup(hippo.CanvasBox, hippo.CanvasItem):
self._window.hide()
self._visible = False
def grab_pointer(self):
gtk.gdk.pointer_grab(self._window.window, owner_events=False,
event_mask=gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.ENTER_NOTIFY_MASK |
gtk.gdk.LEAVE_NOTIFY_MASK |
gtk.gdk.POINTER_MOTION_MASK)
def _button_press_event_cb(self, menu, event):
self.emit('action-completed')

View File

@ -31,7 +31,7 @@ class RoundBox(hippo.CanvasBox, hippo.CanvasItem):
hippo.CanvasBox.__init__(self, **kwargs)
# TODO: we should calculate this value depending on the height of the box.
self._radius = units.points_to_pixels(10)
self._radius = units.points_to_pixels(7)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self.props.border_top = self._BORDER_DEFAULT

View File

@ -85,7 +85,7 @@ class SnowflakeBox(hippo.CanvasBox, hippo.CanvasItem):
return width
def do_allocate(self, width, height, origin_changed):
hippo.CanvasBox.do_allocate(self, width, height)
hippo.CanvasBox.do_allocate(self, width, height, origin_changed)
self._layout_root()

View File

@ -48,7 +48,7 @@ canvas.set_root(vbox)
toolbar = Toolbar()
vbox.append(toolbar)
button = IconButton('theme:stock-close')
button = IconButton(icon_name='theme:stock-close')
toolbar.append(button)
OPTION_ANYTHING = 1

View File

@ -1,6 +1,6 @@
VERSION=0.63
DATE=`date +%Y%m%d`
RELEASE=2.21
RELEASE=2.22
TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2
rm sugar-$VERSION.tar.bz2

View File

@ -14,7 +14,7 @@ def get_bundle_root_dir(file_names):
bundle_root_dir = None
for file_name in file_names:
if not bundle_root_dir:
bundle_root_dir = file_name.partition('/')[0]
bundle_root_dir = file_name.split('/')[0]
if not bundle_root_dir.endswith('.activity'):
raise 'Incorrect bundle.'
else: