Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@localhost.localdomain>2007-06-20 10:05:32 (GMT)
committer Marco Pesenti Gritti <marco@localhost.localdomain>2007-06-20 10:05:32 (GMT)
commitb01684ef273725940f1b67eb95e2119e46140b0d (patch)
tree21fa2e90ec6dc25f45bda956907ce3bc8e90ffe2
parentcd382ba5f9c48d462e1a9d8434f81cd58fdb1ad8 (diff)
parentbd86aee0d4ab8a989ae19a7959e65d563228709a (diff)
Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
-rw-r--r--shell/model/homemodel.py27
-rw-r--r--sugar/activity/activityfactory.py4
-rw-r--r--sugar/activity/activityservice.py17
-rw-r--r--sugar/graphics/palette.py125
-rw-r--r--sugar/graphics/toolbutton.py58
5 files changed, 142 insertions, 89 deletions
diff --git a/shell/model/homemodel.py b/shell/model/homemodel.py
index 7eb4b46..6a2d45f 100644
--- a/shell/model/homemodel.py
+++ b/shell/model/homemodel.py
@@ -71,12 +71,6 @@ class HomeModel(gobject.GObject):
screen.connect('active-window-changed',
self._active_window_changed_cb)
- bus = dbus.SessionBus()
- bus.add_signal_receiver(self._dbus_name_owner_changed_cb,
- 'NameOwnerChanged',
- 'org.freedesktop.DBus',
- 'org.freedesktop.DBus')
-
def get_current_activity(self):
return self._current_activity
@@ -111,7 +105,7 @@ class HomeModel(gobject.GObject):
activity = HomeActivity(bundle, activity_id)
self._add_activity(activity)
- service = self._get_activity_service(window.get_xid())
+ service = self._get_activity_service(activity_id)
activity.set_service(service)
activity.set_window(window)
@@ -125,19 +119,6 @@ class HomeModel(gobject.GObject):
self.emit('active-activity-changed', None)
self._notify_activity_activation(self._current_activity, None)
- def _dbus_name_owner_changed_cb(self, name, old, new):
- """Detect new activity instances on the DBus"""
- if name.startswith(_SERVICE_NAME) and new and not old:
- try:
- xid = int(name[len(_SERVICE_NAME):])
- activity = self._get_activity_by_xid(xid)
- if activity and not activity.get_service():
- service = self._get_activity_service(xid)
- activity.set_service(service)
- except ValueError:
- logging.error('Invalid activity service name, '
- 'cannot extract the xid')
-
def _get_activity_by_xid(self, xid):
for activity in self._activities:
if activity.get_xid() == xid:
@@ -185,12 +166,12 @@ class HomeModel(gobject.GObject):
self.emit('active-activity-changed', self._current_activity)
- def _get_activity_service(self, xid):
+ def _get_activity_service(self, activity_id):
bus = dbus.SessionBus()
try:
service = dbus.Interface(
- bus.get_object(_SERVICE_NAME + '%d' % xid,
- _SERVICE_PATH + "/%s" % xid),
+ bus.get_object(_SERVICE_NAME + activity_id,
+ _SERVICE_PATH + "/" + activity_id),
_SERVICE_INTERFACE)
except dbus.DBusException:
service = None
diff --git a/sugar/activity/activityfactory.py b/sugar/activity/activityfactory.py
index 809a74d..2cdf9a1 100644
--- a/sugar/activity/activityfactory.py
+++ b/sugar/activity/activityfactory.py
@@ -26,10 +26,6 @@ from sugar.presence import presenceservice
from sugar.activity.activityhandle import ActivityHandle
from sugar import util
-_ACTIVITY_SERVICE_NAME = "org.laptop.Activity"
-_ACTIVITY_SERVICE_PATH = "/org/laptop/Activity"
-_ACTIVITY_INTERFACE = "org.laptop.Activity"
-
_ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory"
def create_activity_id():
diff --git a/sugar/activity/activityservice.py b/sugar/activity/activityservice.py
index f456581..3251177 100644
--- a/sugar/activity/activityservice.py
+++ b/sugar/activity/activityservice.py
@@ -33,24 +33,21 @@ class ActivityService(dbus.service.Object):
def __init__(self, activity):
"""Initialise the service for the given activity
- activity -- sugar.activity.activity.Activity instance,
- must have already bound it's window (i.e. it must
- have already initialised to the point of having
- the X window available).
+ activity -- sugar.activity.activity.Activity instance
- Creates dbus services that use the xid of the activity's
- root window as discriminants among all active services
+ Creates dbus services that use the instance's activity_id
+ as discriminants among all active services
of this type. That is, the services are all available
- as names/paths derived from the xid for the window.
+ as names/paths derived from the instance's activity_id.
The various methods exposed on dbus are just forwarded
to the client Activity object's equally-named methods.
"""
activity.realize()
- xid = activity.window.xid
- service_name = _ACTIVITY_SERVICE_NAME + '%d' % xid
- object_path = _ACTIVITY_SERVICE_PATH + "/%s" % xid
+ activity_id = activity.get_id()
+ service_name = _ACTIVITY_SERVICE_NAME + activity_id
+ object_path = _ACTIVITY_SERVICE_PATH + "/" + activity_id
bus = dbus.SessionBus()
bus_name = dbus.service.BusName(service_name, bus=bus)
diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py
index 6c67b8d..643a807 100644
--- a/sugar/graphics/palette.py
+++ b/sugar/graphics/palette.py
@@ -21,6 +21,7 @@ import gtk
from gtk import gdk, keysyms
import gobject
import time
+import hippo
ALIGNMENT_AUTOMATIC = 0
ALIGNMENT_BOTTOM_LEFT = 1
@@ -36,17 +37,16 @@ class Palette(gtk.Window):
__gtype_name__ = 'SugarPalette'
__gproperties__ = {
- 'parent': (object, None, None, gobject.PARAM_READWRITE),
+ 'invoker': (object, None, None, gobject.PARAM_READWRITE),
'alignment': (gobject.TYPE_INT, None, None, 0, 8, ALIGNMENT_AUTOMATIC,
gobject.PARAM_READWRITE),
-
+
'is-tooltip': (bool, None, None, False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY)
}
_PADDING = 1
_WIN_BORDER = 5
- _POPUP_PALETTE_DELAY = 0.15
def __init__(self, **kwargs):
gobject.GObject.__init__(self, type=gtk.WINDOW_POPUP, **kwargs)
@@ -85,7 +85,7 @@ class Palette(gtk.Window):
self.add(vbox)
# Widget events
- self.connect('motion-notify-event', self._mouse_over_widget_cb)
+ self.connect('enter-notify-event', self._mouse_over_widget_cb)
self.connect('leave-notify-event', self._mouse_out_widget_cb)
self.connect('button-press-event', self._close_palette_cb)
self.connect('key-press-event', self._on_key_press_event_cb)
@@ -96,8 +96,8 @@ class Palette(gtk.Window):
self._scr_height = gtk.gdk.screen_height()
def do_set_property(self, pspec, value):
- if pspec.name == 'parent':
- self._parent_widget = value
+ if pspec.name == 'invoker':
+ self._invoker = value
elif pspec.name == 'alignment':
self._alignment = value
elif pspec.name == 'is-tooltip':
@@ -155,41 +155,41 @@ class Palette(gtk.Window):
return True
def _calc_position(self, alignment):
- win_x, win_y = self._parent_widget.window.get_origin()
- parent_rectangle = self._parent_widget.get_allocation()
+ # Invoker: x, y, width and height
+ inv_rect = self._invoker.get_rect()
palette_rectangle = self.get_allocation()
if alignment == ALIGNMENT_BOTTOM_LEFT:
- move_x = win_x + parent_rectangle.x
- move_y = win_y + parent_rectangle.y + parent_rectangle.height
+ move_x = inv_rect.x
+ move_y = inv_rect.y + inv_rect.height
elif alignment == ALIGNMENT_BOTTOM_RIGHT:
- move_x = (win_x + parent_rectangle.x + parent_rectangle.width) - self._width
- move_y = win_y + parent_rectangle.y + parent_rectangle.height
+ move_x = (inv_rect.x + inv_rect.width) - self._width
+ move_y = inv_rect.y + inv_rect.height
elif alignment == ALIGNMENT_LEFT_BOTTOM:
- move_x = (win_x + parent_rectangle.x) - self._width
- move_y = win_y + parent_rectangle.y
+ move_x = inv_rect.x - self._width
+ move_y = inv_rect.y
elif alignment == ALIGNMENT_LEFT_TOP:
- move_x = (win_x + parent_rectangle.x) - self._width
- move_y = (win_y + parent_rectangle.y + parent_rectangle.height) - palette_rectangle.height
+ move_x = inv_rect.x - self._width
+ move_y = (inv_rect.y + inv_rect.height) - palette_rectangle.height
elif alignment == ALIGNMENT_RIGHT_BOTTOM:
- move_x = win_x + parent_rectangle.x + parent_rectangle.width
- move_y = win_y + parent_rectangle.y
+ move_x = inv_rect.x + inv_rect.width
+ move_y = inv_rect.y
elif alignment == ALIGNMENT_RIGHT_TOP:
- move_x = win_x + parent_rectangle.x + parent_rectangle.width
- move_y = (win_y + parent_rectangle.y + parent_rectangle.height) - palette_rectangle.height
+ move_x = inv_rect.x + inv_rect.width
+ move_y = (inv_rect.y + inv_rect.height) - palette_rectangle.height
elif alignment == ALIGNMENT_TOP_LEFT:
- move_x = (win_x + parent_rectangle.x)
- move_y = (win_y + parent_rectangle.y) - (palette_rectangle.height)
+ move_x = inv_rect.x
+ move_y = inv_rect.y - palette_rectangle.height
elif alignment == ALIGNMENT_TOP_RIGHT:
- move_x = (win_x + parent_rectangle.x + parent_rectangle.width) - self._width
- move_y = (win_y + parent_rectangle.y) - (palette_rectangle.height)
+ move_x = (inv_rect.x + inv_rect.width) - self._width
+ move_y = inv_rect.y - palette_rectangle.height
return move_x, move_y
@@ -219,18 +219,13 @@ class Palette(gtk.Window):
# Display the palette and set the position on the screen
def popup(self):
- # We need to know if the mouse pointer continue inside
- # the parent widget (opener)
- pointer_x, pointer_y = self._parent_widget.get_pointer()
- self._parent_alloc = self._parent_widget.get_allocation()
- pointer_rect = gdk.Rectangle(pointer_x + self._parent_alloc.x, pointer_y + self._parent_alloc.y, 1, 1)
-
- if (self._parent_widget.allocation.intersect(pointer_rect).width == 0):
- return
-
self.realize()
self.set_position()
- self._pointer_grab()
+ self._pointer_ungrab()
+
+ def popdown(self):
+ self._pointer_ungrab()
+ self.hide()
# PRIVATE METHODS
@@ -244,32 +239,29 @@ class Palette(gtk.Window):
else:
return False
- def _pointer_grab(self):
- gtk.gdk.pointer_grab(self.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 _pointer_ungrab(self):
+ gdk.keyboard_ungrab()
+ def _pointer_grab(self):
gdk.keyboard_grab(self.window, False)
# SIGNAL HANDLERS
# Release the GDK pointer and hide the palette
def _close_palette_cb(self, widget=None, event=None):
- gtk.gdk.pointer_ungrab()
- self.hide()
+ self.popdown()
# Mouse is out of the widget
def _mouse_out_widget_cb(self, widget, event):
- time.sleep(self._POPUP_PALETTE_DELAY)
if (widget == self) and self._is_mouse_out(widget):
self._close_palette_cb()
+ return
+
+ self._pointer_grab()
# Mouse inside the widget
def _mouse_over_widget_cb(self, widget, event):
- gtk.gdk.pointer_ungrab()
+ self._pointer_ungrab()
# Some key is pressed
def _on_key_press_event_cb(self, window, event):
@@ -282,3 +274,46 @@ class Palette(gtk.Window):
((keyval == keysyms.Up or keyval == keysyms.KP_Up) and
state == gdk.MOD1_MASK)):
self._close_palette_cb()
+
+class WidgetInvoker:
+ def __init__(self, parent):
+ self._parent = parent
+
+ def get_rect(self):
+ win_x, win_y = self._parent.window.get_origin()
+ rectangle = self._parent.get_allocation()
+
+ x = win_x + rectangle.x
+ y = win_y + rectangle.y
+ width = rectangle.width
+ height = rectangle.height
+
+ return gtk.gdk.Rectangle(x, y, width, height)
+
+ # Is mouse over self._parent ?
+ def is_mouse_over(self):
+ pointer_x, pointer_y = self._parent.get_pointer()
+ self._parent_alloc = self._parent.get_allocation()
+
+ pointer_rect = gdk.Rectangle(pointer_x + self._parent_alloc.x, \
+ pointer_y + self._parent_alloc.y, 1, 1)
+
+ if (self._parent.allocation.intersect(pointer_rect).width == 0):
+ return False
+
+ return True
+
+class CanvasInvoker:
+ def __init__(self, parent):
+ self._parent = parent
+
+ def get_rect(self):
+ context = self._parent.get_context()
+ x, y = context.translate_to_screen(self._parent)
+ width, height = self._parent.get_allocation()
+
+ return gtk.gdk.Rectangle(x, y, width, height)
+
+ # Is mouse over self._parent ?
+ def is_mouse_over(self):
+ return True
diff --git a/sugar/graphics/toolbutton.py b/sugar/graphics/toolbutton.py
index 808cc34..b543e1c 100644
--- a/sugar/graphics/toolbutton.py
+++ b/sugar/graphics/toolbutton.py
@@ -16,18 +16,23 @@
# Boston, MA 02111-1307, USA.
import gtk
+import gobject
import time
from sugar.graphics.icon import Icon
from sugar.graphics.palette import *
class ToolButton(gtk.ToolButton):
- _POPUP_PALETTE_DELAY = 0.15
+ _POPUP_PALETTE_DELAY = 100
def __init__(self, icon_name=None):
gtk.ToolButton.__init__(self)
self._palette = None
self.set_icon(icon_name)
+ self.child.connect('enter-notify-event',self._enter_notify_event_cb)
+ self.child.connect('leave-notify-event',self._leave_notify_event_cb)
+ self._enter_tag = None
+ self._leave_tag = None
def set_icon(self, icon_name):
icon = Icon(icon_name)
@@ -36,8 +41,7 @@ class ToolButton(gtk.ToolButton):
def set_palette(self, palette):
self._palette = palette
- self._palette.props.parent = self
- self.child.connect('enter-notify-event', self._show_palette_timeout_cb)
+ self._palette.props.invoker = WidgetInvoker(self)
def set_tooltip(self, text):
if self._palette:
@@ -45,9 +49,49 @@ class ToolButton(gtk.ToolButton):
self._palette = Palette(is_tooltip=True)
self._palette.set_primary_state(text)
- self._palette.props.parent = self
- self.child.connect('enter-notify-event', self._show_palette_timeout_cb)
+ self._palette.props.invoker = WidgetInvoker(self)
- def _show_palette_timeout_cb(self, widget, event):
- time.sleep(self._POPUP_PALETTE_DELAY)
+ def _enter_notify_event_cb(self, widget, event):
+ gtk.gdk.pointer_ungrab()
+
+ if self._leave_tag:
+ gobject.source_remove(self._leave_tag)
+ self._leave_tag = None
+
+ self._enter_tag = gobject.timeout_add(self._POPUP_PALETTE_DELAY, \
+ self._show_palette)
+
+ def _leave_notify_event_cb(self, widget, event):
+ if self._enter_tag:
+ gobject.source_remove(self._enter_tag)
+ self._enter_tag = None
+
+ self._leave_tag = gobject.timeout_add(self._POPUP_PALETTE_DELAY,\
+ self._hide_palette)
+
+ def _show_palette(self):
self._palette.popup()
+ return False
+
+ def _hide_palette(self):
+ # Just hide the palette if the mouse pointer is
+ # out of the toolbutton and the palette
+ if self._is_mouse_out(self._palette):
+ self._palette.popdown()
+ else:
+ gtk.gdk.pointer_ungrab()
+
+ return False
+
+ def _pointer_grab(self):
+ gtk.gdk.pointer_grab(self.window, owner_events=True,\
+ event_mask=gtk.gdk.PROPERTY_CHANGE_MASK )
+
+ def _is_mouse_out(self, widget):
+ mouse_x, mouse_y = widget.get_pointer()
+ event_rect = gdk.Rectangle(mouse_x, mouse_y, 1, 1)
+
+ if (widget.allocation.intersect(event_rect).width==0):
+ return True
+ else:
+ return False