summaryrefslogtreecommitdiff
path: root/chromium/services/ui/ws/focus_controller.h
blob: 7cf76e6c7dbfc7f5085ae5344fc7764d104fddc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_UI_WS_FOCUS_CONTROLLER_H_
#define SERVICES_UI_WS_FOCUS_CONTROLLER_H_

#include <memory>

#include "base/macros.h"
#include "base/observer_list.h"
#include "services/ui/ws/server_window_drawn_tracker_observer.h"
#include "services/ui/ws/server_window_tracker.h"

namespace ui {

namespace ws {

class FocusControllerDelegate;
class FocusControllerObserver;
class ServerWindow;
class ServerWindowDrawnTracker;

// Describes the source of the change.
enum class FocusControllerChangeSource {
  EXPLICIT,
  DRAWN_STATE_CHANGED,
};

// Tracks the focused window. Focus is moved to another window when the drawn
// state of the focused window changes.
class FocusController : public ServerWindowDrawnTrackerObserver {
 public:
  FocusController(FocusControllerDelegate* delegate, ServerWindow* root);
  ~FocusController() override;

  // Sets the focused window. Does nothing if |window| is currently focused.
  // This does not notify the delegate. See ServerWindow::SetFocusedWindow()
  // for details on return value.
  bool SetFocusedWindow(ServerWindow* window);
  ServerWindow* GetFocusedWindow();

  // Moves activation to the next activatable window.
  void ActivateNextWindow();

  void AddObserver(FocusControllerObserver* observer);
  void RemoveObserver(FocusControllerObserver* observer);

 private:
  enum class ActivationChangeReason {
    UNKNONW,
    CYCLE,  // Activation changed because of ActivateNextWindow().
    FOCUS,  // Focus change required a different window to be activated.
    DRAWN_STATE_CHANGED,  // Active window was hidden or destroyed.
  };
  void SetActiveWindow(ServerWindow* window, ActivationChangeReason reason);

  // Returns whether |window| can be focused or activated.
  bool CanBeFocused(ServerWindow* window) const;
  bool CanBeActivated(ServerWindow* window) const;

  // Returns the closest activatable ancestor of |window|. Returns nullptr if
  // there is no such ancestor.
  ServerWindow* GetActivatableAncestorOf(ServerWindow* window) const;

  // Implementation of SetFocusedWindow().
  bool SetFocusedWindowImpl(FocusControllerChangeSource change_source,
                            ServerWindow* window);

  // ServerWindowDrawnTrackerObserver:
  void OnDrawnStateWillChange(ServerWindow* ancestor,
                              ServerWindow* window,
                              bool is_drawn) override;
  void OnDrawnStateChanged(ServerWindow* ancestor,
                           ServerWindow* window,
                           bool is_drawn) override;

  FocusControllerDelegate* delegate_;

  ServerWindow* root_;
  ServerWindow* focused_window_;
  ServerWindow* active_window_;
  // Tracks what caused |active_window_| to be activated.
  ActivationChangeReason activation_reason_;

  // Keeps track of the list of windows that have already been visited during a
  // window cycle. This is only active when |activation_reason_| is set to
  // CYCLE.
  std::unique_ptr<ServerWindowTracker> cycle_windows_;

  base::ObserverList<FocusControllerObserver> observers_;

  // Keeps track of the visibility of the focused and active window.
  std::unique_ptr<ServerWindowDrawnTracker> drawn_tracker_;

  DISALLOW_COPY_AND_ASSIGN(FocusController);
};

}  // namespace ws

}  // namespace ui

#endif  // SERVICES_UI_WS_FOCUS_CONTROLLER_H_