Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(580)

Side by Side Diff: chrome/browser/ui/cocoa/panels/panel_cocoa.mm

Issue 2263863002: Remove implementation of Panels on OSes other than ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR feedback Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "chrome/browser/ui/cocoa/panels/panel_cocoa.h"
6
7 #include "base/logging.h"
8 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
9 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h"
10 #import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h"
11 #import "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h"
12 #include "chrome/browser/ui/panels/panel.h"
13 #include "chrome/browser/ui/panels/stacked_panel_collection.h"
14 #include "content/public/browser/native_web_keyboard_event.h"
15
16 using content::NativeWebKeyboardEvent;
17 using content::WebContents;
18
19 // This creates a shim window class, which in turn creates a Cocoa window
20 // controller which in turn creates actual NSWindow by loading a nib.
21 // Overall chain of ownership is:
22 // PanelWindowControllerCocoa -> PanelCocoa -> Panel.
23 // static
24 NativePanel* Panel::CreateNativePanel(Panel* panel,
25 const gfx::Rect& bounds,
26 bool always_on_top) {
27 return new PanelCocoa(panel, bounds, always_on_top);
28 }
29
30 PanelCocoa::PanelCocoa(Panel* panel,
31 const gfx::Rect& bounds,
32 bool always_on_top)
33 : panel_(panel),
34 bounds_(bounds),
35 always_on_top_(always_on_top),
36 is_shown_(false),
37 attention_request_id_(0),
38 corner_style_(panel::ALL_ROUNDED) {
39 controller_ = [[PanelWindowControllerCocoa alloc] initWithPanel:this];
40 }
41
42 PanelCocoa::~PanelCocoa() {
43 }
44
45 bool PanelCocoa::IsClosed() const {
46 return !controller_;
47 }
48
49 void PanelCocoa::ShowPanel() {
50 ShowPanelInactive();
51 ActivatePanel();
52
53 // |-makeKeyAndOrderFront:| won't send |-windowDidBecomeKey:| until we
54 // return to the runloop. This causes extension tests that wait for the
55 // active status change notification to fail, so we send an active status
56 // notification here.
57 panel_->OnActiveStateChanged(true);
58 }
59
60 void PanelCocoa::ShowPanelInactive() {
61 if (IsClosed())
62 return;
63
64 // This method may be called several times, meaning 'ensure it's shown'.
65 // Animations don't look good when repeated - hence this flag is needed.
66 if (is_shown_) {
67 return;
68 }
69 // A call to SetPanelBounds() before showing it is required to set
70 // the panel frame properly.
71 SetPanelBoundsInstantly(bounds_);
72 is_shown_ = true;
73
74 NSRect finalFrame = cocoa_utils::ConvertRectToCocoaCoordinates(bounds_);
75 [controller_ revealAnimatedWithFrame:finalFrame];
76 }
77
78 gfx::Rect PanelCocoa::GetPanelBounds() const {
79 return bounds_;
80 }
81
82 // |bounds| is the platform-independent screen coordinates, with (0,0) at
83 // top-left of the primary screen.
84 void PanelCocoa::SetPanelBounds(const gfx::Rect& bounds) {
85 setBoundsInternal(bounds, true);
86 }
87
88 void PanelCocoa::SetPanelBoundsInstantly(const gfx::Rect& bounds) {
89 setBoundsInternal(bounds, false);
90 }
91
92 void PanelCocoa::setBoundsInternal(const gfx::Rect& bounds, bool animate) {
93 // We will call SetPanelBoundsInstantly() once before showing the panel
94 // and it should set the panel frame correctly.
95 if (bounds_ == bounds && is_shown_)
96 return;
97
98 bounds_ = bounds;
99
100 // Safely ignore calls to animate bounds before the panel is shown to
101 // prevent the window from loading prematurely.
102 if (animate && !is_shown_)
103 return;
104
105 NSRect frame = cocoa_utils::ConvertRectToCocoaCoordinates(bounds);
106 [controller_ setPanelFrame:frame animate:animate];
107 }
108
109 void PanelCocoa::ClosePanel() {
110 if (IsClosed())
111 return;
112
113 NSWindow* window = [controller_ window];
114 // performClose: contains a nested message loop which can cause reentrancy
115 // if the browser is terminating and closing all the windows.
116 // Use this version that corresponds to protocol of performClose: but does not
117 // spin a nested loop.
118 // TODO(dimich): refactor similar method from BWC and reuse here.
119 if ([controller_ windowShouldClose:window]) {
120 // Make sure that the panel window is not associated with the underlying
121 // stack window because otherwise hiding the panel window could cause all
122 // other panel windows in the same stack to disappear.
123 NSWindow* stackWindow = [window parentWindow];
124 if (stackWindow)
125 [stackWindow removeChildWindow:window];
126
127 [window orderOut:nil];
128 [window close];
129 }
130 }
131
132 void PanelCocoa::ActivatePanel() {
133 if (!is_shown_)
134 return;
135
136 [controller_ activate];
137 }
138
139 void PanelCocoa::DeactivatePanel() {
140 [controller_ deactivate];
141 }
142
143 bool PanelCocoa::IsPanelActive() const {
144 // TODO(dcheng): It seems like a lot of these methods can be called before
145 // our NSWindow is created. Do we really need to check in every one of these
146 // methods if the NSWindow is created, or is there a better way to
147 // gracefully handle this?
148 if (!is_shown_)
149 return false;
150 return [[controller_ window] isMainWindow];
151 }
152
153 void PanelCocoa::PreventActivationByOS(bool prevent_activation) {
154 [controller_ preventBecomingKeyWindow:prevent_activation];
155 return;
156 }
157
158 gfx::NativeWindow PanelCocoa::GetNativePanelWindow() {
159 return [controller_ window];
160 }
161
162 void PanelCocoa::UpdatePanelTitleBar() {
163 if (!is_shown_)
164 return;
165 [controller_ updateTitleBar];
166 }
167
168 void PanelCocoa::UpdatePanelLoadingAnimations(bool should_animate) {
169 [controller_ updateThrobber:should_animate];
170 }
171
172 void PanelCocoa::PanelCut() {
173 // Nothing to do since we do not have panel-specific system menu on Mac.
174 }
175
176 void PanelCocoa::PanelCopy() {
177 // Nothing to do since we do not have panel-specific system menu on Mac.
178 }
179
180 void PanelCocoa::PanelPaste() {
181 // Nothing to do since we do not have panel-specific system menu on Mac.
182 }
183
184 void PanelCocoa::DrawAttention(bool draw_attention) {
185 DCHECK((panel_->attention_mode() & Panel::USE_PANEL_ATTENTION) != 0);
186
187 PanelTitlebarViewCocoa* titlebar = [controller_ titlebarView];
188 if (draw_attention)
189 [titlebar drawAttention];
190 else
191 [titlebar stopDrawingAttention];
192
193 if ((panel_->attention_mode() & Panel::USE_SYSTEM_ATTENTION) != 0) {
194 if (draw_attention) {
195 DCHECK(!attention_request_id_);
196 attention_request_id_ = [NSApp requestUserAttention:NSCriticalRequest];
197 } else {
198 [NSApp cancelUserAttentionRequest:attention_request_id_];
199 attention_request_id_ = 0;
200 }
201 }
202 }
203
204 bool PanelCocoa::IsDrawingAttention() const {
205 PanelTitlebarViewCocoa* titlebar = [controller_ titlebarView];
206 return [titlebar isDrawingAttention];
207 }
208
209 void PanelCocoa::HandlePanelKeyboardEvent(
210 const NativeWebKeyboardEvent& event) {
211 if (event.skip_in_browser || event.type == NativeWebKeyboardEvent::Char)
212 return;
213
214 ChromeEventProcessingWindow* event_window =
215 static_cast<ChromeEventProcessingWindow*>([controller_ window]);
216 DCHECK([event_window isKindOfClass:[ChromeEventProcessingWindow class]]);
217 [event_window redispatchKeyEvent:event.os_event];
218 }
219
220 void PanelCocoa::FullScreenModeChanged(bool is_full_screen) {
221 if (!is_shown_) {
222 // If the panel window is not shown due to that a Chrome tab window is in
223 // fullscreen mode when the panel is being created, we need to show the
224 // panel window now. In addition, its titlebar needs to be updated since it
225 // is not done at the panel creation time.
226 if (!is_full_screen) {
227 ShowPanelInactive();
228 UpdatePanelTitleBar();
229 }
230
231 // No need to proceed when the panel window was not shown previously.
232 // We either show the panel window or do not show it depending on current
233 // full screen state.
234 return;
235 }
236 [controller_ fullScreenModeChanged:is_full_screen];
237 }
238
239 bool PanelCocoa::IsPanelAlwaysOnTop() const {
240 return always_on_top_;
241 }
242
243 void PanelCocoa::SetPanelAlwaysOnTop(bool on_top) {
244 if (always_on_top_ == on_top)
245 return;
246 always_on_top_ = on_top;
247 [controller_ updateWindowLevel];
248 [controller_ updateWindowCollectionBehavior];
249 }
250
251 void PanelCocoa::UpdatePanelMinimizeRestoreButtonVisibility() {
252 [controller_ updateTitleBarMinimizeRestoreButtonVisibility];
253 }
254
255 void PanelCocoa::SetWindowCornerStyle(panel::CornerStyle corner_style) {
256 corner_style_ = corner_style;
257
258 // TODO(dimich): investigate how to support it on Mac.
259 }
260
261 void PanelCocoa::MinimizePanelBySystem() {
262 [controller_ miniaturize];
263 }
264
265 bool PanelCocoa::IsPanelMinimizedBySystem() const {
266 return [controller_ isMiniaturized];
267 }
268
269 bool PanelCocoa::IsPanelShownOnActiveDesktop() const {
270 return [[controller_ window] isOnActiveSpace];
271 }
272
273 void PanelCocoa::ShowShadow(bool show) {
274 [controller_ showShadow:show];
275 }
276
277 void PanelCocoa::PanelExpansionStateChanging(
278 Panel::ExpansionState old_state, Panel::ExpansionState new_state) {
279 [controller_ updateWindowLevel:(new_state != Panel::EXPANDED)];
280 }
281
282 void PanelCocoa::AttachWebContents(content::WebContents* contents) {
283 [controller_ webContentsInserted:contents];
284 }
285
286 void PanelCocoa::DetachWebContents(content::WebContents* contents) {
287 [controller_ webContentsDetached:contents];
288 }
289
290 gfx::Size PanelCocoa::WindowSizeFromContentSize(
291 const gfx::Size& content_size) const {
292 NSRect content = NSMakeRect(0, 0,
293 content_size.width(), content_size.height());
294 NSRect frame = [controller_ frameRectForContentRect:content];
295 return gfx::Size(NSWidth(frame), NSHeight(frame));
296 }
297
298 gfx::Size PanelCocoa::ContentSizeFromWindowSize(
299 const gfx::Size& window_size) const {
300 NSRect frame = NSMakeRect(0, 0, window_size.width(), window_size.height());
301 NSRect content = [controller_ contentRectForFrameRect:frame];
302 return gfx::Size(NSWidth(content), NSHeight(content));
303 }
304
305 int PanelCocoa::TitleOnlyHeight() const {
306 return [controller_ titlebarHeightInScreenCoordinates];
307 }
308
309 Panel* PanelCocoa::panel() const {
310 return panel_.get();
311 }
312
313 void PanelCocoa::DidCloseNativeWindow() {
314 DCHECK(!IsClosed());
315 controller_ = NULL;
316 panel_->OnNativePanelClosed();
317 }
318
319 // NativePanelTesting implementation.
320 class CocoaNativePanelTesting : public NativePanelTesting {
321 public:
322 CocoaNativePanelTesting(NativePanel* native_panel);
323 ~CocoaNativePanelTesting() override {}
324 // Overridden from NativePanelTesting
325 void PressLeftMouseButtonTitlebar(const gfx::Point& mouse_location,
326 panel::ClickModifier modifier) override;
327 void ReleaseMouseButtonTitlebar(panel::ClickModifier modifier) override;
328 void DragTitlebar(const gfx::Point& mouse_location) override;
329 void CancelDragTitlebar() override;
330 void FinishDragTitlebar() override;
331 bool VerifyDrawingAttention() const override;
332 bool VerifyActiveState(bool is_active) override;
333 bool VerifyAppIcon() const override;
334 bool VerifySystemMinimizeState() const override;
335 bool IsWindowVisible() const override;
336 bool IsWindowSizeKnown() const override;
337 bool IsAnimatingBounds() const override;
338 bool IsButtonVisible(panel::TitlebarButtonType button_type) const override;
339 panel::CornerStyle GetWindowCornerStyle() const override;
340 bool EnsureApplicationRunOnForeground() override;
341
342 private:
343 PanelTitlebarViewCocoa* titlebar() const;
344 // Weak, assumed always to outlive this test API object.
345 PanelCocoa* native_panel_window_;
346 };
347
348 NativePanelTesting* PanelCocoa::CreateNativePanelTesting() {
349 return new CocoaNativePanelTesting(this);
350 }
351
352 CocoaNativePanelTesting::CocoaNativePanelTesting(NativePanel* native_panel)
353 : native_panel_window_(static_cast<PanelCocoa*>(native_panel)) {
354 }
355
356 PanelTitlebarViewCocoa* CocoaNativePanelTesting::titlebar() const {
357 return [native_panel_window_->controller_ titlebarView];
358 }
359
360 void CocoaNativePanelTesting::PressLeftMouseButtonTitlebar(
361 const gfx::Point& mouse_location, panel::ClickModifier modifier) {
362 // Convert from platform-indepedent screen coordinates to Cocoa's screen
363 // coordinates because PanelTitlebarViewCocoa method takes Cocoa's screen
364 // coordinates.
365 int modifierFlags =
366 (modifier == panel::APPLY_TO_ALL ? NSShiftKeyMask : 0);
367 [titlebar() pressLeftMouseButtonTitlebar:
368 cocoa_utils::ConvertPointToCocoaCoordinates(mouse_location)
369 modifiers:modifierFlags];
370 }
371
372 void CocoaNativePanelTesting::ReleaseMouseButtonTitlebar(
373 panel::ClickModifier modifier) {
374 int modifierFlags =
375 (modifier == panel::APPLY_TO_ALL ? NSShiftKeyMask : 0);
376 [titlebar() releaseLeftMouseButtonTitlebar:modifierFlags];
377 }
378
379 void CocoaNativePanelTesting::DragTitlebar(const gfx::Point& mouse_location) {
380 // Convert from platform-indepedent screen coordinates to Cocoa's screen
381 // coordinates because PanelTitlebarViewCocoa method takes Cocoa's screen
382 // coordinates.
383 [titlebar() dragTitlebar:
384 cocoa_utils::ConvertPointToCocoaCoordinates(mouse_location)];
385 }
386
387 void CocoaNativePanelTesting::CancelDragTitlebar() {
388 [titlebar() cancelDragTitlebar];
389 }
390
391 void CocoaNativePanelTesting::FinishDragTitlebar() {
392 [titlebar() finishDragTitlebar];
393 }
394
395 bool CocoaNativePanelTesting::VerifyDrawingAttention() const {
396 return [titlebar() isDrawingAttention];
397 }
398
399 bool CocoaNativePanelTesting::VerifyActiveState(bool is_active) {
400 // TODO(jianli): to be implemented.
401 return false;
402 }
403
404 bool CocoaNativePanelTesting::VerifyAppIcon() const {
405 // Nothing to do since panel does not show dock icon.
406 return true;
407 }
408
409 bool CocoaNativePanelTesting::VerifySystemMinimizeState() const {
410 // TODO(jianli): to be implemented.
411 return true;
412 }
413
414 bool CocoaNativePanelTesting::IsWindowVisible() const {
415 return [[native_panel_window_->controller_ window] isVisible];
416 }
417
418 bool CocoaNativePanelTesting::IsWindowSizeKnown() const {
419 return true;
420 }
421
422 bool CocoaNativePanelTesting::IsAnimatingBounds() const {
423 if ([native_panel_window_->controller_ isAnimatingBounds])
424 return true;
425 StackedPanelCollection* stack = native_panel_window_->panel()->stack();
426 if (!stack)
427 return false;
428 return stack->IsAnimatingPanelBounds(native_panel_window_->panel());
429 }
430
431 bool CocoaNativePanelTesting::IsButtonVisible(
432 panel::TitlebarButtonType button_type) const {
433 switch (button_type) {
434 case panel::CLOSE_BUTTON:
435 return ![[titlebar() closeButton] isHidden];
436 case panel::MINIMIZE_BUTTON:
437 return ![[titlebar() minimizeButton] isHidden];
438 case panel::RESTORE_BUTTON:
439 return ![[titlebar() restoreButton] isHidden];
440 default:
441 NOTREACHED();
442 }
443 return false;
444 }
445
446 panel::CornerStyle CocoaNativePanelTesting::GetWindowCornerStyle() const {
447 return native_panel_window_->corner_style_;
448 }
449
450 bool CocoaNativePanelTesting::EnsureApplicationRunOnForeground() {
451 if ([NSApp isActive])
452 return true;
453 [NSApp activateIgnoringOtherApps:YES];
454 return [NSApp isActive];
455 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/panels/panel_cocoa.h ('k') | chrome/browser/ui/cocoa/panels/panel_cocoa_browsertest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698