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

Side by Side Diff: ui/aura/desktop.cc

Issue 8771015: Rename Desktop->RootWindow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « ui/aura/desktop.h ('k') | ui/aura/desktop_host.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "ui/aura/desktop.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/message_loop.h"
14 #include "base/string_number_conversions.h"
15 #include "base/string_split.h"
16 #include "ui/aura/aura_switches.h"
17 #include "ui/aura/client/stacking_client.h"
18 #include "ui/aura/desktop_host.h"
19 #include "ui/aura/desktop_observer.h"
20 #include "ui/aura/event.h"
21 #include "ui/aura/event_filter.h"
22 #include "ui/aura/focus_manager.h"
23 #include "ui/aura/screen_aura.h"
24 #include "ui/aura/window.h"
25 #include "ui/aura/window_delegate.h"
26 #include "ui/base/hit_test.h"
27 #include "ui/gfx/compositor/compositor.h"
28 #include "ui/gfx/compositor/layer.h"
29 #include "ui/gfx/compositor/layer_animator.h"
30
31 #ifdef USE_WEBKIT_COMPOSITOR
32 #include "ui/gfx/compositor/compositor_cc.h"
33 #endif
34
35 using std::string;
36 using std::vector;
37
38 namespace aura {
39
40 namespace {
41
42 // Default bounds for the host window.
43 static const int kDefaultHostWindowX = 200;
44 static const int kDefaultHostWindowY = 200;
45 static const int kDefaultHostWindowWidth = 1280;
46 static const int kDefaultHostWindowHeight = 1024;
47
48 // Returns true if |target| has a non-client (frame) component at |location|,
49 // in window coordinates.
50 bool IsNonClientLocation(Window* target, const gfx::Point& location) {
51 if (!target->delegate())
52 return false;
53 int hit_test_code = target->delegate()->GetNonClientComponent(location);
54 return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
55 }
56
57 class DefaultStackingClient : public StackingClient {
58 public:
59 explicit DefaultStackingClient(Desktop* desktop) : desktop_(desktop) {}
60 virtual ~DefaultStackingClient() {}
61
62 private:
63
64 // Overridden from StackingClient:
65 virtual void AddChildToDefaultParent(Window* window) OVERRIDE {
66 desktop_->AddChild(window);
67 }
68 virtual bool CanActivateWindow(Window* window) const OVERRIDE {
69 return window->parent() == desktop_;
70 }
71 virtual Window* GetTopmostWindowToActivate(Window* ignore) const OVERRIDE {
72 Window::Windows::const_reverse_iterator i;
73 for (i = desktop_->children().rbegin();
74 i != desktop_->children().rend();
75 ++i) {
76 if (*i == ignore)
77 continue;
78 return *i;
79 }
80 return NULL;
81 }
82
83 Desktop* desktop_;
84
85 DISALLOW_COPY_AND_ASSIGN(DefaultStackingClient);
86 };
87
88 typedef std::vector<EventFilter*> EventFilters;
89
90 void GetEventFiltersToNotify(Window* target, EventFilters* filters) {
91 Window* window = target->parent();
92 while (window) {
93 if (window->event_filter())
94 filters->push_back(window->event_filter());
95 window = window->parent();
96 }
97 }
98
99 } // namespace
100
101 Desktop* Desktop::instance_ = NULL;
102 bool Desktop::use_fullscreen_host_window_ = false;
103
104 ////////////////////////////////////////////////////////////////////////////////
105 // Desktop, public:
106
107 // static
108 Desktop* Desktop::GetInstance() {
109 if (!instance_) {
110 instance_ = new Desktop;
111 instance_->Init();
112 }
113 return instance_;
114 }
115
116 // static
117 void Desktop::DeleteInstance() {
118 delete instance_;
119 instance_ = NULL;
120 }
121
122 void Desktop::SetStackingClient(StackingClient* stacking_client) {
123 stacking_client_.reset(stacking_client);
124 }
125
126 void Desktop::ShowDesktop() {
127 host_->Show();
128 }
129
130 void Desktop::SetHostSize(const gfx::Size& size) {
131 host_->SetSize(size);
132 // Requery the location to constrain it within the new desktop size.
133 last_mouse_location_ = host_->QueryMouseLocation();
134 }
135
136 gfx::Size Desktop::GetHostSize() const {
137 gfx::Rect rect(host_->GetSize());
138 layer()->transform().TransformRect(&rect);
139 return rect.size();
140 }
141
142 void Desktop::SetCursor(gfx::NativeCursor cursor) {
143 last_cursor_ = cursor;
144 // A lot of code seems to depend on NULL cursors actually showing an arrow,
145 // so just pass everything along to the host.
146 host_->SetCursor(cursor);
147 }
148
149 void Desktop::Run() {
150 ShowDesktop();
151 MessageLoopForUI::current()->Run();
152 }
153
154 void Desktop::Draw() {
155 compositor_->Draw(false);
156 }
157
158 bool Desktop::DispatchMouseEvent(MouseEvent* event) {
159 static const int kMouseButtonFlagMask =
160 ui::EF_LEFT_BUTTON_DOWN |
161 ui::EF_MIDDLE_BUTTON_DOWN |
162 ui::EF_RIGHT_BUTTON_DOWN;
163
164 event->UpdateForTransform(layer()->transform());
165
166 last_mouse_location_ = event->location();
167
168 Window* target =
169 mouse_pressed_handler_ ? mouse_pressed_handler_ : capture_window_;
170 if (!target)
171 target = GetEventHandlerForPoint(event->location());
172 switch (event->type()) {
173 case ui::ET_MOUSE_MOVED:
174 HandleMouseMoved(*event, target);
175 break;
176 case ui::ET_MOUSE_PRESSED:
177 if (!mouse_pressed_handler_)
178 mouse_pressed_handler_ = target;
179 mouse_button_flags_ = event->flags() & kMouseButtonFlagMask;
180 break;
181 case ui::ET_MOUSE_RELEASED:
182 mouse_pressed_handler_ = NULL;
183 mouse_button_flags_ = event->flags() & kMouseButtonFlagMask;
184 break;
185 default:
186 break;
187 }
188 if (target && target->delegate()) {
189 int flags = event->flags();
190 gfx::Point location_in_window = event->location();
191 Window::ConvertPointToWindow(this, target, &location_in_window);
192 if (IsNonClientLocation(target, location_in_window))
193 flags |= ui::EF_IS_NON_CLIENT;
194 MouseEvent translated_event(*event, this, target, event->type(), flags);
195 return ProcessMouseEvent(target, &translated_event);
196 }
197 return false;
198 }
199
200 bool Desktop::DispatchKeyEvent(KeyEvent* event) {
201 if (focused_window_) {
202 KeyEvent translated_event(*event);
203 return ProcessKeyEvent(focused_window_, &translated_event);
204 }
205 return false;
206 }
207
208 bool Desktop::DispatchTouchEvent(TouchEvent* event) {
209 event->UpdateForTransform(layer()->transform());
210 bool handled = false;
211 Window* target =
212 touch_event_handler_ ? touch_event_handler_ : capture_window_;
213 if (!target)
214 target = GetEventHandlerForPoint(event->location());
215 if (target) {
216 TouchEvent translated_event(*event, this, target);
217 ui::TouchStatus status = ProcessTouchEvent(target, &translated_event);
218 if (status == ui::TOUCH_STATUS_START)
219 touch_event_handler_ = target;
220 else if (status == ui::TOUCH_STATUS_END ||
221 status == ui::TOUCH_STATUS_CANCEL)
222 touch_event_handler_ = NULL;
223 handled = status != ui::TOUCH_STATUS_UNKNOWN;
224 }
225 return handled;
226 }
227
228 void Desktop::OnHostResized(const gfx::Size& size) {
229 // The compositor should have the same size as the native desktop host.
230 compositor_->WidgetSizeChanged(size);
231
232 // The layer, and all the observers should be notified of the
233 // transformed size of the desktop.
234 gfx::Rect bounds(size);
235 layer()->transform().TransformRect(&bounds);
236 SetBounds(gfx::Rect(bounds.size()));
237 FOR_EACH_OBSERVER(DesktopObserver, observers_,
238 OnDesktopResized(bounds.size()));
239 }
240
241 void Desktop::OnNativeScreenResized(const gfx::Size& size) {
242 if (use_fullscreen_host_window_)
243 SetHostSize(size);
244 }
245
246 void Desktop::SetActiveWindow(Window* window, Window* to_focus) {
247 if (!window)
248 return;
249 // The stacking client may impose rules on what window configurations can be
250 // activated or deactivated.
251 if (!stacking_client_->CanActivateWindow(window))
252 return;
253 // The window may not be activate-able.
254 if (!window->CanActivate())
255 return;
256 // Nothing may actually have changed.
257 if (active_window_ == window)
258 return;
259
260 Window* old_active = active_window_;
261 active_window_ = window;
262 // Invoke OnLostActive after we've changed the active window. That way if the
263 // delegate queries for active state it doesn't think the window is still
264 // active.
265 if (old_active && old_active->delegate())
266 old_active->delegate()->OnLostActive();
267 if (active_window_) {
268 active_window_->parent()->StackChildAtTop(active_window_);
269 if (active_window_->delegate())
270 active_window_->delegate()->OnActivated();
271 active_window_->GetFocusManager()->SetFocusedWindow(
272 to_focus ? to_focus : active_window_);
273 }
274 FOR_EACH_OBSERVER(DesktopObserver, observers_,
275 OnActiveWindowChanged(active_window_));
276 }
277
278 void Desktop::ActivateTopmostWindow() {
279 SetActiveWindow(stacking_client_->GetTopmostWindowToActivate(NULL), NULL);
280 }
281
282 void Desktop::Deactivate(Window* window) {
283 // The stacking client may impose rules on what window configurations can be
284 // activated or deactivated.
285 if (!window || !stacking_client_->CanActivateWindow(window))
286 return;
287 if (active_window_ != window)
288 return;
289
290 Window* to_activate = stacking_client_->GetTopmostWindowToActivate(window);
291 if (to_activate)
292 SetActiveWindow(to_activate, NULL);
293 }
294
295 void Desktop::WindowInitialized(Window* window) {
296 FOR_EACH_OBSERVER(DesktopObserver, observers_, OnWindowInitialized(window));
297 }
298
299 void Desktop::WindowDestroying(Window* window) {
300 // Update the focused window state if the window was focused.
301 if (focused_window_ == window)
302 SetFocusedWindow(NULL);
303
304 // When a window is being destroyed it's likely that the WindowDelegate won't
305 // want events, so we reset the mouse_pressed_handler_ and capture_window_ and
306 // don't sent it release/capture lost events.
307 if (mouse_pressed_handler_ == window)
308 mouse_pressed_handler_ = NULL;
309 if (mouse_moved_handler_ == window)
310 mouse_moved_handler_ = NULL;
311 if (capture_window_ == window)
312 capture_window_ = NULL;
313 if (touch_event_handler_ == window)
314 touch_event_handler_ = NULL;
315
316 if (in_destructor_ || window != active_window_)
317 return;
318
319 // Reset active_window_ before invoking SetActiveWindow so that we don't
320 // attempt to notify it while running its destructor.
321 active_window_ = NULL;
322 SetActiveWindow(stacking_client_->GetTopmostWindowToActivate(window), NULL);
323 }
324
325 MessageLoop::Dispatcher* Desktop::GetDispatcher() {
326 return host_.get();
327 }
328
329 void Desktop::AddObserver(DesktopObserver* observer) {
330 observers_.AddObserver(observer);
331 }
332
333 void Desktop::RemoveObserver(DesktopObserver* observer) {
334 observers_.RemoveObserver(observer);
335 }
336
337 bool Desktop::IsMouseButtonDown() const {
338 return mouse_button_flags_ != 0;
339 }
340
341 void Desktop::PostNativeEvent(const base::NativeEvent& native_event) {
342 host_->PostNativeEvent(native_event);
343 }
344
345 void Desktop::ConvertPointToNativeScreen(gfx::Point* point) const {
346 gfx::Point location = host_->GetLocationOnNativeScreen();
347 point->Offset(location.x(), location.y());
348 }
349
350 void Desktop::SetCapture(Window* window) {
351 if (capture_window_ == window)
352 return;
353
354 if (capture_window_ && capture_window_->delegate())
355 capture_window_->delegate()->OnCaptureLost();
356 capture_window_ = window;
357
358 if (capture_window_) {
359 // Make all subsequent mouse events and touch go to the capture window. We
360 // shouldn't need to send an event here as OnCaptureLost should take care of
361 // that.
362 if (mouse_pressed_handler_)
363 mouse_pressed_handler_ = capture_window_;
364 if (touch_event_handler_)
365 touch_event_handler_ = capture_window_;
366 } else {
367 // When capture is lost, we must reset the event handlers.
368 mouse_pressed_handler_ = NULL;
369 touch_event_handler_ = NULL;
370 }
371 }
372
373 void Desktop::ReleaseCapture(Window* window) {
374 if (capture_window_ != window)
375 return;
376 SetCapture(NULL);
377 }
378
379 void Desktop::SetTransform(const ui::Transform& transform) {
380 Window::SetTransform(transform);
381
382 // If the layer is not animating, then we need to update the host size
383 // immediately.
384 if (!layer()->GetAnimator()->is_animating())
385 OnHostResized(host_->GetSize());
386 }
387
388 #if !defined(NDEBUG)
389 void Desktop::ToggleFullScreen() {
390 host_->ToggleFullScreen();
391 }
392 #endif
393
394 ////////////////////////////////////////////////////////////////////////////////
395 // Desktop, private:
396
397 Desktop::Desktop()
398 : Window(NULL),
399 host_(aura::DesktopHost::Create(GetInitialHostWindowBounds())),
400 ALLOW_THIS_IN_INITIALIZER_LIST(
401 stacking_client_(new DefaultStackingClient(this))),
402 ALLOW_THIS_IN_INITIALIZER_LIST(schedule_paint_factory_(this)),
403 active_window_(NULL),
404 mouse_button_flags_(0),
405 last_cursor_(kCursorNull),
406 in_destructor_(false),
407 screen_(new ScreenAura),
408 capture_window_(NULL),
409 mouse_pressed_handler_(NULL),
410 mouse_moved_handler_(NULL),
411 focused_window_(NULL),
412 touch_event_handler_(NULL) {
413 SetName("RootWindow");
414 gfx::Screen::SetInstance(screen_);
415 host_->SetDesktop(this);
416 last_mouse_location_ = host_->QueryMouseLocation();
417
418 if (ui::Compositor::compositor_factory()) {
419 compositor_ = (*ui::Compositor::compositor_factory())(this);
420 } else {
421 #ifdef USE_WEBKIT_COMPOSITOR
422 ui::CompositorCC::Initialize(false);
423 #endif
424 compositor_ = ui::Compositor::Create(this, host_->GetAcceleratedWidget(),
425 host_->GetSize());
426 }
427 DCHECK(compositor_.get());
428 }
429
430 Desktop::~Desktop() {
431 in_destructor_ = true;
432 // Make sure to destroy the compositor before terminating so that state is
433 // cleared and we don't hit asserts.
434 compositor_ = NULL;
435 #ifdef USE_WEBKIT_COMPOSITOR
436 if (!ui::Compositor::compositor_factory())
437 ui::CompositorCC::Terminate();
438 #endif
439 if (instance_ == this)
440 instance_ = NULL;
441 }
442
443 void Desktop::HandleMouseMoved(const MouseEvent& event, Window* target) {
444 if (target == mouse_moved_handler_)
445 return;
446
447 // Send an exited event.
448 if (mouse_moved_handler_ && mouse_moved_handler_->delegate()) {
449 MouseEvent translated_event(event, this, mouse_moved_handler_,
450 ui::ET_MOUSE_EXITED, event.flags());
451 ProcessMouseEvent(mouse_moved_handler_, &translated_event);
452 }
453 mouse_moved_handler_ = target;
454 // Send an entered event.
455 if (mouse_moved_handler_ && mouse_moved_handler_->delegate()) {
456 MouseEvent translated_event(event, this, mouse_moved_handler_,
457 ui::ET_MOUSE_ENTERED, event.flags());
458 ProcessMouseEvent(mouse_moved_handler_, &translated_event);
459 }
460 }
461
462 bool Desktop::ProcessMouseEvent(Window* target, MouseEvent* event) {
463 if (!target->IsVisible())
464 return false;
465
466 EventFilters filters;
467 GetEventFiltersToNotify(target, &filters);
468 for (EventFilters::const_reverse_iterator it = filters.rbegin();
469 it != filters.rend(); ++it) {
470 if ((*it)->PreHandleMouseEvent(target, event))
471 return true;
472 }
473
474 return target->delegate()->OnMouseEvent(event);
475 }
476
477 bool Desktop::ProcessKeyEvent(Window* target, KeyEvent* event) {
478 if (!target->IsVisible())
479 return false;
480
481 EventFilters filters;
482 GetEventFiltersToNotify(target, &filters);
483 for (EventFilters::const_reverse_iterator it = filters.rbegin();
484 it != filters.rend(); ++it) {
485 if ((*it)->PreHandleKeyEvent(target, event))
486 return true;
487 }
488
489 return target->delegate()->OnKeyEvent(event);
490 }
491
492 ui::TouchStatus Desktop::ProcessTouchEvent(Window* target, TouchEvent* event) {
493 if (!target->IsVisible())
494 return ui::TOUCH_STATUS_UNKNOWN;
495
496 EventFilters filters;
497 GetEventFiltersToNotify(target, &filters);
498 for (EventFilters::const_reverse_iterator it = filters.rbegin();
499 it != filters.rend(); ++it) {
500 ui::TouchStatus status = (*it)->PreHandleTouchEvent(target, event);
501 if (status != ui::TOUCH_STATUS_UNKNOWN)
502 return status;
503 }
504
505 return target->delegate()->OnTouchEvent(event);
506 }
507
508 void Desktop::ScheduleDraw() {
509 if (!schedule_paint_factory_.HasWeakPtrs()) {
510 MessageLoop::current()->PostTask(
511 FROM_HERE,
512 base::Bind(&Desktop::Draw, schedule_paint_factory_.GetWeakPtr()));
513 }
514 }
515
516 bool Desktop::CanFocus() const {
517 return IsVisible();
518 }
519
520 internal::FocusManager* Desktop::GetFocusManager() {
521 return this;
522 }
523
524 Desktop* Desktop::GetDesktop() {
525 return this;
526 }
527
528 void Desktop::WindowDetachedFromDesktop(Window* detached) {
529 DCHECK(capture_window_ != this);
530
531 // If the ancestor of the capture window is detached,
532 // release the capture.
533 if (detached->Contains(capture_window_) && detached != this)
534 ReleaseCapture(capture_window_);
535
536 // If the ancestor of the focused window is detached,
537 // release the focus.
538 if (detached->Contains(focused_window_))
539 SetFocusedWindow(NULL);
540
541 // If the ancestor of any event handler windows are detached, release the
542 // pointer to those windows.
543 if (detached->Contains(mouse_pressed_handler_))
544 mouse_pressed_handler_ = NULL;
545 if (detached->Contains(mouse_moved_handler_))
546 mouse_moved_handler_ = NULL;
547 if (detached->Contains(touch_event_handler_))
548 touch_event_handler_ = NULL;
549 }
550
551 void Desktop::OnLayerAnimationEnded(
552 const ui::LayerAnimationSequence* animation) {
553 OnHostResized(host_->GetSize());
554 }
555
556 void Desktop::OnLayerAnimationScheduled(
557 const ui::LayerAnimationSequence* animation) {
558 }
559
560 void Desktop::OnLayerAnimationAborted(
561 const ui::LayerAnimationSequence* animation) {
562 }
563
564 void Desktop::SetFocusedWindow(Window* focused_window) {
565 if (focused_window == focused_window_ ||
566 (focused_window && !focused_window->CanFocus())) {
567 return;
568 }
569 if (focused_window_ && focused_window_->delegate())
570 focused_window_->delegate()->OnBlur();
571 focused_window_ = focused_window;
572 if (focused_window_ && focused_window_->delegate())
573 focused_window_->delegate()->OnFocus();
574 }
575
576 Window* Desktop::GetFocusedWindow() {
577 return focused_window_;
578 }
579
580 bool Desktop::IsFocusedWindow(const Window* window) const {
581 return focused_window_ == window;
582 }
583
584 void Desktop::Init() {
585 Window::Init(ui::Layer::LAYER_HAS_NO_TEXTURE);
586 SetBounds(gfx::Rect(host_->GetSize()));
587 Show();
588 compositor()->SetRootLayer(layer());
589 }
590
591 gfx::Rect Desktop::GetInitialHostWindowBounds() const {
592 gfx::Rect bounds(kDefaultHostWindowX, kDefaultHostWindowY,
593 kDefaultHostWindowWidth, kDefaultHostWindowHeight);
594
595 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
596 switches::kAuraHostWindowSize);
597 vector<string> parts;
598 base::SplitString(size_str, 'x', &parts);
599 int parsed_width = 0, parsed_height = 0;
600 if (parts.size() == 2 &&
601 base::StringToInt(parts[0], &parsed_width) && parsed_width > 0 &&
602 base::StringToInt(parts[1], &parsed_height) && parsed_height > 0) {
603 bounds.set_size(gfx::Size(parsed_width, parsed_height));
604 } else if (use_fullscreen_host_window_) {
605 bounds = gfx::Rect(DesktopHost::GetNativeScreenSize());
606 }
607
608 return bounds;
609 }
610
611 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/desktop.h ('k') | ui/aura/desktop_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698