}
}
+#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(
// 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
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;
}
ApplyOpacityToScrollbars(opacity);
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ if (progress == 1.f || should_stop_animation_)
+#else
if (progress == 1.f)
+#endif
StopAnimation();
}
client_->SetNeedsRedrawForScrollbarAnimation();
}
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
opacity_ = opacity;
+#endif
if (previously_visible_ != currently_visible) {
client_->DidChangeScrollbarVisibility();
}
}
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void ScrollbarAnimationController::SetShouldStopAnimation(
+ bool should_stop_animation) {
+ should_stop_animation_ = should_stop_animation;
+}
+#endif
} // namespace cc
ScrollbarSet Scrollbars() const;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ void SetShouldStopAnimation(bool should_stop_animation);
+#endif
+
SingleScrollbarAnimationControllerThinning& GetScrollbarAnimationController(
ScrollbarOrientation) const;
bool is_mouse_down_;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ bool should_stop_animation_ = false;
+#endif
+
bool tickmarks_showing_;
bool visibility_changed_ = false;
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_(
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_);
} else {
updated |= UpdateProperty(gfx::Size(), &thumb_size_.Write(*this));
}
+
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ updated |= UpdateProperty(scrollbar->IsHovered(), &is_hovered_);
+#endif
+
return updated;
}
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_;
return false;
}
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
LayerTreeSettings::ScrollbarAnimator
PaintedScrollbarLayerImpl::GetScrollbarAnimator() const {
return IsFluentOverlayScrollbarEnabled() ? LayerTreeSettings::AURA_OVERLAY
: LayerTreeSettings::NO_ANIMATOR;
}
-
+#endif
} // namespace cc
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,
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),
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());
}
// 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
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;
private:
bool IsScrollbarLayer() const final;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ bool is_hovered_;
+#endif
+
gfx::Rect ComputeThumbQuadRectWithThumbThicknessScale(
float thumb_thickness_scale_factor) const;
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;
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) {
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);
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;
#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 {
// 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.
// 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
[ "$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"
}
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 =
// (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)
}
#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;
}
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" ]
}
[EnableIf=is_tizen_tv]
bool use_scrollbar_thumb_focus_notifications;
+
+ [EnableIf=tizen_vd_native_scrollbars]
+ bool use_native_scrollbars;
};
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.
InnerSpinButtonExtraParams,
ProgressBarExtraParams,
ScrollbarThumbExtraParams,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ ScrollbarTypeExtraParams,
+#endif
#if BUILDFLAG(IS_MAC)
ScrollbarExtraParams,
#endif
// 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(); }
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;
}
#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);
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;
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,
#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 {
}
#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_;
case kScrollbarBGPart:
UseCounter::Count(document, WebFeature::kCSSSelectorPseudoScrollbar);
break;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ case kCornerPart:
+#endif
case kNoPart:
case kAllParts:
break;
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(
(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;
visitor->Trace(v_bar_);
}
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+void PaintLayerScrollableArea::ScrollbarSizeDidChange() {
+ PositionOverflowControls();
+ SetScrollCornerNeedsPaintInvalidation();
+}
+#endif
+
int PaintLayerScrollableArea::FreezeScrollbarsScope::count_ = 0;
PaintLayerScrollableArea::FreezeScrollbarsRootScope::FreezeScrollbarsRootScope(
bool focused) override;
#endif
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ void ScrollbarSizeDidChange() override;
+#endif
+
void Trace(Visitor*) const override;
gfx::Rect ScrollingBackgroundVisualRect(
// 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;
}
]
}
+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",
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
};
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()) {
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() {}
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();
}
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()) {
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
}
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();
}
: 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;
}
// 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);
float elastic_overscroll_;
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ int corner_height_;
+ EScrollbarWidth scrollbar_width_;
+#endif
+
private:
float ScrollableAreaCurrentPos() const;
float ScrollableAreaTargetPos() 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();
}
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;
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 {
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)) {
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;
}
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);
}
}
+#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
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,
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
#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 {
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();
}
}
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 =
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;
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
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
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;
--- /dev/null
+// 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
--- /dev/null
+// 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
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) {
#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;
// 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
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;
kScrollbarTrackAndButtons,
kScrollbarThumb,
kScrollbarTickmarks,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ kScrollbarBackButtonStart,
+ kScrollbarForwardButtonEnd,
+ kScrollbarTrack,
+#endif
kSelectionTint,
kTableCollapsedBorders,
kWebPlugin,
#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();
#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"
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);
}
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);
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);
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,
// 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,
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)
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",
tizen_tv_video_capture = false
tizen_rtc_unittests = false
+ tizen_vd_native_scrollbars = false
drm_mapi_aarch_64 = false
tizen_tv_riscv64 = false
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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+# 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
--- /dev/null
+<?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
"//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"
}
# 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],
},
"//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",
"//ui/gfx/animation/keyframe",
"//ui/gfx/geometry",
"//ui/resources",
+ "//tizen_src/chromium_impl/ui/resources:ui_resources_tizen_grd"
]
if (use_efl) {
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.
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
#endif
ScrollbarTrackExtraParams,
ScrollbarThumbExtraParams,
+#if defined(TIZEN_VD_NATIVE_SCROLLBARS)
+ ScrollbarTypeExtraParams,
+#endif
SliderExtraParams,
TextFieldExtraParams,
TrackbarExtraParams>;
// NativeTheme:
#if !BUILDFLAG(IS_APPLE)
+#if !defined(TIZEN_VD_NATIVE_SCROLLBARS)
// static
NativeTheme* NativeTheme::GetInstanceForWeb() {
if (IsFluentScrollbarEnabled()) {
}
return NativeThemeAura::web_instance();
}
+#endif //! TIZEN_VD_NATIVE_SCROLLBARS
#if !BUILDFLAG(IS_WIN)
// static
"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
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
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)
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
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