• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9namespace 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.
35void 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
75