forked from mirrors/gecko-dev
Bug 541015 - Support rotating between portrait and landscape on N900 [r=karlt]
This commit is contained in:
parent
75db30109e
commit
d0fffdb53f
2 changed files with 174 additions and 10 deletions
|
|
@ -53,18 +53,36 @@
|
||||||
#include "nsICommandLineRunner.h"
|
#include "nsICommandLineRunner.h"
|
||||||
#include "nsIWindowMediator.h"
|
#include "nsIWindowMediator.h"
|
||||||
#include "nsIDOMWindowInternal.h"
|
#include "nsIDOMWindowInternal.h"
|
||||||
|
#include "nsPIDOMWindow.h"
|
||||||
|
#include "nsIDocShell.h"
|
||||||
|
#include "nsIBaseWindow.h"
|
||||||
|
#include "nsIWidget.h"
|
||||||
|
#include "nsIWritablePropertyBag2.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#ifdef MOZ_X11
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_PLATFORM_MAEMO
|
#ifdef MOZ_PLATFORM_MAEMO
|
||||||
struct DBusMessage; /* libosso.h references internals of dbus */
|
struct DBusMessage; /* libosso.h references internals of dbus */
|
||||||
|
|
||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
#include <dbus/dbus-protocol.h>
|
#include <dbus/dbus-protocol.h>
|
||||||
#include <libosso.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
|
#endif
|
||||||
|
|
||||||
#define MIN_GTK_MAJOR_VERSION 2
|
#define MIN_GTK_MAJOR_VERSION 2
|
||||||
|
|
@ -155,6 +173,7 @@ class nsNativeAppSupportUnix : public nsNativeAppSupportBase
|
||||||
public:
|
public:
|
||||||
NS_IMETHOD Start(PRBool* aRetVal);
|
NS_IMETHOD Start(PRBool* aRetVal);
|
||||||
NS_IMETHOD Stop(PRBool *aResult);
|
NS_IMETHOD Stop(PRBool *aResult);
|
||||||
|
NS_IMETHOD Enable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef MOZ_PLATFORM_MAEMO
|
#ifdef MOZ_PLATFORM_MAEMO
|
||||||
|
|
@ -169,17 +188,118 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef MOZ_PLATFORM_MAEMO
|
#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)
|
static void OssoDisplayCallback(osso_display_state_t state, gpointer data)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
|
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
|
||||||
if (!os)
|
if (!os)
|
||||||
return;
|
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);
|
os->NotifyObservers(nsnull, "system-display-on", nsnull);
|
||||||
else
|
OssoRequestAccelerometer(context, PR_TRUE);
|
||||||
|
} else {
|
||||||
os->NotifyObservers(nsnull, "system-display-dimmed-or-off", nsnull);
|
os->NotifyObservers(nsnull, "system-display-dimmed-or-off", nsnull);
|
||||||
|
OssoRequestAccelerometer(context, PR_FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OssoHardwareCallback(osso_hw_state_t *state, gpointer data)
|
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.
|
// The "top_application" method just wants us to focus the top-most window.
|
||||||
if (!strcmp("top_application", method)) {
|
if (!strcmp("top_application", method)) {
|
||||||
nsCOMPtr<nsIWindowMediator> wm = do_GetService("@mozilla.org/appshell/window-mediator;1");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMWindowInternal> window;
|
nsCOMPtr<nsIDOMWindowInternal> window;
|
||||||
wm->GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
|
GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
|
||||||
if (window) {
|
if (window)
|
||||||
window->Focus();
|
window->Focus();
|
||||||
}
|
|
||||||
return OSSO_OK;
|
return OSSO_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,6 +403,21 @@ OssoDbusCallback(const gchar *interface, const gchar *method,
|
||||||
return OSSO_OK;
|
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
|
#endif
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
@ -323,7 +456,7 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal)
|
||||||
system will happily kill your process.
|
system will happily kill your process.
|
||||||
*/
|
*/
|
||||||
nsCAutoString applicationName;
|
nsCAutoString applicationName;
|
||||||
if(gAppData->vendor) {
|
if (gAppData->vendor) {
|
||||||
applicationName.Append(gAppData->vendor);
|
applicationName.Append(gAppData->vendor);
|
||||||
applicationName.Append(".");
|
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_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);
|
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
|
#endif
|
||||||
|
|
||||||
*aRetVal = PR_TRUE;
|
*aRetVal = PR_TRUE;
|
||||||
|
|
@ -455,6 +593,13 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult)
|
||||||
|
|
||||||
#ifdef MOZ_PLATFORM_MAEMO
|
#ifdef MOZ_PLATFORM_MAEMO
|
||||||
if (m_osso_context) {
|
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_hw_unset_event_cb(m_osso_context, nsnull);
|
||||||
osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
|
osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
|
||||||
osso_deinitialize(m_osso_context);
|
osso_deinitialize(m_osso_context);
|
||||||
|
|
@ -464,6 +609,17 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult)
|
||||||
return NS_OK;
|
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
|
nsresult
|
||||||
NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
|
NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
|
|
||||||
#include "nsIdleService.h"
|
#include "nsIdleService.h"
|
||||||
|
#include "nsIPropertyBag2.h"
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
#include "nsIAccessibilityService.h"
|
#include "nsIAccessibilityService.h"
|
||||||
|
|
@ -4265,6 +4266,13 @@ nsWindow::Create(nsIWidget *aParent,
|
||||||
if (mWindowType == eWindowType_toplevel) {
|
if (mWindowType == eWindowType_toplevel) {
|
||||||
GdkWindow *gdkwin = mShell->window;
|
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
|
// Tell maemo-status-volume daemon to ungrab keys
|
||||||
gulong volume_set = 1;
|
gulong volume_set = 1;
|
||||||
GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE);
|
GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue