From a4f857f0cafb41c3d7c3fd50c6b39c99e629b48a Mon Sep 17 00:00:00 2001 From: "backer@chromium.org" Date: Fri, 26 Aug 2011 18:14:45 +0000 Subject: 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 . git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98453 0039d316-1c4b-4281-b951-d872f2087c98 --- views/controls/combobox/native_combobox_wayland.cc | 15 + views/controls/menu/menu_config_gtk.cc | 29 - views/controls/menu/menu_config_linux.cc | 29 + views/controls/menu/menu_controller.cc | 7 + views/controls/menu/menu_controller.h | 3 + views/controls/menu/menu_image_util_gtk.cc | 115 ---- views/controls/menu/menu_image_util_gtk.h | 24 - views/controls/menu/menu_image_util_linux.cc | 115 ++++ views/controls/menu/menu_image_util_linux.h | 24 + views/controls/menu/menu_item_view_gtk.cc | 141 ----- views/controls/menu/menu_item_view_linux.cc | 141 +++++ views/controls/menu/menu_separator_gtk.cc | 24 - views/controls/menu/menu_separator_linux.cc | 24 + views/controls/menu/native_menu_linux.cc | 168 +++++ views/controls/menu/native_menu_linux.h | 59 ++ views/controls/menu/native_menu_x.cc | 168 ----- views/controls/menu/native_menu_x.h | 59 -- views/controls/native/native_view_host_wayland.cc | 16 + .../scrollbar/native_scroll_bar_wayland.cc | 30 + .../controls/textfield/native_textfield_wayland.cc | 20 + views/desktop/desktop_main.cc | 18 + views/desktop/desktop_window_view.cc | 4 + views/events/event_wayland.cc | 215 +++++++ views/focus/accelerator_handler.h | 5 +- views/focus/accelerator_handler_wayland.cc | 19 + views/ime/input_method_wayland.cc | 76 +++ views/ime/input_method_wayland.h | 36 ++ views/metrics_wayland.cc | 17 + views/mouse_watcher.cc | 22 +- views/native_types.h | 11 + views/view_wayland.cc | 24 + views/views.gyp | 46 +- views/widget/native_widget_wayland.cc | 677 +++++++++++++++++++++ views/widget/native_widget_wayland.h | 204 +++++++ views/widget/tooltip_manager_views.cc | 20 + views/widget/tooltip_manager_views.h | 9 +- views/window/dialog_client_view.cc | 3 + 37 files changed, 2045 insertions(+), 572 deletions(-) create mode 100644 views/controls/combobox/native_combobox_wayland.cc delete mode 100644 views/controls/menu/menu_config_gtk.cc create mode 100644 views/controls/menu/menu_config_linux.cc delete mode 100644 views/controls/menu/menu_image_util_gtk.cc delete mode 100644 views/controls/menu/menu_image_util_gtk.h create mode 100644 views/controls/menu/menu_image_util_linux.cc create mode 100644 views/controls/menu/menu_image_util_linux.h delete mode 100644 views/controls/menu/menu_item_view_gtk.cc create mode 100644 views/controls/menu/menu_item_view_linux.cc delete mode 100644 views/controls/menu/menu_separator_gtk.cc create mode 100644 views/controls/menu/menu_separator_linux.cc create mode 100644 views/controls/menu/native_menu_linux.cc create mode 100644 views/controls/menu/native_menu_linux.h delete mode 100644 views/controls/menu/native_menu_x.cc delete mode 100644 views/controls/menu/native_menu_x.h create mode 100644 views/controls/native/native_view_host_wayland.cc create mode 100644 views/controls/scrollbar/native_scroll_bar_wayland.cc create mode 100644 views/controls/textfield/native_textfield_wayland.cc create mode 100644 views/events/event_wayland.cc create mode 100644 views/focus/accelerator_handler_wayland.cc create mode 100644 views/ime/input_method_wayland.cc create mode 100644 views/ime/input_method_wayland.h create mode 100644 views/metrics_wayland.cc create mode 100644 views/view_wayland.cc create mode 100644 views/widget/native_widget_wayland.cc create mode 100644 views/widget/native_widget_wayland.h (limited to 'views') diff --git a/views/controls/combobox/native_combobox_wayland.cc b/views/controls/combobox/native_combobox_wayland.cc new file mode 100644 index 0000000..c54b068 --- /dev/null +++ b/views/controls/combobox/native_combobox_wayland.cc @@ -0,0 +1,15 @@ +// 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/controls/combobox/native_combobox_views.h" + +namespace views { + +// static +NativeComboboxWrapper* NativeComboboxWrapper::CreateWrapper( + Combobox* combobox) { + return new NativeComboboxViews(combobox); +} + +} // namespace views diff --git a/views/controls/menu/menu_config_gtk.cc b/views/controls/menu/menu_config_gtk.cc deleted file mode 100644 index c55fa91..0000000 --- a/views/controls/menu/menu_config_gtk.cc +++ /dev/null @@ -1,29 +0,0 @@ -// 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/controls/menu/menu_config.h" - -#include "grit/ui_resources.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/resource/resource_bundle.h" - -namespace views { - -// static -MenuConfig* MenuConfig::Create() { - MenuConfig* config = new MenuConfig(); - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); -#if defined(TOUCH_UI) - config->font = rb.GetFont(ResourceBundle::LargeFont); -#else - config->font = rb.GetFont(ResourceBundle::BaseFont); -#endif - config->arrow_width = rb.GetBitmapNamed(IDR_MENU_ARROW)->width(); - // Add 4 to force some padding between check and label. - config->check_width = rb.GetBitmapNamed(IDR_MENU_CHECK)->width() + 4; - config->check_height = rb.GetBitmapNamed(IDR_MENU_CHECK)->height(); - return config; -} - -} // namespace views diff --git a/views/controls/menu/menu_config_linux.cc b/views/controls/menu/menu_config_linux.cc new file mode 100644 index 0000000..c55fa91 --- /dev/null +++ b/views/controls/menu/menu_config_linux.cc @@ -0,0 +1,29 @@ +// 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/controls/menu/menu_config.h" + +#include "grit/ui_resources.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/resource/resource_bundle.h" + +namespace views { + +// static +MenuConfig* MenuConfig::Create() { + MenuConfig* config = new MenuConfig(); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); +#if defined(TOUCH_UI) + config->font = rb.GetFont(ResourceBundle::LargeFont); +#else + config->font = rb.GetFont(ResourceBundle::BaseFont); +#endif + config->arrow_width = rb.GetBitmapNamed(IDR_MENU_ARROW)->width(); + // Add 4 to force some padding between check and label. + config->check_width = rb.GetBitmapNamed(IDR_MENU_CHECK)->width() + 4; + config->check_height = rb.GetBitmapNamed(IDR_MENU_CHECK)->height(); + return config; +} + +} // namespace views diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc index 7cfbb3a..1858993 100644 --- a/views/controls/menu/menu_controller.cc +++ b/views/controls/menu/menu_controller.cc @@ -869,6 +869,13 @@ bool MenuController::Dispatch(const MSG& msg) { DispatchMessage(&msg); return exit_type_ == EXIT_NONE; } +#elif defined(USE_WAYLAND) +base::MessagePumpDispatcher::DispatchStatus + MenuController::Dispatch(ui::WaylandEvent* ev) { + return exit_type_ != EXIT_NONE ? + base::MessagePumpDispatcher::EVENT_QUIT : + base::MessagePumpDispatcher::EVENT_PROCESSED; +} #elif defined(TOUCH_UI) base::MessagePumpDispatcher::DispatchStatus MenuController::Dispatch(XEvent* xev) { diff --git a/views/controls/menu/menu_controller.h b/views/controls/menu/menu_controller.h index 35b7a78..91f4d79 100644 --- a/views/controls/menu/menu_controller.h +++ b/views/controls/menu/menu_controller.h @@ -219,6 +219,9 @@ class VIEWS_EXPORT MenuController : public MessageLoop::Dispatcher { // Dispatcher method. This returns true if the menu was canceled, or // if the message is such that the menu should be closed. virtual bool Dispatch(const MSG& msg); +#elif defined(USE_WAYLAND) + virtual base::MessagePumpDispatcher::DispatchStatus Dispatch( + ui::WaylandEvent* event); #elif defined(TOUCH_UI) virtual base::MessagePumpDispatcher::DispatchStatus Dispatch(XEvent* xevent); #else diff --git a/views/controls/menu/menu_image_util_gtk.cc b/views/controls/menu/menu_image_util_gtk.cc deleted file mode 100644 index e2e3bfb..0000000 --- a/views/controls/menu/menu_image_util_gtk.cc +++ /dev/null @@ -1,115 +0,0 @@ -// 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/controls/menu/menu_image_util_gtk.h" - -#include "base/i18n/rtl.h" -#include "grit/ui_resources.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas_skia.h" - -namespace { - -// Size of the radio button inciator. -const int kSelectedIndicatorSize = 5; -const int kIndicatorSize = 10; - -// Used for the radio indicator. See theme_draw for details. -const double kGradientStop = .5; -const SkColor kGradient0 = SkColorSetRGB(255, 255, 255); -const SkColor kGradient1 = SkColorSetRGB(255, 255, 255); -const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8); -const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F); -const SkColor kRadioButtonIndicatorGradient0 = SkColorSetRGB(0, 0, 0); -const SkColor kRadioButtonIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83); -const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0); - -SkBitmap* CreateRadioButtonImage(bool selected) { - // + 2 (1px on each side) to cover rounding error. - gfx::CanvasSkia canvas(kIndicatorSize + 2, kIndicatorSize + 2, false); - canvas.TranslateInt(1, 1); - - SkPoint gradient_points[3]; - gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0)); - gradient_points[1].set( - SkIntToScalar(0), - SkIntToScalar(static_cast(kIndicatorSize * kGradientStop))); - gradient_points[2].set(SkIntToScalar(0), SkIntToScalar(kIndicatorSize)); - SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 }; - SkShader* shader = SkGradientShader::CreateLinear( - gradient_points, gradient_colors, NULL, arraysize(gradient_points), - SkShader::kClamp_TileMode, NULL); - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setAntiAlias(true); - paint.setShader(shader); - shader->unref(); - int radius = kIndicatorSize / 2; - canvas.drawCircle(radius, radius, radius, paint); - - paint.setStrokeWidth(SkIntToScalar(0)); - paint.setShader(NULL); - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(kBaseStroke); - canvas.drawCircle(radius, radius, radius, paint); - - if (selected) { - SkPoint selected_gradient_points[2]; - selected_gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0)); - selected_gradient_points[1].set( - SkIntToScalar(0), - SkIntToScalar(kSelectedIndicatorSize)); - SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0, - kRadioButtonIndicatorGradient1 }; - shader = SkGradientShader::CreateLinear( - selected_gradient_points, selected_gradient_colors, NULL, - arraysize(selected_gradient_points), SkShader::kClamp_TileMode, NULL); - paint.setShader(shader); - shader->unref(); - paint.setStyle(SkPaint::kFill_Style); - canvas.drawCircle(radius, radius, - kSelectedIndicatorSize / 2, paint); - - paint.setStrokeWidth(SkIntToScalar(0)); - paint.setShader(NULL); - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(kIndicatorStroke); - canvas.drawCircle(radius, radius, - kSelectedIndicatorSize / 2, paint); - } - return new SkBitmap(canvas.ExtractBitmap()); -} - -SkBitmap* GetRtlSubmenuArrowImage() { - static SkBitmap* kRtlArrow = NULL; - if (!kRtlArrow) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap* r = rb.GetBitmapNamed(IDR_MENU_ARROW); - gfx::CanvasSkia canvas(r->width(), r->height(), false); - canvas.ScaleInt(-1, 1); - canvas.DrawBitmapInt(*r, - r->width(), 0); - kRtlArrow = new SkBitmap(canvas.ExtractBitmap()); - } - return kRtlArrow; -} - -} // namespace - -namespace views { - -const SkBitmap* GetRadioButtonImage(bool selected) { - static const SkBitmap* kRadioOn = CreateRadioButtonImage(true); - static const SkBitmap* kRadioOff = CreateRadioButtonImage(false); - - return selected ? kRadioOn : kRadioOff; -} - -const SkBitmap* GetSubmenuArrowImage() { - return base::i18n::IsRTL() ? - GetRtlSubmenuArrowImage() : - ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_MENU_ARROW); -} - -} // namespace views; diff --git a/views/controls/menu/menu_image_util_gtk.h b/views/controls/menu/menu_image_util_gtk.h deleted file mode 100644 index f4c0ead..0000000 --- a/views/controls/menu/menu_image_util_gtk.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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_CONTROLS_MENU_MENU_IMAGE_UTIL_GTK_H_ -#define VIEWS_CONTROLS_MENU_MENU_IMAGE_UTIL_GTK_H_ -#pragma once - -#include "third_party/skia/include/core/SkBitmap.h" - -namespace views { - -// Return the RadioButton image for given state. -// It returns the "selected" image when |selected| is -// true, or the "unselected" image if false. -// The returned image is global object and should not be freed. -const SkBitmap* GetRadioButtonImage(bool selected); - -// Returns the image for submenu arrow for current RTL setting. -const SkBitmap* GetSubmenuArrowImage(); - -} // namespace views - -#endif // VIEWS_CONTROLS_MENU_MENU_IMAGE_UTIL_GTK_H_ diff --git a/views/controls/menu/menu_image_util_linux.cc b/views/controls/menu/menu_image_util_linux.cc new file mode 100644 index 0000000..b2f5d97 --- /dev/null +++ b/views/controls/menu/menu_image_util_linux.cc @@ -0,0 +1,115 @@ +// 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/controls/menu/menu_image_util_linux.h" + +#include "base/i18n/rtl.h" +#include "grit/ui_resources.h" +#include "third_party/skia/include/effects/SkGradientShader.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas_skia.h" + +namespace { + +// Size of the radio button inciator. +const int kSelectedIndicatorSize = 5; +const int kIndicatorSize = 10; + +// Used for the radio indicator. See theme_draw for details. +const double kGradientStop = .5; +const SkColor kGradient0 = SkColorSetRGB(255, 255, 255); +const SkColor kGradient1 = SkColorSetRGB(255, 255, 255); +const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8); +const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F); +const SkColor kRadioButtonIndicatorGradient0 = SkColorSetRGB(0, 0, 0); +const SkColor kRadioButtonIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83); +const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0); + +SkBitmap* CreateRadioButtonImage(bool selected) { + // + 2 (1px on each side) to cover rounding error. + gfx::CanvasSkia canvas(kIndicatorSize + 2, kIndicatorSize + 2, false); + canvas.TranslateInt(1, 1); + + SkPoint gradient_points[3]; + gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0)); + gradient_points[1].set( + SkIntToScalar(0), + SkIntToScalar(static_cast(kIndicatorSize * kGradientStop))); + gradient_points[2].set(SkIntToScalar(0), SkIntToScalar(kIndicatorSize)); + SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 }; + SkShader* shader = SkGradientShader::CreateLinear( + gradient_points, gradient_colors, NULL, arraysize(gradient_points), + SkShader::kClamp_TileMode, NULL); + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setAntiAlias(true); + paint.setShader(shader); + shader->unref(); + int radius = kIndicatorSize / 2; + canvas.drawCircle(radius, radius, radius, paint); + + paint.setStrokeWidth(SkIntToScalar(0)); + paint.setShader(NULL); + paint.setStyle(SkPaint::kStroke_Style); + paint.setColor(kBaseStroke); + canvas.drawCircle(radius, radius, radius, paint); + + if (selected) { + SkPoint selected_gradient_points[2]; + selected_gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0)); + selected_gradient_points[1].set( + SkIntToScalar(0), + SkIntToScalar(kSelectedIndicatorSize)); + SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0, + kRadioButtonIndicatorGradient1 }; + shader = SkGradientShader::CreateLinear( + selected_gradient_points, selected_gradient_colors, NULL, + arraysize(selected_gradient_points), SkShader::kClamp_TileMode, NULL); + paint.setShader(shader); + shader->unref(); + paint.setStyle(SkPaint::kFill_Style); + canvas.drawCircle(radius, radius, + kSelectedIndicatorSize / 2, paint); + + paint.setStrokeWidth(SkIntToScalar(0)); + paint.setShader(NULL); + paint.setStyle(SkPaint::kStroke_Style); + paint.setColor(kIndicatorStroke); + canvas.drawCircle(radius, radius, + kSelectedIndicatorSize / 2, paint); + } + return new SkBitmap(canvas.ExtractBitmap()); +} + +SkBitmap* GetRtlSubmenuArrowImage() { + static SkBitmap* kRtlArrow = NULL; + if (!kRtlArrow) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + SkBitmap* r = rb.GetBitmapNamed(IDR_MENU_ARROW); + gfx::CanvasSkia canvas(r->width(), r->height(), false); + canvas.ScaleInt(-1, 1); + canvas.DrawBitmapInt(*r, - r->width(), 0); + kRtlArrow = new SkBitmap(canvas.ExtractBitmap()); + } + return kRtlArrow; +} + +} // namespace + +namespace views { + +const SkBitmap* GetRadioButtonImage(bool selected) { + static const SkBitmap* kRadioOn = CreateRadioButtonImage(true); + static const SkBitmap* kRadioOff = CreateRadioButtonImage(false); + + return selected ? kRadioOn : kRadioOff; +} + +const SkBitmap* GetSubmenuArrowImage() { + return base::i18n::IsRTL() ? + GetRtlSubmenuArrowImage() : + ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_MENU_ARROW); +} + +} // namespace views; diff --git a/views/controls/menu/menu_image_util_linux.h b/views/controls/menu/menu_image_util_linux.h new file mode 100644 index 0000000..abf9bcb --- /dev/null +++ b/views/controls/menu/menu_image_util_linux.h @@ -0,0 +1,24 @@ +// 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_CONTROLS_MENU_MENU_IMAGE_UTIL_LINUX_H_ +#define VIEWS_CONTROLS_MENU_MENU_IMAGE_UTIL_LINUX_H_ +#pragma once + +#include "third_party/skia/include/core/SkBitmap.h" + +namespace views { + +// Return the RadioButton image for given state. +// It returns the "selected" image when |selected| is +// true, or the "unselected" image if false. +// The returned image is global object and should not be freed. +const SkBitmap* GetRadioButtonImage(bool selected); + +// Returns the image for submenu arrow for current RTL setting. +const SkBitmap* GetSubmenuArrowImage(); + +} // namespace views + +#endif // VIEWS_CONTROLS_MENU_MENU_IMAGE_UTIL_LINUX_H_ diff --git a/views/controls/menu/menu_item_view_gtk.cc b/views/controls/menu/menu_item_view_gtk.cc deleted file mode 100644 index 956a167..0000000 --- a/views/controls/menu/menu_item_view_gtk.cc +++ /dev/null @@ -1,141 +0,0 @@ -// 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/controls/menu/menu_item_view.h" - -#include "base/utf_string_conversions.h" -#include "grit/ui_resources.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/favicon_size.h" -#include "views/controls/button/text_button.h" -#include "views/controls/menu/menu_config.h" -#include "views/controls/menu/menu_image_util_gtk.h" -#include "views/controls/menu/submenu_view.h" - -namespace views { - -// Background color when the menu item is selected. -#if defined(OS_CHROMEOS) -static const SkColor kSelectedBackgroundColor = SkColorSetRGB(0xDC, 0xE4, 0xFA); -#else -static const SkColor kSelectedBackgroundColor = SkColorSetRGB(246, 249, 253); -#endif - -#if defined(TOUCH_UI) -const int kMinTouchHeight = 46; -#endif - -gfx::Size MenuItemView::CalculatePreferredSize() { - gfx::Size child_size = GetChildPreferredSize(); - if (child_count() == 1 && title_.size() == 0) { - return gfx::Size( - child_size.width(), - child_size.height() + GetBottomMargin() + GetTopMargin()); - } - - const gfx::Font& font = GetFont(); -#if defined(TOUCH_UI) - int height = std::max(font.GetHeight(), kMinTouchHeight); -#else - int height = font.GetHeight(); -#endif - return gfx::Size( - font.GetStringWidth(title_) + label_start_ + - item_right_margin_ + child_size.width(), - std::max(height, child_size.height()) + GetBottomMargin() + - GetTopMargin()); -} - -void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { - const MenuConfig& config = MenuConfig::instance(); - bool render_selection = - (mode == PB_NORMAL && IsSelected() && - parent_menu_item_->GetSubmenu()->GetShowSelection(this) && - !has_children()); - - int icon_x = config.item_left_margin; - int top_margin = GetTopMargin(); - int bottom_margin = GetBottomMargin(); - int icon_y = top_margin + (height() - config.item_top_margin - - bottom_margin - config.check_height) / 2; - int icon_height = config.check_height; - int available_height = height() - top_margin - bottom_margin; - - // Render the background. As MenuScrollViewContainer draws the background, we - // only need the background when we want it to look different, as when we're - // selected. - if (render_selection) - canvas->AsCanvasSkia()->drawColor(kSelectedBackgroundColor, - SkXfermode::kSrc_Mode); - - // Render the check. - if (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand())) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap* check = rb.GetBitmapNamed(IDR_MENU_CHECK); - // Don't use config.check_width here as it's padded to force more padding. - gfx::Rect check_bounds(icon_x, icon_y, check->width(), icon_height); - AdjustBoundsForRTLUI(&check_bounds); - canvas->DrawBitmapInt(*check, check_bounds.x(), check_bounds.y()); - } else if (type_ == RADIO) { - const SkBitmap* image = - GetRadioButtonImage(GetDelegate()->IsItemChecked(GetCommand())); - gfx::Rect radio_bounds(icon_x, - top_margin + - (height() - top_margin - bottom_margin - - image->height()) / 2, - image->width(), - image->height()); - AdjustBoundsForRTLUI(&radio_bounds); - canvas->DrawBitmapInt(*image, radio_bounds.x(), radio_bounds.y()); - } - - // Render the foreground. -#if defined(OS_CHROMEOS) - SkColor fg_color = - IsEnabled() ? SK_ColorBLACK : SkColorSetRGB(0x80, 0x80, 0x80); -#else - SkColor fg_color = - IsEnabled() ? TextButton::kEnabledColor : TextButton::kDisabledColor; -#endif - const gfx::Font& font = GetFont(); - int accel_width = parent_menu_item_->GetSubmenu()->max_accelerator_width(); - int width = this->width() - item_right_margin_ - label_start_ - accel_width; - gfx::Rect text_bounds(label_start_, top_margin + - (available_height - font.GetHeight()) / 2, width, - font.GetHeight()); - text_bounds.set_x(GetMirroredXForRect(text_bounds)); - canvas->DrawStringInt(WideToUTF16Hack(GetTitle()), font, fg_color, - text_bounds.x(), text_bounds.y(), text_bounds.width(), - text_bounds.height(), - GetRootMenuItem()->GetDrawStringFlags()); - - PaintAccelerator(canvas); - - // Render the icon. - if (icon_.width() > 0) { - gfx::Rect icon_bounds(config.item_left_margin, - top_margin + (height() - top_margin - - bottom_margin - icon_.height()) / 2, - icon_.width(), - icon_.height()); - icon_bounds.set_x(GetMirroredXForRect(icon_bounds)); - canvas->DrawBitmapInt(icon_, icon_bounds.x(), icon_bounds.y()); - } - - // Render the submenu indicator (arrow). - if (HasSubmenu()) { - gfx::Rect arrow_bounds(this->width() - item_right_margin_ + - config.label_to_arrow_padding, - top_margin + (available_height - - config.arrow_width) / 2, - config.arrow_width, height()); - AdjustBoundsForRTLUI(&arrow_bounds); - canvas->DrawBitmapInt(*GetSubmenuArrowImage(), - arrow_bounds.x(), arrow_bounds.y()); - } -} - -} // namespace views diff --git a/views/controls/menu/menu_item_view_linux.cc b/views/controls/menu/menu_item_view_linux.cc new file mode 100644 index 0000000..b90c7ce --- /dev/null +++ b/views/controls/menu/menu_item_view_linux.cc @@ -0,0 +1,141 @@ +// 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/controls/menu/menu_item_view.h" + +#include "base/utf_string_conversions.h" +#include "grit/ui_resources.h" +#include "third_party/skia/include/effects/SkGradientShader.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas_skia.h" +#include "ui/gfx/favicon_size.h" +#include "views/controls/button/text_button.h" +#include "views/controls/menu/menu_config.h" +#include "views/controls/menu/menu_image_util_linux.h" +#include "views/controls/menu/submenu_view.h" + +namespace views { + +// Background color when the menu item is selected. +#if defined(OS_CHROMEOS) +static const SkColor kSelectedBackgroundColor = SkColorSetRGB(0xDC, 0xE4, 0xFA); +#else +static const SkColor kSelectedBackgroundColor = SkColorSetRGB(246, 249, 253); +#endif + +#if defined(TOUCH_UI) +const int kMinTouchHeight = 46; +#endif + +gfx::Size MenuItemView::CalculatePreferredSize() { + gfx::Size child_size = GetChildPreferredSize(); + if (child_count() == 1 && title_.size() == 0) { + return gfx::Size( + child_size.width(), + child_size.height() + GetBottomMargin() + GetTopMargin()); + } + + const gfx::Font& font = GetFont(); +#if defined(TOUCH_UI) + int height = std::max(font.GetHeight(), kMinTouchHeight); +#else + int height = font.GetHeight(); +#endif + return gfx::Size( + font.GetStringWidth(title_) + label_start_ + + item_right_margin_ + child_size.width(), + std::max(height, child_size.height()) + GetBottomMargin() + + GetTopMargin()); +} + +void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { + const MenuConfig& config = MenuConfig::instance(); + bool render_selection = + (mode == PB_NORMAL && IsSelected() && + parent_menu_item_->GetSubmenu()->GetShowSelection(this) && + !has_children()); + + int icon_x = config.item_left_margin; + int top_margin = GetTopMargin(); + int bottom_margin = GetBottomMargin(); + int icon_y = top_margin + (height() - config.item_top_margin - + bottom_margin - config.check_height) / 2; + int icon_height = config.check_height; + int available_height = height() - top_margin - bottom_margin; + + // Render the background. As MenuScrollViewContainer draws the background, we + // only need the background when we want it to look different, as when we're + // selected. + if (render_selection) + canvas->AsCanvasSkia()->drawColor(kSelectedBackgroundColor, + SkXfermode::kSrc_Mode); + + // Render the check. + if (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand())) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + SkBitmap* check = rb.GetBitmapNamed(IDR_MENU_CHECK); + // Don't use config.check_width here as it's padded to force more padding. + gfx::Rect check_bounds(icon_x, icon_y, check->width(), icon_height); + AdjustBoundsForRTLUI(&check_bounds); + canvas->DrawBitmapInt(*check, check_bounds.x(), check_bounds.y()); + } else if (type_ == RADIO) { + const SkBitmap* image = + GetRadioButtonImage(GetDelegate()->IsItemChecked(GetCommand())); + gfx::Rect radio_bounds(icon_x, + top_margin + + (height() - top_margin - bottom_margin - + image->height()) / 2, + image->width(), + image->height()); + AdjustBoundsForRTLUI(&radio_bounds); + canvas->DrawBitmapInt(*image, radio_bounds.x(), radio_bounds.y()); + } + + // Render the foreground. +#if defined(OS_CHROMEOS) + SkColor fg_color = + IsEnabled() ? SK_ColorBLACK : SkColorSetRGB(0x80, 0x80, 0x80); +#else + SkColor fg_color = + IsEnabled() ? TextButton::kEnabledColor : TextButton::kDisabledColor; +#endif + const gfx::Font& font = GetFont(); + int accel_width = parent_menu_item_->GetSubmenu()->max_accelerator_width(); + int width = this->width() - item_right_margin_ - label_start_ - accel_width; + gfx::Rect text_bounds(label_start_, top_margin + + (available_height - font.GetHeight()) / 2, width, + font.GetHeight()); + text_bounds.set_x(GetMirroredXForRect(text_bounds)); + canvas->DrawStringInt(WideToUTF16Hack(GetTitle()), font, fg_color, + text_bounds.x(), text_bounds.y(), text_bounds.width(), + text_bounds.height(), + GetRootMenuItem()->GetDrawStringFlags()); + + PaintAccelerator(canvas); + + // Render the icon. + if (icon_.width() > 0) { + gfx::Rect icon_bounds(config.item_left_margin, + top_margin + (height() - top_margin - + bottom_margin - icon_.height()) / 2, + icon_.width(), + icon_.height()); + icon_bounds.set_x(GetMirroredXForRect(icon_bounds)); + canvas->DrawBitmapInt(icon_, icon_bounds.x(), icon_bounds.y()); + } + + // Render the submenu indicator (arrow). + if (HasSubmenu()) { + gfx::Rect arrow_bounds(this->width() - item_right_margin_ + + config.label_to_arrow_padding, + top_margin + (available_height - + config.arrow_width) / 2, + config.arrow_width, height()); + AdjustBoundsForRTLUI(&arrow_bounds); + canvas->DrawBitmapInt(*GetSubmenuArrowImage(), + arrow_bounds.x(), arrow_bounds.y()); + } +} + +} // namespace views diff --git a/views/controls/menu/menu_separator_gtk.cc b/views/controls/menu/menu_separator_gtk.cc deleted file mode 100644 index 5283109..0000000 --- a/views/controls/menu/menu_separator_gtk.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2006-2008 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/controls/menu/menu_separator.h" - -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/canvas.h" -#include "views/controls/menu/menu_config.h" - -namespace views { - -static const SkColor kSeparatorColor = SkColorSetARGB(50, 00, 00, 00); - -void MenuSeparator::OnPaint(gfx::Canvas* canvas) { - canvas->DrawLineInt(kSeparatorColor, 0, height() / 2, width(), height() / 2); -} - -gfx::Size MenuSeparator::GetPreferredSize() { - return gfx::Size(10, // Just in case we're the only item in a menu. - MenuConfig::instance().separator_height); -} - -} // namespace views diff --git a/views/controls/menu/menu_separator_linux.cc b/views/controls/menu/menu_separator_linux.cc new file mode 100644 index 0000000..add1639 --- /dev/null +++ b/views/controls/menu/menu_separator_linux.cc @@ -0,0 +1,24 @@ +// 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/controls/menu/menu_separator.h" + +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/canvas.h" +#include "views/controls/menu/menu_config.h" + +namespace views { + +static const SkColor kSeparatorColor = SkColorSetARGB(50, 00, 00, 00); + +void MenuSeparator::OnPaint(gfx::Canvas* canvas) { + canvas->DrawLineInt(kSeparatorColor, 0, height() / 2, width(), height() / 2); +} + +gfx::Size MenuSeparator::GetPreferredSize() { + return gfx::Size(10, // Just in case we're the only item in a menu. + MenuConfig::instance().separator_height); +} + +} // namespace views diff --git a/views/controls/menu/native_menu_linux.cc b/views/controls/menu/native_menu_linux.cc new file mode 100644 index 0000000..7556874 --- /dev/null +++ b/views/controls/menu/native_menu_linux.cc @@ -0,0 +1,168 @@ +// 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/controls/menu/native_menu_linux.h" + +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "ui/gfx/canvas_skia.h" +#include "ui/gfx/skia_util.h" +#include "views/controls/menu/menu_2.h" +#include "views/controls/menu/menu_runner.h" +#include "views/controls/menu/submenu_view.h" + +namespace views { + +NativeMenuLinux::NativeMenuLinux(Menu2* menu) + : model_(menu->model()), + ALLOW_THIS_IN_INITIALIZER_LIST(root_(new MenuItemView(this))), + menu_runner_(new MenuRunner(root_)) { +} + +NativeMenuLinux::~NativeMenuLinux() { +} + +// MenuWrapper implementation: +void NativeMenuLinux::RunMenuAt(const gfx::Point& point, int alignment) { + // TODO: this should really return the value from MenuRunner. + UpdateStates(); + if (menu_runner_->RunMenuAt(NULL, NULL, gfx::Rect(point, gfx::Size()), + alignment == Menu2::ALIGN_TOPLEFT ? MenuItemView::TOPLEFT : + MenuItemView::TOPRIGHT, MenuRunner::HAS_MNEMONICS) == + MenuRunner::MENU_DELETED) + return; +} + +void NativeMenuLinux::CancelMenu() { + NOTIMPLEMENTED(); +} + +void NativeMenuLinux::Rebuild() { + if (SubmenuView* submenu = root_->GetSubmenu()) + submenu->RemoveAllChildViews(true); + AddMenuItemsFromModel(root_, model_); +} + +void NativeMenuLinux::UpdateStates() { + SubmenuView* submenu = root_->CreateSubmenu(); + UpdateMenuFromModel(submenu, model_); +} + +gfx::NativeMenu NativeMenuLinux::GetNativeMenu() const { + NOTIMPLEMENTED(); + return NULL; +} + +MenuWrapper::MenuAction NativeMenuLinux::GetMenuAction() const { + NOTIMPLEMENTED(); + return MENU_ACTION_NONE; +} + +void NativeMenuLinux::AddMenuListener(MenuListener* listener) { + NOTIMPLEMENTED(); +} + +void NativeMenuLinux::RemoveMenuListener(MenuListener* listener) { + NOTIMPLEMENTED(); +} + +void NativeMenuLinux::SetMinimumWidth(int width) { + NOTIMPLEMENTED(); +} + +// MenuDelegate implementation + +bool NativeMenuLinux::IsItemChecked(int cmd) const { + int index; + ui::MenuModel* model = model_; + if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) + return false; + return model->IsItemCheckedAt(index); +} + +bool NativeMenuLinux::IsCommandEnabled(int cmd) const { + int index; + ui::MenuModel* model = model_; + if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) + return false; + return model->IsEnabledAt(index); +} + +void NativeMenuLinux::ExecuteCommand(int cmd) { + int index; + ui::MenuModel* model = model_; + if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) + return; + model->ActivatedAt(index); +} + +bool NativeMenuLinux::GetAccelerator(int id, views::Accelerator* accelerator) { + int index; + ui::MenuModel* model = model_; + if (!ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) + return false; + + ui::Accelerator menu_accelerator; + if (!model->GetAcceleratorAt(index, &menu_accelerator)) + return false; + + *accelerator = views::Accelerator(menu_accelerator.key_code(), + menu_accelerator.modifiers()); + return true; +} + +// private +void NativeMenuLinux::AddMenuItemsFromModel(MenuItemView* parent, + ui::MenuModel* model) { + for (int i = 0; i < model->GetItemCount(); ++i) { + int index = i + model->GetFirstItemIndex(NULL); + MenuItemView* child = parent->AppendMenuItemFromModel(model, index, + model->GetCommandIdAt(index)); + + if (child && child->GetType() == MenuItemView::SUBMENU) { + AddMenuItemsFromModel(child, model->GetSubmenuModelAt(index)); + } + } +} + +void NativeMenuLinux::UpdateMenuFromModel(SubmenuView* menu, + ui::MenuModel* model) { + for (int i = 0, sep = 0; i < model->GetItemCount(); ++i) { + int index = i + model->GetFirstItemIndex(NULL); + if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) { + ++sep; + continue; + } + + // The submenu excludes the separators when counting the menu-items + // in it. So exclude the number of separators to get the correct index. + MenuItemView* mitem = menu->GetMenuItemAt(index - sep); + mitem->SetVisible(model->IsVisibleAt(index)); + mitem->SetEnabled(model->IsEnabledAt(index)); + if (model->IsItemDynamicAt(index)) { + mitem->SetTitle(UTF16ToWide(model->GetLabelAt(index))); + } + + SkBitmap icon; + if (model->GetIconAt(index, &icon)) { + // TODO(atwilson): Support removing the icon dynamically + // (http://crbug.com/66508). + mitem->SetIcon(icon); + } + + if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SUBMENU) { + DCHECK(mitem->HasSubmenu()); + UpdateMenuFromModel(mitem->GetSubmenu(), model->GetSubmenuModelAt(index)); + } + } +} + +// MenuWrapper, public: + +// static +MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { + return new NativeMenuLinux(menu); +} + +} // namespace views diff --git a/views/controls/menu/native_menu_linux.h b/views/controls/menu/native_menu_linux.h new file mode 100644 index 0000000..bfec464 --- /dev/null +++ b/views/controls/menu/native_menu_linux.h @@ -0,0 +1,59 @@ +// 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_CONTROLS_MENU_NATIVE_MENU_LINUX_H_ +#define VIEWS_CONTROLS_MENU_NATIVE_MENU_LINUX_H_ +#pragma once + +#include "views/controls/menu/menu_delegate.h" +#include "views/controls/menu/menu_item_view.h" +#include "views/controls/menu/menu_wrapper.h" + +namespace ui { +class MenuModel; +} + +namespace views { + +class MenuRunner; + +// A non-GTK implementation of MenuWrapper, used currently for touchui. +class NativeMenuLinux : public MenuWrapper, + public MenuDelegate { + public: + explicit NativeMenuLinux(Menu2* menu); + virtual ~NativeMenuLinux(); + + // Overridden from MenuWrapper: + virtual void RunMenuAt(const gfx::Point& point, int alignment); + virtual void CancelMenu(); + virtual void Rebuild(); + virtual void UpdateStates(); + virtual gfx::NativeMenu GetNativeMenu() const; + virtual MenuAction GetMenuAction() const; + virtual void AddMenuListener(MenuListener* listener); + virtual void RemoveMenuListener(MenuListener* listener); + virtual void SetMinimumWidth(int width); + + // Overridden from MenuDelegate: + virtual bool IsItemChecked(int id) const; + virtual bool IsCommandEnabled(int id) const; + virtual void ExecuteCommand(int id); + virtual bool GetAccelerator(int id, views::Accelerator* accelerator); + + private: + void AddMenuItemsFromModel(MenuItemView* parent, ui::MenuModel* model); + void UpdateMenuFromModel(SubmenuView* menu, ui::MenuModel* model); + + // The attached model and delegate. Does not assume ownership. + ui::MenuModel* model_; + MenuItemView* root_; + scoped_ptr menu_runner_; + + DISALLOW_COPY_AND_ASSIGN(NativeMenuLinux); +}; + +} // namespace views + +#endif // VIEWS_CONTROLS_MENU_NATIVE_MENU_LINUX_H_ diff --git a/views/controls/menu/native_menu_x.cc b/views/controls/menu/native_menu_x.cc deleted file mode 100644 index b07389e..0000000 --- a/views/controls/menu/native_menu_x.cc +++ /dev/null @@ -1,168 +0,0 @@ -// 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/controls/menu/native_menu_x.h" - -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/skia_util.h" -#include "views/controls/menu/menu_2.h" -#include "views/controls/menu/menu_runner.h" -#include "views/controls/menu/submenu_view.h" - -namespace views { - -NativeMenuX::NativeMenuX(Menu2* menu) - : model_(menu->model()), - ALLOW_THIS_IN_INITIALIZER_LIST(root_(new MenuItemView(this))), - menu_runner_(new MenuRunner(root_)) { -} - -NativeMenuX::~NativeMenuX() { -} - -// MenuWrapper implementation: -void NativeMenuX::RunMenuAt(const gfx::Point& point, int alignment) { - // TODO: this should really return the value from MenuRunner. - UpdateStates(); - if (menu_runner_->RunMenuAt(NULL, NULL, gfx::Rect(point, gfx::Size()), - alignment == Menu2::ALIGN_TOPLEFT ? MenuItemView::TOPLEFT : - MenuItemView::TOPRIGHT, MenuRunner::HAS_MNEMONICS) == - MenuRunner::MENU_DELETED) - return; -} - -void NativeMenuX::CancelMenu() { - NOTIMPLEMENTED(); -} - -void NativeMenuX::Rebuild() { - if (SubmenuView* submenu = root_->GetSubmenu()) - submenu->RemoveAllChildViews(true); - AddMenuItemsFromModel(root_, model_); -} - -void NativeMenuX::UpdateStates() { - SubmenuView* submenu = root_->CreateSubmenu(); - UpdateMenuFromModel(submenu, model_); -} - -gfx::NativeMenu NativeMenuX::GetNativeMenu() const { - NOTIMPLEMENTED(); - return NULL; -} - -MenuWrapper::MenuAction NativeMenuX::GetMenuAction() const { - NOTIMPLEMENTED(); - return MENU_ACTION_NONE; -} - -void NativeMenuX::AddMenuListener(MenuListener* listener) { - NOTIMPLEMENTED(); -} - -void NativeMenuX::RemoveMenuListener(MenuListener* listener) { - NOTIMPLEMENTED(); -} - -void NativeMenuX::SetMinimumWidth(int width) { - NOTIMPLEMENTED(); -} - -// MenuDelegate implementation - -bool NativeMenuX::IsItemChecked(int cmd) const { - int index; - ui::MenuModel* model = model_; - if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) - return false; - return model->IsItemCheckedAt(index); -} - -bool NativeMenuX::IsCommandEnabled(int cmd) const { - int index; - ui::MenuModel* model = model_; - if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) - return false; - return model->IsEnabledAt(index); -} - -void NativeMenuX::ExecuteCommand(int cmd) { - int index; - ui::MenuModel* model = model_; - if (!ui::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) - return; - model->ActivatedAt(index); -} - -bool NativeMenuX::GetAccelerator(int id, views::Accelerator* accelerator) { - int index; - ui::MenuModel* model = model_; - if (!ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) - return false; - - ui::Accelerator menu_accelerator; - if (!model->GetAcceleratorAt(index, &menu_accelerator)) - return false; - - *accelerator = views::Accelerator(menu_accelerator.key_code(), - menu_accelerator.modifiers()); - return true; -} - -// private -void NativeMenuX::AddMenuItemsFromModel(MenuItemView* parent, - ui::MenuModel* model) { - for (int i = 0; i < model->GetItemCount(); ++i) { - int index = i + model->GetFirstItemIndex(NULL); - MenuItemView* child = parent->AppendMenuItemFromModel(model, index, - model->GetCommandIdAt(index)); - - if (child && child->GetType() == MenuItemView::SUBMENU) { - AddMenuItemsFromModel(child, model->GetSubmenuModelAt(index)); - } - } -} - -void NativeMenuX::UpdateMenuFromModel(SubmenuView* menu, - ui::MenuModel* model) { - for (int i = 0, sep = 0; i < model->GetItemCount(); ++i) { - int index = i + model->GetFirstItemIndex(NULL); - if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) { - ++sep; - continue; - } - - // The submenu excludes the separators when counting the menu-items - // in it. So exclude the number of separators to get the correct index. - MenuItemView* mitem = menu->GetMenuItemAt(index - sep); - mitem->SetVisible(model->IsVisibleAt(index)); - mitem->SetEnabled(model->IsEnabledAt(index)); - if (model->IsItemDynamicAt(index)) { - mitem->SetTitle(UTF16ToWide(model->GetLabelAt(index))); - } - - SkBitmap icon; - if (model->GetIconAt(index, &icon)) { - // TODO(atwilson): Support removing the icon dynamically - // (http://crbug.com/66508). - mitem->SetIcon(icon); - } - - if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SUBMENU) { - DCHECK(mitem->HasSubmenu()); - UpdateMenuFromModel(mitem->GetSubmenu(), model->GetSubmenuModelAt(index)); - } - } -} - -// MenuWrapper, public: - -// static -MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { - return new NativeMenuX(menu); -} - -} // namespace views diff --git a/views/controls/menu/native_menu_x.h b/views/controls/menu/native_menu_x.h deleted file mode 100644 index 34ae894..0000000 --- a/views/controls/menu/native_menu_x.h +++ /dev/null @@ -1,59 +0,0 @@ -// 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_CONTROLS_MENU_NATIVE_MENU_X_H_ -#define VIEWS_CONTROLS_MENU_NATIVE_MENU_X_H_ -#pragma once - -#include "views/controls/menu/menu_delegate.h" -#include "views/controls/menu/menu_item_view.h" -#include "views/controls/menu/menu_wrapper.h" - -namespace ui { -class MenuModel; -} - -namespace views { - -class MenuRunner; - -// A non-GTK implementation of MenuWrapper, used currently for touchui. -class NativeMenuX : public MenuWrapper, - public MenuDelegate { - public: - explicit NativeMenuX(Menu2* menu); - virtual ~NativeMenuX(); - - // Overridden from MenuWrapper: - virtual void RunMenuAt(const gfx::Point& point, int alignment); - virtual void CancelMenu(); - virtual void Rebuild(); - virtual void UpdateStates(); - virtual gfx::NativeMenu GetNativeMenu() const; - virtual MenuAction GetMenuAction() const; - virtual void AddMenuListener(MenuListener* listener); - virtual void RemoveMenuListener(MenuListener* listener); - virtual void SetMinimumWidth(int width); - - // Overridden from MenuDelegate: - virtual bool IsItemChecked(int id) const; - virtual bool IsCommandEnabled(int id) const; - virtual void ExecuteCommand(int id); - virtual bool GetAccelerator(int id, views::Accelerator* accelerator); - - private: - void AddMenuItemsFromModel(MenuItemView* parent, ui::MenuModel* model); - void UpdateMenuFromModel(SubmenuView* menu, ui::MenuModel* model); - - // The attached model and delegate. Does not assume ownership. - ui::MenuModel* model_; - MenuItemView* root_; - scoped_ptr menu_runner_; - - DISALLOW_COPY_AND_ASSIGN(NativeMenuX); -}; - -} // namespace views - -#endif // VIEWS_CONTROLS_MENU_NATIVE_MENU_X_H_ diff --git a/views/controls/native/native_view_host_wayland.cc b/views/controls/native/native_view_host_wayland.cc new file mode 100644 index 0000000..11e6a2b --- /dev/null +++ b/views/controls/native/native_view_host_wayland.cc @@ -0,0 +1,16 @@ +// 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/controls/native/native_view_host.h" +#include "views/controls/native/native_view_host_views.h" + +namespace views { + +// static +NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( + NativeViewHost* host) { + return new NativeViewHostViews(host); +} + +} // namespace views diff --git a/views/controls/scrollbar/native_scroll_bar_wayland.cc b/views/controls/scrollbar/native_scroll_bar_wayland.cc new file mode 100644 index 0000000..706647f --- /dev/null +++ b/views/controls/scrollbar/native_scroll_bar_wayland.cc @@ -0,0 +1,30 @@ +// 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/controls/scrollbar/native_scroll_bar.h" +#include "views/controls/scrollbar/native_scroll_bar_views.h" +#include "views/controls/scrollbar/native_scroll_bar_wrapper.h" + +namespace views { + +//////////////////////////////////////////////////////////////////////////////// +// NativewScrollBarWrapper, public: + +// static +NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper( + NativeScrollBar* scroll_bar) { + return new NativeScrollBarViews(scroll_bar); +} + +// static +int NativeScrollBarWrapper::GetHorizontalScrollBarHeight() { + return 20; +} + +// static +int NativeScrollBarWrapper::GetVerticalScrollBarWidth() { + return 20; +} + +} // namespace views diff --git a/views/controls/textfield/native_textfield_wayland.cc b/views/controls/textfield/native_textfield_wayland.cc new file mode 100644 index 0000000..d5869dc --- /dev/null +++ b/views/controls/textfield/native_textfield_wayland.cc @@ -0,0 +1,20 @@ +// 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 "base/logging.h" +#include "views/controls/textfield/native_textfield_views.h" +#include "views/controls/textfield/textfield.h" + +namespace views { + +/////////////////////////////////////////////////////////////////////////////// +// NativeTextfieldWrapper: + +// static +NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( + Textfield* field) { + return new NativeTextfieldViews(field); +} + +} // namespace views diff --git a/views/desktop/desktop_main.cc b/views/desktop/desktop_main.cc index 09db616..ebee039 100644 --- a/views/desktop/desktop_main.cc +++ b/views/desktop/desktop_main.cc @@ -17,6 +17,12 @@ #include #endif +#if defined(USE_WAYLAND) +#include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/wayland/wayland_display.h" +#include "ui/wayland/wayland_message_pump.h" +#endif + int main(int argc, char** argv) { #if defined(OS_WIN) OleInitialize(NULL); @@ -24,8 +30,10 @@ int main(int argc, char** argv) { // Initializes gtk stuff. g_thread_init(NULL); g_type_init(); +#if !defined(USE_WAYLAND) gtk_init(&argc, &argv); #endif +#endif CommandLine::Init(argc, argv); @@ -39,6 +47,16 @@ int main(int argc, char** argv) { ResourceBundle::InitSharedInstance("en-US"); +#if defined(USE_WAYLAND) + // Wayland uses EGL for drawing, so we need to initialize this as early as + // possible. + if (!gfx::GLSurface::InitializeOneOff()) { + LOG(ERROR) << "Failed to initialize GLSurface"; + return -1; + } + ui::WaylandMessagePump wayland_message_pump( + ui::WaylandDisplay::GetDisplay(gfx::GLSurfaceEGL::GetNativeDisplay())); +#endif MessageLoop main_message_loop(MessageLoop::TYPE_UI); views::desktop::DesktopViewsDelegate views_delegate; diff --git a/views/desktop/desktop_window_view.cc b/views/desktop/desktop_window_view.cc index e2bbaef..7562e67 100644 --- a/views/desktop/desktop_window_view.cc +++ b/views/desktop/desktop_window_view.cc @@ -19,6 +19,8 @@ #include "views/widget/native_widget_aura.h" #elif defined(OS_WIN) #include "views/widget/native_widget_win.h" +#elif defined(USE_WAYLAND) +#include "views/widget/native_widget_wayland.h" #elif defined(TOOLKIT_USES_GTK) #include "views/widget/native_widget_gtk.h" #endif @@ -143,6 +145,8 @@ void DesktopWindowView::CreateDesktopWindow(DesktopType type) { params.native_widget = new views::NativeWidgetAura(window); #elif defined(OS_WIN) params.native_widget = new views::NativeWidgetWin(window); +#elif defined(USE_WAYLAND) + params.native_widget = new views::NativeWidgetWayland(window); #elif defined(TOOLKIT_USES_GTK) params.native_widget = new views::NativeWidgetGtk(window); params.maximize = true; diff --git a/views/events/event_wayland.cc b/views/events/event_wayland.cc new file mode 100644 index 0000000..92b5482 --- /dev/null +++ b/views/events/event_wayland.cc @@ -0,0 +1,215 @@ +// 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/events/event.h" + +#include + +#include "base/logging.h" +#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "ui/wayland/events/wayland_event.h" + +namespace views { + +namespace { + +static int kWheelScrollAmount = 53; + +ui::EventType EventTypeFromNative(NativeEvent native_event) { + switch (native_event->type) { + case ui::WAYLAND_BUTTON: + switch (native_event->button.button) { + case ui::LEFT_BUTTON: + case ui::RIGHT_BUTTON: + case ui::MIDDLE_BUTTON: + return native_event->button.state ? ui::ET_MOUSE_PRESSED + : ui::ET_MOUSE_RELEASED; + case ui::SCROLL_UP: + case ui::SCROLL_DOWN: + return ui::ET_MOUSEWHEEL; + default: + break; + } + break; + case ui::WAYLAND_KEY: + return native_event->key.state ? ui::ET_KEY_PRESSED + : ui::ET_KEY_RELEASED; + case ui::WAYLAND_MOTION: + return ui::ET_MOUSE_MOVED; + case ui::WAYLAND_POINTER_FOCUS: + return native_event->pointer_focus.state ? ui::ET_MOUSE_ENTERED + : ui::ET_MOUSE_EXITED; + case ui::WAYLAND_KEYBOARD_FOCUS: + return ui::ET_UNKNOWN; + default: + break; + } + return ui::ET_UNKNOWN; +} + +gfx::Point GetMouseEventLocation(NativeEvent native_event) { + switch (native_event->type) { + case ui::WAYLAND_BUTTON: + return gfx::Point(native_event->button.x, native_event->button.y); + case ui::WAYLAND_MOTION: + return gfx::Point(native_event->motion.x, native_event->motion.y); + case ui::WAYLAND_POINTER_FOCUS: + return gfx::Point(native_event->pointer_focus.x, + native_event->pointer_focus.y); + default: + return gfx::Point(0, 0); + } +} + +int GetEventFlagsFromState(unsigned int state) { + int flags = 0; + if (state & ControlMask) + flags |= ui::EF_CONTROL_DOWN; + if (state & ShiftMask) + flags |= ui::EF_SHIFT_DOWN; + if (state & Mod1Mask) + flags |= ui::EF_ALT_DOWN; + if (state & LockMask) + flags |= ui::EF_CAPS_LOCK_DOWN; + if (state & Button1Mask) + flags |= ui::EF_LEFT_BUTTON_DOWN; + if (state & Button2Mask) + flags |= ui::EF_MIDDLE_BUTTON_DOWN; + if (state & Button3Mask) + flags |= ui::EF_RIGHT_BUTTON_DOWN; + + return flags; +} + +int GetButtonEventFlagsFromNativeEvent(NativeEvent native_event) { + // TODO(dnicoara): Need to add double click. + int flags = 0; + switch (native_event->button.button) { + case ui::LEFT_BUTTON: + return flags | ui::EF_LEFT_BUTTON_DOWN; + case ui::MIDDLE_BUTTON: + return flags | ui::EF_MIDDLE_BUTTON_DOWN; + case ui::RIGHT_BUTTON: + return flags | ui::EF_RIGHT_BUTTON_DOWN; + } + return flags; +} + +int GetEventFlagsFromNativeEvent(NativeEvent native_event) { + switch (native_event->type) { + case ui::WAYLAND_BUTTON: + return GetButtonEventFlagsFromNativeEvent(native_event) | + GetEventFlagsFromState(native_event->button.modifiers); + case ui::WAYLAND_KEY: + return GetEventFlagsFromState(native_event->key.modifiers); + case ui::WAYLAND_MOTION: + return GetEventFlagsFromState(native_event->motion.modifiers); + case ui::WAYLAND_KEYBOARD_FOCUS: + return GetEventFlagsFromState(native_event->keyboard_focus.modifiers); + default: + return 0; + } +} + +int GetMouseWheelOffset(NativeEvent native_event) { + if (native_event->button.button == ui::SCROLL_UP) { + return kWheelScrollAmount; + } else { + return -kWheelScrollAmount; + } +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// Event, private: + +void Event::Init() { + native_event_ = NULL; + native_event_2_ = NULL; +} + +void Event::InitWithNativeEvent(NativeEvent native_event) { + native_event_ = native_event; + // TODO(dnicoara): Remove once we rid views of Gtk/Gdk. + native_event_2_ = NULL; +} + +void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, + FromNativeEvent2) { + native_event_2_ = NULL; + // TODO(dnicoara): Remove once we rid views of Gtk/Gdk. + native_event_2_ = native_event_2; +} + +//////////////////////////////////////////////////////////////////////////////// +// MouseEvent, public: + +MouseEvent::MouseEvent(NativeEvent native_event) + : LocatedEvent(native_event) { +} + +MouseEvent::MouseEvent(NativeEvent2 native_event_2, + FromNativeEvent2 from_native) + : LocatedEvent(native_event_2, from_native) { + // TODO(dnicoara): Remove once we rid views of Gtk/Gdk. + NOTREACHED(); +} + +//////////////////////////////////////////////////////////////////////////////// +// LocatedEvent, protected: + +LocatedEvent::LocatedEvent(NativeEvent native_event) + : Event(native_event, EventTypeFromNative(native_event), + GetEventFlagsFromNativeEvent(native_event)), + location_(GetMouseEventLocation(native_event)) { +} + +LocatedEvent::LocatedEvent(NativeEvent2 native_event_2, + FromNativeEvent2 from_native) + : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { + // TODO(dnicoara) Remove once we rid views of Gtk. + NOTREACHED(); +} + +////////////////////////////////////////////////////////////////////////////// +// KeyEvent, public: + + +KeyEvent::KeyEvent(NativeEvent native_event) + : Event(native_event, EventTypeFromNative(native_event), + GetEventFlagsFromNativeEvent(native_event)), + key_code_(ui::KeyboardCodeFromXKeysym(native_event->key.sym)) { +} + +KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) + : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { + // TODO(dnicoara) Remove once we rid views of Gtk. + NOTREACHED(); +} + +uint16 KeyEvent::GetCharacter() const { + return GetCharacterFromKeyCode(key_code_, flags()); +} + +uint16 KeyEvent::GetUnmodifiedCharacter() const { + return GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); +} + +////////////////////////////////////////////////////////////////////////////// +// MouseWheelEvent, public: + +MouseWheelEvent::MouseWheelEvent(NativeEvent native_event) + : MouseEvent(native_event), + offset_(GetMouseWheelOffset(native_event)) { +} + +MouseWheelEvent::MouseWheelEvent(NativeEvent2 native_event_2, + FromNativeEvent2 from_native) + : MouseEvent(native_event_2, from_native) { + // TODO(dnicoara) Remove once we rid views of Gtk. + NOTREACHED(); +} + +} // namespace views diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h index b90bc84..9472dc7 100644 --- a/views/focus/accelerator_handler.h +++ b/views/focus/accelerator_handler.h @@ -20,7 +20,7 @@ namespace views { -#if defined(TOUCH_UI) +#if defined(TOUCH_UI) && !defined(USE_WAYLAND) // Dispatch an XEvent to the RootView. Return true if the event was dispatched // and handled, false otherwise. bool VIEWS_EXPORT DispatchXEvent(XEvent* xevent); @@ -40,6 +40,9 @@ class VIEWS_EXPORT AcceleratorHandler : public MessageLoop::Dispatcher { // focus manager #if defined(OS_WIN) virtual bool Dispatch(const MSG& msg); +#elif defined(USE_WAYLAND) + virtual base::MessagePumpDispatcher::DispatchStatus Dispatch( + ui::WaylandEvent* ev); #elif defined(TOUCH_UI) virtual base::MessagePumpDispatcher::DispatchStatus Dispatch(XEvent* xev); #else diff --git a/views/focus/accelerator_handler_wayland.cc b/views/focus/accelerator_handler_wayland.cc new file mode 100644 index 0000000..1039570 --- /dev/null +++ b/views/focus/accelerator_handler_wayland.cc @@ -0,0 +1,19 @@ +// 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/focus/accelerator_handler.h" + +#include "views/accelerator.h" +#include "views/focus/focus_manager.h" + +namespace views { + +AcceleratorHandler::AcceleratorHandler() {} + +base::MessagePumpDispatcher::DispatchStatus + AcceleratorHandler::Dispatch(ui::WaylandEvent* ev) { + return base::MessagePumpDispatcher::EVENT_IGNORED; +} + +} // namespace views diff --git a/views/ime/input_method_wayland.cc b/views/ime/input_method_wayland.cc new file mode 100644 index 0000000..20d3ff2 --- /dev/null +++ b/views/ime/input_method_wayland.cc @@ -0,0 +1,76 @@ +// 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/ime/input_method_wayland.h" + +#include "views/widget/widget.h" + +namespace views { + +InputMethodWayland::InputMethodWayland( + internal::InputMethodDelegate *delegate) { + set_delegate(delegate); +} + +void InputMethodWayland::DispatchKeyEvent(const KeyEvent& key) { + if (!GetTextInputClient()) { + DispatchKeyEventPostIME(key); + return; + } + + if (key.type() == ui::ET_KEY_PRESSED) { + ProcessKeyPressEvent(key); + } else if (key.type() == ui::ET_KEY_RELEASED) { + DispatchKeyEventPostIME(key); + } +} + +void InputMethodWayland::OnTextInputTypeChanged(View* view) { + NOTIMPLEMENTED(); +} + +void InputMethodWayland::OnCaretBoundsChanged(View* view) { + NOTIMPLEMENTED(); +} + +void InputMethodWayland::CancelComposition(View* view) { + NOTIMPLEMENTED(); +} + +std::string InputMethodWayland::GetInputLocale() { + return std::string(""); +} + +base::i18n::TextDirection InputMethodWayland::GetInputTextDirection() { + return base::i18n::UNKNOWN_DIRECTION; +} + +bool InputMethodWayland::IsActive() { + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// InputMethodWayland private + +void InputMethodWayland::ProcessKeyPressEvent(const KeyEvent& key) { + const View* old_focused_view = focused_view(); + DispatchKeyEventPostIME(key); + + // We shouldn't dispatch the character anymore if the key event caused focus + // change. + if (old_focused_view != focused_view()) + return; + + // If a key event was not filtered by |context_| or |context_simple_|, then + // it means the key event didn't generate any result text. For some cases, + // the key event may still generate a valid character, eg. a control-key + // event (ctrl-a, return, tab, etc.). We need to send the character to the + // focused text input client by calling TextInputClient::InsertChar(). + char16 ch = key.GetCharacter(); + TextInputClient* client = GetTextInputClient(); + if (ch && client) + client->InsertChar(ch, key.flags()); +} + +} // namespace views diff --git a/views/ime/input_method_wayland.h b/views/ime/input_method_wayland.h new file mode 100644 index 0000000..60dac30 --- /dev/null +++ b/views/ime/input_method_wayland.h @@ -0,0 +1,36 @@ +// 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_IME_INPUT_METHOD_WAYLAND_H_ +#define VIEWS_IME_INPUT_METHOD_WAYLAND_H_ +#pragma once + +#include + +#include "views/ime/input_method_base.h" + +namespace views { + +class InputMethodWayland : public InputMethodBase { + public: + explicit InputMethodWayland(internal::InputMethodDelegate *delegate); + + virtual void DispatchKeyEvent(const KeyEvent& key) OVERRIDE; + virtual void OnTextInputTypeChanged(View* view) OVERRIDE; + virtual void OnCaretBoundsChanged(View* view) OVERRIDE; + virtual void CancelComposition(View* view) OVERRIDE; + virtual std::string GetInputLocale() OVERRIDE; + virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; + virtual bool IsActive() OVERRIDE; + + private: + + void ProcessKeyPressEvent(const KeyEvent& key); + + DISALLOW_COPY_AND_ASSIGN(InputMethodWayland); +}; + +} // namespace views + +#endif // VIEWS_IME_INPUT_METHOD_WAYLAND_H_ diff --git a/views/metrics_wayland.cc b/views/metrics_wayland.cc new file mode 100644 index 0000000..7d3beb1 --- /dev/null +++ b/views/metrics_wayland.cc @@ -0,0 +1,17 @@ +// 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/metrics.h" + +namespace views { + +int GetDoubleClickInterval() { + return 500; +} + +int GetMenuShowDelay() { + return kDefaultMenuShowDelay; +} + +} // namespace views diff --git a/views/mouse_watcher.cc b/views/mouse_watcher.cc index 810db69..83fe75d 100644 --- a/views/mouse_watcher.cc +++ b/views/mouse_watcher.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -11,6 +11,10 @@ #include "views/view.h" #include "views/widget/widget.h" +#if defined(USE_WAYLAND) +#include "ui/wayland/events/wayland_event.h" +#endif + namespace views { // Amount of time between when the mouse moves outside the view's zone and when @@ -56,6 +60,22 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer { break; } } +#elif defined(USE_WAYLAND) + MessageLoopForUI::Observer::EventStatus WillProcessEvent( + ui::WaylandEvent* event) { + switch (event->type) { + case ui::WAYLAND_MOTION: + HandleGlobalMouseMoveEvent(false); + break; + case ui::WAYLAND_POINTER_FOCUS: + if (!event->pointer_focus.state) + HandleGlobalMouseMoveEvent(true); + break; + default: + break; + } + return EVENT_CONTINUE; + } #else void WillProcessEvent(GdkEvent* event) { } diff --git a/views/native_types.h b/views/native_types.h index 0941879..a5070e7 100644 --- a/views/native_types.h +++ b/views/native_types.h @@ -14,6 +14,11 @@ typedef union _GdkEvent GdkEvent; #if defined(USE_X11) typedef union _XEvent XEvent; #endif +#if defined(USE_WAYLAND) +namespace ui { +union WaylandEvent; +} +#endif #if defined(USE_AURA) namespace aura { @@ -40,9 +45,15 @@ typedef aura::Event* NativeEvent; #elif defined(OS_WIN) typedef MSG NativeEvent; #elif defined(OS_LINUX) + +#if defined(USE_WAYLAND) +typedef ui::WaylandEvent* NativeEvent; +#else typedef GdkEvent* NativeEvent; #endif +#endif + #if defined(USE_X11) typedef XEvent* NativeEvent2; #else diff --git a/views/view_wayland.cc b/views/view_wayland.cc new file mode 100644 index 0000000..7524858 --- /dev/null +++ b/views/view_wayland.cc @@ -0,0 +1,24 @@ +// 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/view.h" + +#include "base/logging.h" + +namespace views { + +gfx::NativeViewAccessible View::GetNativeViewAccessible() { + NOTIMPLEMENTED(); + return NULL; +} + +int View::GetHorizontalDragThreshold() { + return 8; +} + +int View::GetVerticalDragThreshold() { + return GetHorizontalDragThreshold(); +} + +} // namespace views diff --git a/views/views.gyp b/views/views.gyp index 0b91db6..61ce97b 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -86,6 +86,7 @@ 'controls/combobox/native_combobox_gtk.h', 'controls/combobox/native_combobox_views.cc', 'controls/combobox/native_combobox_views.h', + 'controls/combobox/native_combobox_wayland.cc', 'controls/combobox/native_combobox_win.cc', 'controls/combobox/native_combobox_win.h', 'controls/combobox/native_combobox_wrapper.h', @@ -104,7 +105,7 @@ 'controls/menu/menu_2.h', 'controls/menu/menu_config.cc', 'controls/menu/menu_config.h', - 'controls/menu/menu_config_gtk.cc', + 'controls/menu/menu_config_linux.cc', 'controls/menu/menu_config_win.cc', 'controls/menu/menu_controller.cc', 'controls/menu/menu_controller.h', @@ -119,7 +120,7 @@ 'controls/menu/menu_host_root_view.h', 'controls/menu/menu_item_view.cc', 'controls/menu/menu_item_view.h', - 'controls/menu/menu_item_view_gtk.cc', + 'controls/menu/menu_item_view_linux.cc', 'controls/menu/menu_item_view_win.cc', 'controls/menu/menu_model_adapter.cc', 'controls/menu/menu_model_adapter.h', @@ -128,7 +129,7 @@ 'controls/menu/menu_scroll_view_container.cc', 'controls/menu/menu_scroll_view_container.h', 'controls/menu/menu_separator.h', - 'controls/menu/menu_separator_gtk.cc', + 'controls/menu/menu_separator_linux.cc', 'controls/menu/menu_separator_win.cc', 'controls/menu/menu_win.cc', 'controls/menu/menu_win.h', @@ -137,14 +138,14 @@ 'controls/menu/native_menu_gtk.h', 'controls/menu/native_menu_host.h', 'controls/menu/native_menu_host_delegate.h', + 'controls/menu/native_menu_linux.cc', + 'controls/menu/native_menu_linux.h', 'controls/menu/native_menu_win.cc', 'controls/menu/native_menu_win.h', - 'controls/menu/native_menu_x.cc', - 'controls/menu/native_menu_x.h', 'controls/menu/nested_dispatcher_gtk.cc', 'controls/menu/nested_dispatcher_gtk.h', - 'controls/menu/menu_image_util_gtk.cc', - 'controls/menu/menu_image_util_gtk.h', + 'controls/menu/menu_image_util_linux.cc', + 'controls/menu/menu_image_util_linux.h', 'controls/menu/submenu_view.cc', 'controls/menu/submenu_view.h', 'controls/menu/view_menu_delegate.h', @@ -164,6 +165,7 @@ 'controls/native/native_view_host_win.h', 'controls/native/native_view_host_views.cc', 'controls/native/native_view_host_views.h', + 'controls/native/native_view_host_wayland.cc', 'controls/native/native_view_host_wrapper.h', 'controls/progress_bar.h', 'controls/progress_bar.cc', @@ -183,6 +185,7 @@ 'controls/scrollbar/native_scroll_bar_gtk.h', 'controls/scrollbar/native_scroll_bar_views.cc', 'controls/scrollbar/native_scroll_bar_views.h', + 'controls/scrollbar/native_scroll_bar_wayland.cc', 'controls/scrollbar/native_scroll_bar_win.cc', 'controls/scrollbar/native_scroll_bar_win.h', 'controls/scrollbar/native_scroll_bar_wrapper.h', @@ -225,6 +228,7 @@ 'controls/textfield/textfield_views_model.h', 'controls/textfield/native_textfield_gtk.cc', 'controls/textfield/native_textfield_gtk.h', + 'controls/textfield/native_textfield_wayland.cc', 'controls/textfield/native_textfield_win.cc', 'controls/textfield/native_textfield_win.h', 'controls/textfield/native_textfield_wrapper.h', @@ -245,6 +249,7 @@ 'events/event.h', 'events/event_aura.cc', 'events/event_gtk.cc', + 'events/event_wayland.cc', 'events/event_win.cc', 'events/event_utils_win.cc', 'events/event_utils_win.h', @@ -253,6 +258,7 @@ 'focus/accelerator_handler_aura.cc', 'focus/accelerator_handler_gtk.cc', 'focus/accelerator_handler_touch.cc', + 'focus/accelerator_handler_wayland.cc', 'focus/accelerator_handler_win.cc', 'focus/external_focus_tracker.cc', 'focus/external_focus_tracker.h', @@ -276,6 +282,8 @@ 'ime/input_method_gtk.h', 'ime/input_method_ibus.cc', 'ime/input_method_ibus.h', + 'ime/input_method_wayland.cc', + 'ime/input_method_wayland.h', 'ime/input_method_win.cc', 'ime/input_method_win.h', 'ime/mock_input_method.cc', @@ -299,6 +307,7 @@ 'metrics.cc', 'metrics.h', 'metrics_gtk.cc', + 'metrics_wayland.cc', 'metrics_win.cc', 'mouse_watcher.cc', 'mouse_watcher.h', @@ -325,6 +334,7 @@ 'view_gtk.cc', 'view_text_utils.cc', 'view_text_utils.h', + 'view_wayland.cc', 'view_win.cc', 'views_delegate.h', 'widget/aero_tooltip_manager.cc', @@ -364,6 +374,8 @@ 'widget/native_widget_private.h', 'widget/native_widget_gtk.cc', 'widget/native_widget_gtk.h', + 'widget/native_widget_wayland.cc', + 'widget/native_widget_wayland.h', 'widget/native_widget_view.cc', 'widget/native_widget_view.h', 'widget/native_widget_views.cc', @@ -396,6 +408,22 @@ '<(DEPTH)/third_party/wtl/include', ], 'conditions': [ + ['use_wayland == 1', { + 'dependencies': [ + '../ui/wayland/wayland.gyp:wayland', + ], + 'sources/': [ + ['exclude', '_(gtk|x)\\.cc$'], + ['exclude', '/(gtk|x)_[^/]*\\.cc$'], + ['exclude', 'focus/accelerator_handler_touch.cc'], + ['exclude', 'touchui/touch_factory.cc'], + ['exclude', 'touchui/touch_factory.h'], + ['include', 'controls/menu/native_menu_linux.cc'], + ['include', 'controls/menu/native_menu_linux.h'], + ['include', 'drag_utils_gtk.cc'], + ['include', 'widget/tooltip_manager_views.cc'], + ], + }], ['use_aura==1', { 'dependencies': [ '../aura/aura.gyp:aura', @@ -448,8 +476,8 @@ }], ['touchui==0', { 'sources!': [ - 'controls/menu/native_menu_x.cc', - 'controls/menu/native_menu_x.h', + 'controls/menu/native_menu_linux.cc', + 'controls/menu/native_menu_linux.h', 'widget/tooltip_manager_views.cc', 'touchui/touch_selection_controller_impl.cc', 'touchui/touch_selection_controller_impl.h', 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 +#include +#include +#include +#include + +#include +#include + +#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(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 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 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(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( + 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 + +#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 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 tooltip_manager_; + + // The following factory is used to delay destruction. + ScopedRunnableMethodFactory 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 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 surface_; + scoped_refptr 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(); diff --git a/views/window/dialog_client_view.cc b/views/window/dialog_client_view.cc index 08c833b..562c8cc 100644 --- a/views/window/dialog_client_view.cc +++ b/views/window/dialog_client_view.cc @@ -312,6 +312,9 @@ const DialogClientView* DialogClientView::AsDialogClientView() const { void DialogClientView::OnPaint(gfx::Canvas* canvas) { #if defined(OS_WIN) FillViewWithSysColor(canvas, this, GetSysColor(COLOR_3DFACE)); +#elif defined(USE_WAYLAND) + SkColor sk_color = SkColorSetARGB(200, 255, 255, 255); + canvas->FillRectInt(sk_color, 0, 0, width(), height()); #else GtkWidget* widget = GetWidget()->GetNativeView(); if (GTK_IS_WINDOW(widget)) { -- cgit v1.1