Merge
This commit is contained in:
commit
0cad068bf4
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -1 +1 @@
|
||||
SUBDIRS = presence presence2 nm clipboard datastore console
|
||||
SUBDIRS = presence presence2 clipboard datastore console
|
||||
|
@ -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)
|
@ -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>
|
||||
|
@ -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();
|
@ -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))
|
@ -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()
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = data model view intro
|
||||
SUBDIRS = data hardware model view intro
|
||||
|
||||
bin_SCRIPTS = \
|
||||
sugar-activity \
|
||||
|
7
shell/hardware/Makefile.am
Normal file
7
shell/hardware/Makefile.am
Normal file
@ -0,0 +1,7 @@
|
||||
sugardir = $(pkgdatadir)/shell/hardware
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
hardwaremanager.py \
|
||||
nmclient.py \
|
||||
nminfo.py \
|
||||
wepkeydialog.py
|
@ -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()
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -4,4 +4,5 @@ sugar_PYTHON = \
|
||||
device.py \
|
||||
devicesmodel.py \
|
||||
battery.py \
|
||||
network.py
|
||||
wirednetwork.py \
|
||||
wirelessnetwork.py
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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()]
|
||||
|
@ -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
|
12
shell/model/devices/wirednetwork.py
Normal file
12
shell/model/devices/wirednetwork.py
Normal 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'
|
37
shell/model/devices/wirelessnetwork.py
Normal file
37
shell/model/devices/wirelessnetwork.py
Normal 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()
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -11,5 +11,4 @@ sugar_PYTHON = \
|
||||
clipboardmenu.py \
|
||||
keyhandler.py \
|
||||
OverlayWindow.py \
|
||||
Shell.py \
|
||||
hardwaremanager.py
|
||||
Shell.py
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -3,4 +3,5 @@ sugar_PYTHON = \
|
||||
__init__.py \
|
||||
battery.py \
|
||||
deviceview.py \
|
||||
network.py
|
||||
wirednetwork.py \
|
||||
wirelessnetwork.py
|
||||
|
@ -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'
|
||||
|
@ -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'
|
34
shell/view/devices/wirelessnetwork.py
Normal file
34
shell/view/devices/wirelessnetwork.py
Normal 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'
|
@ -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
|
||||
|
@ -8,7 +8,6 @@ sugar_PYTHON = \
|
||||
eventframe.py \
|
||||
frame.py \
|
||||
ZoomBox.py \
|
||||
notificationtray.py \
|
||||
overlaybox.py \
|
||||
PanelWindow.py \
|
||||
framepopupcontext.py
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
@ -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)
|
||||
|
||||
|
@ -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()]
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user