--- /dev/null
+# -*- coding: ascii -*-
+#
+# osuwari.py - a Osuwari compatible Saori module for ninix
+# Copyright (C) 2006 by Shyouzou Sugitani <shy@users.sourceforge.jp>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License (version 2) as
+# published by the Free Software Foundation. It 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.
+#
+#
+
+# TODO: MOVE, NOCLIP, FIX, etc.
+
+import gobject
+import gtk
+
+from ninix.dll import SAORI
+
+
+class Saori(SAORI):
+
+ def __init__(self):
+ SAORI.__init__(self)
+ self.timeout_id = None
+ self.settings = {}
+ self.__ghost = None
+
+ def need_ghost_backdoor(self, ghost):
+ self.__ghost = ghost
+
+ def check_import(self):
+ return 1
+
+ def setup(self): ## FIXME
+ return 1
+
+ def execute(self, argument):
+ if not argument:
+ return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ if argument[0] == 'START':
+ if len(argument) < 7:
+ return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ try:
+ assert argument[2] in ['ACTIVE', 'FIX'] or \
+ arguent[2].stratswith('@') or \
+ argument[2].startswith('#')
+ assert argument[3] in ['TL', 'TR', 'BL', 'BR']
+ self.settings['hwnd'] = argument[1]
+ self.settings['target'] = argument[2]
+ self.settings['position'] = argument[3]
+ self.settings['offset_x'] = int(argument[4])
+ self.settings['offset_y'] = int(argument[5])
+ self.settings['timeout'] = int(argument[6])
+ self.settings['xmove'] = 0
+ self.settings['ymove'] = 0
+ self.settings['noclip'] = 0
+ if len(argument) > 7:
+ if 'XMOVE' in argument[7]:
+ self.settings['xmove'] = 1
+ if 'YMOVE' in argument[7]:
+ self.settings['ymove'] = 1
+ if 'NOCLIP' in argument[7]:
+ self.settings['noclip'] = 1
+ self.settings['except'] = ('DESKTOP', 'CENTER')
+ #if len(argument) > 8:
+ # target, position = argument[8].split()
+ # assert target in ['DESKTOP', 'WORKAREA']
+ # assert position in ['TOP', 'LEFT', 'RIGHT', 'BOTTOM']
+ # self.settings['except'] = (target, position)
+ except:
+ return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ #self.timeout_id = gobject.timeout_add(self.settings['timeout'], self.do_idle_tasks)
+ self.timeout_id = gobject.timeout_add(100, self.do_idle_tasks)
+ return 'SAORI/1.0 204 No Content\r\n\r\n'
+ elif argument[0] == 'STOP':
+ if self.timeout_id is not None:
+ gobject.source_remove(self.timeout_id)
+ self.timeout_id = None
+ self.settings = {}
+ return 'SAORI/1.0 204 No Content\r\n\r\n'
+ else:
+ return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+
+ def do_idle_tasks(self):
+ if self.timeout_id is None:
+ return False
+ target = self.settings['target']
+ if target == 'ACTIVE':
+ active_id = self.get_active_window()
+ gdk_win = gtk.gdk.window_lookup(active_id)
+ if gdk_win and self.__ghost.identify_window(gdk_win):
+ return True
+ root_screen = gtk.gdk.screen_get_default() # XXX
+ active = root_screen.get_active_window()
+ if active:
+ target_x, target_y, target_w, target_h = self.get_geometry(active)
+ else:
+ return True
+ elif target == 'FIX': ## FIXME
+ target_x = 0
+ target_y = 0
+ target_w = gtk.gdk.screen_width()
+ target_h = gtk.gdk.screen_height()
+ elif target.startswith('@'): ## FIXME
+ #win = self.get_window_by_name(target[1:])
+ #if self.__ghost.identify_window(gtk.gdk.window_lookup(win.id)):
+ # return True
+ #target_x, target_y, target_w, target_h = self.get_geometry(win)
+ return False
+ elif target.startswith('#'): ## FIXME
+ return False
+ else:
+ return False # should not reach here
+ pos = self.settings['position']
+ scale = self.__ghost.get_surface_scale()
+ offset_x = int(self.settings['offset_x'] * scale / 100)
+ offset_y = int(self.settings['offset_y'] * scale / 100)
+ if self.settings['hwnd'].startswith('s'):
+ try:
+ side = int(self.settings['hwnd'][1:])
+ except:
+ return False
+ else:
+ try:
+ side = int(self.settings['hwnd'])
+ except:
+ return False
+ w, h = self.__ghost.get_surface_size(side)
+ if pos[0] == 'T':
+ y = target_y + offset_y
+ elif pos[0] == 'B':
+ y = target_y + target_h + offset_y - h
+ else:
+ return False # should not reach here
+ if pos[1] == 'L':
+ x = target_x + offset_x
+ elif pos[1] == 'R':
+ x = target_x + target_w + offset_x - w
+ else:
+ return False # should not reach here
+ if not self.settings['noclip']:
+ if x < 0 or y < 0:
+ pass ## FIXME
+ self.__ghost.set_surface_position(side, x, y)
+ self.__ghost.raise_surface(side) ## FIXME
+ return True
+
+ def get_geometry(self, win):
+ relative_x, relative_y, w, h , d = win.get_geometry() # ._data
+ w = w + relative_x * 2
+ h = h + relative_y + relative_x
+ x, y = win.get_root_origin()
+ return x, y, w, h
+ #return geom['x'], geom['y'], geom['width'], geom['height']
+
+ def get_window_by_name(self, name): ## FIXME
+ return None
+
+ def get_active_window(self):
+ root = gtk.gdk.get_default_root_window()
+ atom = gtk.gdk.atom_intern("_NET_SUPPORTED", True)
+ supported_atom = root.property_get(atom)
+ if supported_atom is None or len(supported_atom) < 2:
+ return None
+ else:
+ assert supported_atom[0] == 'ATOM'
+ supported = supported_atom[2]
+ current_desktop = 0
+ if "_NET_CURRENT_DESKTOP" in supported:
+ atom = gtk.gdk.atom_intern("_NET_CURRENT_DESKTOP", True)
+ current_desktop = root.property_get(atom)[2][0]
+ if "_NET_ACTIVE_WINDOW" in supported:
+ atom = gtk.gdk.atom_intern("_NET_ACTIVE_WINDOW", True)
+ active_window = root.property_get(atom)[2][current_desktop]
+ return active_window