- add sources.
[platform/framework/web/crosswalk.git] / src / ui / base / cocoa / focus_window_set.mm
1 // Copyright 2013 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 #import <Cocoa/Cocoa.h>
6
7 #include "ui/base/cocoa/focus_window_set.h"
8
9 namespace ui {
10
11 // This attempts to match OS X's native behavior, namely that a window
12 // is only ever deminiaturized if ALL windows on ALL workspaces are
13 // miniaturized. (This callback runs before AppKit picks its own
14 // window to deminiaturize, so we get to pick one from the right set.)
15 //
16 // In addition, limit to the windows on the current
17 // workspace. Otherwise we jump spaces haphazardly.
18 //
19 // NOTE: If this is called in the
20 // applicationShouldHandleReopen:hasVisibleWindows: hook when clicking
21 // the dock icon, and that caused OS X to begin switch spaces,
22 // isOnActiveSpace gives the answer for the PREVIOUS space. This means
23 // that we actually raise and focus the wrong space's windows, leaving
24 // the new key window off-screen. To detect this, check if the key
25 // window prior to calling is on an active space.
26 //
27 // Also, if we decide to deminiaturize a window during a space switch,
28 // that can switch spaces and then switch back. Fortunately, this only
29 // happens if, say, space 1 contains an app, space 2 contains a
30 // miniaturized browser. We click the icon, OS X switches to space 1,
31 // we deminiaturize the browser, and that triggers switching back.
32 //
33 // TODO(davidben): To limit those cases, consider preferentially
34 // deminiaturizing a window on the current space.
35 void FocusWindowSet(const std::set<NSWindow*>& windows,
36                     bool allow_workspace_switch) {
37   NSArray* ordered_windows = [NSApp orderedWindows];
38   NSWindow* frontmost_window = nil;
39   NSWindow* frontmost_window_all_spaces = nil;
40   NSWindow* frontmost_miniaturized_window = nil;
41   bool all_miniaturized = true;
42   for (int i = [ordered_windows count] - 1; i >= 0; i--) {
43     NSWindow* win = [ordered_windows objectAtIndex:i];
44     if (windows.find(win) != windows.end()) {
45       if ([win isMiniaturized]) {
46         frontmost_miniaturized_window = win;
47       } else if ([win isVisible]) {
48         all_miniaturized = false;
49         frontmost_window_all_spaces = win;
50         if ([win isOnActiveSpace]) {
51           [win orderFront:nil];
52           frontmost_window = win;
53         }
54       }
55     }
56   }
57   if (all_miniaturized && frontmost_miniaturized_window) {
58     [frontmost_miniaturized_window deminiaturize:nil];
59     frontmost_window = frontmost_miniaturized_window;
60   }
61   // If we couldn't find one on this window, consider all spaces.
62   if (allow_workspace_switch &&
63       !frontmost_window && frontmost_window_all_spaces) {
64     frontmost_window = frontmost_window_all_spaces;
65     [frontmost_window orderFront:nil];
66   }
67   if (frontmost_window) {
68     [NSApp activateIgnoringOtherApps:YES];
69     [frontmost_window makeMainWindow];
70     [frontmost_window makeKeyWindow];
71   }
72 }
73
74 }  // namespace ui