From 1766989d7b5c125c7c96428d558e026d042dc960 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Wed, 4 Apr 2012 23:03:00 -0700 Subject: [PATCH] Bug 707589 - [Gonk] When screen is enabled/disabled, send visibility change events to windows [r=mwu] --- b2g/chrome/content/shell.js | 9 +++++ widget/gonk/nsWindow.cpp | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index ae7a1661a38..0825cdd3bd4 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -93,6 +93,7 @@ var shell = { window.addEventListener('MozApplicationManifest', this); window.addEventListener('mozfullscreenchange', this); + window.addEventListener('sizemodechange', this); this.contentBrowser.addEventListener('load', this, true); // Until the volume can be set from the content side, set it to a @@ -130,6 +131,7 @@ var shell = { stop: function shell_stop() { window.removeEventListener('MozApplicationManifest', this); window.removeEventListener('mozfullscreenchange', this); + window.removeEventListener('sizemodechange', this); }, toggleDebug: function shell_toggleDebug() { @@ -226,6 +228,13 @@ var shell = { if (document.mozFullScreen) Services.fm.focusedWindow = window; break; + case 'sizemodechange': + if (window.windowState == window.STATE_MINIMIZED) { + this.contentBrowser.docShell.isActive = false; + } else { + this.contentBrowser.docShell.isActive = true; + } + break; case 'load': this.contentBrowser.removeEventListener('load', this, true); diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index e1d9f0bf064..cdd182b8c17 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -37,11 +37,13 @@ #include #include +#include #include "android/log.h" #include "ui/FramebufferNativeWindow.h" #include "mozilla/Hal.h" +#include "mozilla/FileUtils.h" #include "Framebuffer.h" #include "gfxContext.h" #include "gfxUtils.h" @@ -74,6 +76,82 @@ static nsWindow *gWindowToRedraw = nsnull; static nsWindow *gFocusedWindow = nsnull; static android::FramebufferNativeWindow *gNativeWindow = nsnull; static bool sFramebufferOpen; +static nsCOMPtr sFramebufferWatchThread; + +namespace { + +class ScreenOnOffEvent : public nsRunnable { +public: + ScreenOnOffEvent(bool on) + : mIsOn(on) + {} + + NS_IMETHOD Run() { + nsSizeModeEvent event(true, NS_SIZEMODE, NULL); + nsEventStatus status; + + event.time = PR_Now() / 1000; + event.mSizeMode = mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized; + + for (PRUint32 i = 0; i < sTopWindows.Length(); i++) { + nsWindow *win = sTopWindows[i]; + event.widget = win; + win->DispatchEvent(&event, status); + } + + return NS_OK; + } + +private: + bool mIsOn; +}; + +static const char* kSleepFile = "/sys/power/wait_for_fb_sleep"; +static const char* kWakeFile = "/sys/power/wait_for_fb_wake"; + +class FramebufferWatcher : public nsRunnable { +public: + FramebufferWatcher() + : mScreenOnEvent(new ScreenOnOffEvent(true)) + , mScreenOffEvent(new ScreenOnOffEvent(false)) + {} + + NS_IMETHOD Run() { + int len = 0; + char buf; + + // Cannot use epoll here because kSleepFile and kWakeFile are + // always ready to read and blocking. + { + ScopedClose fd(open(kSleepFile, O_RDONLY, 0)); + do { + len = read(fd.mFd, &buf, 1); + } while (len < 0 && errno == EINTR); + NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_SLEEP failed"); + NS_DispatchToMainThread(mScreenOffEvent); + } + + { + ScopedClose fd(open(kWakeFile, O_RDONLY, 0)); + do { + len = read(fd.mFd, &buf, 1); + } while (len < 0 && errno == EINTR); + NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_WAKE failed"); + NS_DispatchToMainThread(mScreenOnEvent); + } + + // Dispatch to ourself. + NS_DispatchToCurrentThread(this); + + return NS_OK; + } + +private: + nsRefPtr mScreenOnEvent; + nsRefPtr mScreenOffEvent; +}; + +} // anonymous namespace nsWindow::nsWindow() { @@ -81,6 +159,9 @@ nsWindow::nsWindow() // workaround Bug 725143 hal::SetScreenEnabled(true); + // Watching screen on/off state + NS_NewThread(getter_AddRefs(sFramebufferWatchThread), new FramebufferWatcher()); + // We (apparently) don't have a way to tell if allocating the // fbs succeeded or failed. gNativeWindow = new android::FramebufferNativeWindow();