diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 18:14:45 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 18:14:45 +0000 |
commit | a4f857f0cafb41c3d7c3fd50c6b39c99e629b48a (patch) | |
tree | 521a058f131d900136105ce2ce3c368991de5ad1 /views/widget | |
parent | 3a1381d637b14d103c581990451f92877107893e (diff) | |
download | chromium_src-a4f857f0cafb41c3d7c3fd50c6b39c99e629b48a.zip chromium_src-a4f857f0cafb41c3d7c3fd50c6b39c99e629b48a.tar.gz chromium_src-a4f857f0cafb41c3d7c3fd50c6b39c99e629b48a.tar.bz2 |
Wayland support for views. views_desktop on Wayland.
This CL depends on:
* http://codereview.chromium.org/7457023
* http://codereview.chromium.org/7467007
* http://codereview.chromium.org/7473010
Wayland requires newer libraries than Ubuntu currently provides. I've created a
list of required dependencies:
https://sites.google.com/a/google.com/chrome_on_wayland/home/wayland-build-dependencies
BUG=
TEST=Built Chrome to verify that Wayland dependencies and changes don't interfere with
the usual build.
Review URL: http://codereview.chromium.org/7464027
Patch from Daniel Nicoara <dnicoara@chromium.org>.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98453 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget')
-rw-r--r-- | views/widget/native_widget_wayland.cc | 677 | ||||
-rw-r--r-- | views/widget/native_widget_wayland.h | 204 | ||||
-rw-r--r-- | views/widget/tooltip_manager_views.cc | 20 | ||||
-rw-r--r-- | views/widget/tooltip_manager_views.h | 9 |
4 files changed, 909 insertions, 1 deletions
diff --git a/views/widget/native_widget_wayland.cc b/views/widget/native_widget_wayland.cc new file mode 100644 index 0000000..ec462c6 --- /dev/null +++ b/views/widget/native_widget_wayland.cc @@ -0,0 +1,677 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/widget/native_widget_wayland.h" + +#include <cairo.h> +#include <cairo-gl.h> +#include <EGL/egl.h> +#include <GL/gl.h> +#include <wayland-egl.h> + +#include <algorithm> +#include <list> + +#include "base/memory/scoped_ptr.h" +#include "ui/base/view_prop.h" +#include "ui/gfx/canvas_skia_paint.h" +#include "ui/gfx/compositor/compositor.h" +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/wayland/events/wayland_event.h" +#include "ui/wayland/wayland_display.h" +#include "ui/wayland/wayland_input_device.h" +#include "ui/wayland/wayland_screen.h" +#include "ui/wayland/wayland_window.h" +#include "views/ime/input_method_wayland.h" +#include "views/views_delegate.h" +#include "views/widget/native_widget_views.h" +#include "views/widget/root_view.h" +#include "views/widget/tooltip_manager_views.h" + +using ui::ViewProp; + +namespace views { + +namespace { + +// Links the WaylandWidget to its NativeWidget. +const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; + +} // namespace + +NativeWidgetWayland::NativeWidgetWayland( + internal::NativeWidgetDelegate* delegate) + : delegate_(delegate), + ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)), + ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), + has_mouse_capture_(false), + wayland_display_( + ui:: WaylandDisplay::GetDisplay(gfx::GLSurfaceEGL::GetNativeDisplay())), + wayland_window_(new ui::WaylandWindow(this, wayland_display_)), + surface_data_key_(), + damage_area_() { +} + +NativeWidgetWayland::~NativeWidgetWayland() { + if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) + delete delegate_; + + if (!View::get_use_acceleration_when_possible()) { + cairo_surface_destroy(cairo_surface_); + cairo_device_destroy(device_); + } + + if (egl_window_) + wl_egl_window_destroy(egl_window_); + + if (wayland_window_) + delete wayland_window_; +} + +void NativeWidgetWayland::InitNativeWidget(const Widget::InitParams& params) { + // Cannot create a window with a size smaller than 1x1 + allocation_.set_width(std::max(params.bounds.width(), 1)); + allocation_.set_height(std::max(params.bounds.height(), 1)); + + egl_window_ = wl_egl_window_create(wayland_window_->surface(), + allocation_.width(), + allocation_.height(), + wayland_display_->visual()); + + SetNativeWindowProperty(kNativeWidgetKey, this); + + if (View::get_use_acceleration_when_possible()) { + if (Widget::compositor_factory()) { + compositor_ = (*Widget::compositor_factory())(); + } else { + compositor_ = ui::Compositor::Create(egl_window_, allocation_.size()); + } + if (compositor_.get()) + delegate_->AsWidget()->GetRootView()->SetPaintToLayer(true); + } else { + surface_ = gfx::GLSurface::CreateViewGLSurface(false, egl_window_); + context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get()); + + if (!context_->MakeCurrent(surface_.get())) + DLOG(ERROR) << "Failed to make surface current"; + + device_ = cairo_egl_device_create(gfx::GLSurfaceEGL::GetHardwareDisplay(), + context_->GetHandle()); + if (cairo_device_status(device_) != CAIRO_STATUS_SUCCESS) + DLOG(ERROR) << "Failed to create cairo egl device"; + + cairo_surface_ = cairo_gl_surface_create_for_egl(device_, + surface_->GetHandle(), + allocation_.width(), + allocation_.height()); + cairo_surface_set_user_data(cairo_surface_, + &surface_data_key_, + this, + NULL); + } + + delegate_->OnNativeWidgetCreated(); + + if (params.type != Widget::InitParams::TYPE_TOOLTIP) { + // TODO(dnicoara) Enable this once it works with Wayland + /* + views::TooltipManagerViews* manager = new views::TooltipManagerViews( + static_cast<internal::RootView*>(GetWidget()->GetRootView())); + tooltip_manager_.reset(manager); + */ + } + + // TODO(dnicoara) This should be removed when we can specify the (x, y) + // coordinates for a window. We use fullscreen since it will center the + // window rather than give it random (x, y) coordinates. + wayland_window_->set_fullscreen(true); + Show(); + OnPaint(allocation_); +} + +NonClientFrameView* NativeWidgetWayland::CreateNonClientFrameView() { + return NULL; +} + +void NativeWidgetWayland::UpdateFrameAfterFrameChange() { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::ShouldUseNativeFrame() const { + NOTIMPLEMENTED(); + return false; +} + +void NativeWidgetWayland::FrameTypeChanged() { + // Called when the Theme has changed, so forward the event to the root + // widget + GetWidget()->ThemeChanged(); + GetWidget()->GetRootView()->SchedulePaint(); +} + +Widget* NativeWidgetWayland::GetWidget() { + return delegate_->AsWidget(); +} + +const Widget* NativeWidgetWayland::GetWidget() const { + return delegate_->AsWidget(); +} + +gfx::NativeView NativeWidgetWayland::GetNativeView() const { + return wayland_window_; +} + +gfx::NativeWindow NativeWidgetWayland::GetNativeWindow() const { + return wayland_window_; +} + +Widget* NativeWidgetWayland::GetTopLevelWidget() { + NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView()); + return native_widget ? native_widget->GetWidget() : NULL; +} + +const ui::Compositor* NativeWidgetWayland::GetCompositor() const { + return compositor_.get(); +} + +ui::Compositor* NativeWidgetWayland::GetCompositor() { + return compositor_.get(); +} + +void NativeWidgetWayland::MarkLayerDirty() { +} + +void NativeWidgetWayland::CalculateOffsetToAncestorWithLayer( + gfx::Point* offset, + View** ancestor) { +} + +void NativeWidgetWayland::ViewRemoved(View* view) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetNativeWindowProperty(const char* name, + void* value) { + // Remove the existing property (if any). + for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) { + if ((*i)->Key() == name) { + props_.erase(i); + break; + } + } + + if (value) + props_.push_back(new ViewProp(wayland_window_, name, value)); +} + +void* NativeWidgetWayland::GetNativeWindowProperty(const char* name) const { + return ViewProp::GetValue(wayland_window_, name); +} + +TooltipManager* NativeWidgetWayland::GetTooltipManager() const { + return tooltip_manager_.get(); +} + +bool NativeWidgetWayland::IsScreenReaderActive() const { + return false; +} + +void NativeWidgetWayland::SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetMouseCapture() { + NOTIMPLEMENTED(); + has_mouse_capture_ = true; +} + +void NativeWidgetWayland::ReleaseMouseCapture() { + NOTIMPLEMENTED(); + has_mouse_capture_ = false; +} + +bool NativeWidgetWayland::HasMouseCapture() const { + NOTIMPLEMENTED(); + return has_mouse_capture_; +} + +InputMethod* NativeWidgetWayland::CreateInputMethod() { + return new InputMethodWayland(this); +} + +void NativeWidgetWayland::CenterWindow(const gfx::Size& size) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::GetWindowBoundsAndMaximizedState( + gfx::Rect* bounds, + bool* maximized) const { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetWindowTitle(const std::wstring& title) { +} + +void NativeWidgetWayland::SetWindowIcons(const SkBitmap& window_icon, + const SkBitmap& app_icon) { +} + +void NativeWidgetWayland::SetAccessibleName(const std::wstring& name) { +} + +void NativeWidgetWayland::SetAccessibleRole( + ui::AccessibilityTypes::Role role) { +} + +void NativeWidgetWayland::SetAccessibleState( + ui::AccessibilityTypes::State state) { +} + +void NativeWidgetWayland::BecomeModal() { + NOTIMPLEMENTED(); +} + +gfx::Rect NativeWidgetWayland::GetWindowScreenBounds() const { + return GetClientAreaScreenBounds(); +} + +gfx::Rect NativeWidgetWayland::GetClientAreaScreenBounds() const { + return allocation_; +} + +gfx::Rect NativeWidgetWayland::GetRestoredBounds() const { + return GetWindowScreenBounds(); +} + +void NativeWidgetWayland::SetBounds(const gfx::Rect& bounds) { + saved_allocation_ = allocation_; + allocation_ = bounds; + + // TODO(dnicoara) This needs to be updated to include (x, y). + wl_egl_window_resize(egl_window_, + allocation_.width(), + allocation_.height(), + 0, 0); + if (!View::get_use_acceleration_when_possible()) { + cairo_gl_surface_set_size(cairo_surface_, + allocation_.width(), + allocation_.height()); + } + + if (compositor_.get()) + compositor_->WidgetSizeChanged(allocation_.size()); + delegate_->OnNativeWidgetSizeChanged(allocation_.size()); +} + +void NativeWidgetWayland::SetSize(const gfx::Size& size) { + gfx::Rect new_alloc = allocation_; + new_alloc.set_size(size); + + SetBounds(new_alloc); +} + +void NativeWidgetWayland::SetBoundsConstrained(const gfx::Rect& bounds, + Widget* other_widget) { + // TODO(dnicoara) Need to take into account |other_widget|. + SetBounds(bounds); +} + +void NativeWidgetWayland::MoveAbove(gfx::NativeView native_view) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::MoveToTop() { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetShape(gfx::NativeRegion shape) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::Close() { + Hide(); + if (close_widget_factory_.empty()) { + MessageLoop::current()->PostTask(FROM_HERE, + close_widget_factory_.NewRunnableMethod( + &NativeWidgetWayland::CloseNow)); + } +} + +void NativeWidgetWayland::CloseNow() { + delegate_->OnNativeWidgetDestroying(); + delegate_->OnNativeWidgetDestroyed(); + if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) + delete this; +} + +void NativeWidgetWayland::EnableClose(bool enable) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::Show() { + wayland_window_->SetVisible(true); + delegate_->OnNativeWidgetVisibilityChanged(true); +} + +void NativeWidgetWayland::Hide() { + wayland_window_->SetVisible(false); + delegate_->OnNativeWidgetVisibilityChanged(false); +} + +void NativeWidgetWayland::ShowMaximizedWithBounds( + const gfx::Rect& restored_bounds) { + Show(); + Maximize(); + saved_allocation_ = restored_bounds; +} + +void NativeWidgetWayland::ShowWithState(ShowState state) { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::IsVisible() const { + return wayland_window_->IsVisible(); +} + +void NativeWidgetWayland::Activate() { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::Deactivate() { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::IsActive() const { + NOTIMPLEMENTED(); + return true; +} + +void NativeWidgetWayland::SetAlwaysOnTop(bool always_on_top) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::Maximize() { + std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList(); + + if (screens.empty()) + return; + + // TODO(dnicoara) We need to intersect the current coordinates with the + // screen ones and decide the correct screen to fullscreen on. + ui::WaylandScreen* screen = screens.front(); + + SetBounds(screen->GetAllocation()); +} + +void NativeWidgetWayland::Minimize() { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::IsMaximized() const { + NOTIMPLEMENTED(); + return true; +} + +bool NativeWidgetWayland::IsMinimized() const { + NOTIMPLEMENTED(); + return false; +} + +void NativeWidgetWayland::Restore() { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetFullscreen(bool fullscreen) { + gfx::Rect new_allocation = allocation_; + + if (fullscreen) { + std::list<ui::WaylandScreen*> screens = wayland_display_->GetScreenList(); + + if (screens.empty()) + return; + + // TODO(dnicoara) What does it mean to be fullscreen when having multiple + // monitors? If we're going fullscreen only on one screen then we need to + // intersect the current coordinates with the screen ones and decide the + // correct screen to fullscreen on. + ui::WaylandScreen* screen = screens.front(); + new_allocation = screen->GetAllocation(); + } else { + new_allocation = saved_allocation_; + } + + wayland_window_->set_fullscreen(fullscreen); + SetBounds(new_allocation); +} + +bool NativeWidgetWayland::IsFullscreen() const { + return wayland_window_->fullscreen(); +} + +void NativeWidgetWayland::SetOpacity(unsigned char opacity) { + NOTIMPLEMENTED(); +} + +void NativeWidgetWayland::SetUseDragFrame(bool use_drag_frame) { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::IsAccessibleWidget() const { + NOTIMPLEMENTED(); + return true; +} + +void NativeWidgetWayland::RunShellDrag(View* view, + const ui::OSExchangeData& data, + int operation) { + NOTIMPLEMENTED(); +} + +gboolean NativeWidgetWayland::IdleRedraw(void* ptr) { + NativeWidgetWayland* widget = static_cast<NativeWidgetWayland*>(ptr); + gfx::Rect damage_area = widget->damage_area_; + widget->damage_area_ = gfx::Rect(); + + widget->OnPaint(damage_area); + + return FALSE; +} + +void NativeWidgetWayland::SchedulePaintInRect(const gfx::Rect& rect) { + if (damage_area_.IsEmpty()) + g_idle_add(NativeWidgetWayland::IdleRedraw, this); + + damage_area_ = damage_area_.Union(rect); +} + +void NativeWidgetWayland::SetCursor(gfx::NativeCursor cursor) { + NOTIMPLEMENTED(); +} + + +void NativeWidgetWayland::ClearNativeFocus() { + NOTIMPLEMENTED(); +} + + +void NativeWidgetWayland::FocusNativeView(gfx::NativeView native_view) { + NOTIMPLEMENTED(); +} + +bool NativeWidgetWayland::ConvertPointFromAncestor( + const Widget* ancestor, gfx::Point* point) const { + NOTREACHED(); + return false; +} + +// Overridden from NativeWidget +gfx::AcceleratedWidget NativeWidgetWayland::GetAcceleratedWidget() { + return egl_window_; +} + + +// Overridden from internal::InputMethodDelegate +void NativeWidgetWayland::DispatchKeyEventPostIME(const KeyEvent& key) { + NOTIMPLEMENTED(); + delegate_->OnKeyEvent(key); +} + +///////////////////////////////////////////////////////////////////////////// +// NativeWidgetWayland, private, event handlers + +void NativeWidgetWayland::OnPaint(gfx::Rect damage_area) { + if (!delegate_->OnNativeWidgetPaintAccelerated(damage_area)) { + // This is required since the CanvasSkiaPaint damages the surface + // in the destructor so we need to have this done before calling + // swapbuffers. + { + cairo_rectangle_int_t region = damage_area.ToCairoRectangle(); + gfx::CanvasSkiaPaint canvas(cairo_surface_, ®ion); + if (!canvas.is_empty()) { + canvas.set_composite_alpha(false); + delegate_->OnNativeWidgetPaint(&canvas); + } + } + + // Have cairo swap buffers, then let Wayland know of the damaged area. + cairo_gl_surface_swapbuffers(cairo_surface_); + wl_surface_damage(wayland_window_->surface(), + damage_area.x(), damage_area.y(), + damage_area.width(), damage_area.height()); + } +} + +void NativeWidgetWayland::OnMotionNotify(ui::WaylandEvent event) { + MouseEvent mouse_event(&event); + delegate_->OnMouseEvent(mouse_event); +} + +void NativeWidgetWayland::OnButtonNotify(ui::WaylandEvent event) { + if (event.button.button == ui::SCROLL_UP || + event.button.button == ui::SCROLL_DOWN) { + MouseWheelEvent mouse_event(&event); + delegate_->OnMouseEvent(mouse_event); + } else { + MouseEvent mouse_event(&event); + delegate_->OnMouseEvent(mouse_event); + } +} + +void NativeWidgetWayland::OnKeyNotify(ui::WaylandEvent event) { + KeyEvent key_event(&event); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->DispatchKeyEvent(key_event); + else + DispatchKeyEventPostIME(key_event); +} + +void NativeWidgetWayland::OnPointerFocus(ui::WaylandEvent event) { + MouseEvent mouse_event(&event); + delegate_->OnMouseEvent(mouse_event); +} + +void NativeWidgetWayland::OnKeyboardFocus(ui::WaylandEvent event) { + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) { + if (event.keyboard_focus.state) + input_method->OnFocus(); + else + input_method->OnBlur(); + } +} + +void NativeWidgetWayland::OnGeometryChange(ui::WaylandEvent event) { + SetSize(gfx::Size(event.geometry_change.width, + event.geometry_change.height)); +} + +///////////////////////////////////////////////////////////////////////////// +// Widget + +// static +bool Widget::ConvertRect(const Widget* source, + const Widget* target, + gfx::Rect* rect) { + DCHECK(source); + DCHECK(target); + DCHECK(rect); + + gfx::NativeView source_widget = source->GetNativeView(); + gfx::NativeView target_widget = target->GetNativeView(); + if (source_widget == target_widget) + return true; + + if (!source_widget || !target_widget) + return false; + + NOTIMPLEMENTED(); + return false; +} + +namespace internal { + +///////////////////////////////////////////////////////////////////////////// +// NativeWidget + +// static +NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget( + internal::NativeWidgetDelegate* delegate) { + if (Widget::IsPureViews() && + ViewsDelegate::views_delegate->GetDefaultParentView()) { + return new NativeWidgetViews(delegate); + } + return new NativeWidgetWayland(delegate); +} + +// static +NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView( + gfx::NativeView native_view) { + return reinterpret_cast<NativeWidgetWayland*>( + ViewProp::GetValue(native_view, kNativeWidgetKey)); +} + +// static +NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window) { + return GetNativeWidgetForNativeView(native_window); +} + +// static +NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget( + gfx::NativeView native_view) { + // TODO(dnicoara) What would be the best way to implement this? + // Since there isn't any actual parenting concept in Wayland, we could + // implement it using WaylandWindow->SetParent/GetParent calls. + return GetNativeWidgetForNativeView(native_view); +} + +// static +void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view, + Widget::Widgets* children) { + NOTIMPLEMENTED(); + if (!native_view) + return; +} + +// static +void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, + gfx::NativeView new_parent) { + NOTIMPLEMENTED(); + if (!native_view) + return; +} + +// static +bool NativeWidgetPrivate::IsMouseButtonDown() { + NOTIMPLEMENTED(); + return false; +} + +} // namespace internal + +} // namespace views diff --git a/views/widget/native_widget_wayland.h b/views/widget/native_widget_wayland.h new file mode 100644 index 0000000..fd2b0e3 --- /dev/null +++ b/views/widget/native_widget_wayland.h @@ -0,0 +1,204 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VIEWS_WIDGET_NATIVE_WIDGET_WAYLAND_H_ +#define VIEWS_WIDGET_NATIVE_WIDGET_WAYLAND_H_ +#pragma once + +#include <wayland-client.h> + +#include "base/memory/scoped_vector.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/size.h" +#include "ui/wayland/wayland_widget.h" +#include "views/widget/native_widget_private.h" +#include "views/widget/widget.h" + +typedef struct _cairo_device cairo_device_t; +typedef struct _cairo_surface cairo_surface_t; + +namespace gfx { +class Rect; +} + +namespace ui { +class ViewProp; +class WaylandDisplay; +class WaylandInputDevice; +class WaylandWindow; +} + +namespace views { + +namespace internal { +class NativeWidgetDelegate; +} + +// Widget implementation for Wayland +class NativeWidgetWayland : public internal::NativeWidgetPrivate, + public ui::WaylandWidget { + public: + explicit NativeWidgetWayland(internal::NativeWidgetDelegate* delegate); + virtual ~NativeWidgetWayland(); + + // Overridden from NativeWidget: + virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + virtual void UpdateFrameAfterFrameChange() OVERRIDE; + virtual bool ShouldUseNativeFrame() const OVERRIDE; + virtual void FrameTypeChanged() OVERRIDE; + virtual Widget* GetWidget() OVERRIDE; + virtual const Widget* GetWidget() const OVERRIDE; + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE; + virtual Widget* GetTopLevelWidget() OVERRIDE; + virtual const ui::Compositor* GetCompositor() const OVERRIDE; + virtual ui::Compositor* GetCompositor() OVERRIDE; + virtual void MarkLayerDirty() OVERRIDE; + virtual void CalculateOffsetToAncestorWithLayer(gfx::Point* offset, + View** ancestor) OVERRIDE; + virtual void ViewRemoved(View* view) OVERRIDE; + virtual void SetNativeWindowProperty(const char* name, void* value) OVERRIDE; + virtual void* GetNativeWindowProperty(const char* name) const OVERRIDE; + virtual TooltipManager* GetTooltipManager() const OVERRIDE; + virtual bool IsScreenReaderActive() const OVERRIDE; + virtual void SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) OVERRIDE; + virtual void SetMouseCapture() OVERRIDE; + virtual void ReleaseMouseCapture() OVERRIDE; + virtual bool HasMouseCapture() const OVERRIDE; + virtual InputMethod* CreateInputMethod() OVERRIDE; + virtual void CenterWindow(const gfx::Size& size) OVERRIDE; + virtual void GetWindowBoundsAndMaximizedState(gfx::Rect* bounds, + bool* maximized) const OVERRIDE; + virtual void SetWindowTitle(const std::wstring& title) OVERRIDE; + virtual void SetWindowIcons(const SkBitmap& window_icon, + const SkBitmap& app_icon) OVERRIDE; + virtual void SetAccessibleName(const std::wstring& name) OVERRIDE; + virtual void SetAccessibleRole(ui::AccessibilityTypes::Role role) OVERRIDE; + virtual void SetAccessibleState(ui::AccessibilityTypes::State state) OVERRIDE; + virtual void BecomeModal() OVERRIDE; + virtual gfx::Rect GetWindowScreenBounds() const OVERRIDE; + virtual gfx::Rect GetClientAreaScreenBounds() const OVERRIDE; + virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; + virtual void SetSize(const gfx::Size& size) OVERRIDE; + virtual void SetBoundsConstrained(const gfx::Rect& bounds, + Widget* other_widget) OVERRIDE; + virtual void MoveAbove(gfx::NativeView native_view) OVERRIDE; + virtual void MoveToTop() OVERRIDE; + virtual void SetShape(gfx::NativeRegion shape) OVERRIDE; + virtual void Close() OVERRIDE; + virtual void CloseNow() OVERRIDE; + virtual void EnableClose(bool enable) OVERRIDE; + virtual void Show() OVERRIDE; + virtual void Hide() OVERRIDE; + virtual void ShowMaximizedWithBounds( + const gfx::Rect& restored_bounds) OVERRIDE; + virtual void ShowWithState(ShowState state) OVERRIDE; + virtual bool IsVisible() const OVERRIDE; + virtual void Activate() OVERRIDE; + virtual void Deactivate() OVERRIDE; + virtual bool IsActive() const OVERRIDE; + virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE; + virtual void Maximize() OVERRIDE; + virtual void Minimize() OVERRIDE; + virtual bool IsMaximized() const OVERRIDE; + virtual bool IsMinimized() const OVERRIDE; + virtual void Restore() OVERRIDE; + virtual void SetFullscreen(bool fullscreen) OVERRIDE; + virtual bool IsFullscreen() const OVERRIDE; + virtual void SetOpacity(unsigned char opacity) OVERRIDE; + virtual void SetUseDragFrame(bool use_drag_frame) OVERRIDE; + virtual bool IsAccessibleWidget() const OVERRIDE; + virtual void RunShellDrag(View* view, + const ui::OSExchangeData& data, + int operation) OVERRIDE; + virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE; + virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE; + virtual void ClearNativeFocus() OVERRIDE; + virtual void FocusNativeView(gfx::NativeView native_view) OVERRIDE; + virtual bool ConvertPointFromAncestor( + const Widget* ancestor, gfx::Point* point) const OVERRIDE; + + virtual void OnMotionNotify(ui::WaylandEvent event) OVERRIDE; + virtual void OnButtonNotify(ui::WaylandEvent event) OVERRIDE; + virtual void OnKeyNotify(ui::WaylandEvent event) OVERRIDE; + virtual void OnPointerFocus(ui::WaylandEvent event) OVERRIDE; + virtual void OnKeyboardFocus(ui::WaylandEvent event) OVERRIDE; + + virtual void OnGeometryChange(ui::WaylandEvent event) OVERRIDE; + + private: + typedef ScopedVector<ui::ViewProp> ViewProps; + + // Overridden from NativeWidget + virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; + + // Overridden from internal::InputMethodDelegate + virtual void DispatchKeyEventPostIME(const KeyEvent& key) OVERRIDE; + + void OnPaint(gfx::Rect damage_area); + + static gboolean IdleRedraw(void* ptr); + + // A delegate implementation that handles events received here. + // See class documentation for Widget in widget.h for a note about ownership. + internal::NativeWidgetDelegate* delegate_; + + scoped_ptr<TooltipManager> tooltip_manager_; + + // The following factory is used to delay destruction. + ScopedRunnableMethodFactory<NativeWidgetWayland> close_widget_factory_; + + // See class documentation for Widget in widget.h for a note about ownership. + Widget::InitParams::Ownership ownership_; + + // Keeps track of mause capture for this widget. + bool has_mouse_capture_; + + // Current window allocation + gfx::Rect allocation_; + // Previous allocation. Used to restore the size and location. + gfx::Rect saved_allocation_; + + // The compositor for accelerated drawing. + scoped_refptr<ui::Compositor> compositor_; + + ViewProps props_; + + // Pointer to the Wayland display. This object doesn't own the pointer. + ui::WaylandDisplay* wayland_display_; + + // Wayland window associated with this widget. + ui::WaylandWindow* wayland_window_; + + // The accelerated surface associated with a Wayland window. + struct wl_egl_window* egl_window_; + + cairo_device_t* device_; + + // Cairo surface associated with the Wayland accelerated surface. This is + // used when we're not using the accelerated painting path. + cairo_surface_t* cairo_surface_; + const cairo_user_data_key_t surface_data_key_; + + // Used to accumulate damaged area between repaints. + // Necessary since Wayland seems to expect at most one paint per frame. + gfx::Rect damage_area_; + + // The GL surface and context used to render when we're using unaccelerated + // rendering. If we're using accelerated rendering, we'll have a compositor + // and the compositor will have these, so we don't need to worry about them. + scoped_refptr<gfx::GLSurface> surface_; + scoped_refptr<gfx::GLContext> context_; + + DISALLOW_COPY_AND_ASSIGN(NativeWidgetWayland); +}; + +} // namespace views + +#endif // VIEWS_WIDGET_NATIVE_WIDGET_WAYLAND_H_ diff --git a/views/widget/tooltip_manager_views.cc b/views/widget/tooltip_manager_views.cc index 4c0a728..b952b09 100644 --- a/views/widget/tooltip_manager_views.cc +++ b/views/widget/tooltip_manager_views.cc @@ -21,6 +21,10 @@ #include "views/widget/native_widget.h" #include "views/widget/root_view.h" +#if defined(USE_WAYLAND) +#include "ui/wayland/events/wayland_event.h" +#endif + namespace { SkColor kTooltipBackground = 0xFF7F7F00; int kTooltipTimeoutMs = 500; @@ -100,6 +104,21 @@ void TooltipManagerViews::HideKeyboardTooltip() { NOTREACHED(); } +#if defined(USE_WAYLAND) +base::MessagePumpObserver::EventStatus TooltipManagerViews::WillProcessEvent( + ui::WaylandEvent* event) { + if (event->type == ui::WAYLAND_MOTION) { + if (tooltip_timer_.IsRunning()) + tooltip_timer_.Reset(); + curr_mouse_pos_.SetPoint(event->motion.x, event->motion.y); + + // If tooltip is visible, we may want to hide it. If it is not, we are ok. + if (tooltip_widget_->IsVisible()) + UpdateIfRequired(curr_mouse_pos_.x(), curr_mouse_pos_.y(), false); + } + return base::MessagePumpObserver::EVENT_CONTINUE; +} +#else base::MessagePumpObserver::EventStatus TooltipManagerViews::WillProcessXEvent( XEvent* xevent) { XGenericEventCookie* cookie = &xevent->xcookie; @@ -115,6 +134,7 @@ base::MessagePumpObserver::EventStatus TooltipManagerViews::WillProcessXEvent( } return base::MessagePumpObserver::EVENT_CONTINUE; } +#endif void TooltipManagerViews::TooltipTimerFired() { if (tooltip_widget_->IsVisible()) { diff --git a/views/widget/tooltip_manager_views.h b/views/widget/tooltip_manager_views.h index 8bffaed..648c7cb 100644 --- a/views/widget/tooltip_manager_views.h +++ b/views/widget/tooltip_manager_views.h @@ -7,7 +7,6 @@ #pragma once #include "base/message_loop.h" -#include "base/message_pump_x.h" #include "base/timer.h" #include "views/controls/label.h" #include "views/widget/native_widget.h" @@ -17,6 +16,9 @@ typedef union _GdkEvent GdkEvent; typedef union _XEvent XEvent; +namespace ui { +union WaylandEvent; +} namespace views { @@ -39,9 +41,14 @@ class TooltipManagerViews : public TooltipManager, virtual void ShowKeyboardTooltip(View* view) OVERRIDE; virtual void HideKeyboardTooltip() OVERRIDE; +#if defined(USE_WAYLAND) + virtual base::MessagePumpObserver::EventStatus WillProcessEvent( + ui::WaylandEvent* event) OVERRIDE; +#else // MessageLoopForUI::Observer virtual base::MessagePumpObserver::EventStatus WillProcessXEvent( XEvent* xevent) OVERRIDE; +#endif private: void TooltipTimerFired(); |