[M130 Migration][VD] Implement the specific scrollbar for the TV web browser. 63/325063/6
authorDarla Remo <dk.remo@samsung.com>
Tue, 20 May 2025 09:58:29 +0000 (09:58 +0000)
committerBot Blink <blinkbot@samsung.com>
Thu, 5 Jun 2025 11:39:31 +0000 (11:39 +0000)
The web browser team wants specific scrollbar to the TV.
So we implemented the scrollbar based on the GUI guideline document.

Removed functions referencing UpdateLayerPositionRecursive()
as PaintLayer::UpdateLayerPositionRecursive() was removed from upstream:
    https://chromium-review.googlesource.com/c/chromium/src/+/4990010
scrollbar works properly without the functions referencing the said
method.

Reference:
    https://archive.tizen.org/gerrit/310949/

Change-Id: I0a551292c89b14ee64ad409ca2300cdc6c32abd5
Signed-off-by: Darla Remo <dk.remo@samsung.com>
101 files changed:
base/metrics/field_trial.cc
base/metrics/field_trial.h
cc/input/scrollbar.h
cc/input/scrollbar_animation_controller.cc
cc/input/scrollbar_animation_controller.h
cc/layers/painted_scrollbar_layer.cc
cc/layers/painted_scrollbar_layer.h
cc/layers/painted_scrollbar_layer_impl.cc
cc/layers/painted_scrollbar_layer_impl.h
cc/layers/scrollbar_layer_impl_base.cc
cc/layers/scrollbar_layer_impl_base.h
cc/test/fake_scrollbar.h
cc/trees/layer_tree_impl.cc
cc/trees/layer_tree_impl.h
cc/trees/layer_tree_settings.h
content/browser/web_contents/web_contents_impl.cc
content/child/field_trial.cc
content/shell/BUILD.gn
third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
third_party/blink/public/common/web_preferences/web_preferences.h
third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
third_party/blink/public/mojom/BUILD.gn
third_party/blink/public/mojom/webpreferences/web_preferences.mojom
third_party/blink/public/platform/web_theme_engine.h
third_party/blink/public/web/web_settings.h
third_party/blink/renderer/core/exported/web_settings_impl.cc
third_party/blink/renderer/core/exported/web_settings_impl.h
third_party/blink/renderer/core/exported/web_view_impl.cc
third_party/blink/renderer/core/frame/settings.h
third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
third_party/blink/renderer/core/paint/scrollable_area_painter.cc
third_party/blink/renderer/core/scroll/build.gni
third_party/blink/renderer/core/scroll/scroll_types.h
third_party/blink/renderer/core/scroll/scrollable_area.cc
third_party/blink/renderer/core/scroll/scrollable_area.h
third_party/blink/renderer/core/scroll/scrollbar.cc
third_party/blink/renderer/core/scroll/scrollbar.h
third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
third_party/blink/renderer/core/scroll/scrollbar_theme.cc
third_party/blink/renderer/core/scroll/scrollbar_theme.h
third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.cc [new file with mode: 0644]
third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.h [new file with mode: 0644]
third_party/blink/renderer/platform/graphics/graphics_context.cc
third_party/blink/renderer/platform/graphics/graphics_context.h
third_party/blink/renderer/platform/graphics/paint/display_item.h
third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
third_party/blink/renderer/platform/theme/web_theme_engine_default.h
third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
tizen_src/build/config/BUILD.gn
tizen_src/build/config/tizen_features.gni
tizen_src/build/gn_chromiumefl.sh
tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.cc [new file with mode: 0644]
tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.h [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/BUILD.gn [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_disabled.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_hover.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_normal.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_left.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_right.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_left.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_right.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_bottom.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_top.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_bottom.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_top.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_left.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_right.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_bottom.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_top.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_left.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_right.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_bottom.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_top.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_left.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_right.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_bottom.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_center.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_top.png [new file with mode: 0644]
tizen_src/chromium_impl/ui/resources/ui_resources_tizen.grd [new file with mode: 0644]
tizen_src/ewk/efl_integration/BUILD.gn
tools/gritsettings/resource_ids.spec
ui/native_theme/BUILD.gn
ui/native_theme/native_theme.h
ui/native_theme/native_theme_aura.cc
ui/native_theme/native_theme_features.cc
ui/native_theme/native_theme_features.h

index 2fc84a4215755a5fc16c1b6699cdb1c4369c8b4c..1b7e2dbfe5a5873f395f5d7ba22db7de6ed1dc76 100644 (file)
@@ -727,6 +727,21 @@ void FieldTrialList::ApplyFeatureOverridesInChildProcess(
   }
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void FieldTrialList::ApplyFeatureOverridesInChildProcess(
+    const CommandLine& command_line,
+    FeatureList* feature_list) {
+  if (!global_->field_trial_allocator_.get()) {
+    return feature_list->InitFromCommandLine(
+        command_line.GetSwitchValueASCII(switches::kEnableFeatures),
+        command_line.GetSwitchValueASCII(switches::kDisableFeatures));
+  }
+
+  feature_list->InitFromSharedMemory(
+      global_->field_trial_allocator_.get());
+}
+#endif
+
 #if BUILDFLAG(USE_BLINK)
 // static
 void FieldTrialList::PopulateLaunchOptionsWithFieldTrialState(
index 9c59ce4ba6b7892fa2e4734283f518fa4dd760b7..f4bdcc187481d9d0e9f2c3439498b7d951fb8994 100644 (file)
@@ -614,6 +614,13 @@ class BASE_EXPORT FieldTrialList {
   // Requires CreateTrialsInChildProcess() to have been called first which
   // initializes access to the shared memory segment.
   static void ApplyFeatureOverridesInChildProcess(FeatureList* feature_list);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  // Web browser native scrollbar need use command line to override
+  // base::Feature
+  static void ApplyFeatureOverridesInChildProcess(
+      const CommandLine& command_line,
+      FeatureList* feature_list);
+#endif
 
 #if BUILDFLAG(USE_BLINK)
   // Populates |command_line| and |launch_options| with the handles and command
index f83895f7727daba739bb83560d9d7d725f050388..530ed56c16067a037b92b3bcba80f536fcc1c9c7 100644 (file)
@@ -51,6 +51,9 @@ class Scrollbar : public base::RefCounted<Scrollbar> {
   virtual bool IsRunningWebTest() const = 0;
   virtual bool IsFluentOverlayScrollbarMinimalMode() const = 0;
   virtual bool HasThumb() const = 0;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  virtual bool IsHovered() const = 0;
+#endif
   virtual bool SupportsDragSnapBack() const = 0;
   virtual bool JumpOnTrackClick() const = 0;
   virtual bool IsOpaque() const = 0;
index f515e68045352cecb960fbaee7c89de2fa84ceb6..2d99c2e2f1bf14e7176fd01ed1d6de89dfd15cd7 100644 (file)
@@ -184,7 +184,11 @@ void ScrollbarAnimationController::RunAnimationFrame(float progress) {
   }
 
   ApplyOpacityToScrollbars(opacity);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (progress == 1.f || should_stop_animation_)
+#else
   if (progress == 1.f)
+#endif
     StopAnimation();
 }
 
@@ -399,7 +403,9 @@ void ScrollbarAnimationController::ApplyOpacityToScrollbars(float opacity) {
     client_->SetNeedsRedrawForScrollbarAnimation();
   }
 
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
   opacity_ = opacity;
+#endif
 
   if (previously_visible_ != currently_visible) {
     client_->DidChangeScrollbarVisibility();
@@ -407,4 +413,10 @@ void ScrollbarAnimationController::ApplyOpacityToScrollbars(float opacity) {
   }
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void ScrollbarAnimationController::SetShouldStopAnimation(
+    bool should_stop_animation) {
+  should_stop_animation_ = should_stop_animation;
+}
+#endif
 }  // namespace cc
index fdabd3126deddf38da4c4a2f1095ec0da139d0b3..e277c70c3924820a047b83c845f662c8a317c7fe 100644 (file)
@@ -97,6 +97,10 @@ class CC_EXPORT ScrollbarAnimationController {
 
   ScrollbarSet Scrollbars() const;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  void SetShouldStopAnimation(bool should_stop_animation);
+#endif
+
   SingleScrollbarAnimationControllerThinning& GetScrollbarAnimationController(
       ScrollbarOrientation) const;
 
@@ -162,6 +166,10 @@ class CC_EXPORT ScrollbarAnimationController {
 
   bool is_mouse_down_;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool should_stop_animation_ = false;
+#endif
+
   bool tickmarks_showing_;
 
   bool visibility_changed_ = false;
index 540be2386c3b9e564e684b0cda009a06fd50ede8..1bc00bb6515bf1f46c0c55962a480e199f955f09 100644 (file)
@@ -48,6 +48,9 @@ PaintedScrollbarLayer::PaintedScrollbarLayer(scoped_refptr<Scrollbar> scrollbar)
       has_thumb_(scrollbar_.Read(*this)->HasThumb()),
       jump_on_track_click_(scrollbar_.Read(*this)->JumpOnTrackClick()),
       supports_drag_snap_back_(scrollbar_.Read(*this)->SupportsDragSnapBack()),
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      is_hovered_(scrollbar_.Read(*this)->IsHovered()),
+#endif
       is_overlay_(scrollbar_.Read(*this)->IsOverlay()),
       is_web_test_(scrollbar_.Read(*this)->IsRunningWebTest()),
       uses_nine_patch_track_and_buttons_(
@@ -101,6 +104,10 @@ void PaintedScrollbarLayer::PushPropertiesTo(
 
   scrollbar_layer->SetScrollbarPaintedOpacity(painted_opacity_.Read(*this));
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  scrollbar_layer->SetIsHovered(is_hovered_);
+#endif
+
   scrollbar_layer->set_is_overlay_scrollbar(is_overlay_);
   scrollbar_layer->set_is_web_test(is_web_test_);
 
@@ -175,6 +182,11 @@ bool PaintedScrollbarLayer::UpdateGeometry() {
   } else {
     updated |= UpdateProperty(gfx::Size(), &thumb_size_.Write(*this));
   }
+
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  updated |= UpdateProperty(scrollbar->IsHovered(), &is_hovered_);
+#endif
+
   return updated;
 }
 
index 3376b66cc56369636e109172b5d24122b9aca33f..4dd6474190e0e1ba4d90d74590bbf91452b07f79 100644 (file)
@@ -107,6 +107,9 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerBase {
 
   const bool supports_drag_snap_back_;
   const bool is_overlay_;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool is_hovered_;
+#endif
   const bool is_web_test_;
   const bool uses_nine_patch_track_and_buttons_;
   const bool uses_solid_color_thumb_;
index ed9b32bc1af07201d44e36ceb57bb00f417d1a4a..ba679ed0845d2f15d7e23979cf5e73ee57da16a9 100644 (file)
@@ -513,10 +513,11 @@ bool PaintedScrollbarLayerImpl::IsThumbResizable() const {
   return false;
 }
 
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
 LayerTreeSettings::ScrollbarAnimator
 PaintedScrollbarLayerImpl::GetScrollbarAnimator() const {
   return IsFluentOverlayScrollbarEnabled() ? LayerTreeSettings::AURA_OVERLAY
                                            : LayerTreeSettings::NO_ANIMATOR;
 }
-
+#endif
 }  // namespace cc
index 9ed239f99c229b6a3eedc829a45daecbdc711d50..d5afe71fbf3e633059a26cfb24fe3e257556c732 100644 (file)
@@ -84,7 +84,9 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase {
   gfx::Rect ForwardTrackRect() const override;
   int ThumbThickness() const override;
 
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
   LayerTreeSettings::ScrollbarAnimator GetScrollbarAnimator() const override;
+#endif
 
  protected:
   PaintedScrollbarLayerImpl(LayerTreeImpl* tree_impl,
index fa4130b92a4e79f9af3aa3b8754bf6b72aa18624..6bde2737d4481dca8eeddabfb14e70a847f0ba22 100644 (file)
@@ -21,6 +21,9 @@ ScrollbarLayerImplBase::ScrollbarLayerImplBase(
     bool is_overlay)
     : LayerImpl(tree_impl, id),
       is_overlay_scrollbar_(is_overlay),
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      is_hovered_(false),
+#endif
       thumb_thickness_scale_factor_(1.f),
       current_pos_(0.f),
       clip_layer_length_(0.f),
@@ -41,6 +44,9 @@ void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) {
   scrollbar_layer->SetHasFindInPageTickmarks(has_find_in_page_tickmarks_);
   scrollbar_layer->set_is_overlay_scrollbar(is_overlay_scrollbar_);
   scrollbar_layer->set_is_web_test(is_web_test_);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  scrollbar_layer->SetIsHovered(is_hovered_);
+#endif
   scrollbar_layer->SetScrollElementId(scroll_element_id());
 }
 
@@ -374,5 +380,14 @@ ScrollbarPart ScrollbarLayerImplBase::IdentifyScrollbarPart(
   // hit testing other scrollbar parts is not yet implemented.
   return ScrollbarPart::kNoPart;
 }
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void ScrollbarLayerImplBase::SetIsHovered(bool is_hovered) {
+  if (is_hovered_ == is_hovered)
+    return;
+
+  is_hovered_ = is_hovered;
 
+  layer_tree_impl()->UpdateScrollbarAnimationIfNeeded();
+}
+#endif
 }  // namespace cc
index a3d99e136eef58eab7a5ee342957df34352872cf..eb9c4abb44b06564aa4475525c921998f85bd8c5 100644 (file)
@@ -37,6 +37,11 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
   float scroll_layer_length() const { return scroll_layer_length_; }
   float vertical_adjust() const { return vertical_adjust_; }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool IsHovered() const { return is_hovered_; }
+  void SetIsHovered(bool is_hovered);
+#endif
+
   bool is_overlay_scrollbar() const { return is_overlay_scrollbar_; }
   void set_is_overlay_scrollbar(bool is_overlay) {
     is_overlay_scrollbar_ = is_overlay;
@@ -116,6 +121,10 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
  private:
   bool IsScrollbarLayer() const final;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool is_hovered_;
+#endif
+
   gfx::Rect ComputeThumbQuadRectWithThumbThicknessScale(
       float thumb_thickness_scale_factor) const;
 
index c2e932c3460c2fe1267af51250df6f9303281cba..e6241c98c2d4816190a60a658e5d9f2a23030eff 100644 (file)
@@ -24,6 +24,9 @@ class FakeScrollbar : public Scrollbar {
   bool IsLeftSideVerticalScrollbar() const override;
   bool IsSolidColor() const override;
   bool IsOverlay() const override;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool IsHovered() const override { return false; }
+#endif
   bool IsRunningWebTest() const override;
   bool IsFluentOverlayScrollbarMinimalMode() const override;
   bool HasThumb() const override;
index 6ef14d5c9e5149f97a92c5c5d7a14ffed308c8cd..f0c083da0894fbb44b3ad5e6d884ac3826327a4d 100644 (file)
@@ -3044,6 +3044,33 @@ std::string LayerTreeImpl::LayerListAsJson() const {
   return value.ToFormattedJSON();
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void LayerTreeImpl::UpdateScrollbarAnimationIfNeeded() {
+  if (!host_impl_ || !host_impl_->OuterViewportScrollNode())
+    return;
+
+  ScrollbarAnimationController* controller =
+      host_impl_->ScrollbarAnimationControllerForElementId(
+          host_impl_->OuterViewportScrollNode()->element_id);
+
+  if (!settings().use_native_scrollbars ||
+      settings().scrollbar_animator != LayerTreeSettings::ANDROID_OVERLAY ||
+      !controller)
+    return;
+
+  bool should_stop_animation = false;
+  for (ScrollbarLayerImplBase* scrollbar : controller->Scrollbars()) {
+    if (scrollbar->IsHovered()) {
+      should_stop_animation = true;
+      break;
+    }
+  }
+
+  controller->SetShouldStopAnimation(should_stop_animation);
+  controller->DidScrollUpdate();
+}
+#endif
+
 void LayerTreeImpl::AddViewTransitionRequest(
     std::unique_ptr<ViewTransitionRequest> request) {
   if (IsActiveTree() && request->type() == ViewTransitionRequest::Type::kSave) {
index fd93678059e0f8d32778d779035d05d71edba1cd..70c8ae35cc7bb64616adbbaa5bc5c8e1160162f6 100644 (file)
@@ -811,6 +811,10 @@ class CC_EXPORT LayerTreeImpl {
     return host_impl_->viewport_mobile_optimized();
   }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  void UpdateScrollbarAnimationIfNeeded();
+#endif
+
   // Add a view transition request from the embedder.
   void AddViewTransitionRequest(std::unique_ptr<ViewTransitionRequest> request);
 
index a7b1406a289a6137a2471792ae840b117b91157c..011249b48723ece9a0ab33f98d7bb88fa7eab94a 100644 (file)
@@ -62,6 +62,9 @@ class CC_EXPORT LayerTreeSettings {
     AURA_OVERLAY,
   };
   ScrollbarAnimator scrollbar_animator = NO_ANIMATOR;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool use_native_scrollbars = false;
+#endif
   base::TimeDelta scrollbar_fade_delay;
   base::TimeDelta scrollbar_fade_duration;
   base::TimeDelta scrollbar_thinning_duration;
index 423b1e62a3ed915ccd40da603aa83f198416834e..e7a83f038d82ce59a883838cdc3f6ac78a7890b2 100644 (file)
 #include "tizen_src/ewk/efl_integration/browser/autofill/autofill_request_manager.h"
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+#include "ui/native_theme/native_theme_features.h"
+#endif
+
 namespace content {
 
 namespace {
@@ -3563,6 +3567,10 @@ const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences() {
   // GuestViews in the same StoragePartition need to find each other's frames.
   prefs.renderer_wide_named_frame_lookup = IsGuest();
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  prefs.use_native_scrollbars = ui::IsNativeScrollbarEnabled();
+#endif
+
 #if BUILDFLAG(IS_TIZEN_TV)
   prefs.use_arrow_scroll = false;
   // Disallow file access from external urls by default.
index 54845e36bbda79b0fff33766898071bb4bd476fc..3ae695ee286cd80480df4911cb74a5c00df68c7e 100644 (file)
@@ -36,7 +36,12 @@ void InitializeFieldTrialAndFeatureList() {
   // Ensure any field trials in browser are reflected into the child process.
   base::FieldTrialList::CreateTrialsInChildProcess(command_line);
   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  base::FieldTrialList::ApplyFeatureOverridesInChildProcess(command_line,
+                                                            feature_list.get());
+#else
   base::FieldTrialList::ApplyFeatureOverridesInChildProcess(feature_list.get());
+#endif
   // TODO(crbug.com/40638048): This may be redundant. The way this is supposed
   // to work is that the parent process's state should be passed via
   // command-line to the child process, such that a feature explicitly enabled
index e0ec625dfeae7b64d9bee79f9f703ba912b136f9..ea42e5840df6c9769f64c334d3e2ce214b31a29f 100644 (file)
@@ -599,6 +599,11 @@ repack("pak") {
         [ "$root_gen_dir/content/browser/devtools/devtools_resources.pak" ]
     deps += [ "//content/browser/devtools:devtools_resources" ]
   }
+  if (tizen_vd_native_scrollbars) {
+    sources += [ "$root_gen_dir/ui/resources/ui_resources_tizen.pak" ]
+    deps +=
+        [ "//tizen_src/chromium_impl/ui/resources:ui_resources_tizen_grd_grit" ]
+  }
   output = "$root_out_dir/content_shell.pak"
 }
 
index 6350a060dedf6e40c3e19536e8af5265b2b78803..daa29d3e2c34d7f6f4baa1a5bd3daf15c62454f5 100644 (file)
@@ -263,6 +263,9 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
   out->renderer_wide_named_frame_lookup =
       data.renderer_wide_named_frame_lookup();
   out->modal_context_menu = data.modal_context_menu();
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  out->use_native_scrollbars = data.use_native_scrollbars();
+#endif
 #if BUILDFLAG(IS_TIZEN_TV)
   out->use_arrow_scroll = data.use_arrow_scroll();
   out->allow_file_access_from_external_urls =
index 3cb6309e30facf21a10c8513666a5aa3b72ed322..6ebb4b4bfcc2d37d837e53d80a252afbc16167e8 100644 (file)
@@ -488,6 +488,10 @@ struct BLINK_COMMON_EXPORT WebPreferences {
   // (false). Used by StrictMimetypeCheckForWorkerScriptsEnabled policy.
   bool strict_mime_type_check_for_worker_scripts_enabled = true;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool use_native_scrollbars = false;
+#endif
+
 #if BUILDFLAG(IS_TIZEN_TV)
   // Hosted app need to get local access privilege when they use tv device api
   // located in local path(file://usr/apps/pepper/webapis/webapis.js)
index f3adbadba626e074a66d5ded5395db7c38b468af..fbce4132b7b838f4a363bd191c78f25be7c4abca 100644 (file)
@@ -208,6 +208,12 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
   }
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  static bool use_native_scrollbars(const blink::web_pref::WebPreferences& r) {
+    return r.use_native_scrollbars;
+  }
+#endif
+
   static bool webgl1_enabled(const blink::web_pref::WebPreferences& r) {
     return r.webgl1_enabled;
   }
index 0bfe84d99579e329794e4e26034061dcabbd5817..f8bfdeed4fb657e3e49ef8858a6deffa70996b94 100644 (file)
@@ -401,6 +401,9 @@ mojom("mojom_platform") {
   if (tizen_video_hole) {
     enabled_features += [ "tizen_video_hole" ]
   }
+  if (tizen_vd_native_scrollbars) {
+    enabled_features += [ "tizen_vd_native_scrollbars" ]
+  }
   if (is_android || is_ios) {
     enabled_features += [ "is_android_or_ios" ]
   }
index 21e117daebb6d861b531141447c24fdc46f96e6d..7806252c9f004f20f3d48d2095330dd41d4be23e 100644 (file)
@@ -574,4 +574,7 @@ struct WebPreferences {
 
   [EnableIf=is_tizen_tv]
   bool use_scrollbar_thumb_focus_notifications;
+
+  [EnableIf=tizen_vd_native_scrollbars]
+  bool use_native_scrollbars;
 };
index fbcad81eb9357f1493a9b5b85cabe3eeee574acf..bda8f3a78c91eede880a78b3357011be8d5797e1 100644 (file)
@@ -207,6 +207,12 @@ class WebThemeEngine {
     std::optional<SkColor> track_color;
   };
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  struct ScrollbarTypeExtraParams {
+    bool is_thin_scrollbar;
+  };
+#endif
+
 #if BUILDFLAG(IS_MAC)
   enum ScrollbarOrientation {
     // Vertical scrollbar on the right side of content.
@@ -235,6 +241,9 @@ class WebThemeEngine {
                                     InnerSpinButtonExtraParams,
                                     ProgressBarExtraParams,
                                     ScrollbarThumbExtraParams,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+                                    ScrollbarTypeExtraParams,
+#endif
 #if BUILDFLAG(IS_MAC)
                                     ScrollbarExtraParams,
 #endif
@@ -246,6 +255,9 @@ class WebThemeEngine {
   // like vertical scrollbar thumbs, the width will be the required width of
   // the track while the height will be the minimum height.
   virtual gfx::Size GetSize(Part) { return gfx::Size(); }
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  virtual gfx::Size GetSize(Part, bool) { return gfx::Size(); }
+#endif
 
   virtual bool SupportsNinePatch(Part) const { return false; }
   virtual gfx::Size NinePatchCanvasSize(Part) const { return gfx::Size(); }
index c414480a58c4c7f616911a11656ecf6784323197..7c1b0dc8509eea9b7bdd7c38347b6dc568b239ea 100644 (file)
@@ -302,6 +302,10 @@ class WebSettings {
   virtual std::string GetDefaultAudioInputDeviceId() = 0;
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  virtual void SetUseNativeScrollbars(bool) = 0;
+#endif
+
 #if defined(TIZEN_ATK_SUPPORT)
   virtual void SetAccessibilityEnabled(bool) = 0;
   virtual bool GetAccessibilityEnabled() = 0;
index 0d74eaf75b335ca6e8d2e24047c78419d9de84c3..9a7693d7919f56493f575b1d78273c0b84c6e94b 100644 (file)
@@ -888,6 +888,12 @@ bool WebSettingsImpl::MediaPlaybackNotificationEnabled() {
 }
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void WebSettingsImpl::SetUseNativeScrollbars(bool enabled) {
+  settings_->SetUseNativeScrollbars(enabled);
+}
+#endif
+
 #if defined(TIZEN_VIDEO_HOLE)
 void WebSettingsImpl::SetVideoHoleEnabled(bool enabled) {
   settings_->SetVideoHoleEnabled(enabled);
index 69daed5298089ea4ce37256caef09c4ad6def7d6..286550128d4e4b503de7ad7753a4c8dcde247fc7 100644 (file)
@@ -259,6 +259,10 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
   std::string GetDefaultAudioInputDeviceId() override;
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  void SetUseNativeScrollbars(bool) override;
+#endif
+
 #if defined(TIZEN_ATK_SUPPORT)
   void SetAccessibilityEnabled(bool) override;
   bool GetAccessibilityEnabled() override;
index 6757f59f2328b7f66a2a6be1b389c86ab7098d05..24c4103249838cf31af23371ac263390fdf000c6 100644 (file)
@@ -1854,6 +1854,10 @@ void WebView::ApplyWebPreferences(const web_pref::WebPreferences& prefs,
   settings->SetDragDropEnabled(prefs.drag_drop_enabled);
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  settings->SetUseNativeScrollbars(prefs.use_native_scrollbars);
+#endif
+
 #if BUILDFLAG(IS_EFL)
   settings->SetTizenVersion(prefs.tizen_version_major,
                             prefs.tizen_version_minor,
index bbc29d9168b2fd05263b853c83ea8dceda0f6322..26daff44be0dc8ccc6b2bd2d47a81c87263f4299 100644 (file)
 #include "third_party/blink/renderer/core/settings_base.h"
 #include "third_party/blink/renderer/platform/fonts/generic_font_family_settings.h"
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#endif
+
 namespace blink {
 
 class CORE_EXPORT Settings : public SettingsBase {
@@ -96,6 +100,15 @@ class CORE_EXPORT Settings : public SettingsBase {
   }
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  static void SetUseNativeScrollbars(bool flag) {
+    ScrollbarTheme::SetNativeScrollbarsEnabled(flag);
+  }
+  static bool UseNativeScrollbars() {
+    return ScrollbarTheme::NativeScrollbarsEnabled();
+  }
+#endif
+
  private:
   GenericFontFamilySettings generic_font_family_settings_;
 
index 947fc94b82d1593901639eee2934045f8a9fb125..eb0ac7c111fe2010e9a9a54237f221e5b5bffc49 100644 (file)
@@ -76,6 +76,9 @@ static void RecordScrollbarPartStats(Document& document, ScrollbarPart part) {
     case kScrollbarBGPart:
       UseCounter::Count(document, WebFeature::kCSSSelectorPseudoScrollbar);
       break;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+    case kCornerPart:
+#endif
     case kNoPart:
     case kAllParts:
       break;
index 42817804f61bb5073d39be2e0e1ba5570494b38c..49e565351ac047c25c4923cde69a407dd56c3b7d 100644 (file)
@@ -2059,6 +2059,12 @@ void PaintLayerScrollableArea::PositionOverflowControls() {
   if (scroll_corner_) {
     PhysicalRect rect(ScrollCornerRect());
     scroll_corner_->SetOverriddenSize(rect.size);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+    if (UseNativeScrollbars() && HasVerticalScrollbar()) {
+      VerticalScrollbar()->SetCornerHeight(
+          HasHorizontalScrollbar() ? HorizontalScrollbar()->Height() : 0);
+    }
+#endif
     // TODO(crbug.com/1020913): This should be part of PaintPropertyTreeBuilder
     // when we support subpixel layout of overflow controls.
     scroll_corner_->GetMutableForPainting().FirstFragment().SetPaintOffset(
@@ -2130,6 +2136,14 @@ bool PaintLayerScrollableArea::HitTestOverflowControls(
                              (HasHorizontalScrollbar()
                                   ? HorizontalScrollbar()->ScrollbarThickness()
                                   : resize_control_size));
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+    // If the vertical scrollbar has corner size, we must expand vertical
+    // scrollbar rect with corner size.
+    // It will prevent to deliver the mouse event to content's element when
+    // mouse works on the scroll corner area.
+    v_bar_rect.set_height(v_bar_rect.height() +
+                          VerticalScrollbar()->CornerHeight());
+#endif
     if (v_bar_rect.Contains(local_point)) {
       result.SetScrollbar(VerticalScrollbar());
       return true;
@@ -2812,6 +2826,13 @@ void PaintLayerScrollableArea::ScrollbarManager::Trace(
   visitor->Trace(v_bar_);
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void PaintLayerScrollableArea::ScrollbarSizeDidChange() {
+  PositionOverflowControls();
+  SetScrollCornerNeedsPaintInvalidation();
+}
+#endif
+
 int PaintLayerScrollableArea::FreezeScrollbarsScope::count_ = 0;
 
 PaintLayerScrollableArea::FreezeScrollbarsRootScope::FreezeScrollbarsRootScope(
index bf477849766296f86ad737db0ceea02e6d7436d4..0bb395c650eabf183af7ab73ed4a951b25e38929 100644 (file)
@@ -551,6 +551,10 @@ class CORE_EXPORT PaintLayerScrollableArea final
                              bool focused) override;
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  void ScrollbarSizeDidChange() override;
+#endif
+
   void Trace(Visitor*) const override;
 
   gfx::Rect ScrollingBackgroundVisualRect(
index 26fafec8dc8862175b2b935d1321337e2951d24e..578c5518a49f1fba34a42a5ea90421ef0110c83d 100644 (file)
@@ -370,7 +370,14 @@ void ScrollableAreaPainter::PaintScrollCorner(
 
   // We don't want to paint opaque if we have overlay scrollbars, since we need
   // to see what is behind it.
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  // When native scrollbars is used, we must paint it with white
+  // because we don't need to see what is behind it.
+  if (scrollable_area_.HasOverlayScrollbars() &&
+      !scrollable_area_.UseNativeScrollbars()) {
+#else
   if (scrollable_area_.HasOverlayScrollbars()) {
+#endif
     return;
   }
 
index 117f099f4d36d3eaae5591952eed9c125321fc67..9066ee5617dfc172d17699989b3224af3d95c7bb 100644 (file)
@@ -69,6 +69,13 @@ if (use_aura || use_efl) {
   ]
 }
 
+if (tizen_vd_native_scrollbars) {
+  blink_core_sources_scroll += [
+    "scrollbar_theme_tizen.cc",
+    "scrollbar_theme_tizen.h",
+  ]
+}
+
 blink_core_tests_scroll = [
   "scroll_animator_test.cc",
   "scroll_test.cc",
index 91bea78bb32a565f49fbf20c9ed53cf3066ce20f..54923583b84428bb00cc45ec43ac54c13fc2ed20 100644 (file)
@@ -167,6 +167,9 @@ enum ScrollbarPart {
   kForwardButtonEndPart = 1 << 6,
   kScrollbarBGPart = 1 << 7,  // For custom scrollbars only.
   kTrackBGPart = 1 << 8,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  kCornerPart = 1 << 9,
+#endif
   kAllParts = 0xffffffff
 };
 
index 644675c5c14eb8c02f2ddede4a8ca4bb00c85219..bfc06e69fd868f3d432932d114195522d8740578 100644 (file)
@@ -973,6 +973,12 @@ bool ScrollableArea::HasLayerForScrollCorner() const {
   return LayerForScrollCorner();
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+bool ScrollableArea::UseNativeScrollbars() const {
+  return ScrollbarTheme::NativeScrollbarsEnabled();
+}
+#endif
+
 void ScrollableArea::ServiceScrollAnimations(double monotonic_time) {
   bool requires_animation_service = false;
   if (ScrollAnimatorBase* scroll_animator = ExistingScrollAnimator()) {
index f5c3d27ec7431a2674f102f2ff22406c9038fe5b..64c13dcf0a3fd5a378a4f8df522993e5379c4ccd 100644 (file)
@@ -587,6 +587,11 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
   virtual void ThumbPartFocusChanged(ScrollbarOrientation, bool) {}
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool UseNativeScrollbars() const;
+  virtual void ScrollbarSizeDidChange() {}
+#endif
+
   virtual void SetScrollsnapchangeTargetIds(
       std::optional<cc::TargetSnapAreaElementIds>) {}
   virtual void UpdateSnappedTargetsAndEnqueueScrollSnapChange() {}
index 6b4d91354bfc6063c2a52dd315dee9b4957824df..07f1e772a4335ebbc91432998cf821e407558594 100644 (file)
@@ -89,12 +89,26 @@ Scrollbar::Scrollbar(ScrollableArea* scrollable_area,
                     this,
                     &Scrollbar::AutoscrollTimerFired),
       elastic_overscroll_(0),
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      corner_height_(0),
+      scrollbar_width_(EScrollbarWidth::kAuto),
+#endif
       injected_gesture_scroll_begin_(false),
       scrollbar_manipulation_in_progress_on_cc_thread_(false),
       style_source_(style_source) {
   theme_.RegisterScrollbar(*this);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (ScrollbarTheme::NativeScrollbarsEnabled())
+    scrollbar_width_ = EScrollbarWidth::kThin;
+#endif
   int thickness =
       theme_.ScrollbarThickness(ScaleFromDIP(), CSSScrollbarWidth());
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  LOG(INFO) << " SCROLLBAR "
+            << " NativeScrollbars : "
+            << ScrollbarTheme::NativeScrollbarsEnabled()
+            << " , thickness : " << thickness;
+#endif
   frame_rect_ = gfx::Rect(0, 0, thickness, thickness);
   current_pos_ = ScrollableAreaCurrentPos();
 }
@@ -214,6 +228,14 @@ void Scrollbar::AutoscrollPressedPart(base::TimeDelta delay) {
   if (pressed_part_ == kThumbPart || pressed_part_ == kNoPart)
     return;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  // Handle the corner.
+  if (ScrollbarTheme::NativeScrollbarsEnabled()) {
+    if (pressed_part_ == kCornerPart)
+      return;
+  }
+#endif
+
   // Handle the track.
   if ((pressed_part_ == kBackTrackPart || pressed_part_ == kForwardTrackPart) &&
       ThumbWillBeUnderMouse()) {
@@ -338,6 +360,10 @@ void Scrollbar::SetHoveredPart(ScrollbarPart part) {
   if (part == hovered_part_)
     return;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (ScrollbarTheme::NativeScrollbarsEnabled())
+    UpdateControlSizeIfNeeded(part);
+#endif
   if (((hovered_part_ == kNoPart || part == kNoPart) &&
        GetTheme().InvalidateOnMouseEnterExit())
       // When there's a pressed part, we don't draw a hovered state, so there's
@@ -970,6 +996,10 @@ bool Scrollbar::ContainerIsFormControl() const {
 }
 
 EScrollbarWidth Scrollbar::CSSScrollbarWidth() const {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (ScrollbarTheme::NativeScrollbarsEnabled())
+    return scrollbar_width_;
+#endif
   if (style_source_) {
     return style_source_->StyleRef().UsedScrollbarWidth();
   }
@@ -1012,6 +1042,44 @@ mojom::blink::ColorScheme Scrollbar::UsedColorScheme() const {
              : scrollable_area_->UsedColorSchemeScrollbars();
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+gfx::Rect Scrollbar::AdjustFrameRect(int old_thickness, int new_thickness) {
+  int diff_size = old_thickness - new_thickness;
+  return gfx::Rect(
+      (orientation_ == kHorizontalScrollbar) ? X() : X() + diff_size,
+      (orientation_ == kHorizontalScrollbar) ? Y() + diff_size : Y(),
+      (orientation_ == kHorizontalScrollbar) ? Width() : new_thickness,
+      (orientation_ == kHorizontalScrollbar) ? new_thickness : Height());
+}
+
+bool Scrollbar::IsHovered() const {
+  return hovered_part_ != kNoPart;
+}
+
+void Scrollbar::UpdateControlSizeIfNeeded(ScrollbarPart part) {
+  EScrollbarWidth old_scrollbar_width = scrollbar_width_;
+  EScrollbarWidth new_scrollbar_width =
+      (part == kNoPart) ? EScrollbarWidth::kThin : EScrollbarWidth::kAuto;
+
+  if (old_scrollbar_width == new_scrollbar_width)
+    return;
+
+  scrollbar_width_ = new_scrollbar_width;
+
+  int old_thickness =
+      theme_.ScrollbarThickness(ScaleFromDIP(), old_scrollbar_width);
+  int new_thickness =
+      theme_.ScrollbarThickness(ScaleFromDIP(), new_scrollbar_width);
+  LOG(INFO) << " SCROLLBAR "
+            << " part:" << part << " , old_thickness : " << old_thickness
+            << " , new_thickness : " << new_thickness;
+
+  SetFrameRect(AdjustFrameRect(old_thickness, new_thickness));
+  if (scrollable_area_)
+    scrollable_area_->ScrollbarSizeDidChange();
+}
+#endif
+
 LayoutBox* Scrollbar::GetLayoutBox() const {
   return scrollable_area_ ? scrollable_area_->GetLayoutBox() : nullptr;
 }
index 9576e04e7aa3d5630fb183b6850bba47abbeef4b..45991ab86f2e9671ff4acb652cf07056a8f81e15 100644 (file)
@@ -250,6 +250,14 @@ class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
   // Returns the forced colors state for this scrollbar.
   bool InForcedColorsMode() const;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  gfx::Rect AdjustFrameRect(int old_thickness, int new_thickness);
+  int CornerHeight() const { return corner_height_; }
+  bool IsHovered() const;
+  void SetCornerHeight(int corner_height) { corner_height_ = corner_height; }
+  void UpdateControlSizeIfNeeded(ScrollbarPart);
+#endif
+
  protected:
   void AutoscrollTimerFired(TimerBase*);
   void StartTimerIfNeeded(base::TimeDelta delay);
@@ -286,6 +294,11 @@ class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
 
   float elastic_overscroll_;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  int corner_height_;
+  EScrollbarWidth scrollbar_width_;
+#endif
+
  private:
   float ScrollableAreaCurrentPos() const;
   float ScrollableAreaTargetPos() const;
index 6a81f4e48d3053deb1c4d6653f6c159146425798..de9fd415f2be0489c9ed89ee0650b55260c364a0 100644 (file)
@@ -71,6 +71,12 @@ bool ScrollbarLayerDelegate::IsOverlay() const {
   return scrollbar_->IsOverlayScrollbar();
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+bool ScrollbarLayerDelegate::IsHovered() const {
+  return scrollbar_->IsHovered();
+}
+#endif
+
 bool ScrollbarLayerDelegate::IsRunningWebTest() const {
   return WebTestSupport::IsRunningWebTest();
 }
index def9321d09498f328e31436b53336bca17c80462..e5ab7be5c2938bba22badb21163721b3c257cc38 100644 (file)
@@ -35,6 +35,9 @@ class CORE_EXPORT ScrollbarLayerDelegate : public cc::Scrollbar {
   bool JumpOnTrackClick() const override;
   bool IsOpaque() const override;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  bool IsHovered() const override;
+#endif
   // The following rects are all relative to the scrollbar's origin.
   gfx::Rect ThumbRect() const override;
   gfx::Rect TrackRect() const override;
index b17f82f710b45600a91556e1624c2ac466b9caa9..9f2568a3af62cd189942f828530239f994cb3e11 100644 (file)
 
 namespace blink {
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+bool ScrollbarTheme::g_native_scrollbars_enabled_ = false;
+#endif
+
 ScrollbarPart ScrollbarTheme::HitTestRootFramePosition(
     const Scrollbar& scrollbar,
     const gfx::Point& position_in_root_frame) const {
@@ -66,8 +70,17 @@ ScrollbarPart ScrollbarTheme::HitTestRootFramePosition(
 
 ScrollbarPart ScrollbarTheme::HitTest(const Scrollbar& scrollbar,
                                       const gfx::Point& test_position) const {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  gfx::Rect frame_rect = scrollbar.FrameRect();
+  if (scrollbar.Orientation() == kVerticalScrollbar)
+    frame_rect.set_height(frame_rect.height() + scrollbar.CornerHeight());
+
+  if (!frame_rect.Contains(test_position))
+    return kNoPart;
+#else
   if (!scrollbar.FrameRect().Contains(test_position))
     return kNoPart;
+#endif
 
   gfx::Rect track = TrackRect(scrollbar);
   if (track.Contains(test_position)) {
@@ -89,6 +102,10 @@ ScrollbarPart ScrollbarTheme::HitTest(const Scrollbar& scrollbar,
     return kBackButtonStartPart;
   if (ForwardButtonRect(scrollbar).Contains(test_position))
     return kForwardButtonEndPart;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (CornerRect(scrollbar).Contains(test_position))
+    return kCornerPart;
+#endif
 
   return kScrollbarBGPart;
 }
@@ -305,13 +322,13 @@ void ScrollbarTheme::PaintTrackBackgroundAndButtons(GraphicsContext& context,
   DCHECK(!scrollbar.IsCustomScrollbar());
   CHECK_EQ(rect.size(), scrollbar.FrameRect().size());
   gfx::Vector2d offset = rect.origin() - scrollbar.Location();
-
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
   if (DrawingRecorder::UseCachedDrawingIfPossible(
           context, scrollbar, DisplayItem::kScrollbarTrackAndButtons))
     return;
   DrawingRecorder recorder(context, scrollbar,
                            DisplayItem::kScrollbarTrackAndButtons, rect);
-
+#endif
   if (HasButtons(scrollbar)) {
     gfx::Rect back_button_rect = BackButtonRect(scrollbar);
     back_button_rect.Offset(offset);
@@ -338,4 +355,14 @@ void ScrollbarTheme::PaintTrackAndButtons(GraphicsContext& context,
   }
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+bool ScrollbarTheme::NativeScrollbarsEnabled() {
+  return g_native_scrollbars_enabled_;
+}
+
+void ScrollbarTheme::SetNativeScrollbarsEnabled(bool flag) {
+  g_native_scrollbars_enabled_ = flag;
+}
+#endif
+
 }  // namespace blink
index be3eb08ad4bfd4ec110038753f3c33cdf2a93b57..ad4dc902b9c75d7d7e0c2721cab2b6e016950c6d 100644 (file)
@@ -167,6 +167,12 @@ class CORE_EXPORT ScrollbarTheme {
 
   virtual int MinimumThumbLength(const Scrollbar&) const = 0;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  virtual gfx::Rect CornerRect(const Scrollbar&) const { return gfx::Rect(); }
+  static bool NativeScrollbarsEnabled();
+  static void SetNativeScrollbarsEnabled(bool);
+#endif
+
   virtual void SplitTrack(const Scrollbar&,
                           const gfx::Rect& track,
                           gfx::Rect& start_track,
@@ -281,6 +287,9 @@ class CORE_EXPORT ScrollbarTheme {
  private:
   // Must be implemented to return the correct theme subclass.
   static ScrollbarTheme& NativeTheme();
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  static bool g_native_scrollbars_enabled_;
+#endif
 };
 
 }  // namespace blink
index c694fda2d21a85afdbdfee90c5230fc5db2e44f1..b82d7cdc7fae8cc17403dbd34eb24f0be7ad1abc 100644 (file)
 #include "tizen/system_info.h"
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.h"
+#endif
+
 namespace blink {
 
 namespace {
@@ -144,6 +148,13 @@ ScrollbarTheme& ScrollbarTheme::NativeTheme() {
     return ScrollbarThemeOverlayMobile::GetInstance();
 #endif
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (ScrollbarTheme::NativeScrollbarsEnabled()) {
+    DEFINE_STATIC_LOCAL(ScrollbarThemeTizen, native_theme, ());
+    return native_theme;
+  }
+#endif
+
   if (FluentScrollbarsEnabled()) {
     return ScrollbarThemeFluent::GetInstance();
   }
@@ -262,14 +273,14 @@ void ScrollbarThemeAura::PaintTrackBackgroundAndButtons(
   }
 
   CHECK(!scrollbar.HasTickmarks());
-
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
   if (DrawingRecorder::UseCachedDrawingIfPossible(
           context, scrollbar, DisplayItem::kScrollbarTrackAndButtons)) {
     return;
   }
   DrawingRecorder recorder(context, scrollbar,
                            DisplayItem::kScrollbarTrackAndButtons, rect);
-
+#endif
   CHECK_EQ(rect.size(), NinePatchTrackAndButtonsCanvasSize(scrollbar));
   gfx::Vector2d offset = rect.origin() - scrollbar.Location();
   const int aperture_track_space =
@@ -305,6 +316,14 @@ void ScrollbarThemeAura::PaintTrackBackgroundAndButtons(
 void ScrollbarThemeAura::PaintTrackBackground(GraphicsContext& context,
                                               const Scrollbar& scrollbar,
                                               const gfx::Rect& rect) {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  if (DrawingRecorder::UseCachedDrawingIfPossible(context, scrollbar,
+                                                  DisplayItem::kScrollbarTrack))
+    return;
+  DrawingRecorder recorder(context, scrollbar, DisplayItem::kScrollbarTrack,
+                           rect);
+#endif
+
   if (rect.IsEmpty())
     return;
 
@@ -349,6 +368,15 @@ void ScrollbarThemeAura::PaintButton(GraphicsContext& gc,
   if (!params.should_paint)
     return;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  DisplayItem::Type display_item_type = ButtonPartToDisplayItemType(part);
+  if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
+                                                  display_item_type))
+    return;
+
+  DrawingRecorder recorder(gc, scrollbar, display_item_type, rect);
+#endif
+
   WebThemeEngine::ScrollbarButtonExtraParams scrollbar_button;
   scrollbar_button.zoom = scrollbar.EffectiveZoom();
   // TODO(crbug.com/1493088): Should not draw rounded corner for a button
@@ -591,4 +619,19 @@ gfx::Rect ScrollbarThemeAura::NinePatchTrackAndButtonsAperture(
   return aperture;
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+DisplayItem::Type ScrollbarThemeAura::ButtonPartToDisplayItemType(
+    ScrollbarPart part) {
+  switch (part) {
+    case kBackButtonStartPart:
+      return DisplayItem::kScrollbarBackButtonStart;
+    case kForwardButtonEndPart:
+      return DisplayItem::kScrollbarForwardButtonEnd;
+    default:
+      NOTREACHED();
+      return DisplayItem::kScrollbarBackButtonStart;
+  }
+}
+#endif
+
 }  // namespace blink
index c49737db391f656fdff1b4e62e39a68abe69f93f..2c169b64fa37c05b2cfb96ee2f1ca523410a5aa5 100644 (file)
@@ -91,6 +91,9 @@ class CORE_EXPORT ScrollbarThemeAura : public ScrollbarTheme {
   bool ShouldSnapBackToDragOrigin(const Scrollbar&,
                                   const WebMouseEvent&) const override;
   virtual gfx::Size ButtonSize(const Scrollbar&) const;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  static DisplayItem::Type ButtonPartToDisplayItemType(ScrollbarPart);
+#endif
 
   float Proportion(EScrollbarWidth scrollbar_width) const;
 
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.cc
new file mode 100644 (file)
index 0000000..991dc7a
--- /dev/null
@@ -0,0 +1,254 @@
+// Copyright 2025 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.h"
+
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_theme_engine.h"
+#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mock.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
+
+#include "third_party/blink/renderer/platform/theme/web_theme_engine_helper.h"
+
+namespace blink {
+
+namespace {
+
+static bool UseMockTheme() {
+  return WebTestSupport::IsRunningWebTest();
+}
+
+}  // namespace
+
+int ScrollbarThemeTizen::ScrollbarThickness(float scale_from_dip,
+                                            EScrollbarWidth scrollbar_width) const {
+  gfx::Size scrollbar_size =
+      WebThemeEngineHelper::GetNativeThemeEngine()->GetSize(
+          WebThemeEngine::kPartScrollbarVerticalTrack,
+          IsThinScrollbar(scrollbar_width));
+  return scrollbar_size.width();
+}
+
+int ScrollbarThemeTizen::MinimumThumbLength(const Scrollbar& scrollbar) const {
+  if (scrollbar.Orientation() == kVerticalScrollbar) {
+    gfx::Size size = WebThemeEngineHelper::GetNativeThemeEngine()->GetSize(
+        WebThemeEngine::kPartScrollbarVerticalThumb,
+        IsThinScrollbar(scrollbar.CSSScrollbarWidth()));
+    return size.height();
+  }
+
+  // HorizontalScrollbar
+  gfx::Size size = WebThemeEngineHelper::GetNativeThemeEngine()->GetSize(
+      WebThemeEngine::kPartScrollbarHorizontalThumb,
+      IsThinScrollbar(scrollbar.CSSScrollbarWidth()));
+  return size.width();
+}
+
+void ScrollbarThemeTizen::PaintScrollCorner(
+    GraphicsContext& context,
+    const ScrollableArea& scrollable_area,
+    const DisplayItemClient& display_item_client,
+    const gfx::Rect& corner_rect) {
+  if (corner_rect.IsEmpty())
+    return;
+
+  DisplayItemCacheSkipper cacheSkipper(context);
+
+  if (DrawingRecorder::UseCachedDrawingIfPossible(context, display_item_client,
+                                                  DisplayItem::kScrollCorner))
+    return;
+
+  DrawingRecorder recorder(context, display_item_client,
+                           DisplayItem::kScrollCorner, corner_rect);
+
+  WebThemeEngine::ScrollbarTrackExtraParams scrollbar_track;
+  const Scrollbar* scrollbar = scrollable_area.VerticalScrollbar();
+  if (!scrollbar) {
+    scrollbar = scrollable_area.HorizontalScrollbar();
+  }
+  // The scroll corner exists means at least one scrollbar exists.
+  CHECK(scrollbar);
+  if (scrollbar->ScrollbarTrackColor().has_value()) {
+    scrollbar_track.track_color =
+        scrollbar->ScrollbarTrackColor().value().toSkColor4f().toSkColor();
+  }
+
+  WebThemeEngine::ExtraParams extra_params(scrollbar_track);
+  mojom::blink::ColorScheme color_scheme = scrollbar->UsedColorScheme();
+  WebThemeEngineHelper::GetNativeThemeEngine()->Paint(
+      context.Canvas(), WebThemeEngine::kPartScrollbarCorner,
+      WebThemeEngine::kStateNormal, corner_rect, &extra_params, color_scheme,
+      scrollbar->InForcedColorsMode(),
+      scrollbar->GetColorProvider(color_scheme));
+}
+
+void ScrollbarThemeTizen::PaintTrackBackground(GraphicsContext& gc,
+                                               const Scrollbar& scrollbar,
+                                               const gfx::Rect& rect) {
+
+  const gfx::Rect rects = scrollbar.FrameRect();
+  if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
+                                                  DisplayItem::kScrollbarTrack))
+    return;
+  DrawingRecorder recorder(gc, scrollbar, DisplayItem::kScrollbarTrack, rects);
+
+  WebThemeEngine::State state = scrollbar.HoveredPart() == kTrackBGPart
+                                    ? WebThemeEngine::kStateHover
+                                    : WebThemeEngine::kStateNormal;
+
+  if (UseMockTheme() && !scrollbar.Enabled())
+    state = WebThemeEngine::kStateDisabled;
+
+  gfx::Rect align_rect = TrackRect(scrollbar);
+
+  WebThemeEngine::ScrollbarTypeExtraParams scrollbar_type;
+  scrollbar_type.is_thin_scrollbar =
+      IsThinScrollbar(scrollbar.CSSScrollbarWidth());
+  WebThemeEngine::ExtraParams extra_params(scrollbar_type);
+
+  WebThemeEngineHelper::GetNativeThemeEngine()->Paint(
+      gc.Canvas(),
+      scrollbar.Orientation() == kHorizontalScrollbar
+          ? WebThemeEngine::kPartScrollbarHorizontalTrack
+          : WebThemeEngine::kPartScrollbarVerticalTrack,
+      state, gfx::Rect(rect), &extra_params, scrollbar.UsedColorScheme(), scrollbar.InForcedColorsMode(),
+      scrollbar.GetColorProvider(scrollbar.UsedColorScheme()));
+}
+
+void ScrollbarThemeTizen::PaintButton(GraphicsContext& gc,
+                                      const Scrollbar& scrollbar,
+                                      const gfx::Rect& rect,
+                                      ScrollbarPart part) {
+  DisplayItem::Type display_item_type = ButtonPartToDisplayItemType(part);
+
+  WebThemeEngine::Part paint_part;
+  WebThemeEngine::State state = WebThemeEngine::kStateNormal;
+  bool check_min = false;
+  bool check_max = false;
+
+  if (scrollbar.Orientation() == kHorizontalScrollbar) {
+    if (part == kBackButtonStartPart) {
+      paint_part = WebThemeEngine::kPartScrollbarLeftArrow;
+      check_min = true;
+    } else if (UseMockTheme() && part != kForwardButtonEndPart) {
+      return;
+    } else {
+      paint_part = WebThemeEngine::kPartScrollbarRightArrow;
+      check_max = true;
+    }
+  } else {
+    if (part == kBackButtonStartPart) {
+      paint_part = WebThemeEngine::kPartScrollbarUpArrow;
+      check_min = true;
+    } else if (UseMockTheme() && part != kForwardButtonEndPart) {
+      return;
+    } else {
+      paint_part = WebThemeEngine::kPartScrollbarDownArrow;
+      check_max = true;
+    }
+  }
+
+  if (UseMockTheme() && !scrollbar.Enabled()) {
+    state = WebThemeEngine::kStateDisabled;
+  } else if (!UseMockTheme() &&
+             ((check_min && (scrollbar.CurrentPos() <= 0)) ||
+              (check_max && scrollbar.CurrentPos() >= scrollbar.Maximum()))) {
+    state = WebThemeEngine::kStateDisabled;
+  } else {
+    if (part == scrollbar.PressedPart()) {
+      state = WebThemeEngine::kStatePressed;
+    } else if (part == scrollbar.HoveredPart()) {
+      state = WebThemeEngine::kStateHover;
+    }
+  }
+
+  const gfx::Rect rects = scrollbar.FrameRect();
+  if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
+                                                  display_item_type))
+    return;
+
+  DrawingRecorder recorder(gc, scrollbar, display_item_type, rects);
+
+  WebThemeEngine::ScrollbarTypeExtraParams scrollbar_type;
+  scrollbar_type.is_thin_scrollbar =
+      IsThinScrollbar(scrollbar.CSSScrollbarWidth());
+
+  WebThemeEngine::ExtraParams extra_params(scrollbar_type);
+
+  WebThemeEngineHelper::GetNativeThemeEngine()->Paint(
+      gc.Canvas(), paint_part, state, gfx::Rect(rect), &extra_params,
+      scrollbar.UsedColorScheme(), scrollbar.InForcedColorsMode(),
+      scrollbar.GetColorProvider(scrollbar.UsedColorScheme()));
+}
+
+void ScrollbarThemeTizen::PaintThumb(GraphicsContext& gc,
+                                     const Scrollbar& scrollbar,
+                                     const gfx::Rect& rect) {
+  if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
+                                                  DisplayItem::kScrollbarThumb))
+    return;
+
+  DrawingRecorder recorder(gc, scrollbar, DisplayItem::kScrollbarThumb, rect);
+
+  WebThemeEngine::State state;
+  if (scrollbar.PressedPart() == kThumbPart)
+    state = WebThemeEngine::kStatePressed;
+  else if (scrollbar.HoveredPart() == kThumbPart)
+    state = WebThemeEngine::kStateHover;
+  else
+    state = WebThemeEngine::kStateNormal;
+
+  WebThemeEngine::ScrollbarTypeExtraParams scrollbar_type;
+  scrollbar_type.is_thin_scrollbar =
+      IsThinScrollbar(scrollbar.CSSScrollbarWidth());
+  WebThemeEngine::ExtraParams extra_params(scrollbar_type);
+
+  WebThemeEngineHelper::GetNativeThemeEngine()->Paint(
+      gc.Canvas(),
+      scrollbar.Orientation() == kHorizontalScrollbar
+          ? WebThemeEngine::kPartScrollbarHorizontalThumb
+          : WebThemeEngine::kPartScrollbarVerticalThumb,
+      state, gfx::Rect(rect), &extra_params, scrollbar.UsedColorScheme(),
+      scrollbar.InForcedColorsMode(),
+      scrollbar.GetColorProvider(scrollbar.UsedColorScheme()));
+}
+
+gfx::Size ScrollbarThemeTizen::ButtonSize(const Scrollbar& scrollbar) const {
+  if (scrollbar.Orientation() == kVerticalScrollbar) {
+    gfx::Size size = WebThemeEngineHelper::GetNativeThemeEngine()->GetSize(
+        WebThemeEngine::kPartScrollbarUpArrow,
+        IsThinScrollbar(scrollbar.CSSScrollbarWidth()));
+    int heights = scrollbar.Height() < 2 * size.height()
+                      ? scrollbar.Height() / 2
+                      : size.height();
+    return gfx::Size(size.width(), scrollbar.Height() < 2 * size.height()
+                                       ? scrollbar.Height() / 2
+                                       : size.height());
+  }
+
+  // HorizontalScrollbar
+  gfx::Size size = WebThemeEngineHelper::GetNativeThemeEngine()->GetSize(
+      WebThemeEngine::kPartScrollbarLeftArrow,
+      IsThinScrollbar(scrollbar.CSSScrollbarWidth()));
+  return gfx::Size(scrollbar.Width() < 2 * size.width() ? scrollbar.Width() / 2
+                                                        : size.width(),
+                   size.height());
+}
+
+gfx::Rect ScrollbarThemeTizen::CornerRect(const Scrollbar& scrollbar) const {
+  if (scrollbar.Orientation() == kHorizontalScrollbar)
+    return gfx::Rect();
+
+  int thickness = ScrollbarThickness(scrollbar.ScaleFromDIP(),
+                                     scrollbar.CSSScrollbarWidth());
+  return gfx::Rect(scrollbar.X(), scrollbar.Y() + scrollbar.Height(), thickness,
+                   scrollbar.CornerHeight());
+}
+}  // namespace blink
\ No newline at end of file
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.h b/third_party/blink/renderer/core/scroll/scrollbar_theme_tizen.h
new file mode 100644 (file)
index 0000000..e793307
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2025 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ScrollbarThemeTizen_h
+#define ScrollbarThemeTizen_h
+
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT ScrollbarThemeTizen : public ScrollbarThemeAura {
+ public:
+  int ScrollbarThickness(float scale_from_dip,
+                         EScrollbarWidth scrollbar_width) const override;
+  bool UsesOverlayScrollbars() const override { return true; }
+
+ protected:
+  int MinimumThumbLength(const Scrollbar&) const override;
+
+  void PaintScrollCorner(GraphicsContext&,
+                         const ScrollableArea&,
+                         const DisplayItemClient&,
+                         const gfx::Rect&) override;
+
+  void PaintTrackBackground(GraphicsContext&,
+                            const Scrollbar&,
+                            const gfx::Rect&) override;
+  void PaintButton(GraphicsContext&,
+                   const Scrollbar&,
+                   const gfx::Rect&,
+                   ScrollbarPart) override;
+  void PaintThumb(GraphicsContext&,
+                  const Scrollbar&,
+                  const gfx::Rect&) override;
+
+  gfx::Size ButtonSize(const Scrollbar&) const override;
+
+ private:
+  gfx::Rect CornerRect(const Scrollbar&) const override;
+  bool IsThinScrollbar(const EScrollbarWidth scrollbar_width) const {
+    return scrollbar_width == EScrollbarWidth::kThin;
+  }
+};
+
+}  // namespace blink
+
+#endif  // ScrollbarThemeTizen_h
\ No newline at end of file
index cef548bae492210474ea1fb8694afdca35aa9b50..096c5a31448189d7bf09fe998433ad33f79f7f27 100644 (file)
@@ -284,10 +284,24 @@ void GraphicsContext::BeginRecording() {
     canvas_->SetPaintPreviewTracker(paint_preview_tracker_);
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void GraphicsContext::BeginRecording(const gfx::Size& size) {
+  canvas_ = inspectable_paint_recorder_.beginRecording(size);
+  if (printing_metafile_)
+    canvas_->SetPrintingMetafile(printing_metafile_);
+  if (paint_preview_tracker_)
+    canvas_->SetPaintPreviewTracker(paint_preview_tracker_);
+}
+#endif
+
 PaintRecord GraphicsContext::EndRecording() {
   canvas_->SetPrintingMetafile(nullptr);
   canvas_ = nullptr;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  return inspectable_paint_recorder_.finishRecordingAsPicture();
+#else
   return paint_recorder_.finishRecordingAsPicture();
+#endif
 }
 
 void GraphicsContext::DrawRecord(PaintRecord record) {
index 369c3e898c8d18e46d2deb1865fe37e5aa51c3c4..c470797569c78b5c43c660dfe0c3c1a7426bc52e 100644 (file)
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+#include "cc/paint/paint_recorder.h"
+#endif
+
 class SkPath;
 class SkRRect;
 struct SkRect;
@@ -433,6 +437,9 @@ class PLATFORM_EXPORT GraphicsContext {
   // beginRecording() are stored in a display list that can be replayed at a
   // later time.
   void BeginRecording();
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  void BeginRecording(const gfx::Size& size);
+#endif
 
   // Returns a record with any recorded draw commands since the prerequisite
   // call to beginRecording().  The record is guaranteed to be non-null (but
@@ -568,6 +575,9 @@ class PLATFORM_EXPORT GraphicsContext {
 
   PaintRecorder paint_recorder_;
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  cc::InspectablePaintRecorder inspectable_paint_recorder_;
+#endif
   printing::MetafileSkia* printing_metafile_ = nullptr;
   paint_preview::PaintPreviewTracker* paint_preview_tracker_ = nullptr;
 
index c911f1f7962052c34e46a8fd50e662270c265d38..1f2fd9391a2e40266cdad927d4bc0c9d8ebc275b 100644 (file)
@@ -92,6 +92,11 @@ class PLATFORM_EXPORT DisplayItem {
     kScrollbarTrackAndButtons,
     kScrollbarThumb,
     kScrollbarTickmarks,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+    kScrollbarBackButtonStart,
+    kScrollbarForwardButtonEnd,
+    kScrollbarTrack,
+#endif
     kSelectionTint,
     kTableCollapsedBorders,
     kWebPlugin,
index 844c58d1f2da207df8af9d8b2ba45988594aaab7..fa8b88b8cb1abec2c7a3af72d8b89ffb2713d77b 100644 (file)
@@ -26,7 +26,11 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context,
 #endif
 
   context.SetInDrawingRecorder(true);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  context.BeginRecording(visual_rect.size());
+#else
   context.BeginRecording();
+#endif
 
   if (context.NeedsDOMNodeId()) {
     DOMNodeId dom_node_id = display_item_client.OwnerNodeId();
index ac6c2b861cb8e329cb4ed9915a04d042cafce554..d240f127aca07ef59508c0efaf1bf68f2ed771fa 100644 (file)
@@ -8,6 +8,7 @@
 #include "skia/ext/platform_canvas.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/platform/web_theme_engine.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
 #include "third_party/blink/renderer/platform/graphics/scrollbar_theme_settings.h"
 #include "third_party/blink/renderer/platform/theme/web_theme_engine_conversions.h"
 #include "third_party/blink/renderer/platform/web_test_support.h"
@@ -53,6 +54,20 @@ static ui::NativeTheme::ExtraParams GetNativeThemeExtraParams(
     case WebThemeEngine::kPartScrollbarCorner:
     case WebThemeEngine::kPartScrollbarHorizontalTrack:
     case WebThemeEngine::kPartScrollbarVerticalTrack: {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      if (ScrollbarTheme::NativeScrollbarsEnabled()) {
+        if (absl::holds_alternative<WebThemeEngine::ScrollbarTypeExtraParams>(
+                *extra_params)) {
+          ui::NativeTheme::ScrollbarTypeExtraParams native_scrollbar_type;
+          const auto& scrollbar_type =
+              absl::get<WebThemeEngine::ScrollbarTypeExtraParams>(
+                  *extra_params);
+          native_scrollbar_type.is_thin_scrollbar =
+              scrollbar_type.is_thin_scrollbar;
+          return ui::NativeTheme::ExtraParams(native_scrollbar_type);
+        }
+      }
+#endif
       ui::NativeTheme::ScrollbarTrackExtraParams native_scrollbar_track;
       const auto& scrollbar_track =
           absl::get<WebThemeEngine::ScrollbarTrackExtraParams>(*extra_params);
@@ -169,6 +184,20 @@ static ui::NativeTheme::ExtraParams GetNativeThemeExtraParams(
     }
     case WebThemeEngine::kPartScrollbarHorizontalThumb:
     case WebThemeEngine::kPartScrollbarVerticalThumb: {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      if (ScrollbarTheme::NativeScrollbarsEnabled()) {
+        if (absl::holds_alternative<WebThemeEngine::ScrollbarTypeExtraParams>(
+                *extra_params)) {
+          ui::NativeTheme::ScrollbarTypeExtraParams native_scrollbar_type;
+          const auto& scrollbar_type =
+              absl::get<WebThemeEngine::ScrollbarTypeExtraParams>(
+                  *extra_params);
+          native_scrollbar_type.is_thin_scrollbar =
+              scrollbar_type.is_thin_scrollbar;
+          return ui::NativeTheme::ExtraParams(native_scrollbar_type);
+        }
+      }
+#endif
       ui::NativeTheme::ScrollbarThumbExtraParams native_scrollbar_thumb;
       const auto& scrollbar_thumb =
           absl::get<WebThemeEngine::ScrollbarThumbExtraParams>(*extra_params);
@@ -182,6 +211,20 @@ static ui::NativeTheme::ExtraParams GetNativeThemeExtraParams(
     case WebThemeEngine::kPartScrollbarLeftArrow:
     case WebThemeEngine::kPartScrollbarRightArrow:
     case WebThemeEngine::kPartScrollbarUpArrow: {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+      if (ScrollbarTheme::NativeScrollbarsEnabled()) {
+        if (absl::holds_alternative<WebThemeEngine::ScrollbarTypeExtraParams>(
+                *extra_params)) {
+          ui::NativeTheme::ScrollbarTypeExtraParams native_scrollbar_type;
+          const auto& scrollbar_type =
+              absl::get<WebThemeEngine::ScrollbarTypeExtraParams>(
+                  *extra_params);
+          native_scrollbar_type.is_thin_scrollbar =
+              scrollbar_type.is_thin_scrollbar;
+          return ui::NativeTheme::ExtraParams(native_scrollbar_type);
+        }
+      }
+#endif
       ui::NativeTheme::ScrollbarArrowExtraParams native_scrollbar_arrow;
       const auto& scrollbar_button =
           absl::get<WebThemeEngine::ScrollbarButtonExtraParams>(*extra_params);
@@ -232,6 +275,20 @@ gfx::Size WebThemeEngineDefault::GetSize(WebThemeEngine::Part part) {
       native_theme_part, ui::NativeTheme::kNormal, extra);
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+gfx::Size WebThemeEngineDefault::GetSize(WebThemeEngine::Part part,
+                                         bool is_thin_scrollbar) {
+  ui::NativeTheme::ScrollbarTypeExtraParams scrollbar_type;
+  scrollbar_type.is_thin_scrollbar = is_thin_scrollbar;
+  ui::NativeTheme::ExtraParams extra(scrollbar_type);
+
+  ui::NativeTheme::Part native_theme_part = NativeThemePart(part);
+
+  return ui::NativeTheme::GetInstanceForWeb()->GetPartSize(
+      native_theme_part, ui::NativeTheme::kNormal, extra);
+}
+#endif
+
 void WebThemeEngineDefault::Paint(
     cc::PaintCanvas* canvas,
     WebThemeEngine::Part part,
index 379b16a221cedfd97cc380daa57042e5f89c16d6..38d6066f8e4c0299f86b491c951d7c6cc638f6b8 100644 (file)
@@ -20,6 +20,9 @@ class WebThemeEngineDefault : public WebThemeEngine {
 
   // WebThemeEngine:
   gfx::Size GetSize(WebThemeEngine::Part) override;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  gfx::Size GetSize(WebThemeEngine::Part, bool) override;
+#endif
   void Paint(cc::PaintCanvas* canvas,
              WebThemeEngine::Part part,
              WebThemeEngine::State state,
index eb02d01d3cbd2da652adc6c7da843c29cf21df4e..2c098b1f9c8da8b4216e04151ddfcb351e1f9f13 100644 (file)
@@ -58,7 +58,14 @@ constexpr base::FeatureParam<double> kFadeDurationScalingFactor{
 
 void InitializeScrollbarFadeAndDelay(cc::LayerTreeSettings& settings) {
   // Default settings that may be overridden below for specific platforms.
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  settings.use_native_scrollbars = ui::IsNativeScrollbarEnabled();
+  settings.scrollbar_fade_delay = settings.use_native_scrollbars
+                                      ? base::Milliseconds(1000)
+                                      : base::Milliseconds(300);
+#else
   settings.scrollbar_fade_delay = base::Milliseconds(300);
+#endif
   settings.scrollbar_fade_duration = base::Milliseconds(300);
 
 #if !BUILDFLAG(IS_ANDROID)
index 2dd9327e95fb10f4d667804f71b4f533ace39c72..5fdd9159d34b6fb8be832fac99d1633f003772f4 100644 (file)
@@ -116,6 +116,11 @@ config("tizen_feature_flags") {
     if (is_clang) {
       defines += [ "USE_CLANG" ]
     }
+    if (tizen_vd_native_scrollbars) {
+      defines += [
+        "TIZEN_VD_NATIVE_SCROLLBARS"
+      ]
+    }
     if (is_samsung_next_browser) {
       defines += [
         "SAMSUNG_NEXT_BROWSER",
index d9e943e61923ef5cfd34dc018358e10a800bfeb7..8c5d413fe0bbf7c16ce6a070dbc390ca6ad6d241 100644 (file)
@@ -102,6 +102,7 @@ declare_args() {
   tizen_tv_video_capture = false
   tizen_rtc_unittests = false
 
+  tizen_vd_native_scrollbars = false
   drm_mapi_aarch_64 = false
   tizen_tv_riscv64 = false
 
index cf203c423fff8694e71419fb019b4087a747d35c..1a32f1e0e394144cb2b1206a22e29ec28d943996 100755 (executable)
@@ -246,6 +246,7 @@ add_tizen_flags() {
     ADDITIONAL_GN_PARAMETERS+="enable_plugins=true
                                use_libgav1_parser=true
                                use_plugin_placeholder_hole=true
+                               tizen_vd_native_scrollbars=true
                               "
     if [ "$tizen_emulator_support" != "true" ]; then
       ADDITIONAL_GN_PARAMETERS+="tizen_tv_wasm_caching=true
diff --git a/tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.cc b/tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.cc
new file mode 100644 (file)
index 0000000..08e34c5
--- /dev/null
@@ -0,0 +1,566 @@
+// Copyright 2025 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/native_theme/native_theme_tizen_tv.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "cc/paint/paint_canvas.h"
+#include "third_party/blink/public/platform/web_theme_engine.h"
+#include "third_party/blink/renderer/platform/theme/web_theme_engine_helper.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rrect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/skia_conversions.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/native_theme/common_theme.h"
+#include "ui/native_theme/native_theme_features.h"
+#include "ui/resources/grit/ui_resources_tizen.h"
+
+namespace ui {
+
+namespace {
+const unsigned int kLocationVariation = 3;
+const unsigned int kSizeVariation = 5;
+
+const unsigned int kDefaultScrollbarWidth[] = {15, 54};
+const unsigned int kDefaultScrollbarButtonLength[] = {0, 54};
+
+#define VERTICAL_IMAGE_GRID(x) \
+  { x##_TOP, x##_CENTER, x##_BOTTOM, }
+#define HORIZONTAL_IMAGE_GRID(x) \
+  { x##_LEFT, x##_CENTER, x##_RIGHT, }
+
+const int kThinVerticalTrackImages[] =
+    VERTICAL_IMAGE_GRID(IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_TRACK);
+const int kThinVerticalThumbImages[] =
+    VERTICAL_IMAGE_GRID(IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_THUMB);
+
+const int kThinHorizontalTrackImages[] =
+    HORIZONTAL_IMAGE_GRID(IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_TRACK);
+const int kThinHorizontalThumbImages[] =
+    HORIZONTAL_IMAGE_GRID(IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_THUMB);
+
+const int kThickVerticalTrackNormalImages[] =
+    VERTICAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_TRACK_NORMAL);
+const int kThickVerticalThumbNormalImages[] =
+    VERTICAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_NORMAL);
+const int kThickVerticalThumbPressedImages[] =
+    VERTICAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_PRESSED);
+
+const int kThickHorizontalTrackNormalImages[] =
+    HORIZONTAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_TRACK_NORMAL);
+const int kThickHorizontalThumbNormalImages[] =
+    HORIZONTAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_NORMAL);
+const int kThickHorizontalThumbPressedImages[] =
+    HORIZONTAL_IMAGE_GRID(IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_PRESSED);
+
+#undef VERTICAL_IMAGE_GRID
+#undef HORIZONTAL_IMAGE_GRID
+
+bool IsScrollbarPart(NativeTheme::Part part) {
+  switch (part) {
+    case NativeTheme::kScrollbarDownArrow:
+    case NativeTheme::kScrollbarLeftArrow:
+    case NativeTheme::kScrollbarRightArrow:
+    case NativeTheme::kScrollbarUpArrow:
+    case NativeTheme::kScrollbarHorizontalThumb:
+    case NativeTheme::kScrollbarVerticalThumb:
+    case NativeTheme::kScrollbarHorizontalTrack:
+    case NativeTheme::kScrollbarVerticalTrack:
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
+NativeTheme::ScrollDirection GetScrollDirection(NativeTheme::Part part) {
+  switch (part) {
+    case NativeTheme::kScrollbarDownArrow:
+      return NativeTheme::kScrollDown;
+    case NativeTheme::kScrollbarLeftArrow:
+      return NativeTheme::kScrollLeft;
+    case NativeTheme::kScrollbarRightArrow:
+      return NativeTheme::kScrollRight;
+    case NativeTheme::kScrollbarUpArrow:
+      return NativeTheme::kScrollUp;
+    default:
+      break;
+  }
+  return NativeTheme::kNumDirections;
+}
+
+const int GetArrowButtonImageIds(NativeTheme::State state) {
+  switch (state) {
+    case NativeTheme::kDisabled:
+      return IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_DISABLED;
+    case NativeTheme::kNormal:
+      return IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_NORMAL;
+    case NativeTheme::kHovered:
+    case NativeTheme::kPressed:
+      return IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_HOVER;
+    default:
+      break;
+  }
+  return 0;
+}
+
+const gfx::ImageSkia GetArrowButtonImage(NativeTheme::ScrollDirection direction,
+                                         NativeTheme::State state) {
+  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
+  const gfx::ImageSkia* base_image =
+      resource_bundle.GetImageSkiaNamed(GetArrowButtonImageIds(state));
+  if (!base_image)
+    return gfx::ImageSkia();
+  switch (direction) {
+    case NativeTheme::kScrollUp: {
+      return *base_image;
+    }
+    case NativeTheme::kScrollRight: {
+      return gfx::ImageSkiaOperations::CreateRotatedImage(
+          *base_image, SkBitmapOperations::ROTATION_90_CW);
+    }
+    case NativeTheme::kScrollDown: {
+      return gfx::ImageSkiaOperations::CreateRotatedImage(
+          *base_image, SkBitmapOperations::ROTATION_180_CW);
+    }
+    case NativeTheme::kScrollLeft: {
+      return gfx::ImageSkiaOperations::CreateRotatedImage(
+          *base_image, SkBitmapOperations::ROTATION_270_CW);
+    }
+    default:
+      break;
+  }
+  return gfx::ImageSkia();
+}
+
+const int* GetPartImageIds(bool is_thin_scrollbar,
+                           NativeTheme::Part part,
+                           NativeTheme::State state,
+                           size_t* num) {
+  DCHECK(num);
+  *num = 3;
+  switch (state) {
+    case NativeTheme::kDisabled:
+    case NativeTheme::kNormal:
+    case NativeTheme::kHovered: {
+      switch (part) {
+        case NativeTheme::kScrollbarVerticalTrack:
+          return (is_thin_scrollbar ? kThinVerticalTrackImages
+                                    : kThickVerticalTrackNormalImages);
+        case NativeTheme::kScrollbarHorizontalTrack:
+          return (is_thin_scrollbar ? kThinHorizontalTrackImages
+                                    : kThickHorizontalTrackNormalImages);
+        case NativeTheme::kScrollbarVerticalThumb:
+          return (is_thin_scrollbar ? kThinVerticalThumbImages
+                                    : kThickVerticalThumbNormalImages);
+        case NativeTheme::kScrollbarHorizontalThumb:
+          return (is_thin_scrollbar ? kThinHorizontalThumbImages
+                                    : kThickHorizontalThumbNormalImages);
+        default:
+          break;
+      }
+      break;
+    }
+    case NativeTheme::kPressed: {
+      switch (part) {
+        case NativeTheme::kScrollbarVerticalTrack:
+          return (is_thin_scrollbar ? kThinVerticalTrackImages
+                                    : kThickVerticalTrackNormalImages);
+        case NativeTheme::kScrollbarHorizontalTrack:
+          return (is_thin_scrollbar ? kThinHorizontalTrackImages
+                                    : kThickHorizontalTrackNormalImages);
+        case NativeTheme::kScrollbarVerticalThumb:
+          return (is_thin_scrollbar ? kThinVerticalThumbImages
+                                    : kThickVerticalThumbPressedImages);
+        case NativeTheme::kScrollbarHorizontalThumb:
+          return (is_thin_scrollbar ? kThinHorizontalThumbImages
+                                    : kThickHorizontalThumbPressedImages);
+        default:
+          break;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  return nullptr;
+}
+
+std::vector<const gfx::ImageSkia*> GetPartImage(bool is_small,
+                                                NativeTheme::Part part,
+                                                NativeTheme::State state) {
+  size_t num_ids = 0;
+  const int* ids = GetPartImageIds(is_small, part, state, &num_ids);
+  if (!ids)
+    return std::vector<const gfx::ImageSkia*>();
+
+  std::vector<const gfx::ImageSkia*> images;
+  images.reserve(num_ids);
+  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
+  for (size_t i = 0; i < num_ids; i++)
+    images.push_back(resource_bundle.GetImageSkiaNamed(ids[i]));
+  return images;
+}
+
+void PaintImagesVertically(gfx::Canvas* canvas,
+                           const gfx::ImageSkia& top_image,
+                           const gfx::ImageSkia& center_image,
+                           const gfx::ImageSkia& bottom_image,
+                           const gfx::Rect& rect) {
+  canvas->DrawImageInt(top_image, 0, 0, top_image.width(), top_image.height(),
+                       rect.x(), rect.y(), rect.width(), top_image.height(),
+                       false);
+  int y = rect.y() + top_image.height();
+  const int center_height =
+      rect.height() - top_image.height() - bottom_image.height();
+  canvas->DrawImageInt(center_image, 0, 0, center_image.width(),
+                       center_image.height(), rect.x(), y, rect.width(),
+                       center_height, false);
+  y += center_height;
+  canvas->DrawImageInt(bottom_image, 0, 0, bottom_image.width(),
+                       bottom_image.height(), rect.x(), y, rect.width(),
+                       bottom_image.height(), false);
+}
+
+void PaintImagesHorizontally(gfx::Canvas* canvas,
+                             const gfx::ImageSkia& left_image,
+                             const gfx::ImageSkia& center_image,
+                             const gfx::ImageSkia& right_image,
+                             const gfx::Rect& rect) {
+  canvas->DrawImageInt(left_image, 0, 0, left_image.width(),
+                       left_image.height(), rect.x(), rect.y(),
+                       left_image.width(), rect.height(), false);
+
+  int x = rect.x() + left_image.width();
+  const int center_width =
+      rect.width() - left_image.width() - right_image.width();
+  canvas->DrawImageInt(center_image, 0, 0, center_image.width(),
+                       center_image.height(), x, rect.y(), center_width,
+                       rect.height(), false);
+  x += center_width;
+  canvas->DrawImageInt(right_image, 0, 0, right_image.width(),
+                       right_image.height(), x, rect.y(), right_image.width(),
+                       rect.height(), false);
+}
+
+// Creates a gfx::Canvas wrapping an cc::PaintCanvas.
+std::unique_ptr<gfx::Canvas> CommonThemeCreateCanvas(cc::PaintCanvas* canvas) {
+  // SkMatrix matrix = canvas->getTotalMatrix();
+  // float device_scale = static_cast<float>(SkScalarAbs(matrix.getScaleX()));
+  return base::WrapUnique(new gfx::Canvas(canvas, 1.0));
+}
+
+}  // namespace
+
+// static
+NativeTheme* NativeTheme::GetInstanceForWeb() {
+  if (IsNativeScrollbarEnabled())
+    return NativeThemeTizenTV::web_instance();
+
+  return NativeThemeAura::web_instance();
+}
+
+// static
+NativeThemeTizenTV* NativeThemeTizenTV::web_instance() {
+  static base::NoDestructor<NativeThemeTizenTV> s_native_theme_for_tv;
+  return s_native_theme_for_tv.get();
+}
+
+NativeThemeTizenTV::NativeThemeTizenTV()
+    : NativeThemeAura(IsOverlayScrollbarEnabled(), false) {
+  const State states[] = {
+      State::kDisabled,
+      State::kHovered,
+      State::kNormal,
+      State::kPressed,
+  };
+
+  const ScrollbarType types[] = {
+      ScrollbarType::kThinScrollbar,
+      ScrollbarType::kThickScrollbar,
+  };
+
+  const ScrollDirection directions[] = {
+      ScrollDirection::kScrollUp,
+      ScrollDirection::kScrollRight,
+      ScrollDirection::kScrollDown,
+      ScrollDirection::kScrollLeft,
+  };
+
+  for (size_t i = 0; i < std::size(states); i++) {
+    State state = states[i];
+    for (size_t j = 0; j < std::size(types); j++) {
+      ScrollbarType type = types[j];
+      bool is_thin_scrollbar = (type == kThinScrollbar);
+      track_vertical_images_[type][state] =
+          GetPartImage(is_thin_scrollbar, kScrollbarVerticalTrack, state);
+      track_horizontal_images_[type][state] =
+          GetPartImage(is_thin_scrollbar, kScrollbarHorizontalTrack, state);
+      thumb_vertical_images_[type][state] =
+          GetPartImage(is_thin_scrollbar, kScrollbarVerticalThumb, state);
+      thumb_horizontal_images_[type][state] =
+          GetPartImage(is_thin_scrollbar, kScrollbarHorizontalThumb, state);
+    }
+
+    for (size_t k = 0; k < std::size(directions); k++) {
+      ScrollDirection direction = directions[k];
+      arrow_button_images_[direction][state] =
+          GetArrowButtonImage(direction, state);
+    }
+  }
+}
+
+NativeThemeTizenTV::~NativeThemeTizenTV() {}
+
+gfx::Size NativeThemeTizenTV::GetPartSize(Part part,
+                                          State state,
+                                          const ExtraParams& extra) const {
+  if (!IsScrollbarPart(part) || !IsNativeScrollbarEnabled())
+    return NativeThemeAura::GetPartSize(part, state, extra);
+
+  ScrollbarType type =
+      absl::get<ScrollbarTypeExtraParams>(extra).is_thin_scrollbar
+          ? kThinScrollbar
+          : kThickScrollbar;
+  int scrollbar_width = kDefaultScrollbarWidth[type];
+  int scrollbar_button_length = kDefaultScrollbarButtonLength[type];
+  switch (part) {
+    case kScrollbarDownArrow:
+    case kScrollbarUpArrow:
+      return gfx::Size(scrollbar_width, scrollbar_button_length);
+    case kScrollbarLeftArrow:
+    case kScrollbarRightArrow:
+      return gfx::Size(scrollbar_button_length, scrollbar_width);
+    case kScrollbarHorizontalThumb:
+      return gfx::Size(2 * scrollbar_width, scrollbar_width);
+    case kScrollbarVerticalThumb:
+      return gfx::Size(scrollbar_width, 2 * scrollbar_width);
+    case kScrollbarHorizontalTrack:
+      return gfx::Size(0, scrollbar_width);
+    case kScrollbarVerticalTrack:
+      return gfx::Size(scrollbar_width, 0);
+    default:
+      break;
+  }
+  return gfx::Size();
+}
+
+void NativeThemeTizenTV::Paint(
+    cc::PaintCanvas* canvas,
+    const ui::ColorProvider* color_provider,
+    Part part,
+    State state,
+    const gfx::Rect& rect,
+    const ExtraParams& extra,
+    ColorScheme color_scheme,
+    bool in_forced_colors,
+    const std::optional<SkColor>& accent_color) const {
+  if (rect.IsEmpty())
+    return;
+
+  if (IsScrollbarPart(part) && IsNativeScrollbarEnabled()) {
+    switch (part) {
+      case kScrollbarDownArrow:
+      case kScrollbarUpArrow:
+      case kScrollbarLeftArrow:
+      case kScrollbarRightArrow:
+        PaintArrowButtonWithExtraParams(
+            canvas, part, state, rect,
+            absl::get<ScrollbarTypeExtraParams>(extra));
+        return;
+      case kScrollbarHorizontalThumb:
+      case kScrollbarVerticalThumb:
+        PaintScrollbarThumbWithExtraParams(
+            canvas, part, state, rect,
+            absl::get<ScrollbarTypeExtraParams>(extra));
+        return;
+      case kScrollbarHorizontalTrack:
+      case kScrollbarVerticalTrack:
+        PaintScrollbarTrackWithExtraParams(
+            canvas, part, state, rect,
+            absl::get<ScrollbarTypeExtraParams>(extra));
+        return;
+      default:
+        break;
+    }
+  }
+
+  NativeThemeBase::Paint(canvas, color_provider, part, state, rect, extra,
+                         color_scheme, in_forced_colors, accent_color);
+}
+
+void NativeThemeTizenTV::PaintArrowButtonBackgroundWithExtraParams(
+    cc::PaintCanvas* paint_canvas,
+    Part part,
+    State state,
+    const gfx::Rect& rect,
+    const ScrollbarTypeExtraParams& extra) const {
+  std::unique_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(paint_canvas));
+  ScrollbarType type =
+      extra.is_thin_scrollbar ? kThinScrollbar : kThickScrollbar;
+  switch (part) {
+    case kScrollbarDownArrow:
+    case kScrollbarUpArrow: {
+      const std::vector<const gfx::ImageSkia*>& track_vertical_images =
+          track_vertical_images_[type][state];
+      if (part == kScrollbarDownArrow) {
+        PaintImagesVertically(canvas.get(),
+                              *track_vertical_images[kVerticalCenter],
+                              *track_vertical_images[kVerticalCenter],
+                              *track_vertical_images[kVerticalBottom], rect);
+        break;
+      }
+      // kScrollbarUpArrow
+      PaintImagesVertically(canvas.get(), *track_vertical_images[kVerticalTop],
+                            *track_vertical_images[kVerticalCenter],
+                            *track_vertical_images[kVerticalCenter], rect);
+      break;
+    }
+    case kScrollbarLeftArrow:
+    case kScrollbarRightArrow: {
+      const std::vector<const gfx::ImageSkia*>& track_horizontal_images =
+          track_horizontal_images_[type][state];
+      if (part == kScrollbarLeftArrow) {
+        PaintImagesHorizontally(
+            canvas.get(), *track_horizontal_images[kHorizontalLeft],
+            *track_horizontal_images[kHorizontalCenter],
+            *track_horizontal_images[kHorizontalCenter], rect);
+        break;
+      }
+      // kScrollbarRightArrow
+      PaintImagesHorizontally(canvas.get(),
+                              *track_horizontal_images[kHorizontalCenter],
+                              *track_horizontal_images[kHorizontalCenter],
+                              *track_horizontal_images[kHorizontalRight], rect);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void NativeThemeTizenTV::PaintArrowButtonWithExtraParams(
+    cc::PaintCanvas* paint_canvas,
+    Part part,
+    State state,
+    const gfx::Rect& rect,
+    const ScrollbarTypeExtraParams& extra) const {
+  PaintArrowButtonBackgroundWithExtraParams(paint_canvas, part, state, rect,
+                                            extra);
+  ScrollDirection direction = GetScrollDirection(part);
+  if (direction == kNumDirections)
+    return;
+
+  const gfx::ImageSkia arrow_button_image =
+      arrow_button_images_[direction][state];
+  std::unique_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(paint_canvas));
+  canvas->DrawImageInt(arrow_button_image, 0, 0, arrow_button_image.width(),
+                       arrow_button_image.height(), rect.x(), rect.y(),
+                       rect.width(), rect.height(), false);
+}
+
+void NativeThemeTizenTV::PaintScrollbarTrackWithExtraParams(
+    cc::PaintCanvas* paint_canvas,
+    Part part,
+    State state,
+    const gfx::Rect& rect,
+    const ScrollbarTypeExtraParams& extra) const {
+  ScrollbarType type =
+      extra.is_thin_scrollbar ? kThinScrollbar : kThickScrollbar;
+
+  std::unique_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(paint_canvas));
+
+  if (part == kScrollbarVerticalTrack) {
+    const std::vector<const gfx::ImageSkia*>& track_vertical_images =
+        track_vertical_images_[type][state];
+    if (type == kThickScrollbar) {
+      // The thickScrollbar has buttons.
+      // Top and bottom track will be painted when painting arrow buttons.
+      PaintImagesVertically(canvas.get(),
+                            *track_vertical_images[kVerticalCenter],
+                            *track_vertical_images[kVerticalCenter],
+                            *track_vertical_images[kVerticalCenter], rect);
+      return;
+    }
+    // kThinScrollbar
+    PaintImagesVertically(canvas.get(), *track_vertical_images[kVerticalTop],
+                          *track_vertical_images[kVerticalCenter],
+                          *track_vertical_images[kVerticalBottom], rect);
+    return;
+  }
+  // kScrollbarHorizontalTrack
+  const std::vector<const gfx::ImageSkia*>& track_horizontal_images =
+      track_horizontal_images_[type][state];
+  if (type == kThickScrollbar) {
+    // The thickScrollbar has buttons.
+    // Left and right track will be painted when painting arrow buttons.
+    PaintImagesHorizontally(canvas.get(),
+                            *track_horizontal_images[kHorizontalCenter],
+                            *track_horizontal_images[kHorizontalCenter],
+                            *track_horizontal_images[kHorizontalCenter], rect);
+    return;
+  }
+  // kThinScrollbar
+  PaintImagesHorizontally(canvas.get(),
+                          *track_horizontal_images[kHorizontalLeft],
+                          *track_horizontal_images[kHorizontalCenter],
+                          *track_horizontal_images[kHorizontalRight], rect);
+}
+
+void NativeThemeTizenTV::PaintScrollbarThumbWithExtraParams(
+    cc::PaintCanvas* paint_canvas,
+    Part part,
+    State state,
+    const gfx::Rect& rect,
+    const ScrollbarTypeExtraParams& extra) const {
+  ScrollbarType type =
+      extra.is_thin_scrollbar ? kThinScrollbar : kThickScrollbar;
+  gfx::Rect adjusted_rect =
+      gfx::Rect(rect.x() + kLocationVariation, rect.y() + kLocationVariation,
+                rect.width() - kSizeVariation, rect.height() - kSizeVariation);
+
+  std::unique_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(paint_canvas));
+  if (part == kScrollbarVerticalThumb) {
+    const std::vector<const gfx::ImageSkia*>& thumb_vertical_images =
+        thumb_vertical_images_[type][state];
+    PaintImagesVertically(canvas.get(), *thumb_vertical_images[kVerticalTop],
+                          *thumb_vertical_images[kVerticalCenter],
+                          *thumb_vertical_images[kVerticalBottom],
+                          adjusted_rect);
+    return;
+  }
+  // kScrollbarHorizontalThumb
+  const std::vector<const gfx::ImageSkia*>& thumb_horizontal_images =
+      thumb_horizontal_images_[type][state];
+  PaintImagesHorizontally(
+      canvas.get(), *thumb_horizontal_images[kHorizontalLeft],
+      *thumb_horizontal_images[kHorizontalCenter],
+      *thumb_horizontal_images[kHorizontalRight], adjusted_rect);
+}
+
+void NativeThemeTizenTV::PaintScrollbarCorner(
+    cc::PaintCanvas* canvas,
+    const ColorProvider* color_provider,
+    State state,
+    const gfx::Rect& rect,
+    const ScrollbarTrackExtraParams& extra_params,
+    ColorScheme color_scheme) const {
+  cc::PaintFlags paint;
+  paint.setColor(SkColorSetRGB(0xFF, 0xFF, 0xFF));
+  paint.setStyle(cc::PaintFlags::kFill_Style);
+  paint.setBlendMode(SkBlendMode::kSrc);
+  canvas->drawIRect(RectToSkIRect(rect), paint);
+}
+
+}  // namespace ui
diff --git a/tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.h b/tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.h
new file mode 100644 (file)
index 0000000..3f4d505
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2025 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_NATIVE_THEME_NATIVE_THEME_TIZEN_H_
+#define UI_NATIVE_THEME_NATIVE_THEME_TIZEN_H_
+
+#include "base/no_destructor.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/native_theme/native_theme_aura.h"
+
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+#endif  // DISALLOW_COPY_AND_ASSIGN
+namespace ui {
+
+// Tizen implementation of native theme support.
+class NATIVE_THEME_EXPORT NativeThemeTizenTV : public NativeThemeAura {
+ public:
+  static NativeThemeTizenTV* web_instance();
+
+ protected:
+  friend class base::NoDestructor<NativeThemeTizenTV>;
+  explicit NativeThemeTizenTV();
+  ~NativeThemeTizenTV() override;
+
+  // NativeTheme implementation:
+  gfx::Size GetPartSize(Part, State, const ExtraParams&) const override;
+
+  void Paint(cc::PaintCanvas*,
+             const ui::ColorProvider* color_provider,
+             Part,
+             State,
+             const gfx::Rect&,
+             const ExtraParams&,
+             ColorScheme,
+             bool in_forced_colors,
+             const std::optional<SkColor>&) const override;
+
+  // This functions is implemented only for NativeThemeTizenTV.
+  void PaintArrowButtonBackgroundWithExtraParams(
+      cc::PaintCanvas*,
+      Part,
+      State,
+      const gfx::Rect&,
+      const ScrollbarTypeExtraParams&) const;
+
+  void PaintArrowButtonWithExtraParams(cc::PaintCanvas*,
+                                       Part,
+                                       State,
+                                       const gfx::Rect&,
+                                       const ScrollbarTypeExtraParams&) const;
+
+  void PaintScrollbarTrackWithExtraParams(
+      cc::PaintCanvas*,
+      Part,
+      State,
+      const gfx::Rect&,
+      const ScrollbarTypeExtraParams&) const;
+
+  void PaintScrollbarThumbWithExtraParams(
+      cc::PaintCanvas*,
+      Part,
+      State,
+      const gfx::Rect&,
+      const ScrollbarTypeExtraParams&) const;
+
+  void PaintScrollbarCorner(cc::PaintCanvas* canvas,
+                            const ColorProvider* color_provider,
+                            State state,
+                            const gfx::Rect& rect,
+                            const ScrollbarTrackExtraParams& extra_params,
+                            ColorScheme color_scheme) const override;
+
+ private:
+  enum VerticalPart {
+    kVerticalTop = 0,
+    kVerticalCenter = 1,
+    kVerticalBottom = 2
+  };
+
+  enum HorizontalPart {
+    kHorizontalLeft = 0,
+    kHorizontalCenter = 1,
+    kHorizontalRight = 2
+  };
+
+  gfx::ImageSkia arrow_button_images_[kNumDirections][kNumStates];
+  std::vector<const gfx::ImageSkia*> track_vertical_images_[kNumScrollbarTypes]
+                                                           [kNumStates];
+  std::vector<const gfx::ImageSkia*>
+      track_horizontal_images_[kNumScrollbarTypes][kNumStates];
+  std::vector<const gfx::ImageSkia*> thumb_vertical_images_[kNumScrollbarTypes]
+                                                           [kNumStates];
+  std::vector<const gfx::ImageSkia*>
+      thumb_horizontal_images_[kNumScrollbarTypes][kNumStates];
+
+  DISALLOW_COPY_AND_ASSIGN(NativeThemeTizenTV);
+};
+
+}  // namespace ui
+#endif  // UI_NATIVE_THEME_NATIVE_THEME_TIZEN_H_
\ No newline at end of file
diff --git a/tizen_src/chromium_impl/ui/resources/BUILD.gn b/tizen_src/chromium_impl/ui/resources/BUILD.gn
new file mode 100644 (file)
index 0000000..2bba92a
--- /dev/null
@@ -0,0 +1,14 @@
+# copyright (c) 2025 samsung electronics. all rights reserved.
+# use of this source code is governed by a bsd-style license that can be
+# found in the license file.
+
+import("//tools/grit/grit_rule.gni")
+
+grit("ui_resources_tizen_grd") {
+  source = "ui_resources_tizen.grd"
+  output_dir = "$root_gen_dir/ui/resources"
+  outputs = [
+    "grit/ui_resources_tizen.h",
+    "ui_resources_tizen.pak",
+  ]
+}
\ No newline at end of file
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_disabled.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_disabled.png
new file mode 100644 (file)
index 0000000..4ddd2ec
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_disabled.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_hover.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_hover.png
new file mode 100644 (file)
index 0000000..c17922b
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_hover.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_normal.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_normal.png
new file mode 100644 (file)
index 0000000..22fdb77
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_arrow_button_normal.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_center.png
new file mode 100644 (file)
index 0000000..bae8f83
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_left.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_left.png
new file mode 100644 (file)
index 0000000..dc321a3
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_left.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_right.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_right.png
new file mode 100644 (file)
index 0000000..b9b0fcf
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_normal_right.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_center.png
new file mode 100644 (file)
index 0000000..dff6208
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_left.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_left.png
new file mode 100644 (file)
index 0000000..4b158ef
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_left.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_right.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_right.png
new file mode 100644 (file)
index 0000000..25a7765
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_horizontal_pressed_right.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_bottom.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_bottom.png
new file mode 100644 (file)
index 0000000..39db623
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_bottom.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_center.png
new file mode 100644 (file)
index 0000000..dbd54fe
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_top.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_top.png
new file mode 100644 (file)
index 0000000..c8d9f3c
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_normal_top.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_bottom.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_bottom.png
new file mode 100644 (file)
index 0000000..0d06454
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_bottom.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_center.png
new file mode 100644 (file)
index 0000000..1d2b264
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_top.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_top.png
new file mode 100644 (file)
index 0000000..5d1cad8
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_thumb_vertical_pressed_top.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_center.png
new file mode 100644 (file)
index 0000000..7663543
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_left.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_left.png
new file mode 100644 (file)
index 0000000..7663543
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_left.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_right.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_right.png
new file mode 100644 (file)
index 0000000..063fe1d
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_horizontal_normal_right.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_bottom.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_bottom.png
new file mode 100644 (file)
index 0000000..f56d61a
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_bottom.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_center.png
new file mode 100644 (file)
index 0000000..bd132d0
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_top.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_top.png
new file mode 100644 (file)
index 0000000..bd132d0
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thick_track_vertical_normal_top.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_center.png
new file mode 100644 (file)
index 0000000..8cf6e0e
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_left.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_left.png
new file mode 100644 (file)
index 0000000..c02a77e
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_left.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_right.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_right.png
new file mode 100644 (file)
index 0000000..019f67f
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_horizontal_normal_right.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_bottom.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_bottom.png
new file mode 100644 (file)
index 0000000..55d70ca
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_bottom.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_center.png
new file mode 100644 (file)
index 0000000..eeaa4fc
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_top.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_top.png
new file mode 100644 (file)
index 0000000..81a277d
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_thumb_vertical_normal_top.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_center.png
new file mode 100644 (file)
index 0000000..72a1213
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_left.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_left.png
new file mode 100644 (file)
index 0000000..a29814c
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_left.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_right.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_right.png
new file mode 100644 (file)
index 0000000..2829928
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_horizontal_normal_right.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_bottom.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_bottom.png
new file mode 100644 (file)
index 0000000..0927d90
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_bottom.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_center.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_center.png
new file mode 100644 (file)
index 0000000..2baea79
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_center.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_top.png b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_top.png
new file mode 100644 (file)
index 0000000..fea2983
Binary files /dev/null and b/tizen_src/chromium_impl/ui/resources/tizen/scrollbar_thin_track_vertical_normal_top.png differ
diff --git a/tizen_src/chromium_impl/ui/resources/ui_resources_tizen.grd b/tizen_src/chromium_impl/ui/resources/ui_resources_tizen.grd
new file mode 100644 (file)
index 0000000..03881a1
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+  <outputs>
+    <output filename="grit/ui_resources_tizen.h" type="rc_header" >
+      <emit emit_type='prepend'></emit>
+    </output>
+    <output filename="ui_resources_tizen.pak" type="data_package" />
+  </outputs>
+  <release seq="1">
+    <includes>
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_DISABLED" file="tizen/scrollbar_thick_arrow_button_disabled.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_HOVER" file="tizen/scrollbar_thick_arrow_button_hover.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_ARROW_BUTTON_NORMAL" file="tizen/scrollbar_thick_arrow_button_normal.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_NORMAL_CENTER" file="tizen/scrollbar_thick_thumb_horizontal_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_NORMAL_LEFT" file="tizen/scrollbar_thick_thumb_horizontal_normal_left.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_NORMAL_RIGHT" file="tizen/scrollbar_thick_thumb_horizontal_normal_right.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_PRESSED_CENTER" file="tizen/scrollbar_thick_thumb_horizontal_pressed_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_PRESSED_LEFT" file="tizen/scrollbar_thick_thumb_horizontal_pressed_left.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_THUMB_PRESSED_RIGHT" file="tizen/scrollbar_thick_thumb_horizontal_pressed_right.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_NORMAL_BOTTOM" file="tizen/scrollbar_thick_thumb_vertical_normal_bottom.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_NORMAL_CENTER" file="tizen/scrollbar_thick_thumb_vertical_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_NORMAL_TOP" file="tizen/scrollbar_thick_thumb_vertical_normal_top.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_PRESSED_BOTTOM" file="tizen/scrollbar_thick_thumb_vertical_pressed_bottom.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_PRESSED_CENTER" file="tizen/scrollbar_thick_thumb_vertical_pressed_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_THUMB_PRESSED_TOP" file="tizen/scrollbar_thick_thumb_vertical_pressed_top.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_TRACK_NORMAL_CENTER" file="tizen/scrollbar_thick_track_horizontal_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_TRACK_NORMAL_LEFT" file="tizen/scrollbar_thick_track_horizontal_normal_left.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_HORIZONTAL_TRACK_NORMAL_RIGHT" file="tizen/scrollbar_thick_track_horizontal_normal_right.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_TRACK_NORMAL_BOTTOM" file="tizen/scrollbar_thick_track_vertical_normal_bottom.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_TRACK_NORMAL_CENTER" file="tizen/scrollbar_thick_track_vertical_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THICK_SCROLLBAR_VERTICAL_TRACK_NORMAL_TOP" file="tizen/scrollbar_thick_track_vertical_normal_top.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_THUMB_CENTER" file="tizen/scrollbar_thin_thumb_horizontal_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_THUMB_LEFT" file="tizen/scrollbar_thin_thumb_horizontal_normal_left.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_THUMB_RIGHT" file="tizen/scrollbar_thin_thumb_horizontal_normal_right.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_THUMB_BOTTOM" file="tizen/scrollbar_thin_thumb_vertical_normal_bottom.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_THUMB_CENTER" file="tizen/scrollbar_thin_thumb_vertical_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_THUMB_TOP" file="tizen/scrollbar_thin_thumb_vertical_normal_top.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_TRACK_CENTER" file="tizen/scrollbar_thin_track_horizontal_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_TRACK_LEFT" file="tizen/scrollbar_thin_track_horizontal_normal_left.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_HORIZONTAL_TRACK_RIGHT" file="tizen/scrollbar_thin_track_horizontal_normal_right.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_TRACK_BOTTOM" file="tizen/scrollbar_thin_track_vertical_normal_bottom.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_TRACK_CENTER" file="tizen/scrollbar_thin_track_vertical_normal_center.png" type="BINDATA" />
+      <include name="IDR_TIZEN_THIN_SCROLLBAR_VERTICAL_TRACK_TOP" file="tizen/scrollbar_thin_track_vertical_normal_top.png" type="BINDATA" />
+    </includes>
+  </release>
+</grit>
\ No newline at end of file
index 23ce2f213c0af35c91e9a424087236637fe0b4ef..f859ca736f3f624c6324fab0694b7d906e3a4db1 100644 (file)
@@ -77,6 +77,11 @@ repack("efl_pak") {
     "//ui/resources",
     "//ui/strings",
   ]
+  if (tizen_vd_native_scrollbars) {
+    sources += [ "$root_gen_dir/ui/resources/ui_resources_tizen.pak" ]
+    deps +=
+        [ "//tizen_src/chromium_impl/ui/resources:ui_resources_tizen_grd_grit" ]
+  }
 
   output = "$root_out_dir/ewk_efl_resources.pak"
 }
index 8c2b5b2615a21720406c01cd8e98df0021294fb2..939c5ad78d339922d4e6c82ef6694f068a8b4ebd 100644 (file)
 
   # Thinking about appending to the end?
   # Please read the header and find the right section above instead.
+
+  "tizen_src/chromium_impl/ui/resources/ui_resources_tizen.grd": {
+    "includes": [31000],
+  },
+
   "tizen_src/ewk/efl_integration/efl_resources.grd": {
     "includes": [31100],
   },
index 3d4f25b9535c7db0f0e76c635136631427cfd3b7..1863421fb61e857dc00e977da7227cb333f73292 100644 (file)
@@ -92,6 +92,13 @@ component("native_theme") {
     "//skia",
   ]
 
+  if (tizen_vd_native_scrollbars) {
+    sources += [
+      "//tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.cc",
+      "//tizen_src/chromium_impl/ui/native_theme/native_theme_tizen_tv.h",
+    ]
+  }
+
   deps = [
     "//base",
     "//build:chromeos_buildflags",
@@ -106,6 +113,7 @@ component("native_theme") {
     "//ui/gfx/animation/keyframe",
     "//ui/gfx/geometry",
     "//ui/resources",
+    "//tizen_src/chromium_impl/ui/resources:ui_resources_tizen_grd"
   ]
 
   if (use_efl) {
index 0ba23d2d8ea58024b48d1dd3b0a411bc53d6e26e..238776f84cff6ee3485eac143ae52972dc9e54ad 100644 (file)
@@ -118,6 +118,24 @@ class NATIVE_THEME_EXPORT NativeTheme {
     kNumStates = kPressed + 1,
   };
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  enum ScrollbarType {
+    // IDs defined as specific values for use in arrays.
+    kThinScrollbar = 0,
+    kThickScrollbar = 1,
+    kNumScrollbarTypes = kThickScrollbar + 1
+  };
+
+  enum ScrollDirection {
+    // IDs defined as specific values for use in arrays.
+    kScrollUp = 0,
+    kScrollRight = 1,
+    kScrollDown = 2,
+    kScrollLeft = 3,
+    kNumDirections = kScrollLeft + 1
+  };
+#endif
+
   // Enum used for kPageColors pref. Page Colors is a browser setting that can
   // be used to simulate forced colors mode. This enum should match its React
   // counterpart.
@@ -294,6 +312,12 @@ class NATIVE_THEME_EXPORT NativeTheme {
     std::optional<SkColor> track_color;
   };
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  struct ScrollbarTypeExtraParams {
+    bool is_thin_scrollbar;
+  };
+#endif
+
   struct ScrollbarThumbExtraParams {
     bool is_hovering = false;
     // This allows clients to directly override the color values to support
@@ -376,6 +400,9 @@ class NATIVE_THEME_EXPORT NativeTheme {
 #endif
                                     ScrollbarTrackExtraParams,
                                     ScrollbarThumbExtraParams,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+                                    ScrollbarTypeExtraParams,
+#endif
                                     SliderExtraParams,
                                     TextFieldExtraParams,
                                     TrackbarExtraParams>;
index 35c74aa51109db33dbc0dcefa35cbe262b55235e..739c4c5be7f364fbc9a3140d75fd4a710c27a831 100644 (file)
@@ -61,6 +61,7 @@ BASE_FEATURE(kNewScrollbarArrowRadius,
 // NativeTheme:
 
 #if !BUILDFLAG(IS_APPLE)
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
 // static
 NativeTheme* NativeTheme::GetInstanceForWeb() {
   if (IsFluentScrollbarEnabled()) {
@@ -68,6 +69,7 @@ NativeTheme* NativeTheme::GetInstanceForWeb() {
   }
   return NativeThemeAura::web_instance();
 }
+#endif  //! TIZEN_VD_NATIVE_SCROLLBARS
 
 #if !BUILDFLAG(IS_WIN)
 // static
index b09058022eeb728a1d318e7e447586c3e29b1239..5d6a91b6c3f09132de4e0151e2c06eaa3eaf8a74 100644 (file)
@@ -26,6 +26,12 @@ BASE_FEATURE(kOverlayScrollbar,
              "OverlayScrollbar",
              kOverlayScrollbarFeatureState);
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+BASE_FEATURE(kNativeScrollbar,
+             "NativeScrollbar",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif
+
 // Fluent scrollbars aim to modernize the Chromium scrollbars (both overlay and
 // non-overlay) to fit the Fluent design language. For now, the feature will
 // only support the Windows and Linux platforms. The feature is currently in
@@ -48,6 +54,12 @@ BASE_FEATURE(kFluentOverlayScrollbar,
 namespace ui {
 
 bool IsOverlayScrollbarEnabled() {
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+  // Native scrollbar type is overlay, So not need to enable overlay again.
+  if (IsNativeScrollbarEnabled())
+    return false;
+#endif
+
 #if BUILDFLAG(IS_TIZEN_TV)
   return true;
 #endif
@@ -56,6 +68,12 @@ bool IsOverlayScrollbarEnabled() {
          IsFluentOverlayScrollbarEnabled();
 }
 
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+bool IsNativeScrollbarEnabled() {
+  return base::FeatureList::IsEnabled(features::kNativeScrollbar);
+}
+#endif
+
 bool IsFluentScrollbarEnabled() {
 // Fluent scrollbars are only used for some OSes due to UI design guidelines.
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
index 378b4fe7ac32d978516b65f2553079e78d09d15d..745aed1f718df93641e42769cfb4b376baf9f921 100644 (file)
@@ -15,6 +15,9 @@ namespace features {
 NATIVE_THEME_EXPORT BASE_DECLARE_FEATURE(kOverlayScrollbar);
 NATIVE_THEME_EXPORT BASE_DECLARE_FEATURE(kFluentScrollbar);
 NATIVE_THEME_EXPORT BASE_DECLARE_FEATURE(kFluentOverlayScrollbar);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+NATIVE_THEME_EXPORT BASE_DECLARE_FEATURE(kNativeScrollbar);
+#endif
 
 }  // namespace features
 
@@ -23,6 +26,10 @@ namespace ui {
 NATIVE_THEME_EXPORT bool IsOverlayScrollbarEnabled();
 NATIVE_THEME_EXPORT bool IsFluentScrollbarEnabled();
 NATIVE_THEME_EXPORT bool IsFluentOverlayScrollbarEnabled();
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+NATIVE_THEME_EXPORT bool IsNativeScrollbarEnabled();
+#endif
+
 
 }  // namespace ui