1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2009 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
29 class FremantleRotation(object):
30 """thp's screen rotation for Maemo 5
32 Simply instantiate an object of this class and let it auto-rotate
33 your StackableWindows depending on the device orientation.
35 If you need to relayout a window, connect to its "configure-event"
36 signal and measure the ratio of width/height and relayout for that.
38 You can set the mode for rotation to AUTOMATIC (default), NEVER or
39 ALWAYS with the set_mode() method.
41 AUTOMATIC, NEVER, ALWAYS = range(3)
43 # Human-readable captions for the above constants
44 MODE_CAPTIONS = ("Automatic", "Landscape", "Portrait")
46 # Privately-used constants
47 _PORTRAIT, _LANDSCAPE = ('portrait', 'landscape')
48 _ENABLE_ACCEL = 'req_accelerometer_enable'
49 _DISABLE_ACCEL = 'req_accelerometer_disable'
51 # Defined in mce/dbus-names.h
52 _MCE_SERVICE = 'com.nokia.mce'
53 _MCE_REQUEST_PATH = '/com/nokia/mce/request'
54 _MCE_REQUEST_IF = 'com.nokia.mce.request'
56 def __init__(self, app_name, main_window=None, version='1.0', mode=0, app=None):
57 """Create a new rotation manager
59 app_name ... The name of your application (for osso.Context)
60 main_window ... The root window (optional, hildon.StackableWindow)
61 version ... The version of your application (optional, string)
62 mode ... Initial mode for this manager (default: AUTOMATIC)
64 self._orientation = None
65 self._main_window = main_window
66 self._stack = hildon.WindowStack.get_default()
69 app_id = '-'.join((app_name, self.__class__.__name__))
70 self._osso_context = osso.Context(app_id, version, False)
71 self._last_dbus_orientation = self._get_current_orientation()
72 program = hildon.Program.get_instance()
73 program.connect('notify::is-topmost', self._on_topmost_changed)
74 system_bus = dbus.Bus.get_system()
75 system_bus.add_signal_receiver(self._on_orientation_signal, \
76 signal_name='sig_device_orientation_ind', \
77 dbus_interface='com.nokia.mce.signal', \
78 path='/com/nokia/mce/signal')
81 def _get_current_orientation(self):
82 """Return the current orientation
84 Returns portrait if in portrait mode for sure, landscape if
85 in landscape mode or unknown.
87 if self._send_mce_request('get_device_orientation', True) \
91 return self._LANDSCAPE
94 """Get the currently-set rotation mode
96 This will return one of three values: AUTOMATIC, ALWAYS or NEVER.
100 def set_mode(self, new_mode):
101 """Set the rotation mode
103 You can set the rotation mode to AUTOMATIC (use hardware rotation
104 info), ALWAYS (force portrait) and NEVER (force landscape).
106 if new_mode not in (self.AUTOMATIC, self.ALWAYS, self.NEVER):
107 raise ValueError('Unknown rotation mode')
109 if self._mode != new_mode:
110 if self._mode == self.AUTOMATIC:
111 # Remember the current "automatic" orientation for later
112 self._last_dbus_orientation = self._orientation
113 # Tell MCE that we don't need the accelerometer anymore
114 self._send_mce_request(self._DISABLE_ACCEL)
116 if new_mode == self.NEVER:
117 self._orientation_changed(self._LANDSCAPE)
118 elif new_mode == self.ALWAYS:
119 self._orientation_changed(self._PORTRAIT)
120 elif new_mode == self.AUTOMATIC:
121 # Restore the last-known "automatic" orientation
122 self._orientation_changed(self._last_dbus_orientation)
123 # Tell MCE that we need the accelerometer again
124 self._send_mce_request(self._ENABLE_ACCEL)
126 self._mode = new_mode
128 def _send_mce_request(self, request, wait_reply=False):
129 rpc = osso.Rpc(self._osso_context)
130 return rpc.rpc_run(self._MCE_SERVICE,
131 self._MCE_REQUEST_PATH,
132 self._MCE_REQUEST_IF,
134 wait_reply=wait_reply,
137 def _on_topmost_changed(self, program, property_spec):
138 # XXX: This seems to never get called on Fremantle(?)
139 if self._mode == self.AUTOMATIC:
140 if program.get_is_topmost():
141 self._send_mce_request(self._ENABLE_ACCEL)
143 self._send_mce_request(self._DISABLE_ACCEL)
145 def _get_main_window(self):
146 if self._main_window:
147 # If we have gotten the main window as parameter, return it and
148 # don't try "harder" to find another window using the stack
149 return self._main_window
151 # The main window is at the "bottom" of the window stack, and as
152 # the list we get with get_windows() is sorted "topmost first", we
153 # simply take the last item of the list to get our main window
154 windows = self._stack.get_windows()
160 def _orientation_changed(self, orientation):
161 if self._orientation == orientation:
162 # Ignore repeated requests
167 if orientation != self._LANDSCAPE:
168 flags |= hildon.PORTRAIT_MODE_SUPPORT
170 if orientation == self._PORTRAIT:
171 flags |= hildon.PORTRAIT_MODE_REQUEST
173 window = self._get_main_window()
174 if window is not None:
175 hildon.hildon_gtk_window_set_portrait_flags(window, flags)
177 self._orientation = orientation
178 #if orientation == self._PORTRAIT:
180 # self.app.disp.clear()
181 # self.app.disp.displayFeed()
185 def _on_orientation_signal(self, orientation, stand, face, x, y, z):
186 if orientation in (self._PORTRAIT, self._LANDSCAPE):
187 if (self._mode == self.AUTOMATIC) and (not gconf.client_get_default().get_bool('/system/osso/af/slide-open')):
188 # Automatically set the rotation based on hardware orientation, if the keyboard is not open
189 self._orientation_changed(orientation)
191 # Ignore orientation changes for non-automatic modes, but save
192 # the current orientation for "automatic" mode later on
193 self._last_dbus_orientation = orientation