summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/fullscreen.h20
-rw-r--r--chrome/browser/fullscreen_linux.cc144
-rw-r--r--chrome/browser/fullscreen_mac.mm100
-rw-r--r--chrome/browser/fullscreen_win.cc80
-rw-r--r--chrome/browser/idle.h7
-rw-r--r--chrome/browser/idle_linux.cc65
-rw-r--r--chrome/browser/idle_mac.cc16
-rw-r--r--chrome/browser/idle_mac.mm99
-rw-r--r--chrome/browser/notifications/notification_ui_manager.cc40
-rw-r--r--chrome/browser/notifications/notification_ui_manager.h8
-rw-r--r--chrome/browser/ui/gtk/gtk_util.cc2
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--ui/base/x/x11_util.cc192
-rw-r--r--ui/base/x/x11_util.h15
14 files changed, 696 insertions, 98 deletions
diff --git a/chrome/browser/fullscreen.h b/chrome/browser/fullscreen.h
new file mode 100644
index 0000000..3ed7ecc
--- /dev/null
+++ b/chrome/browser/fullscreen.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FULLSCREEN_H_
+#define CHROME_BROWSER_FULLSCREEN_H_
+#pragma once
+
+#include "build/build_config.h"
+
+// For MacOSX, InitFullScreenMonitor needs to be called first to setup the
+// monitor. StopFullScreenMonitor should be called if it is not needed any more.
+#if defined(OS_MACOSX)
+void InitFullScreenMonitor();
+void StopFullScreenMonitor();
+#endif
+
+bool IsFullScreenMode();
+
+#endif // CHROME_BROWSER_FULLSCREEN_H_
diff --git a/chrome/browser/fullscreen_linux.cc b/chrome/browser/fullscreen_linux.cc
new file mode 100644
index 0000000..599ecdd
--- /dev/null
+++ b/chrome/browser/fullscreen_linux.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/fullscreen.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "gfx/rect.h"
+#include "ui/base/x/x11_util.h"
+
+namespace {
+
+// TODO (jianli): Merge with gtk_util::EnumerateTopLevelWindows.
+void EnumerateAllChildWindows(ui::EnumerateWindowsDelegate* delegate,
+ XID window) {
+ std::vector<XID> windows;
+
+ if (!ui::GetXWindowStack(window, &windows)) {
+ // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
+ // to old school enumeration of all X windows.
+ XID root, parent, *children;
+ unsigned int num_children;
+ int status = XQueryTree(ui::GetXDisplay(), window, &root, &parent,
+ &children, &num_children);
+ if (status) {
+ for (long i = static_cast<long>(num_children) - 1; i >= 0; i--)
+ windows.push_back(children[i]);
+ XFree(children);
+ }
+ }
+
+ std::vector<XID>::iterator iter;
+ for (iter = windows.begin(); iter != windows.end(); iter++) {
+ if (delegate->ShouldStopIterating(*iter))
+ return;
+ }
+}
+
+// To find the top-most window:
+// 1) Enumerate all top-level windows from the top to the bottom.
+// 2) For each window:
+// 2.1) If it is hidden, continue the iteration.
+// 2.2) If it is managed by the Window Manager (has a WM_STATE property).
+// Return this window as the top-most window.
+// 2.3) Enumerate all its child windows. If there is a child window that is
+// managed by the Window Manager (has a WM_STATE property). Return this
+// child window as the top-most window.
+// 2.4) Otherwise, continue the iteration.
+
+class WindowManagerWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+ WindowManagerWindowFinder() : window_(None) { }
+
+ XID window() const { return window_; }
+
+ protected:
+ virtual bool ShouldStopIterating(XID window) {
+ if (ui::PropertyExists(window, "WM_STATE")) {
+ window_ = window;
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ XID window_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowManagerWindowFinder);
+};
+
+class TopMostWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+ TopMostWindowFinder()
+ : top_most_window_(None) {}
+
+ XID top_most_window() const { return top_most_window_; }
+
+ protected:
+ virtual bool ShouldStopIterating(XID window) {
+ if (!ui::IsWindowVisible(window))
+ return false;
+ if (ui::PropertyExists(window, "WM_STATE")) {
+ top_most_window_ = window;
+ return true;
+ }
+ WindowManagerWindowFinder child_finder;
+ EnumerateAllChildWindows(&child_finder, window);
+ XID child_window = child_finder.window();
+ if (child_window == None)
+ return false;
+ top_most_window_ = child_window;
+ return true;
+ }
+
+ private:
+ XID top_most_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(TopMostWindowFinder);
+};
+
+bool IsTopMostWindowFullScreen() {
+ // Find the topmost window.
+ TopMostWindowFinder finder;
+ EnumerateAllChildWindows(&finder, ui::GetX11RootWindow());
+ XID window = finder.top_most_window();
+ if (window == None)
+ return false;
+
+ // Make sure it is not the desktop window.
+ static Atom desktop_atom = gdk_x11_get_xatom_by_name_for_display(
+ gdk_display_get_default(), "_NET_WM_WINDOW_TYPE_DESKTOP");
+
+ std::vector<Atom> atom_properties;
+ if (ui::GetAtomArrayProperty(window,
+ "_NET_WM_WINDOW_TYPE",
+ &atom_properties) &&
+ std::find(atom_properties.begin(), atom_properties.end(), desktop_atom)
+ != atom_properties.end())
+ return false;
+
+ // If it is a GDK window, check it using gdk function.
+ GdkWindow* gwindow = gdk_window_lookup(window);
+ if (gwindow && window != GDK_ROOT_WINDOW())
+ return gdk_window_get_state(gwindow) == GDK_WINDOW_STATE_FULLSCREEN;
+
+ // Otherwise, do the check via xlib function.
+ return ui::IsX11WindowFullScreen(window);
+}
+
+}
+
+bool IsFullScreenMode() {
+ gdk_error_trap_push();
+ bool result = IsTopMostWindowFullScreen();
+ bool got_error = gdk_error_trap_pop();
+ return result && !got_error;
+}
diff --git a/chrome/browser/fullscreen_mac.mm b/chrome/browser/fullscreen_mac.mm
new file mode 100644
index 0000000..303f6f2
--- /dev/null
+++ b/chrome/browser/fullscreen_mac.mm
@@ -0,0 +1,100 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/fullscreen.h"
+
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+
+#import "base/logging.h"
+
+@interface FullScreenMonitor : NSObject {
+ @private
+ BOOL fullScreen_;
+ EventHandlerRef eventHandler_;
+}
+
+@property (nonatomic, getter=isFullScreen) BOOL fullScreen;
+
+@end
+
+static OSStatus handleAppEvent(EventHandlerCallRef myHandler,
+ EventRef event,
+ void* userData) {
+ DCHECK(userData);
+
+ FullScreenMonitor* fullScreenMonitor =
+ reinterpret_cast<FullScreenMonitor*>(userData);
+
+ UInt32 mode = 0;
+ OSStatus status = GetEventParameter(event,
+ kEventParamSystemUIMode,
+ typeUInt32,
+ NULL,
+ sizeof(UInt32),
+ NULL,
+ &mode);
+ if (status != noErr)
+ return status;
+ BOOL isFullScreenMode = mode == kUIModeAllHidden;
+ [fullScreenMonitor setFullScreen:isFullScreenMode];
+ return noErr;
+}
+
+@implementation FullScreenMonitor
+
+@synthesize fullScreen = fullScreen_;
+
+- (id)init {
+ if ((self = [super init])) {
+ // Check if the user is in presentation mode initially.
+ SystemUIMode currentMode;
+ GetSystemUIMode(&currentMode, NULL);
+ fullScreen_ = currentMode == kUIModeAllHidden;
+
+ // Register a Carbon event to receive the notification about the login
+ // session's UI mode change.
+ EventTypeSpec events[] =
+ {{ kEventClassApplication, kEventAppSystemUIModeChanged }};
+ OSStatus status = InstallApplicationEventHandler(
+ NewEventHandlerUPP(handleAppEvent),
+ GetEventTypeCount(events),
+ events,
+ self,
+ &eventHandler_);
+ if (status) {
+ [self release];
+ self = nil;
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ if (eventHandler_)
+ RemoveEventHandler(eventHandler_);
+ [super dealloc];
+}
+
+@end
+
+static FullScreenMonitor* g_fullScreenMonitor = nil;
+
+void InitFullScreenMonitor() {
+ if (!g_fullScreenMonitor)
+ g_fullScreenMonitor = [[FullScreenMonitor alloc] init];
+}
+
+void StopFullScreenMonitor() {
+ [g_fullScreenMonitor release];
+ g_fullScreenMonitor = nil;
+}
+
+bool IsFullScreenMode() {
+ // Check if the main display has been captured (game in particular).
+ if (CGDisplayIsCaptured(CGMainDisplayID()))
+ return true;
+
+ return [g_fullScreenMonitor isFullScreen];
+}
diff --git a/chrome/browser/fullscreen_win.cc b/chrome/browser/fullscreen_win.cc
new file mode 100644
index 0000000..68ddc18
--- /dev/null
+++ b/chrome/browser/fullscreen_win.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/fullscreen.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+static bool IsPlatformFullScreenMode() {
+ // SHQueryUserNotificationState is only available for Vista and above.
+#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_VISTA)
+ QUERY_USER_NOTIFICATION_STATE state;
+ if (FAILED(::SHQueryUserNotificationState(&state)))
+ return false;
+ return state == QUNS_RUNNING_D3D_FULL_SCREEN ||
+ state == QUNS_PRESENTATION_MODE;
+#else
+ return false;
+#endif
+}
+
+static bool IsFullScreenWindowMode() {
+ // Get the foreground window which the user is currently working on.
+ HWND wnd = ::GetForegroundWindow();
+ if (!wnd)
+ return false;
+
+ // Get the monitor where the window is located.
+ RECT wnd_rect;
+ if (!::GetWindowRect(wnd, &wnd_rect))
+ return false;
+ HMONITOR monitor = ::MonitorFromRect(&wnd_rect, MONITOR_DEFAULTTONULL);
+ if (!monitor)
+ return false;
+ MONITORINFO monitor_info = { sizeof(monitor_info) };
+ if (!::GetMonitorInfo(monitor, &monitor_info))
+ return false;
+
+ // It should be the main monitor.
+ if (!(monitor_info.dwFlags & MONITORINFOF_PRIMARY))
+ return false;
+
+ // The window should be at least as large as the monitor.
+ if (!::IntersectRect(&wnd_rect, &wnd_rect, &monitor_info.rcMonitor))
+ return false;
+ if (!::EqualRect(&wnd_rect, &monitor_info.rcMonitor))
+ return false;
+
+ // At last, the window style should not have WS_DLGFRAME and WS_THICKFRAME and
+ // its extended style should not have WS_EX_WINDOWEDGE and WS_EX_TOOLWINDOW.
+ LONG style = ::GetWindowLong(wnd, GWL_STYLE);
+ LONG ext_style = ::GetWindowLong(wnd, GWL_EXSTYLE);
+ return !((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
+ (ext_style & (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW)));
+}
+
+static bool IsFullScreenConsoleMode() {
+ // We detect this by attaching the current process to the console of the
+ // foreground window and then checking if it is in full screen mode.
+ DWORD pid = 0;
+ ::GetWindowThreadProcessId(::GetForegroundWindow(), &pid);
+ if (!pid)
+ return false;
+
+ if (!::AttachConsole(pid))
+ return false;
+
+ DWORD modes = 0;
+ ::GetConsoleDisplayMode(&modes);
+ ::FreeConsole();
+
+ return (modes & (CONSOLE_FULLSCREEN | CONSOLE_FULLSCREEN_HARDWARE)) != 0;
+}
+
+bool IsFullScreenMode() {
+ return IsPlatformFullScreenMode() ||
+ IsFullScreenWindowMode() ||
+ IsFullScreenConsoleMode();
+}
diff --git a/chrome/browser/idle.h b/chrome/browser/idle.h
index 3ea8067..4f99bef 100644
--- a/chrome/browser/idle.h
+++ b/chrome/browser/idle.h
@@ -12,6 +12,13 @@ enum IdleState {
IDLE_STATE_LOCKED = 2 // Only available on supported systems.
};
+// For MacOSX, InitIdleMonitor needs to be called first to setup the monitor.
+// StopIdleMonitor should be called if it is not needed any more.
+#if defined(OS_MACOSX)
+void InitIdleMonitor();
+void StopIdleMonitor();
+#endif
+
IdleState CalculateIdleState(unsigned int idle_threshold);
#endif // CHROME_BROWSER_IDLE_H_
diff --git a/chrome/browser/idle_linux.cc b/chrome/browser/idle_linux.cc
index 0da7f72..e1cdac2 100644
--- a/chrome/browser/idle_linux.cc
+++ b/chrome/browser/idle_linux.cc
@@ -4,9 +4,74 @@
#include "chrome/browser/idle.h"
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <vector>
+
+#include "base/basictypes.h"
#include "chrome/browser/sync/engine/idle_query_linux.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/x/x11_util.h"
+
+namespace {
+
+class ScreensaverWindowFinder : public ui::EnumerateWindowsDelegate {
+ public:
+ ScreensaverWindowFinder()
+ : exists_(false) {}
+
+ bool exists() const { return exists_; }
+
+ protected:
+ virtual bool ShouldStopIterating(XID window) {
+ if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
+ return false;
+ exists_ = true;
+ return true;
+ }
+
+ private:
+ bool IsScreensaverWindow(XID window) const {
+ // It should occupy the full screen.
+ if (!ui::IsX11WindowFullScreen(window))
+ return false;
+
+ // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
+ if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
+ return true;
+
+ // For all others, like gnome-screensaver, the window's WM_CLASS property
+ // should contain "screensaver".
+ std::string value;
+ if (!ui::GetStringProperty(window, "WM_CLASS", &value))
+ return false;
+
+ return value.find("screensaver") != std::string::npos;
+ }
+
+ bool exists_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreensaverWindowFinder);
+};
+
+bool ScreensaverWindowExists() {
+ ScreensaverWindowFinder finder;
+ gtk_util::EnumerateTopLevelWindows(&finder);
+ return finder.exists();
+}
+
+}
IdleState CalculateIdleState(unsigned int idle_threshold) {
+ // Usually the screensaver is used to lock the screen, so we do not need to
+ // check if the workstation is locked.
+ gdk_error_trap_push();
+ bool result = ScreensaverWindowExists();
+ bool got_error = gdk_error_trap_pop();
+ if (result && !got_error)
+ return IDLE_STATE_LOCKED;
+
browser_sync::IdleQueryLinux idle_query;
unsigned int idle_time = idle_query.IdleTime();
if (idle_time >= idle_threshold)
diff --git a/chrome/browser/idle_mac.cc b/chrome/browser/idle_mac.cc
deleted file mode 100644
index 383e4c7..0000000
--- a/chrome/browser/idle_mac.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/idle.h"
-
-#include <CoreGraphics/CGEventSource.h>
-
-IdleState CalculateIdleState(unsigned int idle_threshold) {
- unsigned int idle_time = CGEventSourceSecondsSinceLastEventType(
- kCGEventSourceStateCombinedSessionState,
- kCGAnyInputEventType);
- if (idle_time >= idle_threshold)
- return IDLE_STATE_IDLE;
- return IDLE_STATE_ACTIVE;
-}
diff --git a/chrome/browser/idle_mac.mm b/chrome/browser/idle_mac.mm
new file mode 100644
index 0000000..4032408
--- /dev/null
+++ b/chrome/browser/idle_mac.mm
@@ -0,0 +1,99 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/idle.h"
+
+#import <Cocoa/Cocoa.h>
+#import <CoreGraphics/CGEventSource.h>
+
+@interface MacScreenMonitor : NSObject {
+ @private
+ BOOL screensaverRunning_;
+ BOOL screenLocked_;
+}
+
+@property (readonly,
+ nonatomic,
+ getter=isScreensaverRunning) BOOL screensaverRunning;
+@property (readonly, nonatomic, getter=isScreenLocked) BOOL screenLocked;
+
+@end
+
+@implementation MacScreenMonitor
+
+@synthesize screensaverRunning = screensaverRunning_;
+@synthesize screenLocked = screenLocked_;
+
+- (id)init {
+ if ((self = [super init])) {
+ NSDistributedNotificationCenter* distCenter =
+ [NSDistributedNotificationCenter defaultCenter];
+ [distCenter addObserver:self
+ selector:@selector(onScreenSaverStarted:)
+ name:@"com.apple.screensaver.didstart"
+ object:nil];
+ [distCenter addObserver:self
+ selector:@selector(onScreenSaverStopped:)
+ name:@"com.apple.screensaver.didstop"
+ object:nil];
+ [distCenter addObserver:self
+ selector:@selector(onScreenLocked:)
+ name:@"com.apple.screenIsLocked"
+ object:nil];
+ [distCenter addObserver:self
+ selector:@selector(onScreenUnlocked:)
+ name:@"com.apple.screenIsUnlocked"
+ object:nil];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [[NSDistributedNotificationCenter defaultCenter] removeObject:self];
+ [super dealloc];
+}
+
+- (void)onScreenSaverStarted:(NSNotification*)notification {
+ screensaverRunning_ = YES;
+}
+
+- (void)onScreenSaverStopped:(NSNotification*)notification {
+ screensaverRunning_ = NO;
+}
+
+- (void)onScreenLocked:(NSNotification*)notification {
+ screenLocked_ = YES;
+}
+
+- (void)onScreenUnlocked:(NSNotification*)notification {
+ screenLocked_ = NO;
+}
+
+@end
+
+static MacScreenMonitor* g_screenMonitor = nil;
+
+void InitIdleMonitor() {
+ if (!g_screenMonitor)
+ g_screenMonitor = [[MacScreenMonitor alloc] init];
+}
+
+void StopIdleMonitor() {
+ [g_screenMonitor release];
+ g_screenMonitor = nil;
+}
+
+IdleState CalculateIdleState(unsigned int idle_threshold) {
+ if ([g_screenMonitor isScreensaverRunning] ||
+ [g_screenMonitor isScreenLocked])
+ return IDLE_STATE_LOCKED;
+
+ CFTimeInterval idle_time = CGEventSourceSecondsSinceLastEventType(
+ kCGEventSourceStateCombinedSessionState,
+ kCGAnyInputEventType);
+ if (idle_time >= idle_threshold)
+ return IDLE_STATE_IDLE;
+
+ return IDLE_STATE_ACTIVE;
+}
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
index 950bd6c..51a2c66 100644
--- a/chrome/browser/notifications/notification_ui_manager.cc
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -8,6 +8,8 @@
#include "base/scoped_ptr.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/fullscreen.h"
+#include "chrome/browser/idle.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/prefs/pref_service.h"
@@ -16,6 +18,10 @@
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
+namespace {
+const int kUserStatePollingIntervalSeconds = 1;
+}
+
// A class which represents a notification waiting to be shown.
class QueuedNotification {
public:
@@ -42,14 +48,21 @@ class QueuedNotification {
};
NotificationUIManager::NotificationUIManager(PrefService* local_state)
- : balloon_collection_(NULL) {
+ : balloon_collection_(NULL),
+ is_user_active_(true) {
registrar_.Add(this, NotificationType::APP_TERMINATING,
NotificationService::AllSources());
position_pref_.Init(prefs::kDesktopNotificationPosition, local_state, this);
+#if defined(OS_MACOSX)
+ InitFullScreenMonitor();
+#endif
}
NotificationUIManager::~NotificationUIManager() {
STLDeleteElements(&show_queue_);
+#if defined(OS_MACOSX)
+ StopFullScreenMonitor();
+#endif
}
// static
@@ -126,8 +139,29 @@ void NotificationUIManager::CancelAll() {
}
void NotificationUIManager::CheckAndShowNotifications() {
- // TODO(johnnyg): http://crbug.com/25061 - Check for user idle/presentation.
- ShowNotifications();
+ CheckUserState();
+ if (is_user_active_)
+ ShowNotifications();
+}
+
+void NotificationUIManager::CheckUserState() {
+ bool is_user_active_previously = is_user_active_;
+ is_user_active_ = CalculateIdleState(0) != IDLE_STATE_LOCKED &&
+ !IsFullScreenMode();
+ if (is_user_active_ == is_user_active_previously)
+ return;
+
+ if (is_user_active_) {
+ user_state_check_timer_.Stop();
+ // We need to show any postponed nofications when the user becomes active
+ // again.
+ ShowNotifications();
+ } else if (!user_state_check_timer_.IsRunning()) {
+ // Start a timer to detect the moment at which the user becomes active.
+ user_state_check_timer_.Start(
+ base::TimeDelta::FromSeconds(kUserStatePollingIntervalSeconds), this,
+ &NotificationUIManager::CheckUserState);
+ }
}
void NotificationUIManager::ShowNotifications() {
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
index 1b9475d..7ac63a2 100644
--- a/chrome/browser/notifications/notification_ui_manager.h
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -11,6 +11,7 @@
#include "base/id_map.h"
#include "base/scoped_ptr.h"
+#include "base/timer.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/prefs/pref_member.h"
@@ -93,6 +94,9 @@ class NotificationUIManager
// returns true if the replacement happened.
bool TryReplacement(const Notification& notification);
+ // Checks the user state to decide if we want to show the notification.
+ void CheckUserState();
+
// An owned pointer to the collection of active balloons.
scoped_ptr<BalloonCollection> balloon_collection_;
@@ -106,6 +110,10 @@ class NotificationUIManager
// Prefs listener for the position preference.
IntegerPrefMember position_pref_;
+ // Used by screen-saver and full-screen handling support.
+ bool is_user_active_;
+ base::RepeatingTimer<NotificationUIManager> user_state_check_timer_;
+
DISALLOW_COPY_AND_ASSIGN(NotificationUIManager);
};
diff --git a/chrome/browser/ui/gtk/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc
index 9ba091b..d377093 100644
--- a/chrome/browser/ui/gtk/gtk_util.cc
+++ b/chrome/browser/ui/gtk/gtk_util.cc
@@ -548,7 +548,7 @@ bool IsScreenComposited() {
void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
std::vector<XID> stack;
- if (!ui::GetXWindowStack(&stack)) {
+ if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
// Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
// to old school enumeration of all X windows. Some WMs parent 'top-level'
// windows in unnamed actual top-level windows (ion WM), so extend the
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 081a766..cccf05f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1253,6 +1253,10 @@
'browser/first_run/first_run_win.cc',
'browser/first_run/first_run_gtk.cc',
'browser/fonts_languages_window.h',
+ 'browser/fullscreen.h',
+ 'browser/fullscreen_linux.cc',
+ 'browser/fullscreen_mac.mm',
+ 'browser/fullscreen_win.cc',
'browser/gears_integration.cc',
'browser/gears_integration.h',
'browser/geolocation/access_token_store.cc',
@@ -1657,7 +1661,7 @@
'browser/icon_manager_mac.mm',
'browser/icon_manager_win.cc',
'browser/idle_linux.cc',
- 'browser/idle_mac.cc',
+ 'browser/idle_mac.mm',
'browser/idle_win.cc',
'browser/ime_input.cc',
'browser/ime_input.h',
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 2b5863a..fda637c 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -16,7 +16,7 @@
#include <sys/shm.h>
#include <list>
-#include <set>
+#include <vector>
#include "base/command_line.h"
#include "base/logging.h"
@@ -66,6 +66,28 @@ int DefaultX11IOErrorHandler(Display* d) {
_exit(1);
}
+// Note: The caller should free the resulting value data.
+bool GetProperty(XID window, const std::string& property_name, long max_length,
+ Atom* type, int* format, unsigned long* num_items,
+ unsigned char** property) {
+ Atom property_atom = gdk_x11_get_xatom_by_name_for_display(
+ gdk_display_get_default(), property_name.c_str());
+
+ unsigned long remaining_bytes = 0;
+ return XGetWindowProperty(GetXDisplay(),
+ window,
+ property_atom,
+ 0, // offset into property data to read
+ max_length, // max length to get
+ False, // deleted
+ AnyPropertyType,
+ type,
+ format,
+ num_items,
+ &remaining_bytes,
+ property);
+}
+
} // namespace
bool XDisplayExists() {
@@ -221,27 +243,29 @@ bool GetWindowRect(XID window, gfx::Rect* rect) {
return true;
}
-bool GetIntProperty(XID window, const std::string& property_name, int* value) {
- Atom property_atom = gdk_x11_get_xatom_by_name_for_display(
- gdk_display_get_default(), property_name.c_str());
+bool PropertyExists(XID window, const std::string& property_name) {
+ Atom type = None;
+ int format = 0; // size in bits of each item in 'property'
+ long unsigned int num_items = 0;
+ unsigned char* property = NULL;
+
+ int result = GetProperty(window, property_name, 1,
+ &type, &format, &num_items, &property);
+ if (result != Success)
+ return false;
+
+ XFree(property);
+ return num_items > 0;
+}
+bool GetIntProperty(XID window, const std::string& property_name, int* value) {
Atom type = None;
int format = 0; // size in bits of each item in 'property'
- long unsigned int num_items = 0, remaining_bytes = 0;
+ long unsigned int num_items = 0;
unsigned char* property = NULL;
- int result = XGetWindowProperty(GetXDisplay(),
- window,
- property_atom,
- 0, // offset into property data to read
- 1, // max length to get
- False, // deleted
- AnyPropertyType,
- &type,
- &format,
- &num_items,
- &remaining_bytes,
- &property);
+ int result = GetProperty(window, property_name, 1,
+ &type, &format, &num_items, &property);
if (result != Success)
return false;
@@ -258,26 +282,14 @@ bool GetIntProperty(XID window, const std::string& property_name, int* value) {
bool GetIntArrayProperty(XID window,
const std::string& property_name,
std::vector<int>* value) {
- Atom property_atom = gdk_x11_get_xatom_by_name_for_display(
- gdk_display_get_default(), property_name.c_str());
-
Atom type = None;
int format = 0; // size in bits of each item in 'property'
- long unsigned int num_items = 0, remaining_bytes = 0;
+ long unsigned int num_items = 0;
unsigned char* properties = NULL;
- int result = XGetWindowProperty(GetXDisplay(),
- window,
- property_atom,
- 0, // offset into property data to read
- (~0L), // max length to get (all of them)
- False, // deleted
- AnyPropertyType,
- &type,
- &format,
- &num_items,
- &remaining_bytes,
- &properties);
+ int result = GetProperty(window, property_name,
+ (~0L), // (all of them)
+ &type, &format, &num_items, &properties);
if (result != Success)
return false;
@@ -293,28 +305,41 @@ bool GetIntArrayProperty(XID window,
return true;
}
+bool GetAtomArrayProperty(XID window,
+ const std::string& property_name,
+ std::vector<Atom>* value) {
+ Atom type = None;
+ int format = 0; // size in bits of each item in 'property'
+ long unsigned int num_items = 0;
+ unsigned char* properties = NULL;
+
+ int result = GetProperty(window, property_name,
+ (~0L), // (all of them)
+ &type, &format, &num_items, &properties);
+ if (result != Success)
+ return false;
+
+ if (type != XA_ATOM) {
+ XFree(properties);
+ return false;
+ }
+
+ Atom* atom_properties = reinterpret_cast<Atom*>(properties);
+ value->clear();
+ value->insert(value->begin(), atom_properties, atom_properties + num_items);
+ XFree(properties);
+ return true;
+}
+
bool GetStringProperty(
XID window, const std::string& property_name, std::string* value) {
- Atom property_atom = gdk_x11_get_xatom_by_name_for_display(
- gdk_display_get_default(), property_name.c_str());
-
Atom type = None;
int format = 0; // size in bits of each item in 'property'
- long unsigned int num_items = 0, remaining_bytes = 0;
+ long unsigned int num_items = 0;
unsigned char* property = NULL;
- int result = XGetWindowProperty(GetXDisplay(),
- window,
- property_atom,
- 0, // offset into property data to read
- 1024, // max length to get
- False, // deleted
- AnyPropertyType,
- &type,
- &format,
- &num_items,
- &remaining_bytes,
- &property);
+ int result = GetProperty(window, property_name, 1024,
+ &type, &format, &num_items, &property);
if (result != Success)
return false;
@@ -376,16 +401,16 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window,
if (status == 0)
return false;
- std::set<XID> windows;
- for (unsigned int i = 0; i < num_children; i++)
- windows.insert(children[i]);
+ std::vector<XID> windows;
+ for (int i = static_cast<int>(num_children) - 1; i >= 0; i--)
+ windows.push_back(children[i]);
XFree(children);
// XQueryTree returns the children of |window| in bottom-to-top order, so
// reverse-iterate the list to check the windows from top-to-bottom.
- std::set<XID>::reverse_iterator iter;
- for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
+ std::vector<XID>::iterator iter;
+ for (iter = windows.begin(); iter != windows.end(); iter++) {
if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter))
return true;
}
@@ -395,7 +420,7 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window,
// loop because the recursion and call to XQueryTree are expensive and is only
// needed for a small number of cases.
if (++depth <= max_depth) {
- for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
+ for (iter = windows.begin(); iter != windows.end(); iter++) {
if (EnumerateChildren(delegate, *iter, max_depth, depth))
return true;
}
@@ -409,29 +434,20 @@ bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) {
return EnumerateChildren(delegate, root, max_depth, 0);
}
-bool GetXWindowStack(std::vector<XID>* windows) {
+bool GetXWindowStack(Window window, std::vector<XID>* windows) {
windows->clear();
- static Atom atom = XInternAtom(GetXDisplay(),
- "_NET_CLIENT_LIST_STACKING", False);
-
Atom type;
int format;
unsigned long count;
- unsigned long bytes_after;
unsigned char *data = NULL;
- if (XGetWindowProperty(GetXDisplay(),
- GetX11RootWindow(),
- atom,
- 0, // offset
- ~0L, // length
- False, // delete
- AnyPropertyType, // requested type
- &type,
- &format,
- &count,
- &bytes_after,
- &data) != Success) {
+ if (!GetProperty(window,
+ "_NET_CLIENT_LIST_STACKING",
+ ~0L,
+ &type,
+ &format,
+ &count,
+ &data)) {
return false;
}
@@ -439,8 +455,8 @@ bool GetXWindowStack(std::vector<XID>* windows) {
if (type == XA_WINDOW && format == 32 && data && count > 0) {
result = true;
XID* stack = reinterpret_cast<XID*>(data);
- for (unsigned long i = 0; i < count; i++)
- windows->insert(windows->begin(), stack[i]);
+ for (long i = static_cast<long>(count) - 1; i >= 0; i--)
+ windows->push_back(stack[i]);
}
if (data)
@@ -752,6 +768,34 @@ void SetDefaultX11ErrorHandlers() {
SetX11ErrorHandlers(NULL, NULL);
}
+bool IsX11WindowFullScreen(XID window) {
+ // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN.
+ static Atom atom = gdk_x11_get_xatom_by_name_for_display(
+ gdk_display_get_default(), "_NET_WM_STATE_FULLSCREEN");
+
+ std::vector<Atom> atom_properties;
+ if (GetAtomArrayProperty(window,
+ "_NET_WM_STATE",
+ &atom_properties) &&
+ std::find(atom_properties.begin(), atom_properties.end(), atom)
+ != atom_properties.end())
+ return true;
+
+ // As the last resort, check if the window size is as large as the main
+ // screen.
+ GdkRectangle monitor_rect;
+ gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect);
+
+ gfx::Rect window_rect;
+ if (!ui::GetWindowRect(window, &window_rect))
+ return false;
+
+ return monitor_rect.x == window_rect.x() &&
+ monitor_rect.y == window_rect.y() &&
+ monitor_rect.width == window_rect.width() &&
+ monitor_rect.height == window_rect.height();
+}
+
// ----------------------------------------------------------------------------
// These functions are declared in x11_util_internal.h because they require
// XLib.h to be included, and it conflicts with many other headers.
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index 58f9157..3284fcb 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -17,6 +17,7 @@
#include "base/basictypes.h"
+typedef unsigned long Atom;
typedef struct _GdkDrawable GdkWindow;
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkWindow GtkWindow;
@@ -76,11 +77,15 @@ int BitsPerPixelForPixmapDepth(Display* display, int depth);
bool IsWindowVisible(XID window);
// Returns the bounds of |window|.
bool GetWindowRect(XID window, gfx::Rect* rect);
-// Get the value of an int, int array, or string property. On
+// Return true if |window| has any property with |property_name|.
+bool PropertyExists(XID window, const std::string& property_name);
+// Get the value of an int, int array, atom array or string property. On
// success, true is returned and the value is stored in |value|.
bool GetIntProperty(XID window, const std::string& property_name, int* value);
bool GetIntArrayProperty(XID window, const std::string& property_name,
std::vector<int>* value);
+bool GetAtomArrayProperty(XID window, const std::string& property_name,
+ std::vector<Atom>* value);
bool GetStringProperty(
XID window, const std::string& property_name, std::string* value);
@@ -111,8 +116,9 @@ class EnumerateWindowsDelegate {
// windows up to a depth of |max_depth|.
bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth);
-// Returns a list of top-level windows in top-to-bottom stacking order.
-bool GetXWindowStack(std::vector<XID>* windows);
+// Returns all children windows of a given window in top-to-bottom stacking
+// order.
+bool GetXWindowStack(XID window, std::vector<XID>* windows);
// Restack a window in relation to one of its siblings. If |above| is true,
// |window| will be stacked directly above |sibling|; otherwise it will stacked
@@ -178,6 +184,9 @@ bool ChangeWindowDesktop(XID window, XID destination);
// to set your own error handlers.
void SetDefaultX11ErrorHandlers();
+// Return true if a given window is in full-screen mode.
+bool IsX11WindowFullScreen(XID window);
+
} // namespace ui
#endif // UI_BASE_X_X11_UTIL_H_