Bug 1888033 - [Menu Redesign] Add a secret setting and feature flag for the menu...
[gecko.git] / toolkit / xre / nsNativeAppSupportCocoa.mm
blob6f4b96b88d2c4947839ee1eac4439ae529c7726d
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsString.h"
8 #import <CoreServices/CoreServices.h>
9 #import <Cocoa/Cocoa.h>
11 #include "nsCOMPtr.h"
12 #include "nsCocoaFeatures.h"
13 #include "nsNativeAppSupportBase.h"
14 #include "nsServiceManagerUtils.h"
16 #include "nsIBaseWindow.h"
17 #include "nsCommandLine.h"
18 #include "mozIDOMWindow.h"
19 #include "nsIWebNavigation.h"
20 #include "nsIWidget.h"
21 #include "nsIWindowMediator.h"
22 #include "nsPIDOMWindow.h"
23 #include "WidgetUtils.h"
25 // This must be included last:
26 #include "nsObjCExceptions.h"
28 using mozilla::widget::WidgetUtils;
30 nsresult GetNativeWindowPointerFromDOMWindow(mozIDOMWindowProxy* a_window,
31                                              NSWindow** a_nativeWindow) {
32   *a_nativeWindow = nil;
33   if (!a_window) return NS_ERROR_INVALID_ARG;
35   nsPIDOMWindowOuter* win = nsPIDOMWindowOuter::From(a_window);
36   nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(win);
37   if (!widget) {
38     return NS_ERROR_FAILURE;
39   }
41   *a_nativeWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
43   return NS_OK;
46 class nsNativeAppSupportCocoa : public nsNativeAppSupportBase {
47  public:
48   nsNativeAppSupportCocoa() : mCanShowUI(false) {}
50   NS_IMETHOD Start(bool* aRetVal) override;
51   NS_IMETHOD ReOpen() override;
52   NS_IMETHOD Enable() override;
54  private:
55   bool mCanShowUI;
58 NS_IMETHODIMP
59 nsNativeAppSupportCocoa::Enable() {
60   mCanShowUI = true;
61   return NS_OK;
64 NS_IMETHODIMP nsNativeAppSupportCocoa::Start(bool* _retval) {
65   int major, minor, bugfix;
66   nsCocoaFeatures::GetSystemVersion(major, minor, bugfix);
68   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
70   // Check that the OS version is supported, if not return false,
71   // which will make the browser quit.  In principle we could display an
72   // alert here.  But the alert's message and buttons would require custom
73   // localization.  So (for now at least) we just log an English message
74   // to the console before quitting.
75   if (major < 10 || (major == 10 && minor < 12)) {
76     NSLog(@"Minimum OS version requirement not met!");
77     return NS_OK;
78   }
80   *_retval = true;
82   return NS_OK;
84   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
87 NS_IMETHODIMP
88 nsNativeAppSupportCocoa::ReOpen() {
89   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
91   if (!mCanShowUI) return NS_ERROR_FAILURE;
93   bool haveNonMiniaturized = false;
94   bool haveOpenWindows = false;
95   bool done = false;
97   nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
98   if (!wm) {
99     return NS_ERROR_FAILURE;
100   } else {
101     nsCOMPtr<nsISimpleEnumerator> windowList;
102     wm->GetAppWindowEnumerator(nullptr, getter_AddRefs(windowList));
103     bool more;
104     windowList->HasMoreElements(&more);
105     while (more) {
106       nsCOMPtr<nsISupports> nextWindow = nullptr;
107       windowList->GetNext(getter_AddRefs(nextWindow));
108       nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(nextWindow));
109       if (!baseWindow) {
110         windowList->HasMoreElements(&more);
111         continue;
112       } else {
113         haveOpenWindows = true;
114       }
116       nsCOMPtr<nsIWidget> widget = nullptr;
117       baseWindow->GetMainWidget(getter_AddRefs(widget));
118       if (!widget || !widget->IsVisible()) {
119         windowList->HasMoreElements(&more);
120         continue;
121       }
122       NSWindow* cocoaWindow =
123           (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
124       if (![cocoaWindow isMiniaturized]) {
125         haveNonMiniaturized = true;
126         break;  // have un-minimized windows, nothing to do
127       }
128       windowList->HasMoreElements(&more);
129     }  // end while
131     if (!haveNonMiniaturized) {
132       // Prioritize browser windows for deminiaturization
133       nsCOMPtr<mozIDOMWindowProxy> mru;
134       wm->GetMostRecentBrowserWindow(getter_AddRefs(mru));
136       // Failing that, deminiaturize the most recently used window
137       if (!mru) {
138         wm->GetMostRecentWindow(nullptr, getter_AddRefs(mru));
139       }
141       if (mru) {
142         NSWindow* cocoaMru = nil;
143         GetNativeWindowPointerFromDOMWindow(mru, &cocoaMru);
144         if (cocoaMru) {
145           [cocoaMru deminiaturize:nil];
146           done = true;
147         }
148       }
149     }  // end if have non miniaturized
151     if (!haveOpenWindows && !done) {
152       char* argv[] = {nullptr};
154       // use an empty command line to make the right kind(s) of window open
155       nsCOMPtr<nsICommandLineRunner> cmdLine(new nsCommandLine());
157       nsresult rv;
158       rv = cmdLine->Init(0, argv, nullptr,
159                          nsICommandLine::STATE_REMOTE_EXPLICIT);
160       NS_ENSURE_SUCCESS(rv, rv);
162       return cmdLine->Run();
163     }
165   }  // got window mediator
166   return NS_OK;
168   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
171 #pragma mark -
173 // Create and return an instance of class nsNativeAppSupportCocoa.
174 nsresult NS_CreateNativeAppSupport(nsINativeAppSupport** aResult) {
175   *aResult = new nsNativeAppSupportCocoa;
176   if (!*aResult) return NS_ERROR_OUT_OF_MEMORY;
178   NS_ADDREF(*aResult);
179   return NS_OK;