Upstream version 10.38.217.0
[platform/framework/web/crosswalk.git] / src / ozone / ui / desktop_aura / desktop_window_tree_host_wayland.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Copyright 2013 Intel Corporation. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "ozone/ui/desktop_aura/desktop_window_tree_host_wayland.h"
7
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ozone/ui/desktop_aura/desktop_drag_drop_client_wayland.h"
13 #include "ozone/ui/desktop_aura/desktop_screen_wayland.h"
14 #include "ozone/ui/desktop_aura/window_tree_host_delegate_wayland.h"
15 #include "ozone/ui/events/window_state_change_handler.h"
16 #include "ui/aura/client/cursor_client.h"
17 #include "ui/aura/client/focus_client.h"
18 #include "ui/aura/window_property.h"
19 #include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
20 #include "ui/base/ime/composition_text.h"
21 #include "ui/base/ime/input_method.h"
22 #include "ui/base/ime/input_method_auralinux.h"
23 #include "ui/events/event_utils.h"
24 #include "ui/gfx/insets.h"
25 #include "ui/native_theme/native_theme.h"
26 #include "ui/ozone/public/ozone_platform.h"
27 #include "ui/ozone/public/surface_factory_ozone.h"
28 #include "ui/platform_window/platform_window.h"
29 #include "ui/platform_window/platform_window_delegate.h"
30 #include "ui/views/corewm/tooltip_aura.h"
31 #include "ui/views/ime/input_method.h"
32 #include "ui/views/linux_ui/linux_ui.h"
33 #include "ui/views/views_export.h"
34 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
35 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
36 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
37 #include "ui/views/widget/desktop_aura/desktop_screen_position_client.h"
38 #include "ui/wm/core/input_method_event_filter.h"
39 #include "ui/wm/core/window_util.h"
40 #include "ui/wm/public/window_move_client.h"
41
42 namespace views {
43
44 WindowTreeHostDelegateWayland*
45     DesktopWindowTreeHostWayland::g_delegate_ozone_wayland_ = NULL;
46
47 DEFINE_WINDOW_PROPERTY_KEY(
48     aura::Window*, kViewsWindowForRootWindow, NULL);
49
50 DEFINE_WINDOW_PROPERTY_KEY(
51     DesktopWindowTreeHostWayland*, kHostForRootWindow, NULL);
52
53 DesktopWindowTreeHostWayland::DesktopWindowTreeHostWayland(
54     internal::NativeWidgetDelegate* native_widget_delegate,
55     DesktopNativeWidgetAura* desktop_native_widget_aura)
56     : aura::WindowTreeHost(),
57       state_(Uninitialized),
58       bounds_(0, 0, 0, 0),
59       previous_bounds_(0, 0, 0, 0),
60       previous_maximize_bounds_(0, 0, 0, 0),
61       window_(0),
62       title_(base::string16()),
63       close_widget_factory_(this),
64       drag_drop_client_(NULL),
65       native_widget_delegate_(native_widget_delegate),
66       content_window_(NULL),
67       desktop_native_widget_aura_(desktop_native_widget_aura),
68       window_parent_(NULL),
69       window_children_() {
70 }
71
72 DesktopWindowTreeHostWayland::~DesktopWindowTreeHostWayland() {
73   window()->ClearProperty(kHostForRootWindow);
74   aura::client::SetWindowMoveClient(window(), NULL);
75   desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
76   DestroyDispatcher();
77 }
78
79 // static
80 DesktopWindowTreeHostWayland*
81 DesktopWindowTreeHostWayland::GetHostForAcceleratedWidget(
82     gfx::AcceleratedWidget widget) {
83   aura::WindowTreeHost* host =
84       aura::WindowTreeHost::GetForAcceleratedWidget(widget);
85
86   return host ? host->window()->GetProperty(kHostForRootWindow) : NULL;
87 }
88
89 // static
90 const std::vector<aura::Window*>&
91 DesktopWindowTreeHostWayland::GetAllOpenWindows() {
92   DCHECK(g_delegate_ozone_wayland_);
93   return g_delegate_ozone_wayland_->GetAllOpenWindows();
94 }
95
96 // static
97 aura::Window*
98 DesktopWindowTreeHostWayland::GetContentWindowForAcceleratedWidget(
99     gfx::AcceleratedWidget widget) {
100   aura::WindowTreeHost* host =
101       aura::WindowTreeHost::GetForAcceleratedWidget(widget);
102
103   return host ?
104       host->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
105 }
106
107 gfx::Rect DesktopWindowTreeHostWayland::GetBoundsInScreen() const {
108   return bounds_;
109 }
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // DesktopWindowTreeHostWayland, private:
113
114 void DesktopWindowTreeHostWayland::InitWaylandWindow(
115     const Widget::InitParams& params) {
116   bounds_ = params.bounds;
117   platform_window_ =
118       ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds_);
119   DCHECK(window_);
120   // Maintain parent child relation as done in X11 version.
121   // If we have a parent, record the parent/child relationship. We use this
122   // data during destruction to make sure that when we try to close a parent
123   // window, we also destroy all child windows.
124   if (params.parent && params.parent->GetHost()) {
125     gfx::AcceleratedWidget windowId = params.parent->GetHost()->
126         GetAcceleratedWidget();
127     window_parent_ = GetHostForAcceleratedWidget(windowId);
128     DCHECK(window_parent_);
129     window_parent_->window_children_.insert(this);
130   }
131
132   ui::WindowStateChangeHandler* state_handler =
133       ui::WindowStateChangeHandler::GetInstance();
134   switch (params.type) {
135     case Widget::InitParams::TYPE_TOOLTIP:
136     case Widget::InitParams::TYPE_POPUP:
137     case Widget::InitParams::TYPE_MENU: {
138       // Wayland surfaces don't know their position on the screen and transient
139       // surfaces always require a parent surface for relative placement. Here
140       // there's a catch because content_shell menus don't have parent and
141       // therefore we use root window to calculate their position.
142       DesktopWindowTreeHostWayland* parent = window_parent_;
143       if (!parent)
144         parent = GetHostForAcceleratedWidget(
145                      g_delegate_ozone_wayland_->GetActiveWindow()->window_);
146
147       // Transient type expects a position relative to the parent
148       gfx::Point transientPos(bounds_.x() - parent->bounds_.x(),
149                               bounds_.y() - parent->bounds_.y());
150
151       // Different platforms implement different input grab pointer behaviors
152       // on Chromium. While the Linux GTK+ grab button clicks but not the
153       // pointer movement, the MS Windows implementation don't implement any
154       // pointer grab. In here we're using another different behavior for
155       // Chromium, but which is the common sense on most Wayland UI
156       // environments, where the input pointer is grabbed as a whole when a
157       // menu type of window is opened. I.e. both pointer clicks and movements
158       // will be routed only to the newly created window (grab installed). For
159       // more information please refer to the Wayland protocol.
160       state_handler->SetWidgetAttributes(window_,
161                                          parent->window_,
162                                          transientPos.x(),
163                                          transientPos.y(),
164                                          ui::POPUP);
165       break;
166     }
167     case Widget::InitParams::TYPE_BUBBLE:
168     case Widget::InitParams::TYPE_WINDOW:
169       state_handler->SetWidgetAttributes(window_,
170                                          0,
171                                          0,
172                                          0,
173                                          ui::WINDOW);
174       break;
175     case Widget::InitParams::TYPE_WINDOW_FRAMELESS:
176       NOTIMPLEMENTED();
177       break;
178     default:
179       break;
180   }
181
182   CreateCompositor(GetAcceleratedWidget());
183 }
184
185 void DesktopWindowTreeHostWayland::OnAcceleratedWidgetAvailable(
186       gfx::AcceleratedWidget widget) {
187   window_ = widget;
188 }
189
190 ////////////////////////////////////////////////////////////////////////////////
191 // DesktopWindowTreeHostWayland, DesktopWindowTreeHost implementation:
192
193 void DesktopWindowTreeHostWayland::Init(
194     aura::Window* content_window,
195     const Widget::InitParams& params) {
196   content_window_ = content_window;
197   // In some situations, views tries to make a zero sized window, and that
198   // makes us crash. Make sure we have valid sizes.
199   Widget::InitParams sanitized_params = params;
200   if (sanitized_params.bounds.width() == 0)
201     sanitized_params.bounds.set_width(100);
202   if (sanitized_params.bounds.height() == 0)
203     sanitized_params.bounds.set_height(100);
204
205   InitWaylandWindow(sanitized_params);
206 }
207
208 void DesktopWindowTreeHostWayland::OnNativeWidgetCreated(
209     const Widget::InitParams& params) {
210   window()->SetProperty(kViewsWindowForRootWindow, content_window_);
211   window()->SetProperty(kHostForRootWindow, this);
212
213   // If we're given a parent, we need to mark ourselves as transient to another
214   // window. Otherwise activation gets screwy.
215   gfx::NativeView parent = params.parent;
216   if (!params.child && params.parent)
217     wm::AddTransientChild(parent, content_window_);
218
219   native_widget_delegate_->OnNativeWidgetCreated(true);
220
221   if (!g_delegate_ozone_wayland_)
222     g_delegate_ozone_wayland_ = new WindowTreeHostDelegateWayland();
223
224   g_delegate_ozone_wayland_->OnRootWindowCreated(window_);
225
226   // Add DesktopWindowTreeHostWayland as dispatcher.
227   bool root_window = params.type == Widget::InitParams::TYPE_BUBBLE ||
228       params.type == Widget::InitParams::TYPE_WINDOW ||
229       params.type == Widget::InitParams::TYPE_WINDOW_FRAMELESS;
230   if (!window_parent_ && root_window)
231     g_delegate_ozone_wayland_->SetActiveWindow(this);
232 }
233
234 scoped_ptr<corewm::Tooltip>
235 DesktopWindowTreeHostWayland::CreateTooltip() {
236   return scoped_ptr<corewm::Tooltip>(
237              new corewm::TooltipAura(gfx::SCREEN_TYPE_NATIVE));
238 }
239
240 scoped_ptr<aura::client::DragDropClient>
241 DesktopWindowTreeHostWayland::CreateDragDropClient(
242     DesktopNativeCursorManager* cursor_manager) {
243   drag_drop_client_ = new DesktopDragDropClientWayland(window());
244   return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
245 }
246
247 void DesktopWindowTreeHostWayland::Close() {
248   if (!close_widget_factory_.HasWeakPtrs()) {
249     // And we delay the close so that if we are called from an ATL callback,
250     // we don't destroy the window before the callback returned (as the caller
251     // may delete ourselves on destroy and the ATL callback would still
252     // dereference us when the callback returns).
253     base::MessageLoop::current()->PostTask(
254         FROM_HERE,
255         base::Bind(&DesktopWindowTreeHostWayland::CloseNow,
256                    close_widget_factory_.GetWeakPtr()));
257   }
258 }
259
260 void DesktopWindowTreeHostWayland::CloseNow() {
261   DCHECK(g_delegate_ozone_wayland_);
262   unsigned widgetId = window_;
263   native_widget_delegate_->OnNativeWidgetDestroying();
264
265   // If we have children, close them. Use a copy for iteration because they'll
266   // remove themselves.
267   std::set<DesktopWindowTreeHostWayland*> window_children_copy =
268       window_children_;
269   for (std::set<DesktopWindowTreeHostWayland*>::iterator it =
270            window_children_copy.begin(); it != window_children_copy.end();
271        ++it) {
272     (*it)->CloseNow();
273   }
274   DCHECK(window_children_.empty());
275
276   // If we have a parent, remove ourselves from its children list.
277   if (window_parent_)
278     window_parent_->window_children_.erase(this);
279
280   g_delegate_ozone_wayland_->OnRootWindowClosed(widgetId);
281   // Destroy the compositor before destroying the window since shutdown
282   // may try to swap, and the swap without a window causes an error, which
283   // causes a crash with in-process renderer.
284   DestroyCompositor();
285   window_parent_ = NULL;
286   if (!g_delegate_ozone_wayland_->GetActiveWindow()) {
287     // We have no open windows, free g_delegate_ozone_wayland_.
288     delete g_delegate_ozone_wayland_;
289     g_delegate_ozone_wayland_ = NULL;
290   }
291
292   desktop_native_widget_aura_->OnHostClosed();
293 }
294
295 aura::WindowTreeHost* DesktopWindowTreeHostWayland::AsWindowTreeHost() {
296   return this;
297 }
298
299 void DesktopWindowTreeHostWayland::ShowWindowWithState(
300     ui::WindowShowState show_state) {
301   if (show_state != ui::SHOW_STATE_DEFAULT &&
302       show_state != ui::SHOW_STATE_NORMAL) {
303     // Only forwarding to Show().
304     NOTIMPLEMENTED();
305   }
306
307   Show();
308   if (show_state == ui::SHOW_STATE_MAXIMIZED)
309     Maximize();
310
311   // Set initial focus for root window.
312   if (!window_parent_)
313     native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
314 }
315
316 void DesktopWindowTreeHostWayland::ShowMaximizedWithBounds(
317     const gfx::Rect& restored_bounds) {
318   Maximize();
319   previous_bounds_ = restored_bounds;
320   Show();
321 }
322
323 bool DesktopWindowTreeHostWayland::IsVisible() const {
324   return state_ & Visible;
325 }
326
327 void DesktopWindowTreeHostWayland::SetSize(const gfx::Size& size) {
328   gfx::Rect new_bounds = bounds_;
329   new_bounds.set_size(size);
330   SetBounds(new_bounds);
331 }
332
333 void DesktopWindowTreeHostWayland::StackAtTop() {
334 }
335
336 void DesktopWindowTreeHostWayland::CenterWindow(const gfx::Size& size) {
337   gfx::Rect parent_bounds = GetWorkAreaBoundsInScreen();
338
339   // If |window_|'s transient parent bounds are big enough to contain |size|,
340   // use them instead.
341   if (wm::GetTransientParent(content_window_)) {
342     gfx::Rect transient_parent_rect =
343         wm::GetTransientParent(content_window_)->GetBoundsInScreen();
344     if (transient_parent_rect.height() >= size.height() &&
345         transient_parent_rect.width() >= size.width()) {
346       parent_bounds = transient_parent_rect;
347     }
348   }
349
350   gfx::Rect window_bounds(
351       parent_bounds.x() + (parent_bounds.width() - size.width()) / 2,
352       parent_bounds.y() + (parent_bounds.height() - size.height()) / 2,
353       size.width(),
354       size.height());
355   // Don't size the window bigger than the parent, otherwise the user may not be
356   // able to close or move it.
357   window_bounds.AdjustToFit(parent_bounds);
358   SetBounds(window_bounds);
359 }
360
361 void DesktopWindowTreeHostWayland::GetWindowPlacement(
362     gfx::Rect* bounds,
363     ui::WindowShowState* show_state) const {
364   *bounds = GetRestoredBounds();
365
366   if (IsMinimized()) {
367     *show_state = ui::SHOW_STATE_MINIMIZED;
368   } else if (IsFullscreen()) {
369     *show_state = ui::SHOW_STATE_FULLSCREEN;
370   } else if (IsMaximized()) {
371     *show_state = ui::SHOW_STATE_MAXIMIZED;
372   } else if (!IsActive()) {
373     *show_state = ui::SHOW_STATE_INACTIVE;
374   } else {
375     *show_state = ui::SHOW_STATE_NORMAL;
376   }
377 }
378
379 gfx::Rect DesktopWindowTreeHostWayland::GetWindowBoundsInScreen() const {
380   return bounds_;
381 }
382
383 gfx::Rect DesktopWindowTreeHostWayland::GetClientAreaBoundsInScreen() const {
384   // TODO(erg): The NativeWidgetAura version returns |bounds_|, claiming its
385   // needed for View::ConvertPointToScreen() to work
386   // correctly. DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() just
387   // asks windows what it thinks the client rect is.
388   //
389   // Attempts to calculate the rect by asking the NonClientFrameView what it
390   // thought its GetBoundsForClientView() were broke combobox drop down
391   // placement.
392   return bounds_;
393 }
394
395 gfx::Rect DesktopWindowTreeHostWayland::GetRestoredBounds() const {
396   if (!previous_bounds_.IsEmpty())
397     return previous_bounds_;
398
399   return GetWindowBoundsInScreen();
400 }
401
402 gfx::Rect DesktopWindowTreeHostWayland::GetWorkAreaBoundsInScreen() const {
403   // TODO(kalyan): Take into account wm decorations. i.e Dock, panel etc.
404   gfx::Screen *screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
405   if (!screen)
406     NOTREACHED() << "Unable to retrieve valid gfx::Screen";
407
408   gfx::Display display = screen->GetPrimaryDisplay();
409   return display.bounds();
410 }
411
412 void DesktopWindowTreeHostWayland::SetShape(gfx::NativeRegion native_region) {
413   // TODO(erg):
414   NOTIMPLEMENTED();
415 }
416
417 void DesktopWindowTreeHostWayland::Activate() {
418   if (state_ & Active)
419     return;
420
421   state_ |= Active;
422   if (state_ & Visible)
423     ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
424                                                                 ui::ACTIVE);
425 }
426
427 void DesktopWindowTreeHostWayland::Deactivate() {
428   if (!(state_ & Active))
429     return;
430
431   state_ &= ~Active;
432   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
433                                                               ui::INACTIVE);
434 }
435
436 bool DesktopWindowTreeHostWayland::IsActive() const {
437   return state_ & Active;
438 }
439
440 void DesktopWindowTreeHostWayland::Maximize() {
441   if (state_ & Maximized)
442     return;
443   if (IsMinimized() && !window_parent_)
444     native_widget_delegate_->AsWidget()->SetInitialFocus(ui::SHOW_STATE_NORMAL);
445
446   state_ |= Maximized;
447   state_ &= ~Minimized;
448   state_ &= ~Normal;
449   previous_bounds_ = bounds_;
450   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
451                                                               ui::MAXIMIZED);
452 }
453
454 void DesktopWindowTreeHostWayland::Minimize() {
455   if (state_ & Minimized)
456     return;
457
458   state_ |= Minimized;
459   previous_bounds_ = bounds_;
460   bounds_ = gfx::Rect();
461   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
462                                                               ui::MINIMIZED);
463   OnHostResized(bounds_.size());
464 }
465
466 void DesktopWindowTreeHostWayland::Restore() {
467   if (state_ & Normal)
468     return;
469
470   if (IsMinimized() && !window_parent_)
471     native_widget_delegate_->AsWidget()->SetInitialFocus(ui::SHOW_STATE_NORMAL);
472   state_ &= ~Maximized;
473   state_ &= ~Minimized;
474   state_ |= Normal;
475   bounds_ = previous_bounds_;
476   previous_bounds_ = gfx::Rect();
477   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(
478       window_, ui::RESTORE, bounds_.width(), bounds_.height());
479   native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
480   OnHostResized(bounds_.size());
481 }
482
483 bool DesktopWindowTreeHostWayland::IsMaximized() const {
484   return state_ & Maximized;
485 }
486
487 bool DesktopWindowTreeHostWayland::IsMinimized() const {
488   return state_ & Minimized;
489 }
490
491 void DesktopWindowTreeHostWayland::OnCaptureReleased() {
492   OnHostLostWindowCapture();
493   native_widget_delegate_->OnMouseCaptureLost();
494 }
495
496 bool DesktopWindowTreeHostWayland::HasCapture() const {
497   return g_delegate_ozone_wayland_->GetCurrentCapture() == this;
498 }
499
500 bool DesktopWindowTreeHostWayland::IsAlwaysOnTop() const {
501   NOTIMPLEMENTED();
502   return false;
503 }
504
505 void DesktopWindowTreeHostWayland::SetVisibleOnAllWorkspaces(
506     bool always_visible) {
507   NOTIMPLEMENTED();
508 }
509
510 void DesktopWindowTreeHostWayland::SetAlwaysOnTop(bool always_on_top) {
511   // TODO(erg):
512   NOTIMPLEMENTED();
513 }
514
515 bool DesktopWindowTreeHostWayland::SetWindowTitle(const base::string16& title) {
516   if (title.compare(title_)) {
517     ui::WindowStateChangeHandler::GetInstance()->SetWidgetTitle(window_, title);
518     title_ = title;
519     return true;
520   }
521
522   return false;
523 }
524
525 void DesktopWindowTreeHostWayland::ClearNativeFocus() {
526   // This method is weird and misnamed. Instead of clearing the native focus,
527   // it sets the focus to our |content_window_|, which will trigger a cascade
528   // of focus changes into views.
529   if (content_window_ && aura::client::GetFocusClient(content_window_) &&
530       content_window_->Contains(
531           aura::client::GetFocusClient(content_window_)->GetFocusedWindow())) {
532     aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
533   }
534 }
535
536 Widget::MoveLoopResult DesktopWindowTreeHostWayland::RunMoveLoop(
537     const gfx::Vector2d& drag_offset,
538     Widget::MoveLoopSource source,
539     Widget::MoveLoopEscapeBehavior escape_behavior) {
540   NOTIMPLEMENTED();
541   return Widget::MOVE_LOOP_SUCCESSFUL;
542 }
543
544 void DesktopWindowTreeHostWayland::EndMoveLoop() {
545   NOTIMPLEMENTED();
546 }
547
548 void DesktopWindowTreeHostWayland::SetVisibilityChangedAnimationsEnabled(
549     bool value) {
550   // Much like the previous NativeWidgetGtk, we don't have anything to do here.
551 }
552
553 bool DesktopWindowTreeHostWayland::ShouldUseNativeFrame() const {
554   return false;
555 }
556
557 bool DesktopWindowTreeHostWayland::ShouldWindowContentsBeTransparent() const {
558   return false;
559 }
560
561 void DesktopWindowTreeHostWayland::FrameTypeChanged() {
562   Widget::FrameType new_type =
563     native_widget_delegate_->AsWidget()->frame_type();
564   if (new_type == Widget::FRAME_TYPE_DEFAULT) {
565     // The default is determined by Widget::InitParams::remove_standard_frame
566     // and does not change.
567     return;
568   }
569
570   // Replace the frame and layout the contents. Even though we don't have a
571   // swapable glass frame like on Windows, we still replace the frame because
572   // the button assets don't update otherwise.
573   native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame();
574 }
575
576 void DesktopWindowTreeHostWayland::SetFullscreen(bool fullscreen) {
577   if ((state_ & FullScreen) == fullscreen)
578     return;
579
580   if (fullscreen) {
581     state_ |= FullScreen;
582     state_ &= ~Normal;
583   } else {
584     state_ &= ~FullScreen;
585   }
586
587   if (!(state_ & FullScreen)) {
588     if (state_ & Maximized) {
589       previous_bounds_ = previous_maximize_bounds_;
590       previous_maximize_bounds_ = gfx::Rect();
591       ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(
592           window_, ui::MAXIMIZED);
593     } else {
594       Restore();
595     }
596   } else {
597     if (state_ & Maximized)
598       previous_maximize_bounds_ = previous_bounds_;
599
600     previous_bounds_ = bounds_;
601     gfx::Screen *screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
602     if (!screen)
603       NOTREACHED() << "Unable to retrieve valid gfx::Screen";
604
605     bounds_ = screen->GetPrimaryDisplay().bounds();
606     // We could use HandleConfigure in ShellSurface to set the correct bounds of
607     // egl window associated with this opaque handle. How ever, this would need
608     // to handle race conditions and ensure correct size is set for
609     // wl_egl_window_resize before eglsurface is resized. Passing window size
610     // attributes already here, ensures that wl_egl_window_resize is resized
611     // before eglsurface is resized. This doesn't add any extra overhead as the
612     // IPC call needs to be done.
613     ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(
614         window_, ui::FULLSCREEN, bounds_.width(), bounds_.height());
615     OnHostResized(bounds_.size());
616   }
617 }
618
619 bool DesktopWindowTreeHostWayland::IsFullscreen() const {
620   return state_ & FullScreen;
621 }
622
623 void DesktopWindowTreeHostWayland::SetOpacity(unsigned char opacity) {
624   // TODO(erg):
625   NOTIMPLEMENTED();
626 }
627
628 void DesktopWindowTreeHostWayland::SetWindowIcons(
629     const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
630   // TODO(erg):
631   NOTIMPLEMENTED();
632 }
633
634 void DesktopWindowTreeHostWayland::InitModalType(ui::ModalType modal_type) {
635   switch (modal_type) {
636     case ui::MODAL_TYPE_NONE:
637       break;
638     default:
639       // TODO(erg): Figure out under what situations |modal_type| isn't
640       // none. The comment in desktop_native_widget_aura.cc suggests that this
641       // is rare.
642       NOTIMPLEMENTED();
643   }
644 }
645
646 void DesktopWindowTreeHostWayland::FlashFrame(bool flash_frame) {
647   // TODO(erg):
648   NOTIMPLEMENTED();
649 }
650
651 void DesktopWindowTreeHostWayland::OnRootViewLayout() {
652   NOTIMPLEMENTED();
653 }
654
655 void DesktopWindowTreeHostWayland::OnNativeWidgetFocus() {
656   native_widget_delegate_->AsWidget()->GetInputMethod()->OnFocus();
657 }
658
659 void DesktopWindowTreeHostWayland::OnNativeWidgetBlur() {
660   if (window_)
661     native_widget_delegate_->AsWidget()->GetInputMethod()->OnBlur();
662 }
663
664 bool DesktopWindowTreeHostWayland::IsAnimatingClosed() const {
665   return false;
666 }
667
668 bool DesktopWindowTreeHostWayland::IsTranslucentWindowOpacitySupported() const {
669   return false;
670 }
671
672 ////////////////////////////////////////////////////////////////////////////////
673 // DesktopWindowTreeHostWayland, aura::WindowTreeHost implementation:
674
675 ui::EventSource* DesktopWindowTreeHostWayland::GetEventSource() {
676   NOTIMPLEMENTED();
677   return NULL;
678 }
679
680 gfx::AcceleratedWidget DesktopWindowTreeHostWayland::GetAcceleratedWidget() {
681   return window_;
682 }
683
684 void DesktopWindowTreeHostWayland::Show() {
685   if (state_ & Visible)
686     return;
687
688   // Window is being shown, set the state as active to be able to handle events.
689   Activate();
690
691   state_ |= Visible;
692   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
693                                                               ui::SHOW);
694   native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);
695 }
696
697 void DesktopWindowTreeHostWayland::Hide() {
698   if (!(state_ & Visible))
699     return;
700
701   state_ &= ~Visible;
702   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
703                                                               ui::HIDE);
704   native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);
705 }
706
707 gfx::Rect DesktopWindowTreeHostWayland::GetBounds() const {
708   return bounds_;
709 }
710
711 void DesktopWindowTreeHostWayland::SetBounds(const gfx::Rect& bounds) {
712   bool origin_changed = bounds_.origin() != bounds.origin();
713   bool size_changed = bounds_.size() != bounds.size();
714
715   bounds_ = bounds;
716
717   if (origin_changed)
718     native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
719   if (size_changed)
720     OnHostResized(bounds.size());
721   else
722     compositor()->ScheduleRedrawRect(bounds);
723 }
724
725 gfx::Point DesktopWindowTreeHostWayland::GetLocationOnNativeScreen() const {
726   return bounds_.origin();
727 }
728
729 void DesktopWindowTreeHostWayland::SetCapture() {
730   g_delegate_ozone_wayland_->SetCapture(this);
731 }
732
733 void DesktopWindowTreeHostWayland::ReleaseCapture() {
734   g_delegate_ozone_wayland_->SetCapture(NULL);
735 }
736
737 void DesktopWindowTreeHostWayland::SetCursorNative(gfx::NativeCursor cursor) {
738   // TODO(kalyan): Add support for custom cursor.
739   ui::WindowStateChangeHandler::GetInstance()->SetWidgetCursor(
740       cursor.native_type());
741 }
742
743 void DesktopWindowTreeHostWayland::OnCursorVisibilityChangedNative(bool show) {
744   // TODO(erg): Conditional on us enabling touch on desktop linux builds, do
745   // the same tap-to-click disabling here that chromeos does.
746 }
747
748 void DesktopWindowTreeHostWayland::MoveCursorToNative(
749     const gfx::Point& location) {
750   NOTIMPLEMENTED();
751 }
752
753 void DesktopWindowTreeHostWayland::PostNativeEvent(
754     const base::NativeEvent& native_event) {
755   NOTIMPLEMENTED();
756 }
757
758 ////////////////////////////////////////////////////////////////////////////////
759 // DesktopWindowTreeHostWayland, Private implementation:
760
761 void DesktopWindowTreeHostWayland::HandleNativeWidgetActivationChanged(
762     bool active) {
763   // We can skip during initialization phase.
764   if (!state_)
765     return;
766
767   if (active)
768     OnHostActivated();
769
770   desktop_native_widget_aura_->HandleActivationChanged(active);
771   native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
772 }
773
774 void DesktopWindowTreeHostWayland::HandleWindowResize(unsigned width,
775                                                       unsigned height) {
776   unsigned current_width = bounds_.width();
777   unsigned current_height = bounds_.height();
778   if ((current_width == width) && (current_height == height)) {
779     compositor()->ScheduleRedrawRect(bounds_);
780   } else {
781     bounds_ = gfx::Rect(bounds_.x(), bounds_.y(), width, height);
782     OnHostResized(bounds_.size());
783     Widget* widget = native_widget_delegate_->AsWidget();
784     NonClientView* non_client_view = widget->non_client_view();
785     // non_client_view may be NULL, especially during creation.
786     if (non_client_view) {
787       non_client_view->client_view()->InvalidateLayout();
788       non_client_view->InvalidateLayout();
789     }
790     widget->GetRootView()->Layout();
791   }
792 }
793
794 void DesktopWindowTreeHostWayland::HandleWindowUnminimized() {
795   state_ &= ~Minimized;
796   bounds_ = previous_bounds_;
797   previous_bounds_ = gfx::Rect();
798   OnHostResized(bounds_.size());
799 }
800
801 void DesktopWindowTreeHostWayland::HandleCommit(const std::string& text) {
802   ui::InputMethodAuraLinux* inputMethod =
803       static_cast<ui::InputMethodAuraLinux*>(desktop_native_widget_aura_->
804       input_method_event_filter()->input_method());
805   inputMethod->OnCommit(base::string16(base::ASCIIToUTF16(text.c_str())));
806 }
807
808 void DesktopWindowTreeHostWayland::HandlePreeditChanged(const std::string& text,
809   const std::string& commit) {
810   ui::CompositionText composition_text;
811   composition_text.text = base::string16(base::ASCIIToUTF16(text.c_str()));
812   ui::InputMethodAuraLinux* inputMethod =
813       static_cast<ui::InputMethodAuraLinux*>(desktop_native_widget_aura_->
814       input_method_event_filter()->input_method());
815   inputMethod->OnPreeditChanged(composition_text);
816 }
817
818 // static
819 VIEWS_EXPORT ui::NativeTheme*
820 DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
821   const views::LinuxUI* linux_ui = views::LinuxUI::instance();
822   if (linux_ui) {
823     ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window);
824     if (native_theme)
825       return native_theme;
826   }
827
828   return ui::NativeTheme::instance();
829 }
830
831 }  // namespace views