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