зеркало из https://github.com/mozilla/gecko-dev.git
Bug 541015 - Support rotating between portrait and landscape on N900 [r=karlt]
This commit is contained in:
Родитель
75db30109e
Коммит
d0fffdb53f
|
@ -53,18 +53,36 @@
|
|||
#include "nsICommandLineRunner.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
struct DBusMessage; /* libosso.h references internals of dbus */
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-protocol.h>
|
||||
#include <libosso.h>
|
||||
|
||||
// These come from <mce/dbus-names.h> (maemo sdk 5+)
|
||||
#define MCE_SERVICE "com.nokia.mce"
|
||||
#define MCE_REQUEST_IF "com.nokia.mce.request"
|
||||
#define MCE_REQUEST_PATH "/com/nokia/mce/request"
|
||||
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
|
||||
#define MCE_DEVICE_ORIENTATION_SIG "sig_device_orientation_ind"
|
||||
#define MCE_MATCH_RULE "type='signal',interface='" MCE_SIGNAL_IF "',member='" MCE_DEVICE_ORIENTATION_SIG "'"
|
||||
#endif
|
||||
|
||||
#define MIN_GTK_MAJOR_VERSION 2
|
||||
|
@ -155,6 +173,7 @@ class nsNativeAppSupportUnix : public nsNativeAppSupportBase
|
|||
public:
|
||||
NS_IMETHOD Start(PRBool* aRetVal);
|
||||
NS_IMETHOD Stop(PRBool *aResult);
|
||||
NS_IMETHOD Enable();
|
||||
|
||||
private:
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
|
@ -169,17 +188,118 @@ private:
|
|||
};
|
||||
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
static nsresult
|
||||
GetMostRecentWindow(const PRUnichar* aType, nsIDOMWindowInternal** aWindow)
|
||||
{
|
||||
nsCOMPtr<nsIWindowMediator> wm = do_GetService("@mozilla.org/appshell/window-mediator;1");
|
||||
if (wm)
|
||||
return wm->GetMostRecentWindow(aType, aWindow);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
WidgetForDOMWindow(nsISupports *aWindow)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aWindow));
|
||||
if (!domWindow)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(domWindow->GetDocShell());
|
||||
if (!baseWindow)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
baseWindow->GetMainWidget(getter_AddRefs(widget));
|
||||
if (!widget)
|
||||
return NULL;
|
||||
|
||||
return (GtkWidget*)(widget->GetNativeData(NS_NATIVE_SHELLWIDGET));
|
||||
}
|
||||
|
||||
static void
|
||||
OssoSetWindowOrientation(PRBool aPortrait)
|
||||
{
|
||||
// Tell Hildon desktop to force our window to be either portrait or landscape,
|
||||
// depending on the current rotation
|
||||
// NOTE: We only update the most recent top-level window so this is only
|
||||
// suitable for apps with only one window.
|
||||
nsCOMPtr<nsIDOMWindowInternal> window;
|
||||
GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
|
||||
GtkWidget* widget = WidgetForDOMWindow(window);
|
||||
if (widget && widget->window) {
|
||||
GdkWindow *gdk = widget->window;
|
||||
GdkAtom request = gdk_atom_intern("_HILDON_PORTRAIT_MODE_REQUEST", FALSE);
|
||||
|
||||
if (aPortrait) {
|
||||
gulong portrait_set = 1;
|
||||
gdk_property_change(gdk, request, gdk_x11_xatom_to_atom(XA_CARDINAL),
|
||||
32, GDK_PROP_MODE_REPLACE, (const guchar *) &portrait_set, 1);
|
||||
}
|
||||
else {
|
||||
gdk_property_delete(gdk, request);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the system info property
|
||||
nsCOMPtr<nsIWritablePropertyBag2> info = do_GetService("@mozilla.org/system-info;1");
|
||||
if (info) {
|
||||
info->SetPropertyAsAString(NS_LITERAL_STRING("screen-orientation"),
|
||||
aPortrait ? NS_LITERAL_STRING("portrait") : NS_LITERAL_STRING("landscape"));
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool OssoIsScreenOn(osso_context_t* ctx)
|
||||
{
|
||||
osso_return_t rv;
|
||||
osso_rpc_t ret;
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
rv = osso_rpc_run_system(ctx, MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF,
|
||||
"get_display_status", &ret, DBUS_TYPE_INVALID);
|
||||
if (rv == OSSO_OK) {
|
||||
if (strcmp(ret.value.s, "on") == 0)
|
||||
result = PR_TRUE;
|
||||
|
||||
osso_rpc_free_val(&ret);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void OssoRequestAccelerometer(osso_context_t *ctx, PRBool aEnabled)
|
||||
{
|
||||
osso_return_t rv;
|
||||
osso_rpc_t ret;
|
||||
|
||||
rv = osso_rpc_run_system(ctx,
|
||||
MCE_SERVICE,
|
||||
MCE_REQUEST_PATH, MCE_REQUEST_IF,
|
||||
aEnabled ? "req_accelerometer_enable" : "req_accelerometer_disable",
|
||||
aEnabled ? &ret : NULL,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
// Orientation might changed while the accelerometer was off, so let's update
|
||||
// the window's orientation
|
||||
if (rv == OSSO_OK && aEnabled) {
|
||||
OssoSetWindowOrientation(strcmp(ret.value.s, "portrait") == 0);
|
||||
osso_rpc_free_val(&ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void OssoDisplayCallback(osso_display_state_t state, gpointer data)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
|
||||
if (!os)
|
||||
return;
|
||||
|
||||
if (state == OSSO_DISPLAY_ON)
|
||||
|
||||
osso_context_t* context = (osso_context_t*) data;
|
||||
|
||||
if (state == OSSO_DISPLAY_ON) {
|
||||
os->NotifyObservers(nsnull, "system-display-on", nsnull);
|
||||
else
|
||||
OssoRequestAccelerometer(context, PR_TRUE);
|
||||
} else {
|
||||
os->NotifyObservers(nsnull, "system-display-dimmed-or-off", nsnull);
|
||||
OssoRequestAccelerometer(context, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void OssoHardwareCallback(osso_hw_state_t *state, gpointer data)
|
||||
|
@ -226,13 +346,11 @@ OssoDbusCallback(const gchar *interface, const gchar *method,
|
|||
|
||||
// The "top_application" method just wants us to focus the top-most window.
|
||||
if (!strcmp("top_application", method)) {
|
||||
nsCOMPtr<nsIWindowMediator> wm = do_GetService("@mozilla.org/appshell/window-mediator;1");
|
||||
|
||||
nsCOMPtr<nsIDOMWindowInternal> window;
|
||||
wm->GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
|
||||
if (window) {
|
||||
GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
|
||||
if (window)
|
||||
window->Focus();
|
||||
}
|
||||
|
||||
return OSSO_OK;
|
||||
}
|
||||
|
||||
|
@ -285,6 +403,21 @@ OssoDbusCallback(const gchar *interface, const gchar *method,
|
|||
return OSSO_OK;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
OssoModeControlCallback(DBusConnection *con, DBusMessage *msg, gpointer data)
|
||||
{
|
||||
if (dbus_message_is_signal(msg, MCE_SIGNAL_IF, MCE_DEVICE_ORIENTATION_SIG)) {
|
||||
DBusMessageIter iter;
|
||||
if (dbus_message_iter_init(msg, &iter)) {
|
||||
const gchar *mode = NULL;
|
||||
dbus_message_iter_get_basic(&iter, &mode);
|
||||
|
||||
OssoSetWindowOrientation(strcmp(mode, "portrait") == 0);
|
||||
}
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -323,7 +456,7 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal)
|
|||
system will happily kill your process.
|
||||
*/
|
||||
nsCAutoString applicationName;
|
||||
if(gAppData->vendor) {
|
||||
if (gAppData->vendor) {
|
||||
applicationName.Append(gAppData->vendor);
|
||||
applicationName.Append(".");
|
||||
}
|
||||
|
@ -341,8 +474,13 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal)
|
|||
}
|
||||
|
||||
osso_hw_set_event_cb(m_osso_context, nsnull, OssoHardwareCallback, &m_hw_state);
|
||||
osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, nsnull);
|
||||
osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, m_osso_context);
|
||||
osso_rpc_set_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
|
||||
|
||||
// Setup an MCE callback to monitor orientation
|
||||
DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context);
|
||||
dbus_bus_add_match(connnection, MCE_MATCH_RULE, nsnull);
|
||||
dbus_connection_add_filter(connnection, OssoModeControlCallback, nsnull, nsnull);
|
||||
#endif
|
||||
|
||||
*aRetVal = PR_TRUE;
|
||||
|
@ -455,6 +593,13 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult)
|
|||
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
if (m_osso_context) {
|
||||
// Disable the accelerometer when closing
|
||||
OssoRequestAccelerometer(m_osso_context, PR_FALSE);
|
||||
|
||||
// Remove the MCE callback filter
|
||||
DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context);
|
||||
dbus_connection_remove_filter(connnection, OssoModeControlCallback, nsnull);
|
||||
|
||||
osso_hw_unset_event_cb(m_osso_context, nsnull);
|
||||
osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
|
||||
osso_deinitialize(m_osso_context);
|
||||
|
@ -464,6 +609,17 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeAppSupportUnix::Enable()
|
||||
{
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
// Enable the accelerometer for orientation support
|
||||
if (OssoIsScreenOn(m_osso_context))
|
||||
OssoRequestAccelerometer(m_osso_context, PR_TRUE);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
|
||||
#include "nsIdleService.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsIAccessibilityService.h"
|
||||
|
@ -4265,6 +4266,13 @@ nsWindow::Create(nsIWidget *aParent,
|
|||
if (mWindowType == eWindowType_toplevel) {
|
||||
GdkWindow *gdkwin = mShell->window;
|
||||
|
||||
// Tell the Hildon desktop that we support being rotated
|
||||
gulong portrait_set = 1;
|
||||
GdkAtom support = gdk_atom_intern("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
|
||||
gdk_property_change(gdkwin, support, gdk_x11_xatom_to_atom(XA_CARDINAL),
|
||||
32, GDK_PROP_MODE_REPLACE,
|
||||
(const guchar *) &portrait_set, 1);
|
||||
|
||||
// Tell maemo-status-volume daemon to ungrab keys
|
||||
gulong volume_set = 1;
|
||||
GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE);
|
||||
|
|
Загрузка…
Ссылка в новой задаче