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

Side by Side Diff: components/mus/ws/window_manager_state.cc

Issue 1775133003: Moves EventDispatcher from Display to WindowManagerState (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: todo Created 4 years, 9 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
« no previous file with comments | « components/mus/ws/window_manager_state.h ('k') | components/mus/ws/window_tree.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/mus/ws/window_manager_state.h" 5 #include "components/mus/ws/window_manager_state.h"
6 6
7 #include "components/mus/ws/connection_manager.h" 7 #include "components/mus/ws/connection_manager.h"
8 #include "components/mus/ws/display_manager.h" 8 #include "components/mus/ws/display_manager.h"
9 #include "components/mus/ws/platform_display.h"
9 #include "components/mus/ws/server_window.h" 10 #include "components/mus/ws/server_window.h"
10 #include "components/mus/ws/user_display_manager.h" 11 #include "components/mus/ws/user_display_manager.h"
12 #include "components/mus/ws/user_id_tracker.h"
13 #include "components/mus/ws/window_tree.h"
14 #include "mojo/converters/input_events/input_events_type_converters.h"
11 #include "mojo/shell/public/interfaces/connector.mojom.h" 15 #include "mojo/shell/public/interfaces/connector.mojom.h"
16 #include "ui/events/event.h"
12 17
13 namespace mus { 18 namespace mus {
14 namespace ws { 19 namespace ws {
20 namespace {
15 21
16 WindowManagerState::WindowManagerState(Display* display) 22 base::TimeDelta GetDefaultAckTimerDelay() {
17 : WindowManagerState(display, false, mojo::shell::mojom::kRootUserID) {} 23 #if defined(NDEBUG)
24 return base::TimeDelta::FromMilliseconds(100);
25 #else
26 return base::TimeDelta::FromMilliseconds(1000);
27 #endif
28 }
18 29
19 WindowManagerState::WindowManagerState(Display* display, const UserId& user_id) 30 bool EventsCanBeCoalesced(const ui::Event& one, const ui::Event& two) {
20 : WindowManagerState(display, true, user_id) {} 31 if (one.type() != two.type() || one.flags() != two.flags())
32 return false;
33
34 // TODO(sad): wheel events can also be merged.
35 if (one.type() != ui::ET_POINTER_MOVED)
36 return false;
37
38 return one.AsPointerEvent()->pointer_id() ==
39 two.AsPointerEvent()->pointer_id();
40 }
41
42 scoped_ptr<ui::Event> CoalesceEvents(scoped_ptr<ui::Event> first,
43 scoped_ptr<ui::Event> second) {
44 DCHECK(first->type() == ui::ET_POINTER_MOVED)
45 << " Non-move events cannot be merged yet.";
46 // For mouse moves, the new event just replaces the old event.
47 return second;
48 }
49
50 } // namespace
51
52 class WindowManagerState::ProcessedEventTarget {
53 public:
54 ProcessedEventTarget(ServerWindow* window, bool in_nonclient_area)
55 : in_nonclient_area_(in_nonclient_area) {
56 tracker_.Add(window);
57 }
58
59 ~ProcessedEventTarget() {}
60
61 // Return true if the event is still valid. The event becomes invalid if
62 // the window is destroyed while waiting to dispatch.
63 bool IsValid() const { return !tracker_.windows().empty(); }
64
65 ServerWindow* window() {
66 DCHECK(IsValid());
67 return tracker_.windows().front();
68 }
69
70 bool in_nonclient_area() const { return in_nonclient_area_; }
71
72 private:
73 ServerWindowTracker tracker_;
74 const bool in_nonclient_area_;
75
76 DISALLOW_COPY_AND_ASSIGN(ProcessedEventTarget);
77 };
78
79 WindowManagerState::QueuedEvent::QueuedEvent() {}
80 WindowManagerState::QueuedEvent::~QueuedEvent() {}
81
82 WindowManagerState::WindowManagerState(Display* display,
83 PlatformDisplay* platform_display,
84 cc::SurfaceId surface_id)
85 : WindowManagerState(display,
86 platform_display,
87 surface_id,
88 false,
89 mojo::shell::mojom::kRootUserID) {}
90
91 WindowManagerState::WindowManagerState(Display* display,
92 PlatformDisplay* platform_display,
93 cc::SurfaceId surface_id,
94 const UserId& user_id)
95 : WindowManagerState(display, platform_display, surface_id, true, user_id) {
96 }
21 97
22 WindowManagerState::~WindowManagerState() {} 98 WindowManagerState::~WindowManagerState() {}
23 99
100 void WindowManagerState::SetFrameDecorationValues(
101 mojom::FrameDecorationValuesPtr values) {
102 got_frame_decoration_values_ = true;
103 frame_decoration_values_ = values.Clone();
104 display_->display_manager()
105 ->GetUserDisplayManager(user_id_)
106 ->OnFrameDecorationValuesChanged(this);
107 }
108
109 void WindowManagerState::SetCapture(ServerWindow* window,
110 bool in_nonclient_area) {
111 // TODO(sky): capture should be a singleton. Need to route to
112 // ConnectionManager so that all other EventDispatchers are updated.
113 DCHECK(IsActive());
114 if (capture_window() == window)
115 return;
116 DCHECK(!window || root_->Contains(window));
117 event_dispatcher_.SetCaptureWindow(window, in_nonclient_area);
118 }
119
120 mojom::DisplayPtr WindowManagerState::ToMojomDisplay() const {
121 mojom::DisplayPtr display_ptr = display_->ToMojomDisplay();
122 // TODO(sky): set work area.
123 display_ptr->work_area = display_ptr->bounds.Clone();
124 display_ptr->frame_decoration_values = frame_decoration_values_.Clone();
125 return display_ptr;
126 }
127
128 void WindowManagerState::OnWillDestroyTree(WindowTree* tree) {
129 if (tree_awaiting_input_ack_ != tree)
130 return;
131 // The WindowTree is dying. So it's not going to ack the event.
132 OnEventAck(tree_awaiting_input_ack_);
133 }
134
24 WindowManagerState::WindowManagerState(Display* display, 135 WindowManagerState::WindowManagerState(Display* display,
136 PlatformDisplay* platform_display,
137 cc::SurfaceId surface_id,
25 bool is_user_id_valid, 138 bool is_user_id_valid,
26 const UserId& user_id) 139 const UserId& user_id)
27 : display_(display), 140 : display_(display),
141 platform_display_(platform_display),
28 is_user_id_valid_(is_user_id_valid), 142 is_user_id_valid_(is_user_id_valid),
29 user_id_(user_id) { 143 user_id_(user_id),
144 event_dispatcher_(this) {
30 frame_decoration_values_ = mojom::FrameDecorationValues::New(); 145 frame_decoration_values_ = mojom::FrameDecorationValues::New();
31 frame_decoration_values_->normal_client_area_insets = mojo::Insets::New(); 146 frame_decoration_values_->normal_client_area_insets = mojo::Insets::New();
32 frame_decoration_values_->maximized_client_area_insets = mojo::Insets::New(); 147 frame_decoration_values_->maximized_client_area_insets = mojo::Insets::New();
33 frame_decoration_values_->max_title_bar_button_width = 0u; 148 frame_decoration_values_->max_title_bar_button_width = 0u;
34 149
35 ConnectionManager* connection_manager = display_->connection_manager(); 150 ConnectionManager* connection_manager = display_->connection_manager();
36 root_.reset(connection_manager->CreateServerWindow( 151 root_.reset(connection_manager->CreateServerWindow(
37 connection_manager->display_manager()->GetAndAdvanceNextRootId(), 152 connection_manager->display_manager()->GetAndAdvanceNextRootId(),
38 ServerWindow::Properties())); 153 ServerWindow::Properties()));
39 // Our root is always a child of the Display's root. Do this 154 // Our root is always a child of the Display's root. Do this
40 // before the WindowTree has been created so that the client doesn't get 155 // before the WindowTree has been created so that the client doesn't get
41 // notified of the add, bounds change and visibility change. 156 // notified of the add, bounds change and visibility change.
42 root_->SetBounds(gfx::Rect(display->root_window()->bounds().size())); 157 root_->SetBounds(gfx::Rect(display->root_window()->bounds().size()));
43 root_->SetVisible(true); 158 root_->SetVisible(true);
44 display->root_window()->Add(root_.get()); 159 display->root_window()->Add(root_.get());
160
161 event_dispatcher_.set_root(root_.get());
162 event_dispatcher_.set_surface_id(surface_id);
45 } 163 }
46 164
47 void WindowManagerState::SetFrameDecorationValues( 165 bool WindowManagerState::IsActive() const {
48 mojom::FrameDecorationValuesPtr values) { 166 return display()->GetActiveWindowManagerState() == this;
49 got_frame_decoration_values_ = true;
50 frame_decoration_values_ = values.Clone();
51 display_->display_manager()
52 ->GetUserDisplayManager(user_id_)
53 ->OnFrameDecorationValuesChanged(this);
54 } 167 }
55 168
56 mojom::DisplayPtr WindowManagerState::ToMojomDisplay() const { 169 void WindowManagerState::ProcessEvent(const ui::Event& event) {
57 mojom::DisplayPtr display_ptr = display_->ToMojomDisplay(); 170 mojom::EventPtr mojo_event(mojom::Event::From(event));
58 // TODO(sky): set work area. 171 // If this is still waiting for an ack from a previously sent event, then
59 display_ptr->work_area = display_ptr->bounds.Clone(); 172 // queue up the event to be dispatched once the ack is received.
60 display_ptr->frame_decoration_values = frame_decoration_values_.Clone(); 173 if (event_ack_timer_.IsRunning()) {
61 return display_ptr; 174 if (!event_queue_.empty() && !event_queue_.back()->processed_target &&
175 EventsCanBeCoalesced(*event_queue_.back()->event, event)) {
176 event_queue_.back()->event = CoalesceEvents(
177 std::move(event_queue_.back()->event), ui::Event::Clone(event));
178 return;
179 }
180 QueueEvent(event, nullptr);
181 return;
182 }
183 event_dispatcher_.ProcessEvent(event);
184 }
185
186 void WindowManagerState::OnEventAck(mojom::WindowTree* tree) {
187 if (tree_awaiting_input_ack_ != tree) {
188 // TODO(sad): The ack must have arrived after the timeout. We should do
189 // something here, and in OnEventAckTimeout().
190 return;
191 }
192 tree_awaiting_input_ack_ = nullptr;
193 event_ack_timer_.Stop();
194 ProcessNextEventFromQueue();
195 }
196
197 ConnectionManager* WindowManagerState::connection_manager() {
198 return display_->connection_manager();
199 }
200
201 void WindowManagerState::OnEventAckTimeout() {
202 // TODO(sad): Figure out what we should do.
203 NOTIMPLEMENTED() << "Event ACK timed out.";
204 OnEventAck(tree_awaiting_input_ack_);
205 }
206
207 void WindowManagerState::QueueEvent(
208 const ui::Event& event,
209 scoped_ptr<ProcessedEventTarget> processed_event_target) {
210 scoped_ptr<QueuedEvent> queued_event(new QueuedEvent);
211 queued_event->event = ui::Event::Clone(event);
212 queued_event->processed_target = std::move(processed_event_target);
213 event_queue_.push(std::move(queued_event));
214 }
215
216 void WindowManagerState::ProcessNextEventFromQueue() {
217 // Loop through |event_queue_| stopping after dispatching the first valid
218 // event.
219 while (!event_queue_.empty()) {
220 scoped_ptr<QueuedEvent> queued_event = std::move(event_queue_.front());
221 event_queue_.pop();
222 if (!queued_event->processed_target) {
223 event_dispatcher_.ProcessEvent(*queued_event->event);
224 return;
225 }
226 if (queued_event->processed_target->IsValid()) {
227 DispatchInputEventToWindowImpl(
228 queued_event->processed_target->window(),
229 queued_event->processed_target->in_nonclient_area(),
230 *queued_event->event);
231 return;
232 }
233 }
234 }
235
236 void WindowManagerState::DispatchInputEventToWindowImpl(
237 ServerWindow* target,
238 bool in_nonclient_area,
239 const ui::Event& event) {
240 if (target == root_->parent())
241 target = root_.get();
242
243 if (event.IsMousePointerEvent()) {
244 DCHECK(event_dispatcher_.mouse_cursor_source_window());
245 display_->UpdateNativeCursor(
246 event_dispatcher_.mouse_cursor_source_window()->cursor());
247 }
248
249 // If the event is in the non-client area the event goes to the owner of
250 // the window. Otherwise if the window is an embed root, forward to the
251 // embedded window.
252 WindowTree* tree =
253 in_nonclient_area
254 ? connection_manager()->GetTreeWithId(target->id().connection_id)
255 : connection_manager()->GetTreeWithRoot(target);
256 if (!tree) {
257 DCHECK(!in_nonclient_area);
258 tree = connection_manager()->GetTreeWithId(target->id().connection_id);
259 }
260
261 // TOOD(sad): Adjust this delay, possibly make this dynamic.
262 const base::TimeDelta max_delay = base::debug::BeingDebugged()
263 ? base::TimeDelta::FromDays(1)
264 : GetDefaultAckTimerDelay();
265 event_ack_timer_.Start(FROM_HERE, max_delay, this,
266 &WindowManagerState::OnEventAckTimeout);
267
268 tree_awaiting_input_ack_ = tree;
269 tree->DispatchInputEvent(target, mojom::Event::From(event));
270 }
271
272 void WindowManagerState::OnAccelerator(uint32_t accelerator_id,
273 const ui::Event& event) {
274 DCHECK(IsActive());
275 tree_->OnAccelerator(accelerator_id, mojom::Event::From(event));
276 }
277
278 void WindowManagerState::SetFocusedWindowFromEventDispatcher(
279 ServerWindow* new_focused_window) {
280 DCHECK(IsActive());
281 display_->SetFocusedWindow(new_focused_window);
282 }
283
284 ServerWindow* WindowManagerState::GetFocusedWindowForEventDispatcher() {
285 return display()->GetFocusedWindow();
286 }
287
288 void WindowManagerState::SetNativeCapture() {
289 DCHECK(IsActive());
290 platform_display_->SetCapture();
291 }
292
293 void WindowManagerState::ReleaseNativeCapture() {
294 platform_display_->ReleaseCapture();
295 }
296
297 void WindowManagerState::OnServerWindowCaptureLost(ServerWindow* window) {
298 DCHECK(window);
299 display_->connection_manager()->ProcessLostCapture(window);
300 }
301
302 void WindowManagerState::DispatchInputEventToWindow(ServerWindow* target,
303 bool in_nonclient_area,
304 const ui::Event& event) {
305 DCHECK(IsActive());
306 // TODO(sky): this needs to see if another wms has capture and if so forward
307 // to it.
308 if (event_ack_timer_.IsRunning()) {
309 scoped_ptr<ProcessedEventTarget> processed_event_target(
310 new ProcessedEventTarget(target, in_nonclient_area));
311 QueueEvent(event, std::move(processed_event_target));
312 return;
313 }
314
315 DispatchInputEventToWindowImpl(target, in_nonclient_area, event);
62 } 316 }
63 317
64 } // namespace ws 318 } // namespace ws
65 } // namespace mus 319 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/window_manager_state.h ('k') | components/mus/ws/window_tree.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698