| 1 | # Copyright (C) 2010, Walter Bender, Sugar Labs |
| 2 | # |
| 3 | # This program is free software; you can redistribute it and/or modify |
| 4 | # it under the terms of the GNU General Public License as published by |
| 5 | # the Free Software Foundation; either version 2 of the License, or |
| 6 | # (at your option) any later version. |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | # GNU General Public License for more details. |
| 12 | # |
| 13 | # You should have received a copy of the GNU General Public License |
| 14 | # along with this program; if not, write to the Free Software |
| 15 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 16 | |
| 17 | |
| 18 | from gettext import gettext as _ |
| 19 | |
| 20 | import gtk |
| 21 | import gconf |
| 22 | from os import system, path, remove |
| 23 | |
| 24 | from sugar.graphics.tray import TrayIcon |
| 25 | from sugar.graphics.xocolor import XoColor |
| 26 | from sugar.graphics.palette import Palette |
| 27 | from jarabe.frame.frameinvoker import FrameWidgetInvoker |
| 28 | |
| 29 | _STATUS_TEXT = {'capacitive': _('finger'), 'resistive': _('stylus')} |
| 30 | _CAPACITIVE_ICON_NAME = 'touchpad-capacitive' |
| 31 | _RESISTIVE_ICON_NAME = 'touchpad-resistive' |
| 32 | _FLAG_PATH = '/home/olpc/.olpc-pentablet-mode' |
| 33 | _NODE_PATH = '/sys/devices/platform/i8042/serio1/ptmode' |
| 34 | |
| 35 | |
| 36 | class DeviceView(TrayIcon): |
| 37 | """ Manage the touchpad mode from the device palette on the Frame """ |
| 38 | |
| 39 | FRAME_POSITION_RELATIVE = 500 |
| 40 | |
| 41 | def __init__(self): |
| 42 | """ Create the touchpad palette and display it on Frame """ |
| 43 | |
| 44 | # Only appears when the device exisits |
| 45 | if not path.exists(_NODE_PATH): |
| 46 | return |
| 47 | |
| 48 | if get_touchpad() == 'resistive': |
| 49 | icon_name = _RESISTIVE_ICON_NAME |
| 50 | else: |
| 51 | icon_name = _CAPACITIVE_ICON_NAME |
| 52 | |
| 53 | client = gconf.client_get_default() |
| 54 | color = XoColor(client.get_string('/desktop/sugar/user/color')) |
| 55 | TrayIcon.__init__(self, icon_name=icon_name, xo_color=color) |
| 56 | self.set_palette_invoker(FrameWidgetInvoker(self)) |
| 57 | self.connect('button-release-event', self.__button_release_event_cb) |
| 58 | self.connect('expose-event', self.__expose_event_cb) |
| 59 | |
| 60 | def create_palette(self): |
| 61 | """ On create, set the current mode """ |
| 62 | self.palette = ResourcePalette(_('My touchpad'), self.icon) |
| 63 | self.palette.set_group_id('frame') |
| 64 | return self.palette |
| 65 | |
| 66 | def __button_release_event_cb(self, widget, event): |
| 67 | """ On button release, switch modes """ |
| 68 | self.palette.toggle_mode() |
| 69 | return True |
| 70 | |
| 71 | def __expose_event_cb(self, *args): |
| 72 | pass |
| 73 | |
| 74 | |
| 75 | class ResourcePalette(Palette): |
| 76 | """ Query the current state of the touchpad and update the display """ |
| 77 | |
| 78 | def __init__(self, primary_text, icon): |
| 79 | """ Get the status """ |
| 80 | Palette.__init__(self, label=primary_text) |
| 81 | |
| 82 | self._icon = icon |
| 83 | |
| 84 | self.connect('popup', self.__popup_cb) |
| 85 | self.connect('popdown', self.__popdown_cb) |
| 86 | |
| 87 | self.updating = False |
| 88 | |
| 89 | vbox = gtk.VBox() |
| 90 | self.set_content(vbox) |
| 91 | |
| 92 | self._status_text = gtk.Label() |
| 93 | vbox.pack_start(self._status_text, padding=10) |
| 94 | self._status_text.show() |
| 95 | |
| 96 | vbox.show() |
| 97 | |
| 98 | self._mode = get_touchpad() |
| 99 | self.set_mode_graphics() |
| 100 | |
| 101 | def set_mode_graphics(self): |
| 102 | """ Set the label and icon based on the current mode """ |
| 103 | self._status_text.set_label(_STATUS_TEXT[self._mode]) |
| 104 | if self._mode == 'resistive': |
| 105 | self._icon.props.icon_name = _RESISTIVE_ICON_NAME |
| 106 | else: |
| 107 | self._icon.props.icon_name = _CAPACITIVE_ICON_NAME |
| 108 | |
| 109 | def toggle_mode(self): |
| 110 | """ On mouse click, toggle the mode """ |
| 111 | if self._mode == 'capacitive': |
| 112 | self._mode = 'resistive' |
| 113 | else: |
| 114 | self._mode = 'capacitive' |
| 115 | |
| 116 | set_touchpad(self._mode) |
| 117 | self.set_mode_graphics() |
| 118 | |
| 119 | def __popup_cb(self, gobject): |
| 120 | self.updating = True |
| 121 | |
| 122 | def __popdown_cb(self, gobject): |
| 123 | self.updating = False |
| 124 | |
| 125 | |
| 126 | def setup(tray): |
| 127 | tray.add_device(DeviceView()) |
| 128 | |
| 129 | |
| 130 | def get_touchpad(): |
| 131 | """ Get the touchpad mode. """ |
| 132 | _file_handle = open(_NODE_PATH, "r") |
| 133 | _text = _file_handle.read() |
| 134 | _file_handle.close() |
| 135 | |
| 136 | if _text[0] == '1': |
| 137 | return 'resistive' |
| 138 | else: |
| 139 | return 'capacitive' |
| 140 | |
| 141 | |
| 142 | def set_touchpad(touchpad): |
| 143 | """ Set the touchpad mode. """ |
| 144 | if touchpad == 'capacitive': |
| 145 | if path.exists(_FLAG_PATH): |
| 146 | remove(_FLAG_PATH) |
| 147 | system("echo 0 > %s" % (_NODE_PATH)) |
| 148 | else: |
| 149 | _file_handle = open(_FLAG_PATH, "w") |
| 150 | _file_handle.close() |
| 151 | system("echo 1 > %s" % (_NODE_PATH)) |
| 152 | return |