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

Side by Side Diff: views/widget/native_widget_wayland.cc

Issue 7464027: Wayland support for views. views_desktop on Wayland. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Updated files to latest and fixed changes for dependent CLs Created 9 years, 4 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 | Annotate | Revision Log
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 "views/widget/native_widget_wayland.h"
6
7 #include <cairo.h>
8 #include <cairo-gl.h>
9 #include <EGL/egl.h>
10 #include <GL/gl.h>
11 #include <wayland-egl.h>
12
13 #include "base/memory/scoped_ptr.h"
14 #include "ui/base/view_prop.h"
15 #include "ui/gfx/canvas_skia_paint.h"
16 #include "ui/gfx/compositor/compositor.h"
17 #include "ui/gfx/gl/gl_surface.h"
18 #include "ui/gfx/gl/gl_surface_egl.h"
19 #include "ui/wayland/events/wayland_event.h"
20 #include "ui/wayland/wayland_display.h"
21 #include "ui/wayland/wayland_input_device.h"
22 #include "ui/wayland/wayland_screen.h"
23 #include "ui/wayland/wayland_window.h"
24 #include "views/ime/input_method_wayland.h"
25 #include "views/views_delegate.h"
26 #include "views/widget/native_widget_views.h"
27 #include "views/widget/root_view.h"
28 #include "views/widget/tooltip_manager_views.h"
29
30 using ui::ViewProp;
31
32 namespace views {
33
34 namespace {
35
36 // Links the WaylandWidget to its NativeWidget.
37 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
38
39 } // namespace
40
41 NativeWidgetWayland::NativeWidgetWayland(
42 internal::NativeWidgetDelegate* delegate)
43 : delegate_(delegate),
44 ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
45 ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
46 wayland_display_(
47 ui:: WaylandDisplay::GetDisplay(gfx::GLSurfaceEGL::GetNativeDisplay())),
48 wayland_window_(new ui::WaylandWindow(this, wayland_display_)),
49 surface_data_key_(),
50 damage_area_() {
51 }
52
53 NativeWidgetWayland::~NativeWidgetWayland() {
54 input_method_.reset();
55 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
56 delete delegate_;
57
58 if (!View::get_use_acceleration_when_possible()) {
59 cairo_surface_destroy(cairo_surface_);
60 cairo_device_destroy(device_);
61 }
62
63 if (egl_window_)
64 wl_egl_window_destroy(egl_window_);
65
66 if (wayland_window_)
67 delete wayland_window_;
68 }
69
70 void NativeWidgetWayland::InitNativeWidget(const Widget::InitParams& params) {
71 // Cannot create a window with a size smaller than 1x1
72 allocation_.set_width(std::max(params.bounds.width(), 1));
73 allocation_.set_height(std::max(params.bounds.height(), 1));
74
75 egl_window_ = wl_egl_window_create(wayland_window_->surface(),
76 allocation_.width(),
77 allocation_.height(),
78 wayland_display_->visual());
79
80 SetNativeWindowProperty(kNativeWidgetKey, this);
81
82 if (View::get_use_acceleration_when_possible()) {
83 if (Widget::compositor_factory()) {
84 compositor_ = (*Widget::compositor_factory())();
85 } else {
86 compositor_ = ui::Compositor::Create(egl_window_, allocation_.size());
87 }
88 if (compositor_.get())
89 delegate_->AsWidget()->GetRootView()->SetPaintToLayer(true);
90 } else {
91 surface_ = gfx::GLSurface::CreateViewGLSurface(false, egl_window_);
92 context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get());
93
94 if (!context_->MakeCurrent(surface_.get()))
95 DLOG(ERROR) << "Failed to make surface current";
96
97 device_ = cairo_egl_device_create(gfx::GLSurfaceEGL::GetHardwareDisplay(),
98 context_->GetHandle());
99 if (cairo_device_status(device_) != CAIRO_STATUS_SUCCESS)
100 DLOG(ERROR) << "Failed to create cairo egl device";
101
102 cairo_surface_ = cairo_gl_surface_create_for_egl(device_,
103 surface_->GetHandle(),
104 allocation_.width(),
105 allocation_.height());
106 cairo_surface_set_user_data(cairo_surface_,
107 &surface_data_key_,
108 this,
109 NULL);
110 }
111
112 delegate_->OnNativeWidgetCreated();
113
114 input_method_.reset(new InputMethodWayland(this));
115 input_method_->Init(GetWidget());
116
117 if (params.type != Widget::InitParams::TYPE_TOOLTIP) {
118 // TODO(dnicoara) Enable this once it works with Wayland
119 /*
120 views::TooltipManagerViews* manager = new views::TooltipManagerViews(
121 static_cast<internal::RootView*>(GetWidget()->GetRootView()));
122 tooltip_manager_.reset(manager);
123 */
124 }
125
126 // TODO(dnicoara) This should be removed when we can specify the (x, y)
127 // coordinates for a window. We use fullscreen since it will center the
128 // window rather than give it random (x, y) coordinates.
129 wayland_window_->set_fullscreen(true);
130 Show();
131 OnPaint(allocation_);
132 }
133
134 NonClientFrameView* NativeWidgetWayland::CreateNonClientFrameView() {
135 return NULL;
136 }
137
138 void NativeWidgetWayland::UpdateFrameAfterFrameChange() {
139 NOTIMPLEMENTED();
140 }
141
142 bool NativeWidgetWayland::ShouldUseNativeFrame() const {
143 NOTIMPLEMENTED();
144 return false;
145 }
146
147 void NativeWidgetWayland::FrameTypeChanged() {
148 // Called when the Theme has changed, so forward the event to the root
149 // widget
150 GetWidget()->ThemeChanged();
151 GetWidget()->GetRootView()->SchedulePaint();
152 }
153
154 Widget* NativeWidgetWayland::GetWidget() {
155 return delegate_->AsWidget();
156 }
157
158 const Widget* NativeWidgetWayland::GetWidget() const {
159 return delegate_->AsWidget();
160 }
161
162 gfx::NativeView NativeWidgetWayland::GetNativeView() const {
163 return wayland_window_;
164 }
165
166 gfx::NativeWindow NativeWidgetWayland::GetNativeWindow() const {
167 return wayland_window_;
168 }
169
170 Widget* NativeWidgetWayland::GetTopLevelWidget() {
171 NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView());
172 return native_widget ? native_widget->GetWidget() : NULL;
173 }
174
175 const ui::Compositor* NativeWidgetWayland::GetCompositor() const {
176 return compositor_.get();
177 }
178
179 ui::Compositor* NativeWidgetWayland::GetCompositor() {
180 return compositor_.get();
181 }
182
183 void NativeWidgetWayland::MarkLayerDirty() {
184 }
185
186 void NativeWidgetWayland::CalculateOffsetToAncestorWithLayer(
187 gfx::Point* offset,
188 View** ancestor) {
189 }
190
191 void NativeWidgetWayland::ViewRemoved(View* view) {
192 NOTIMPLEMENTED();
193 }
194
195 void NativeWidgetWayland::SetNativeWindowProperty(const char* name,
196 void* value) {
197 // Remove the existing property (if any).
198 for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) {
199 if ((*i)->Key() == name) {
200 props_.erase(i);
201 break;
202 }
203 }
204
205 if (value)
206 props_.push_back(new ViewProp(wayland_window_, name, value));
207 }
208
209 void* NativeWidgetWayland::GetNativeWindowProperty(const char* name) const {
210 return ViewProp::GetValue(wayland_window_, name);
211 }
212
213 TooltipManager* NativeWidgetWayland::GetTooltipManager() const {
214 return tooltip_manager_.get();
215 }
216
217 bool NativeWidgetWayland::IsScreenReaderActive() const {
218 return false;
219 }
220
221 void NativeWidgetWayland::SendNativeAccessibilityEvent(
222 View* view,
223 ui::AccessibilityTypes::Event event_type) {
224 NOTIMPLEMENTED();
225 }
226
227 void NativeWidgetWayland::SetMouseCapture() {
228 NOTIMPLEMENTED();
229 }
230
231 void NativeWidgetWayland::ReleaseMouseCapture() {
232 NOTIMPLEMENTED();
233 }
234
235 bool NativeWidgetWayland::HasMouseCapture() const {
236 NOTIMPLEMENTED();
237 return true;
238 }
239
240
241 void NativeWidgetWayland::SetKeyboardCapture() {
242 NOTIMPLEMENTED();
243 }
244
245
246 void NativeWidgetWayland::ReleaseKeyboardCapture() {
247 NOTIMPLEMENTED();
248 }
249
250
251 bool NativeWidgetWayland::HasKeyboardCapture() const {
252 NOTIMPLEMENTED();
253 return true;
254 }
255
256 InputMethod* NativeWidgetWayland::GetInputMethodNative() {
257 if (!input_method_.get()) {
258 input_method_.reset(new InputMethodWayland(this));
259 input_method_->Init(GetWidget());
260 }
261 return input_method_.get();
262 }
263
264 void NativeWidgetWayland::ReplaceInputMethod(InputMethod* input_method) {
265 input_method_.reset(input_method);
266 if (input_method) {
267 input_method->set_delegate(this);
268 input_method->Init(GetWidget());
269 }
270 }
271
272 void NativeWidgetWayland::CenterWindow(const gfx::Size& size) {
273 NOTIMPLEMENTED();
274 }
275
276 void NativeWidgetWayland::GetWindowBoundsAndMaximizedState(
277 gfx::Rect* bounds,
278 bool* maximized) const {
279 NOTIMPLEMENTED();
280
281 }
282
283 void NativeWidgetWayland::SetWindowTitle(const std::wstring& title) {
284 }
285
286 void NativeWidgetWayland::SetWindowIcons(const SkBitmap& window_icon,
287 const SkBitmap& app_icon) {
288 }
289
290 void NativeWidgetWayland::SetAccessibleName(const std::wstring& name) {
291 }
292
293 void NativeWidgetWayland::SetAccessibleRole(
294 ui::AccessibilityTypes::Role role) {
295 }
296
297 void NativeWidgetWayland::SetAccessibleState(
298 ui::AccessibilityTypes::State state) {
299 }
300
301 void NativeWidgetWayland::BecomeModal() {
302 NOTIMPLEMENTED();
303 }
304
305 gfx::Rect NativeWidgetWayland::GetWindowScreenBounds() const {
306 return GetClientAreaScreenBounds();
307 }
308
309 gfx::Rect NativeWidgetWayland::GetClientAreaScreenBounds() const {
310 return allocation_;
311 }
312
313 gfx::Rect NativeWidgetWayland::GetRestoredBounds() const {
314 return GetWindowScreenBounds();
315 }
316
317 void NativeWidgetWayland::SetBounds(const gfx::Rect& bounds) {
318 saved_allocation_ = allocation_;
319 allocation_ = bounds;
320
321 // TODO(dnicoara) This needs to be updated to include (x, y).
322 wl_egl_window_resize(egl_window_,
323 allocation_.width(),
324 allocation_.height(),
325 0, 0);
326 if (!View::get_use_acceleration_when_possible()) {
327 cairo_gl_surface_set_size(cairo_surface_,
328 allocation_.width(),
329 allocation_.height());
330 }
331
332 if (compositor_.get())
333 compositor_->OnWidgetSizeChanged(allocation_.size());
334 delegate_->OnNativeWidgetSizeChanged(allocation_.size());
335 }
336
337 void NativeWidgetWayland::SetSize(const gfx::Size& size) {
338 gfx::Rect new_alloc = allocation_;
339 new_alloc.set_size(size);
340
341 SetBounds(new_alloc);
342 }
343
344 void NativeWidgetWayland::SetBoundsConstrained(const gfx::Rect& bounds,
345 Widget* other_widget) {
346 // TODO(dnicoara) Need to take into account |other_widget|.
347 SetBounds(bounds);
348 }
349
350 void NativeWidgetWayland::MoveAbove(gfx::NativeView native_view) {
351 NOTIMPLEMENTED();
352 }
353
354 void NativeWidgetWayland::MoveToTop() {
355 NOTIMPLEMENTED();
356 }
357
358 void NativeWidgetWayland::SetShape(gfx::NativeRegion shape) {
359 NOTIMPLEMENTED();
360 }
361
362 void NativeWidgetWayland::Close() {
363 Hide();
364 if (close_widget_factory_.empty()) {
365 MessageLoop::current()->PostTask(FROM_HERE,
366 close_widget_factory_.NewRunnableMethod(
367 &NativeWidgetWayland::CloseNow));
368 }
369 }
370
371 void NativeWidgetWayland::CloseNow() {
372 delegate_->OnNativeWidgetDestroying();
373 delegate_->OnNativeWidgetDestroyed();
374 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
375 delete this;
376 }
377
378 void NativeWidgetWayland::EnableClose(bool enable) {
379 NOTIMPLEMENTED();
380 }
381
382 void NativeWidgetWayland::Show() {
383 wayland_window_->SetVisible(true);
384 delegate_->OnNativeWidgetVisibilityChanged(true);
385 }
386
387 void NativeWidgetWayland::Hide() {
388 wayland_window_->SetVisible(false);
389 delegate_->OnNativeWidgetVisibilityChanged(false);
390 }
391
392 void NativeWidgetWayland::ShowMaximizedWithBounds(
393 const gfx::Rect& restored_bounds) {
394 Show();
395 Maximize();
396 saved_allocation_ = restored_bounds;
397 }
398
399 void NativeWidgetWayland::ShowWithState(ShowState state) {
400 NOTIMPLEMENTED();
401 }
402
403 bool NativeWidgetWayland::IsVisible() const {
404 return wayland_window_->IsVisible();
405 }
406
407 void NativeWidgetWayland::Activate() {
408 NOTIMPLEMENTED();
409 }
410
411 void NativeWidgetWayland::Deactivate() {
412 NOTIMPLEMENTED();
413 }
414
415 bool NativeWidgetWayland::IsActive() const {
416 NOTIMPLEMENTED();
417 return true;
418 }
419
420 void NativeWidgetWayland::SetAlwaysOnTop(bool always_on_top) {
421 NOTIMPLEMENTED();
422 }
423
424 void NativeWidgetWayland::Maximize() {
425 std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList();
426
427 if (screens.empty())
428 return;
429
430 // TODO(dnicoara) We need to intersect the current coordinates with the
431 // screen ones and decide the correct screen to fullscreen on.
432 ui::WaylandScreen* screen = screens.front();
433
434 SetBounds(screen->GetAllocation());
435 }
436
437 void NativeWidgetWayland::Minimize() {
438 NOTIMPLEMENTED();
439 }
440
441 bool NativeWidgetWayland::IsMaximized() const {
442 NOTIMPLEMENTED();
443 return true;
444 }
445
446 bool NativeWidgetWayland::IsMinimized() const {
447 NOTIMPLEMENTED();
448 return false;
449 }
450
451 void NativeWidgetWayland::Restore() {
452 NOTIMPLEMENTED();
453 }
454
455 void NativeWidgetWayland::SetFullscreen(bool fullscreen) {
456 gfx::Rect new_allocation = allocation_;
457
458 if (fullscreen) {
459 std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList();
460
461 if (screens.empty())
462 return;
463
464 // TODO(dnicoara) What does it mean to be fullscreen when having multiple
465 // monitors? If we're going fullscreen only on one screen then we need to
466 // intersect the current coordinates with the screen ones and decide the
467 // correct screen to fullscreen on.
468 ui::WaylandScreen* screen = screens.front();
469 new_allocation = screen->GetAllocation();
470 } else {
471 new_allocation = saved_allocation_;
472 }
473
474 wayland_window_->set_fullscreen(fullscreen);
475 SetBounds(new_allocation);
476 }
477
478 bool NativeWidgetWayland::IsFullscreen() const {
479 return wayland_window_->fullscreen();
480 }
481
482 void NativeWidgetWayland::SetOpacity(unsigned char opacity) {
483 NOTIMPLEMENTED();
484 }
485
486 void NativeWidgetWayland::SetUseDragFrame(bool use_drag_frame) {
487 NOTIMPLEMENTED();
488 }
489
490 bool NativeWidgetWayland::IsAccessibleWidget() const {
491 NOTIMPLEMENTED();
492 return true;
493 }
494
495 bool NativeWidgetWayland::ContainsNativeView(
496 gfx::NativeView native_view) const {
497 NOTIMPLEMENTED();
498 return true;
499 }
500
501 void NativeWidgetWayland::RunShellDrag(View* view,
502 const ui::OSExchangeData& data,
503 int operation) {
504 NOTIMPLEMENTED();
505 }
506
507 gboolean NativeWidgetWayland::IdleRedraw(void* ptr) {
508 NativeWidgetWayland* widget = static_cast<NativeWidgetWayland*>(ptr);
509 gfx::Rect damage_area = widget->damage_area_;
510 widget->damage_area_ = gfx::Rect();
511
512 widget->OnPaint(damage_area);
513
514 return FALSE;
515 }
516
517 void NativeWidgetWayland::SchedulePaintInRect(const gfx::Rect& rect) {
518 if (damage_area_.IsEmpty())
519 g_idle_add(NativeWidgetWayland::IdleRedraw, this);
520
521 damage_area_ = damage_area_.Union(rect);
522 }
523
524 void NativeWidgetWayland::SetCursor(gfx::NativeCursor cursor) {
525 NOTIMPLEMENTED();
526 }
527
528
529 void NativeWidgetWayland::ClearNativeFocus() {
530 NOTIMPLEMENTED();
531 }
532
533
534 void NativeWidgetWayland::FocusNativeView(gfx::NativeView native_view) {
535 NOTIMPLEMENTED();
536 }
537
538 // Overridden from NativeWidget
539 gfx::AcceleratedWidget NativeWidgetWayland::GetAcceleratedWidget() {
540 return egl_window_;
541 }
542
543
544 // Overridden from internal::InputMethodDelegate
545 void NativeWidgetWayland::DispatchKeyEventPostIME(const KeyEvent& key) {
546 NOTIMPLEMENTED();
547 delegate_->OnKeyEvent(key);
548 }
549
550 /////////////////////////////////////////////////////////////////////////////
551 // NativeWidgetWayland, private, event handlers
552
553 void NativeWidgetWayland::OnPaint(gfx::Rect damage_area) {
554 if (!delegate_->OnNativeWidgetPaintAccelerated(damage_area)) {
555
556 // This is required since the CanvasSkiaPaint damages the surface
557 // in the destructor so we need to have this done before calling
558 // swapbuffers.
559 {
560 cairo_rectangle_int_t region = damage_area.ToCairoRectangle();
561 gfx::CanvasSkiaPaint canvas(cairo_surface_, &region);
562 if (!canvas.is_empty()) {
563 canvas.set_composite_alpha(false);
564 delegate_->OnNativeWidgetPaint(&canvas);
565 }
566 }
567
568 // Have cairo swap buffers, then let Wayland know of the damaged area.
569 cairo_gl_surface_swapbuffers(cairo_surface_);
570 wl_surface_damage(wayland_window_->surface(),
571 damage_area.x(), damage_area.y(),
572 damage_area.width(), damage_area.height());
573 }
574 }
575
576 void NativeWidgetWayland::OnMotionNotify(ui::WaylandEvent event) {
577 MouseEvent mouse_event(&event);
578 delegate_->OnMouseEvent(mouse_event);
579 }
580
581 void NativeWidgetWayland::OnButtonNotify(ui::WaylandEvent event) {
582 if (event.button.button == ui::SCROLL_UP ||
583 event.button.button == ui::SCROLL_DOWN) {
584 MouseWheelEvent mouse_event(&event);
585 delegate_->OnMouseEvent(mouse_event);
586 } else {
587 MouseEvent mouse_event(&event);
588 delegate_->OnMouseEvent(mouse_event);
589 }
590 }
591
592 void NativeWidgetWayland::OnKeyNotify(ui::WaylandEvent event) {
593 KeyEvent key_event(&event);
594 if (input_method_.get())
595 input_method_->DispatchKeyEvent(key_event);
596 else
597 DispatchKeyEventPostIME(key_event);
598 }
599
600 void NativeWidgetWayland::OnPointerFocus(ui::WaylandEvent event) {
601 MouseEvent mouse_event(&event);
602 delegate_->OnMouseEvent(mouse_event);
603 }
604
605 void NativeWidgetWayland::OnKeyboardFocus(ui::WaylandEvent event) {
606 if (input_method_.get()) {
607 if (event.keyboard_focus.state)
608 input_method_->OnFocus();
609 else
610 input_method_->OnBlur();
611 }
612 }
613
614 void NativeWidgetWayland::OnGeometryChange(ui::WaylandEvent event) {
615 SetSize(gfx::Size(event.geometry_change.width,
616 event.geometry_change.height));
617 }
618
619 /////////////////////////////////////////////////////////////////////////////
620 // Widget
621
622 // static
623 bool Widget::ConvertRect(const Widget* source,
624 const Widget* target,
625 gfx::Rect* rect) {
626 DCHECK(source);
627 DCHECK(target);
628 DCHECK(rect);
629
630 gfx::NativeView source_widget = source->GetNativeView();
631 gfx::NativeView target_widget = target->GetNativeView();
632 if (source_widget == target_widget)
633 return true;
634
635 if (!source_widget || !target_widget)
636 return false;
637
638 NOTIMPLEMENTED();
639 return false;
640 }
641
642 namespace internal {
643
644 /////////////////////////////////////////////////////////////////////////////
645 // NativeWidget
646
647 // static
648 NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
649 internal::NativeWidgetDelegate* delegate) {
650 if (Widget::IsPureViews() &&
651 ViewsDelegate::views_delegate->GetDefaultParentView()) {
652 return new NativeWidgetViews(delegate);
653 }
654 return new NativeWidgetWayland(delegate);
655 }
656
657 // static
658 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
659 gfx::NativeView native_view) {
660 return reinterpret_cast<NativeWidgetWayland*>(
661 ViewProp::GetValue(native_view, kNativeWidgetKey));
662 }
663
664 // static
665 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
666 gfx::NativeWindow native_window) {
667 return GetNativeWidgetForNativeView(native_window);
668 }
669
670 // static
671 NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
672 gfx::NativeView native_view) {
673 // TODO(dnicoara) What would be the best way to implement this?
674 // Since there isn't any actual parenting concept in Wayland, we could
675 // implement it using WaylandWindow->SetParent/GetParent calls.
676 return GetNativeWidgetForNativeView(native_view);
677 }
678
679 // static
680 void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
681 Widget::Widgets* children) {
682 NOTIMPLEMENTED();
683 if (!native_view)
684 return;
685 }
686
687 // static
688 void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
689 gfx::NativeView new_parent) {
690 NOTIMPLEMENTED();
691 if (!native_view)
692 return;
693 }
694
695 // static
696 bool NativeWidgetPrivate::IsMouseButtonDown() {
697 NOTIMPLEMENTED();
698 return false;
699 }
700
701 } // namespace internal
702
703 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698