|
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/. */ |
|
5 |
|
6 #include "nsString.h" |
|
7 |
|
8 #import <CoreServices/CoreServices.h> |
|
9 #import <Cocoa/Cocoa.h> |
|
10 |
|
11 #include "nsCOMPtr.h" |
|
12 #include "nsNativeAppSupportBase.h" |
|
13 |
|
14 #include "nsIAppShellService.h" |
|
15 #include "nsIAppStartup.h" |
|
16 #include "nsIBaseWindow.h" |
|
17 #include "nsICommandLineRunner.h" |
|
18 #include "nsIDOMWindow.h" |
|
19 #include "nsIDocShellTreeItem.h" |
|
20 #include "nsIDocShellTreeOwner.h" |
|
21 #include "nsIInterfaceRequestorUtils.h" |
|
22 #include "nsIObserver.h" |
|
23 #include "nsIServiceManager.h" |
|
24 #include "nsIWebNavigation.h" |
|
25 #include "nsIWidget.h" |
|
26 #include "nsIWindowMediator.h" |
|
27 |
|
28 // This must be included last: |
|
29 #include "nsObjCExceptions.h" |
|
30 |
|
31 nsresult |
|
32 GetNativeWindowPointerFromDOMWindow(nsIDOMWindow *a_window, NSWindow **a_nativeWindow) |
|
33 { |
|
34 *a_nativeWindow = nil; |
|
35 if (!a_window) |
|
36 return NS_ERROR_INVALID_ARG; |
|
37 |
|
38 nsCOMPtr<nsIWebNavigation> mruWebNav(do_GetInterface(a_window)); |
|
39 if (mruWebNav) { |
|
40 nsCOMPtr<nsIDocShellTreeItem> mruTreeItem(do_QueryInterface(mruWebNav)); |
|
41 nsCOMPtr<nsIDocShellTreeOwner> mruTreeOwner = nullptr; |
|
42 mruTreeItem->GetTreeOwner(getter_AddRefs(mruTreeOwner)); |
|
43 if(mruTreeOwner) { |
|
44 nsCOMPtr<nsIBaseWindow> mruBaseWindow(do_QueryInterface(mruTreeOwner)); |
|
45 if (mruBaseWindow) { |
|
46 nsCOMPtr<nsIWidget> mruWidget = nullptr; |
|
47 mruBaseWindow->GetMainWidget(getter_AddRefs(mruWidget)); |
|
48 if (mruWidget) { |
|
49 *a_nativeWindow = (NSWindow*)mruWidget->GetNativeData(NS_NATIVE_WINDOW); |
|
50 } |
|
51 } |
|
52 } |
|
53 } |
|
54 |
|
55 return NS_OK; |
|
56 } |
|
57 |
|
58 class nsNativeAppSupportCocoa : public nsNativeAppSupportBase |
|
59 { |
|
60 public: |
|
61 nsNativeAppSupportCocoa() : |
|
62 mCanShowUI(false) { } |
|
63 |
|
64 NS_IMETHOD Start(bool* aRetVal); |
|
65 NS_IMETHOD ReOpen(); |
|
66 NS_IMETHOD Enable(); |
|
67 |
|
68 private: |
|
69 bool mCanShowUI; |
|
70 }; |
|
71 |
|
72 NS_IMETHODIMP |
|
73 nsNativeAppSupportCocoa::Enable() |
|
74 { |
|
75 mCanShowUI = true; |
|
76 return NS_OK; |
|
77 } |
|
78 |
|
79 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060 |
|
80 |
|
81 NS_IMETHODIMP nsNativeAppSupportCocoa::Start(bool *_retval) |
|
82 { |
|
83 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; |
|
84 |
|
85 SInt32 response = 0; |
|
86 OSErr err = ::Gestalt (gestaltSystemVersion, &response); |
|
87 response &= 0xFFFF; // The system version is in the low order word |
|
88 |
|
89 // Check that the OS version is supported, if not return false, |
|
90 // which will make the browser quit. In principle we could display an |
|
91 // alert here. But the alert's message and buttons would require custom |
|
92 // localization. So (for now at least) we just log an English message |
|
93 // to the console before quitting. |
|
94 if ((err != noErr) || response < MAC_OS_X_VERSION_10_6_HEX) { |
|
95 NSLog(@"Minimum OS version requirement not met!"); |
|
96 return NS_OK; |
|
97 } |
|
98 |
|
99 *_retval = true; |
|
100 return NS_OK; |
|
101 |
|
102 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; |
|
103 } |
|
104 |
|
105 NS_IMETHODIMP |
|
106 nsNativeAppSupportCocoa::ReOpen() |
|
107 { |
|
108 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; |
|
109 |
|
110 if (!mCanShowUI) |
|
111 return NS_ERROR_FAILURE; |
|
112 |
|
113 bool haveNonMiniaturized = false; |
|
114 bool haveOpenWindows = false; |
|
115 bool done = false; |
|
116 |
|
117 nsCOMPtr<nsIWindowMediator> |
|
118 wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); |
|
119 if (!wm) { |
|
120 return NS_ERROR_FAILURE; |
|
121 } |
|
122 else { |
|
123 nsCOMPtr<nsISimpleEnumerator> windowList; |
|
124 wm->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList)); |
|
125 bool more; |
|
126 windowList->HasMoreElements(&more); |
|
127 while (more) { |
|
128 nsCOMPtr<nsISupports> nextWindow = nullptr; |
|
129 windowList->GetNext(getter_AddRefs(nextWindow)); |
|
130 nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(nextWindow)); |
|
131 if (!baseWindow) { |
|
132 windowList->HasMoreElements(&more); |
|
133 continue; |
|
134 } |
|
135 else { |
|
136 haveOpenWindows = true; |
|
137 } |
|
138 |
|
139 nsCOMPtr<nsIWidget> widget = nullptr; |
|
140 baseWindow->GetMainWidget(getter_AddRefs(widget)); |
|
141 if (!widget) { |
|
142 windowList->HasMoreElements(&more); |
|
143 continue; |
|
144 } |
|
145 NSWindow *cocoaWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); |
|
146 if (![cocoaWindow isMiniaturized]) { |
|
147 haveNonMiniaturized = true; |
|
148 break; //have un-minimized windows, nothing to do |
|
149 } |
|
150 windowList->HasMoreElements(&more); |
|
151 } // end while |
|
152 |
|
153 if (!haveNonMiniaturized) { |
|
154 // Deminiaturize the most recenty used window |
|
155 nsCOMPtr<nsIDOMWindow> mru; |
|
156 wm->GetMostRecentWindow(nullptr, getter_AddRefs(mru)); |
|
157 |
|
158 if (mru) { |
|
159 NSWindow *cocoaMru = nil; |
|
160 GetNativeWindowPointerFromDOMWindow(mru, &cocoaMru); |
|
161 if (cocoaMru) { |
|
162 [cocoaMru deminiaturize:nil]; |
|
163 done = true; |
|
164 } |
|
165 } |
|
166 |
|
167 } // end if have non miniaturized |
|
168 |
|
169 if (!haveOpenWindows && !done) { |
|
170 char* argv[] = { nullptr }; |
|
171 |
|
172 // use an empty command line to make the right kind(s) of window open |
|
173 nsCOMPtr<nsICommandLineRunner> cmdLine |
|
174 (do_CreateInstance("@mozilla.org/toolkit/command-line;1")); |
|
175 NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE); |
|
176 |
|
177 nsresult rv; |
|
178 rv = cmdLine->Init(0, argv, nullptr, |
|
179 nsICommandLine::STATE_REMOTE_EXPLICIT); |
|
180 NS_ENSURE_SUCCESS(rv, rv); |
|
181 |
|
182 return cmdLine->Run(); |
|
183 } |
|
184 |
|
185 } // got window mediator |
|
186 return NS_OK; |
|
187 |
|
188 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; |
|
189 } |
|
190 |
|
191 #pragma mark - |
|
192 |
|
193 // Create and return an instance of class nsNativeAppSupportCocoa. |
|
194 nsresult NS_CreateNativeAppSupport(nsINativeAppSupport**aResult) |
|
195 { |
|
196 *aResult = new nsNativeAppSupportCocoa; |
|
197 if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; |
|
198 |
|
199 NS_ADDREF(*aResult); |
|
200 return NS_OK; |
|
201 } |