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

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 native_widget_wayland.cc to match compositor changes Created 9 years, 3 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
« no previous file with comments | « views/widget/native_widget_wayland.h ('k') | views/widget/tooltip_manager_views.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 "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 <algorithm>
14 #include <list>
15
16 #include "base/memory/scoped_ptr.h"
17 #include "ui/base/view_prop.h"
18 #include "ui/gfx/canvas_skia_paint.h"
19 #include "ui/gfx/compositor/compositor.h"
20 #include "ui/gfx/gl/gl_surface.h"
21 #include "ui/gfx/gl/gl_surface_egl.h"
22 #include "ui/wayland/events/wayland_event.h"
23 #include "ui/wayland/wayland_display.h"
24 #include "ui/wayland/wayland_input_device.h"
25 #include "ui/wayland/wayland_screen.h"
26 #include "ui/wayland/wayland_window.h"
27 #include "views/ime/input_method_wayland.h"
28 #include "views/views_delegate.h"
29 #include "views/widget/native_widget_views.h"
30 #include "views/widget/root_view.h"
31 #include "views/widget/tooltip_manager_views.h"
32
33 using ui::ViewProp;
34
35 namespace views {
36
37 namespace {
38
39 // Links the WaylandWidget to its NativeWidget.
40 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
41
42 } // namespace
43
44 NativeWidgetWayland::NativeWidgetWayland(
45 internal::NativeWidgetDelegate* delegate)
46 : delegate_(delegate),
47 ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
48 ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
49 has_mouse_capture_(false),
50 wayland_display_(
51 ui:: WaylandDisplay::GetDisplay(gfx::GLSurfaceEGL::GetNativeDisplay())),
52 wayland_window_(new ui::WaylandWindow(this, wayland_display_)),
53 surface_data_key_(),
54 damage_area_() {
55 }
56
57 NativeWidgetWayland::~NativeWidgetWayland() {
58 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
59 delete delegate_;
60
61 if (!View::get_use_acceleration_when_possible()) {
62 cairo_surface_destroy(cairo_surface_);
63 cairo_device_destroy(device_);
64 }
65
66 if (egl_window_)
67 wl_egl_window_destroy(egl_window_);
68
69 if (wayland_window_)
70 delete wayland_window_;
71 }
72
73 void NativeWidgetWayland::InitNativeWidget(const Widget::InitParams& params) {
74 // Cannot create a window with a size smaller than 1x1
75 allocation_.set_width(std::max(params.bounds.width(), 1));
76 allocation_.set_height(std::max(params.bounds.height(), 1));
77
78 egl_window_ = wl_egl_window_create(wayland_window_->surface(),
79 allocation_.width(),
80 allocation_.height(),
81 wayland_display_->visual());
82
83 SetNativeWindowProperty(kNativeWidgetKey, this);
84
85 if (View::get_use_acceleration_when_possible()) {
86 if (Widget::compositor_factory()) {
87 compositor_ = (*Widget::compositor_factory())();
88 } else {
89 compositor_ = ui::Compositor::Create(egl_window_, allocation_.size());
90 }
91 if (compositor_.get())
92 delegate_->AsWidget()->GetRootView()->SetPaintToLayer(true);
93 } else {
94 surface_ = gfx::GLSurface::CreateViewGLSurface(false, egl_window_);
95 context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get());
96
97 if (!context_->MakeCurrent(surface_.get()))
98 DLOG(ERROR) << "Failed to make surface current";
99
100 device_ = cairo_egl_device_create(gfx::GLSurfaceEGL::GetHardwareDisplay(),
101 context_->GetHandle());
102 if (cairo_device_status(device_) != CAIRO_STATUS_SUCCESS)
103 DLOG(ERROR) << "Failed to create cairo egl device";
104
105 cairo_surface_ = cairo_gl_surface_create_for_egl(device_,
106 surface_->GetHandle(),
107 allocation_.width(),
108 allocation_.height());
109 cairo_surface_set_user_data(cairo_surface_,
110 &surface_data_key_,
111 this,
112 NULL);
113 }
114
115 delegate_->OnNativeWidgetCreated();
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 has_mouse_capture_ = true;
230 }
231
232 void NativeWidgetWayland::ReleaseMouseCapture() {
233 NOTIMPLEMENTED();
234 has_mouse_capture_ = false;
235 }
236
237 bool NativeWidgetWayland::HasMouseCapture() const {
238 NOTIMPLEMENTED();
239 return has_mouse_capture_;
240 }
241
242 InputMethod* NativeWidgetWayland::CreateInputMethod() {
243 return new InputMethodWayland(this);
244 }
245
246 void NativeWidgetWayland::CenterWindow(const gfx::Size& size) {
247 NOTIMPLEMENTED();
248 }
249
250 void NativeWidgetWayland::GetWindowBoundsAndMaximizedState(
251 gfx::Rect* bounds,
252 bool* maximized) const {
253 NOTIMPLEMENTED();
254 }
255
256 void NativeWidgetWayland::SetWindowTitle(const std::wstring& title) {
257 }
258
259 void NativeWidgetWayland::SetWindowIcons(const SkBitmap& window_icon,
260 const SkBitmap& app_icon) {
261 }
262
263 void NativeWidgetWayland::SetAccessibleName(const std::wstring& name) {
264 }
265
266 void NativeWidgetWayland::SetAccessibleRole(
267 ui::AccessibilityTypes::Role role) {
268 }
269
270 void NativeWidgetWayland::SetAccessibleState(
271 ui::AccessibilityTypes::State state) {
272 }
273
274 void NativeWidgetWayland::BecomeModal() {
275 NOTIMPLEMENTED();
276 }
277
278 gfx::Rect NativeWidgetWayland::GetWindowScreenBounds() const {
279 return GetClientAreaScreenBounds();
280 }
281
282 gfx::Rect NativeWidgetWayland::GetClientAreaScreenBounds() const {
283 return allocation_;
284 }
285
286 gfx::Rect NativeWidgetWayland::GetRestoredBounds() const {
287 return GetWindowScreenBounds();
288 }
289
290 void NativeWidgetWayland::SetBounds(const gfx::Rect& bounds) {
291 saved_allocation_ = allocation_;
292 allocation_ = bounds;
293
294 // TODO(dnicoara) This needs to be updated to include (x, y).
295 wl_egl_window_resize(egl_window_,
296 allocation_.width(),
297 allocation_.height(),
298 0, 0);
299 if (!View::get_use_acceleration_when_possible()) {
300 cairo_gl_surface_set_size(cairo_surface_,
301 allocation_.width(),
302 allocation_.height());
303 }
304
305 if (compositor_.get())
306 compositor_->WidgetSizeChanged(allocation_.size());
307 delegate_->OnNativeWidgetSizeChanged(allocation_.size());
308 }
309
310 void NativeWidgetWayland::SetSize(const gfx::Size& size) {
311 gfx::Rect new_alloc = allocation_;
312 new_alloc.set_size(size);
313
314 SetBounds(new_alloc);
315 }
316
317 void NativeWidgetWayland::SetBoundsConstrained(const gfx::Rect& bounds,
318 Widget* other_widget) {
319 // TODO(dnicoara) Need to take into account |other_widget|.
320 SetBounds(bounds);
321 }
322
323 void NativeWidgetWayland::MoveAbove(gfx::NativeView native_view) {
324 NOTIMPLEMENTED();
325 }
326
327 void NativeWidgetWayland::MoveToTop() {
328 NOTIMPLEMENTED();
329 }
330
331 void NativeWidgetWayland::SetShape(gfx::NativeRegion shape) {
332 NOTIMPLEMENTED();
333 }
334
335 void NativeWidgetWayland::Close() {
336 Hide();
337 if (close_widget_factory_.empty()) {
338 MessageLoop::current()->PostTask(FROM_HERE,
339 close_widget_factory_.NewRunnableMethod(
340 &NativeWidgetWayland::CloseNow));
341 }
342 }
343
344 void NativeWidgetWayland::CloseNow() {
345 delegate_->OnNativeWidgetDestroying();
346 delegate_->OnNativeWidgetDestroyed();
347 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
348 delete this;
349 }
350
351 void NativeWidgetWayland::EnableClose(bool enable) {
352 NOTIMPLEMENTED();
353 }
354
355 void NativeWidgetWayland::Show() {
356 wayland_window_->SetVisible(true);
357 delegate_->OnNativeWidgetVisibilityChanged(true);
358 }
359
360 void NativeWidgetWayland::Hide() {
361 wayland_window_->SetVisible(false);
362 delegate_->OnNativeWidgetVisibilityChanged(false);
363 }
364
365 void NativeWidgetWayland::ShowMaximizedWithBounds(
366 const gfx::Rect& restored_bounds) {
367 Show();
368 Maximize();
369 saved_allocation_ = restored_bounds;
370 }
371
372 void NativeWidgetWayland::ShowWithState(ShowState state) {
373 NOTIMPLEMENTED();
374 }
375
376 bool NativeWidgetWayland::IsVisible() const {
377 return wayland_window_->IsVisible();
378 }
379
380 void NativeWidgetWayland::Activate() {
381 NOTIMPLEMENTED();
382 }
383
384 void NativeWidgetWayland::Deactivate() {
385 NOTIMPLEMENTED();
386 }
387
388 bool NativeWidgetWayland::IsActive() const {
389 NOTIMPLEMENTED();
390 return true;
391 }
392
393 void NativeWidgetWayland::SetAlwaysOnTop(bool always_on_top) {
394 NOTIMPLEMENTED();
395 }
396
397 void NativeWidgetWayland::Maximize() {
398 std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList();
399
400 if (screens.empty())
401 return;
402
403 // TODO(dnicoara) We need to intersect the current coordinates with the
404 // screen ones and decide the correct screen to fullscreen on.
405 ui::WaylandScreen* screen = screens.front();
406
407 SetBounds(screen->GetAllocation());
408 }
409
410 void NativeWidgetWayland::Minimize() {
411 NOTIMPLEMENTED();
412 }
413
414 bool NativeWidgetWayland::IsMaximized() const {
415 NOTIMPLEMENTED();
416 return true;
417 }
418
419 bool NativeWidgetWayland::IsMinimized() const {
420 NOTIMPLEMENTED();
421 return false;
422 }
423
424 void NativeWidgetWayland::Restore() {
425 NOTIMPLEMENTED();
426 }
427
428 void NativeWidgetWayland::SetFullscreen(bool fullscreen) {
429 gfx::Rect new_allocation = allocation_;
430
431 if (fullscreen) {
432 std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList();
433
434 if (screens.empty())
435 return;
436
437 // TODO(dnicoara) What does it mean to be fullscreen when having multiple
438 // monitors? If we're going fullscreen only on one screen then we need to
439 // intersect the current coordinates with the screen ones and decide the
440 // correct screen to fullscreen on.
441 ui::WaylandScreen* screen = screens.front();
442 new_allocation = screen->GetAllocation();
443 } else {
444 new_allocation = saved_allocation_;
445 }
446
447 wayland_window_->set_fullscreen(fullscreen);
448 SetBounds(new_allocation);
449 }
450
451 bool NativeWidgetWayland::IsFullscreen() const {
452 return wayland_window_->fullscreen();
453 }
454
455 void NativeWidgetWayland::SetOpacity(unsigned char opacity) {
456 NOTIMPLEMENTED();
457 }
458
459 void NativeWidgetWayland::SetUseDragFrame(bool use_drag_frame) {
460 NOTIMPLEMENTED();
461 }
462
463 bool NativeWidgetWayland::IsAccessibleWidget() const {
464 NOTIMPLEMENTED();
465 return true;
466 }
467
468 void NativeWidgetWayland::RunShellDrag(View* view,
469 const ui::OSExchangeData& data,
470 int operation) {
471 NOTIMPLEMENTED();
472 }
473
474 gboolean NativeWidgetWayland::IdleRedraw(void* ptr) {
475 NativeWidgetWayland* widget = static_cast<NativeWidgetWayland*>(ptr);
476 gfx::Rect damage_area = widget->damage_area_;
477 widget->damage_area_ = gfx::Rect();
478
479 widget->OnPaint(damage_area);
480
481 return FALSE;
482 }
483
484 void NativeWidgetWayland::SchedulePaintInRect(const gfx::Rect& rect) {
485 if (damage_area_.IsEmpty())
486 g_idle_add(NativeWidgetWayland::IdleRedraw, this);
487
488 damage_area_ = damage_area_.Union(rect);
489 }
490
491 void NativeWidgetWayland::SetCursor(gfx::NativeCursor cursor) {
492 NOTIMPLEMENTED();
493 }
494
495
496 void NativeWidgetWayland::ClearNativeFocus() {
497 NOTIMPLEMENTED();
498 }
499
500
501 void NativeWidgetWayland::FocusNativeView(gfx::NativeView native_view) {
502 NOTIMPLEMENTED();
503 }
504
505 bool NativeWidgetWayland::ConvertPointFromAncestor(
506 const Widget* ancestor, gfx::Point* point) const {
507 NOTREACHED();
508 return false;
509 }
510
511 // Overridden from NativeWidget
512 gfx::AcceleratedWidget NativeWidgetWayland::GetAcceleratedWidget() {
513 return egl_window_;
514 }
515
516
517 // Overridden from internal::InputMethodDelegate
518 void NativeWidgetWayland::DispatchKeyEventPostIME(const KeyEvent& key) {
519 NOTIMPLEMENTED();
520 delegate_->OnKeyEvent(key);
521 }
522
523 /////////////////////////////////////////////////////////////////////////////
524 // NativeWidgetWayland, private, event handlers
525
526 void NativeWidgetWayland::OnPaint(gfx::Rect damage_area) {
527 if (!delegate_->OnNativeWidgetPaintAccelerated(damage_area)) {
528 // This is required since the CanvasSkiaPaint damages the surface
529 // in the destructor so we need to have this done before calling
530 // swapbuffers.
531 {
532 cairo_rectangle_int_t region = damage_area.ToCairoRectangle();
533 gfx::CanvasSkiaPaint canvas(cairo_surface_, &region);
534 if (!canvas.is_empty()) {
535 canvas.set_composite_alpha(false);
536 delegate_->OnNativeWidgetPaint(&canvas);
537 }
538 }
539
540 // Have cairo swap buffers, then let Wayland know of the damaged area.
541 cairo_gl_surface_swapbuffers(cairo_surface_);
542 wl_surface_damage(wayland_window_->surface(),
543 damage_area.x(), damage_area.y(),
544 damage_area.width(), damage_area.height());
545 }
546 }
547
548 void NativeWidgetWayland::OnMotionNotify(ui::WaylandEvent event) {
549 MouseEvent mouse_event(&event);
550 delegate_->OnMouseEvent(mouse_event);
551 }
552
553 void NativeWidgetWayland::OnButtonNotify(ui::WaylandEvent event) {
554 if (event.button.button == ui::SCROLL_UP ||
555 event.button.button == ui::SCROLL_DOWN) {
556 MouseWheelEvent mouse_event(&event);
557 delegate_->OnMouseEvent(mouse_event);
558 } else {
559 MouseEvent mouse_event(&event);
560 delegate_->OnMouseEvent(mouse_event);
561 }
562 }
563
564 void NativeWidgetWayland::OnKeyNotify(ui::WaylandEvent event) {
565 KeyEvent key_event(&event);
566 InputMethod* input_method = GetWidget()->GetInputMethodDirect();
567 if (input_method)
568 input_method->DispatchKeyEvent(key_event);
569 else
570 DispatchKeyEventPostIME(key_event);
571 }
572
573 void NativeWidgetWayland::OnPointerFocus(ui::WaylandEvent event) {
574 MouseEvent mouse_event(&event);
575 delegate_->OnMouseEvent(mouse_event);
576 }
577
578 void NativeWidgetWayland::OnKeyboardFocus(ui::WaylandEvent event) {
579 InputMethod* input_method = GetWidget()->GetInputMethodDirect();
580 if (input_method) {
581 if (event.keyboard_focus.state)
582 input_method->OnFocus();
583 else
584 input_method->OnBlur();
585 }
586 }
587
588 void NativeWidgetWayland::OnGeometryChange(ui::WaylandEvent event) {
589 SetSize(gfx::Size(event.geometry_change.width,
590 event.geometry_change.height));
591 }
592
593 /////////////////////////////////////////////////////////////////////////////
594 // Widget
595
596 // static
597 bool Widget::ConvertRect(const Widget* source,
598 const Widget* target,
599 gfx::Rect* rect) {
600 DCHECK(source);
601 DCHECK(target);
602 DCHECK(rect);
603
604 gfx::NativeView source_widget = source->GetNativeView();
605 gfx::NativeView target_widget = target->GetNativeView();
606 if (source_widget == target_widget)
607 return true;
608
609 if (!source_widget || !target_widget)
610 return false;
611
612 NOTIMPLEMENTED();
613 return false;
614 }
615
616 namespace internal {
617
618 /////////////////////////////////////////////////////////////////////////////
619 // NativeWidget
620
621 // static
622 NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
623 internal::NativeWidgetDelegate* delegate) {
624 if (Widget::IsPureViews() &&
625 ViewsDelegate::views_delegate->GetDefaultParentView()) {
626 return new NativeWidgetViews(delegate);
627 }
628 return new NativeWidgetWayland(delegate);
629 }
630
631 // static
632 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
633 gfx::NativeView native_view) {
634 return reinterpret_cast<NativeWidgetWayland*>(
635 ViewProp::GetValue(native_view, kNativeWidgetKey));
636 }
637
638 // static
639 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
640 gfx::NativeWindow native_window) {
641 return GetNativeWidgetForNativeView(native_window);
642 }
643
644 // static
645 NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
646 gfx::NativeView native_view) {
647 // TODO(dnicoara) What would be the best way to implement this?
648 // Since there isn't any actual parenting concept in Wayland, we could
649 // implement it using WaylandWindow->SetParent/GetParent calls.
650 return GetNativeWidgetForNativeView(native_view);
651 }
652
653 // static
654 void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
655 Widget::Widgets* children) {
656 NOTIMPLEMENTED();
657 if (!native_view)
658 return;
659 }
660
661 // static
662 void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
663 gfx::NativeView new_parent) {
664 NOTIMPLEMENTED();
665 if (!native_view)
666 return;
667 }
668
669 // static
670 bool NativeWidgetPrivate::IsMouseButtonDown() {
671 NOTIMPLEMENTED();
672 return false;
673 }
674
675 } // namespace internal
676
677 } // namespace views
OLDNEW
« no previous file with comments | « views/widget/native_widget_wayland.h ('k') | views/widget/tooltip_manager_views.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698