Rewrite the wm, implement smarter sliding, "merge"
presence window and chat, activate by F1
This commit is contained in:
parent
446754f4d3
commit
63c93e4f2d
@ -72,29 +72,21 @@ class ActivityContainer(dbus.service.Object):
|
|||||||
|
|
||||||
self._presence_window = PresenceWindow(self)
|
self._presence_window = PresenceWindow(self)
|
||||||
self._presence_window.set_transient_for(self.window)
|
self._presence_window.set_transient_for(self.window)
|
||||||
self._presence_window.set_decorated(False)
|
|
||||||
self._presence_window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
|
|
||||||
self._presence_window.set_skip_taskbar_hint(True)
|
|
||||||
|
|
||||||
wm = WindowManager(self._presence_window)
|
wm = WindowManager(self._presence_window)
|
||||||
|
wm.set_type(WindowManager.TYPE_POPUP)
|
||||||
wm.set_width(170, WindowManager.ABSOLUTE)
|
wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
|
||||||
wm.set_height(1.0, WindowManager.SCREEN_RELATIVE)
|
wm.set_geometry(0.02, 0.1, 0.25, 0.9)
|
||||||
wm.set_position(WindowManager.LEFT)
|
wm.set_key(gtk.keysyms.F1)
|
||||||
wm.manage()
|
|
||||||
|
|
||||||
self._chat_window = ChatWindow()
|
self._chat_window = ChatWindow()
|
||||||
self._chat_window.set_transient_for(self.window)
|
self._chat_window.set_transient_for(self.window)
|
||||||
self._chat_window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
|
|
||||||
self._chat_window.set_decorated(False)
|
|
||||||
self._chat_window.set_skip_taskbar_hint(True)
|
|
||||||
|
|
||||||
self._chat_wm = WindowManager(self._chat_window)
|
self._chat_wm = WindowManager(self._chat_window)
|
||||||
|
self._chat_wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
|
||||||
self._chat_wm.set_width(420, WindowManager.ABSOLUTE)
|
self._chat_wm.set_type(WindowManager.TYPE_POPUP)
|
||||||
self._chat_wm.set_height(380, WindowManager.ABSOLUTE)
|
self._chat_wm.set_geometry(0.28, 0.1, 0.5, 0.9)
|
||||||
self._chat_wm.set_position(WindowManager.TOP)
|
self._chat_wm.set_key(gtk.keysyms.F1)
|
||||||
self._chat_wm.manage()
|
|
||||||
|
|
||||||
self._mesh_chat = MeshChat()
|
self._mesh_chat = MeshChat()
|
||||||
|
|
||||||
@ -111,9 +103,6 @@ class ActivityContainer(dbus.service.Object):
|
|||||||
else:
|
else:
|
||||||
self._chat_window.set_chat(self._mesh_chat)
|
self._chat_window.set_chat(self._mesh_chat)
|
||||||
|
|
||||||
# For some reason the substitution screw up window position
|
|
||||||
self._chat_wm.update()
|
|
||||||
|
|
||||||
def notebook_tab_changed(self, notebook, page, page_number):
|
def notebook_tab_changed(self, notebook, page, page_number):
|
||||||
new_activity = notebook.get_nth_page(page_number).get_data("sugar-activity")
|
new_activity = notebook.get_nth_page(page_number).get_data("sugar-activity")
|
||||||
|
|
||||||
|
@ -13,9 +13,6 @@ class ConsoleLogger(dbus.service.Object):
|
|||||||
|
|
||||||
self._window = gtk.Window()
|
self._window = gtk.Window()
|
||||||
self._window.set_title("Console")
|
self._window.set_title("Console")
|
||||||
self._window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
|
|
||||||
self._window.set_decorated(False)
|
|
||||||
self._window.set_skip_taskbar_hint(True)
|
|
||||||
self._window.connect("delete_event", lambda w, e: w.hide_on_delete())
|
self._window.connect("delete_event", lambda w, e: w.hide_on_delete())
|
||||||
|
|
||||||
self._nb = gtk.Notebook()
|
self._nb = gtk.Notebook()
|
||||||
@ -25,11 +22,8 @@ class ConsoleLogger(dbus.service.Object):
|
|||||||
self._consoles = {}
|
self._consoles = {}
|
||||||
|
|
||||||
console_wm = WindowManager(self._window)
|
console_wm = WindowManager(self._window)
|
||||||
|
console_wm.set_type(WindowManager.TYPE_POPUP)
|
||||||
console_wm.set_width(0.7, WindowManager.SCREEN_RELATIVE)
|
console_wm.set_geometry(0.1, 0.1, 0.8, 0.8)
|
||||||
console_wm.set_height(0.9, WindowManager.SCREEN_RELATIVE)
|
|
||||||
console_wm.set_position(WindowManager.BOTTOM)
|
|
||||||
console_wm.manage()
|
|
||||||
|
|
||||||
def _create_console(self, application):
|
def _create_console(self, application):
|
||||||
sw = gtk.ScrolledWindow()
|
sw = gtk.ScrolledWindow()
|
||||||
|
@ -29,11 +29,7 @@ class Shell(gobject.GObject):
|
|||||||
activity_container.show()
|
activity_container.show()
|
||||||
|
|
||||||
wm = WindowManager(activity_container.window)
|
wm = WindowManager(activity_container.window)
|
||||||
wm.set_width(640, WindowManager.ABSOLUTE)
|
|
||||||
wm.set_height(480, WindowManager.ABSOLUTE)
|
|
||||||
wm.set_position(WindowManager.CENTER)
|
|
||||||
wm.show()
|
wm.show()
|
||||||
wm.manage()
|
|
||||||
|
|
||||||
def __activity_container_destroy_cb(self, activity_container):
|
def __activity_container_destroy_cb(self, activity_container):
|
||||||
self.emit('close')
|
self.emit('close')
|
||||||
|
@ -1,169 +1,204 @@
|
|||||||
import pygtk
|
import time
|
||||||
pygtk.require('2.0')
|
import logging
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
import gobject
|
import gobject
|
||||||
|
|
||||||
SM_SPACE_PROPORTIONAL = 0
|
DEFAULT_WIDTH = 640
|
||||||
SM_STEP = 1
|
DEFAULT_HEIGHT = 480
|
||||||
|
|
||||||
SLIDING_TIMEOUT = 50
|
SLIDING_TIME = 0.8
|
||||||
SLIDING_MODE = SM_SPACE_PROPORTIONAL
|
|
||||||
|
|
||||||
#SLIDING_TIMEOUT = 10
|
class SlidingHelper:
|
||||||
#SLIDING_MODE = SM_STEP
|
IN = 0
|
||||||
#SLIDING_STEP = 0.05
|
OUT = 1
|
||||||
|
|
||||||
|
def __init__(self, manager, direction):
|
||||||
|
self._direction = direction
|
||||||
|
self._cur_time = time.time()
|
||||||
|
self._target_time = self._cur_time + SLIDING_TIME
|
||||||
|
self._manager = manager
|
||||||
|
self._start = True
|
||||||
|
self._end = False
|
||||||
|
|
||||||
|
(x, y, width, height) = manager.get_geometry()
|
||||||
|
self._orig_y = y
|
||||||
|
if direction == SlidingHelper.IN:
|
||||||
|
self._target_y = y
|
||||||
|
manager.set_geometry(x, y - height, width, height)
|
||||||
|
else:
|
||||||
|
self._target_y = y - height
|
||||||
|
|
||||||
|
def get_direction(self):
|
||||||
|
return self._direction
|
||||||
|
|
||||||
|
def is_start(self):
|
||||||
|
return self._start
|
||||||
|
|
||||||
|
def is_end(self):
|
||||||
|
return self._end
|
||||||
|
|
||||||
|
def get_next_y(self):
|
||||||
|
self._start = False
|
||||||
|
|
||||||
|
(x, y, width, height) = self._manager.get_geometry()
|
||||||
|
|
||||||
|
old_time = self._cur_time
|
||||||
|
self._cur_time = time.time()
|
||||||
|
remaining = self._target_time - self._cur_time
|
||||||
|
|
||||||
|
if remaining <= 0:
|
||||||
|
self._end = True
|
||||||
|
y = self._orig_y
|
||||||
|
else:
|
||||||
|
approx_time_step = float(self._cur_time - old_time)
|
||||||
|
approx_n_steps = remaining / approx_time_step
|
||||||
|
step = (self._target_y - y) / approx_n_steps
|
||||||
|
y += step
|
||||||
|
|
||||||
|
return y
|
||||||
|
|
||||||
class WindowManager:
|
class WindowManager:
|
||||||
__managers_list = []
|
__managers_list = []
|
||||||
|
|
||||||
CENTER = 0
|
TYPE_ACTIVITY = 0
|
||||||
LEFT = 1
|
TYPE_POPUP = 1
|
||||||
RIGHT = 2
|
|
||||||
TOP = 3
|
|
||||||
BOTTOM = 4
|
|
||||||
|
|
||||||
ABSOLUTE = 0
|
ANIMATION_NONE = 0
|
||||||
SCREEN_RELATIVE = 1
|
ANIMATION_SLIDE_IN = 1
|
||||||
|
|
||||||
def __init__(self, window):
|
def __init__(self, window):
|
||||||
self._window = window
|
self._window = window
|
||||||
self._sliding_pos = 0
|
self._window_type = WindowManager.TYPE_ACTIVITY
|
||||||
|
self._animation = WindowManager.ANIMATION_NONE
|
||||||
WindowManager.__managers_list.append(self)
|
self._key = 0
|
||||||
|
self._animating = False
|
||||||
|
|
||||||
window.connect("key-press-event", self.__key_press_event_cb)
|
window.connect("key-press-event", self.__key_press_event_cb)
|
||||||
|
|
||||||
|
WindowManager.__managers_list.append(self)
|
||||||
|
|
||||||
def __key_press_event_cb(self, window, event):
|
def __key_press_event_cb(self, window, event):
|
||||||
manager = None
|
# FIXME we should fix this to work also while animating
|
||||||
|
if self._animating:
|
||||||
|
return False
|
||||||
|
|
||||||
if event.keyval == gtk.keysyms.Left and \
|
for manager in WindowManager.__managers_list:
|
||||||
event.state & gtk.gdk.CONTROL_MASK:
|
if event.keyval == manager._key:
|
||||||
for wm in WindowManager.__managers_list:
|
if manager._window.get_property('visible'):
|
||||||
if wm._position == WindowManager.LEFT:
|
manager.hide()
|
||||||
manager = wm
|
else:
|
||||||
|
manager.show()
|
||||||
|
|
||||||
if event.keyval == gtk.keysyms.Up and \
|
def get_geometry(self):
|
||||||
event.state & gtk.gdk.CONTROL_MASK:
|
return (self._x, self._y, self._width, self._height)
|
||||||
for wm in WindowManager.__managers_list:
|
|
||||||
if wm._position == WindowManager.TOP:
|
|
||||||
manager = wm
|
|
||||||
|
|
||||||
if event.keyval == gtk.keysyms.Down and \
|
def set_geometry(self, x, y, width, height):
|
||||||
event.state & gtk.gdk.CONTROL_MASK:
|
if self._window_type == WindowManager.TYPE_ACTIVITY:
|
||||||
for wm in WindowManager.__managers_list:
|
logging.error('The geometry will be ignored for activity windows')
|
||||||
if wm._position == WindowManager.BOTTOM:
|
|
||||||
manager = wm
|
|
||||||
|
|
||||||
if manager and manager._window.get_property('visible'):
|
self._x = x
|
||||||
manager.slide_window_out()
|
self._y = y
|
||||||
elif manager:
|
|
||||||
manager.slide_window_in()
|
|
||||||
|
|
||||||
def set_width(self, width, width_type):
|
|
||||||
self._width = width
|
self._width = width
|
||||||
self._width_type = width_type
|
|
||||||
|
|
||||||
def set_height(self, height, height_type):
|
|
||||||
self._height = height
|
self._height = height
|
||||||
self._height_type = height_type
|
|
||||||
|
|
||||||
def set_position(self, position):
|
def set_animation(self, animation):
|
||||||
self._position = position
|
self._animation = animation
|
||||||
|
|
||||||
def _update_size(self):
|
def set_type(self, window_type):
|
||||||
screen_width = self._window.get_screen().get_width()
|
self._window_type = window_type
|
||||||
screen_height = self._window.get_screen().get_height()
|
|
||||||
|
|
||||||
if self._width_type is WindowManager.ABSOLUTE:
|
def set_key(self, key):
|
||||||
width = self._width
|
self._key = key
|
||||||
elif self._width_type is WindowManager.SCREEN_RELATIVE:
|
|
||||||
width = int(screen_width * self._width)
|
|
||||||
|
|
||||||
if self._height_type is WindowManager.ABSOLUTE:
|
|
||||||
height = self._height
|
|
||||||
elif self._height_type is WindowManager.SCREEN_RELATIVE:
|
|
||||||
height = int(screen_height * self._height)
|
|
||||||
|
|
||||||
self._real_width = width
|
|
||||||
self._real_height = height
|
|
||||||
|
|
||||||
self._window.set_size_request(self._real_width,
|
|
||||||
self._real_height)
|
|
||||||
|
|
||||||
def _update_position(self):
|
|
||||||
screen_width = self._window.get_screen().get_width()
|
|
||||||
screen_height = self._window.get_screen().get_height()
|
|
||||||
|
|
||||||
width = self._real_width
|
|
||||||
height = self._real_height
|
|
||||||
|
|
||||||
if self._position is WindowManager.CENTER:
|
|
||||||
self._x = int((screen_width - width) / 2)
|
|
||||||
self._y = int((screen_height - height) / 2)
|
|
||||||
elif self._position is WindowManager.LEFT:
|
|
||||||
self._x = - int((1.0 - self._sliding_pos) * width)
|
|
||||||
self._y = int((screen_height - height) / 2)
|
|
||||||
elif self._position is WindowManager.TOP:
|
|
||||||
self._x = int(screen_width - width - 10)
|
|
||||||
self._y = - int((1.0 - self._sliding_pos) * height)
|
|
||||||
elif self._position is WindowManager.BOTTOM:
|
|
||||||
self._x = int((screen_width - width) / 2)
|
|
||||||
self._y = screen_height - int(self._sliding_pos * height)
|
|
||||||
|
|
||||||
self._window.move(self._x, self._y)
|
|
||||||
|
|
||||||
def __slide_in_timeout_cb(self):
|
|
||||||
if self._sliding_pos == 0:
|
|
||||||
self._window.show()
|
|
||||||
|
|
||||||
if SLIDING_MODE == SM_SPACE_PROPORTIONAL:
|
|
||||||
space_to_go = 1.0 - self._sliding_pos
|
|
||||||
self._sliding_pos += (space_to_go / 2)
|
|
||||||
else:
|
|
||||||
self._sliding_pos += SLIDING_STEP
|
|
||||||
|
|
||||||
if self._sliding_pos > .999:
|
|
||||||
self._sliding_pos = 1.0
|
|
||||||
|
|
||||||
self._update_position()
|
|
||||||
|
|
||||||
if self._sliding_pos == 1.0:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __slide_out_timeout_cb(self):
|
|
||||||
if SLIDING_MODE == SM_SPACE_PROPORTIONAL:
|
|
||||||
space_to_go = self._sliding_pos
|
|
||||||
self._sliding_pos -= (space_to_go / 2)
|
|
||||||
else:
|
|
||||||
self._sliding_pos -= SLIDING_STEP
|
|
||||||
|
|
||||||
if self._sliding_pos < .001:
|
|
||||||
self._sliding_pos = 0
|
|
||||||
|
|
||||||
self._update_position()
|
|
||||||
|
|
||||||
if self._sliding_pos == 0:
|
|
||||||
self._window.hide()
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def slide_window_in(self):
|
|
||||||
self._sliding_pos = 0
|
|
||||||
gobject.timeout_add(SLIDING_TIMEOUT, self.__slide_in_timeout_cb)
|
|
||||||
|
|
||||||
def slide_window_out(self):
|
|
||||||
self._sliding_pos = 1.0
|
|
||||||
gobject.timeout_add(SLIDING_TIMEOUT, self.__slide_out_timeout_cb)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
self._window.show()
|
self._update_hints()
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self._update_position()
|
|
||||||
|
|
||||||
def manage(self):
|
|
||||||
self._update_size()
|
self._update_size()
|
||||||
|
|
||||||
|
if self._animation == WindowManager.ANIMATION_SLIDE_IN:
|
||||||
|
self._slide_in()
|
||||||
|
else:
|
||||||
|
self._update_position()
|
||||||
|
self._window.show()
|
||||||
|
|
||||||
|
def hide(self):
|
||||||
|
if self._animation == WindowManager.ANIMATION_SLIDE_IN:
|
||||||
|
self._slide_out()
|
||||||
|
else:
|
||||||
|
self._window.hide()
|
||||||
|
|
||||||
|
def _get_screen_dimensions(self):
|
||||||
|
screen_width = DEFAULT_WIDTH
|
||||||
|
screen_height = DEFAULT_HEIGHT
|
||||||
|
|
||||||
|
for manager in WindowManager.__managers_list:
|
||||||
|
if manager._window_type == WindowManager.TYPE_ACTIVITY:
|
||||||
|
screen_width = manager._window.allocation.width
|
||||||
|
screen_height = manager._window.allocation.height
|
||||||
|
|
||||||
|
return (screen_width, screen_height)
|
||||||
|
|
||||||
|
def _get_screen_position(self):
|
||||||
|
result = (0, 0)
|
||||||
|
for manager in WindowManager.__managers_list:
|
||||||
|
if manager._window_type == WindowManager.TYPE_ACTIVITY:
|
||||||
|
result = manager._window.get_position()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _transform_position(self):
|
||||||
|
(screen_width, screen_height) = self._get_screen_dimensions()
|
||||||
|
(screen_x, screen_y) = self._get_screen_position()
|
||||||
|
|
||||||
|
x = int(screen_width * self._x) + screen_x
|
||||||
|
y = int(screen_height * self._y) + screen_y
|
||||||
|
|
||||||
|
return (x, y)
|
||||||
|
|
||||||
|
def _transform_dimensions(self):
|
||||||
|
(screen_width, screen_height) = self._get_screen_dimensions()
|
||||||
|
|
||||||
|
width = int(screen_width * self._width)
|
||||||
|
height = int(screen_height * self._height)
|
||||||
|
|
||||||
|
return (width, height)
|
||||||
|
|
||||||
|
def _update_hints(self):
|
||||||
|
if self._window_type == WindowManager.TYPE_POPUP:
|
||||||
|
self._window.set_decorated(False)
|
||||||
|
self._window.set_skip_taskbar_hint(True)
|
||||||
|
|
||||||
|
def _update_size(self):
|
||||||
|
if self._window_type == WindowManager.TYPE_ACTIVITY:
|
||||||
|
self._window.resize(DEFAULT_WIDTH, DEFAULT_HEIGHT)
|
||||||
|
else:
|
||||||
|
(width, height) = self._transform_dimensions()
|
||||||
|
self._window.resize(width, height)
|
||||||
|
|
||||||
|
def _update_position(self):
|
||||||
|
if self._window_type == WindowManager.TYPE_POPUP:
|
||||||
|
(x, y) = self._transform_position()
|
||||||
|
self._window.move(x, y)
|
||||||
|
|
||||||
|
def __slide_timeout_cb(self, helper):
|
||||||
|
start = helper.is_start()
|
||||||
|
|
||||||
|
self._y = helper.get_next_y()
|
||||||
self._update_position()
|
self._update_position()
|
||||||
|
|
||||||
|
if start and helper.get_direction() == SlidingHelper.IN:
|
||||||
|
self._window.show()
|
||||||
|
elif helper.is_end() and helper.get_direction() == SlidingHelper.OUT:
|
||||||
|
self._window.hide()
|
||||||
|
|
||||||
|
self._animating = not helper.is_end()
|
||||||
|
|
||||||
|
return not helper.is_end()
|
||||||
|
|
||||||
|
def _slide_in(self):
|
||||||
|
helper = SlidingHelper(self, SlidingHelper.IN)
|
||||||
|
gobject.idle_add(self.__slide_timeout_cb, helper)
|
||||||
|
|
||||||
|
def _slide_out(self):
|
||||||
|
helper = SlidingHelper(self, SlidingHelper.OUT)
|
||||||
|
gobject.idle_add(self.__slide_timeout_cb, helper)
|
||||||
|
@ -25,7 +25,6 @@ class ChatEditor(gtk.HBox):
|
|||||||
chat_view_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
chat_view_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||||
self._text_view = richtext.RichTextView()
|
self._text_view = richtext.RichTextView()
|
||||||
self._text_view.connect("key-press-event", self.__key_press_event_cb)
|
self._text_view.connect("key-press-event", self.__key_press_event_cb)
|
||||||
self._text_view.connect("button-press-event", self.__button_press_event_cb)
|
|
||||||
chat_view_sw.add(self._text_view)
|
chat_view_sw.add(self._text_view)
|
||||||
self._text_view.show()
|
self._text_view.show()
|
||||||
|
|
||||||
@ -88,9 +87,3 @@ class ChatEditor(gtk.HBox):
|
|||||||
if event.keyval == gtk.keysyms.Return:
|
if event.keyval == gtk.keysyms.Return:
|
||||||
self._send()
|
self._send()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __button_press_event_cb(self, text_view, event):
|
|
||||||
# Need to explicitly get keyboard focus in the window
|
|
||||||
# because docks doesn't take it by default.
|
|
||||||
toplevel = text_view.get_toplevel()
|
|
||||||
toplevel.window.focus()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user