- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / panels / display_settings_provider_cocoa.mm
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/mac/mac_util.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #import "chrome/browser/app_controller_mac.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/fullscreen.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
15 #include "chrome/browser/ui/panels/display_settings_provider.h"
16 #include "content/public/browser/notification_observer.h"
17 #include "content/public/browser/notification_registrar.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h"
20 #include "ui/base/work_area_watcher_observer.h"
21
22 namespace {
23
24 // The time, in milliseconds, that a fullscreen check will be started after
25 // the active workspace change is notified. This value is from experiment.
26 const int kCheckFullScreenDelayTimeMs = 200;
27
28 class DisplaySettingsProviderCocoa : public DisplaySettingsProvider,
29                                      public ui::WorkAreaWatcherObserver,
30                                      public content::NotificationObserver {
31  public:
32   DisplaySettingsProviderCocoa();
33   virtual ~DisplaySettingsProviderCocoa();
34
35   void ActiveSpaceChanged();
36
37  protected:
38   // Overridden from DisplaySettingsProvider:
39   virtual bool NeedsPeriodicFullScreenCheck() const OVERRIDE;
40   virtual bool IsFullScreen() OVERRIDE;
41
42   // Overridden from ui::WorkAreaWatcherObserver:
43   virtual void WorkAreaChanged() OVERRIDE;
44
45   // Overridden from content::NotificationObserver:
46   virtual void Observe(int type,
47                        const content::NotificationSource& source,
48                        const content::NotificationDetails& details) OVERRIDE;
49
50  private:
51   void ActiveWorkSpaceChanged();
52
53   content::NotificationRegistrar registrar_;
54   id active_space_change_;
55
56   // Owned by MessageLoop after posting.
57   base::WeakPtrFactory<DisplaySettingsProviderCocoa> weak_factory_;
58
59   DISALLOW_COPY_AND_ASSIGN(DisplaySettingsProviderCocoa);
60 };
61
62 DisplaySettingsProviderCocoa::DisplaySettingsProviderCocoa()
63     : active_space_change_(nil),
64       weak_factory_(this) {
65   AppController* appController = static_cast<AppController*>([NSApp delegate]);
66   [appController addObserverForWorkAreaChange:this];
67
68   registrar_.Add(
69       this,
70       chrome::NOTIFICATION_FULLSCREEN_CHANGED,
71       content::NotificationService::AllSources());
72
73   active_space_change_ = [[[NSWorkspace sharedWorkspace] notificationCenter]
74       addObserverForName:NSWorkspaceActiveSpaceDidChangeNotification
75                   object:nil
76                    queue:[NSOperationQueue mainQueue]
77               usingBlock:^(NSNotification* notification) {
78                   ActiveWorkSpaceChanged();
79               }];
80 }
81
82 DisplaySettingsProviderCocoa::~DisplaySettingsProviderCocoa() {
83   AppController* appController = static_cast<AppController*>([NSApp delegate]);
84   [appController removeObserverForWorkAreaChange:this];
85
86   [[[NSWorkspace sharedWorkspace] notificationCenter]
87       removeObserver:active_space_change_];
88 }
89
90 bool DisplaySettingsProviderCocoa::NeedsPeriodicFullScreenCheck() const {
91   // Lion system introduces fullscreen support. When a window of an application
92   // enters fullscreen mode, the system will automatically hide all other
93   // windows, even including topmost windows that come from other applications.
94   // So we don't need to do anything when any other application enters
95   // fullscreen mode. We still need to handle the case when chrome enters
96   // fullscreen mode and our topmost windows will not get hided by the system.
97   return !chrome::mac::SupportsSystemFullscreen();
98 }
99
100 bool DisplaySettingsProviderCocoa::IsFullScreen() {
101   // For Lion and later, we only need to check if chrome enters fullscreen mode
102   // (see detailed reason above in NeedsPeriodicFullScreenCheck).
103   if (!chrome::mac::SupportsSystemFullscreen())
104     return DisplaySettingsProvider::IsFullScreen();
105
106   Browser* browser = chrome::GetLastActiveBrowser();
107   if (!browser)
108     return false;
109   BrowserWindow* browser_window = browser->window();
110   if (!browser_window->IsFullscreen())
111     return false;
112
113   // If the user switches to another space where the fullscreen browser window
114   // does not live, we do not call it fullscreen.
115   NSWindow* native_window = browser_window->GetNativeWindow();
116   return [native_window isOnActiveSpace];
117 }
118
119 void DisplaySettingsProviderCocoa::WorkAreaChanged() {
120   OnDisplaySettingsChanged();
121 }
122
123 void DisplaySettingsProviderCocoa::Observe(
124     int type,
125     const content::NotificationSource& source,
126     const content::NotificationDetails& details) {
127   DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
128   // When we receive the fullscreen notification, the Chrome Window has not been
129   // put on the active space yet and thus IsFullScreen will return false.
130   // Since the fullscreen result is already known here, we can pass it dierctly
131   // to CheckFullScreenMode.
132   bool is_fullscreen = *(content::Details<bool>(details)).ptr();
133   CheckFullScreenMode(
134       is_fullscreen ? ASSUME_FULLSCREEN_ON : ASSUME_FULLSCREEN_OFF);
135 }
136
137 void DisplaySettingsProviderCocoa::ActiveWorkSpaceChanged() {
138   // The active workspace notification might be received earlier than the
139   // browser window knows that it is not in active space.
140   base::MessageLoop::current()->PostDelayedTask(
141       FROM_HERE,
142       base::Bind(&DisplaySettingsProviderCocoa::CheckFullScreenMode,
143                  weak_factory_.GetWeakPtr(),
144                  PERFORM_FULLSCREEN_CHECK),
145       base::TimeDelta::FromMilliseconds(kCheckFullScreenDelayTimeMs));
146 }
147
148 }  // namespace
149
150 // static
151 DisplaySettingsProvider* DisplaySettingsProvider::Create() {
152   return new DisplaySettingsProviderCocoa();
153 }