| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "webkit/child/webthemeengine_impl_win.h" |
| |
| #include <vsstyle.h> // To convert to ui::NativeTheme::State |
| |
| #include "base/logging.h" |
| #include "skia/ext/platform_canvas.h" |
| #include "skia/ext/skia_utils_win.h" |
| #include "third_party/WebKit/public/platform/WebRect.h" |
| #include "ui/gfx/win/dpi.h" |
| #include "ui/native_theme/native_theme.h" |
| |
| using blink::WebCanvas; |
| using blink::WebColor; |
| using blink::WebRect; |
| using blink::WebSize; |
| |
| namespace webkit_glue { |
| |
| static RECT WebRectToRECT(const WebRect& rect) { |
| RECT result; |
| result.left = rect.x; |
| result.top = rect.y; |
| result.right = rect.x + rect.width; |
| result.bottom = rect.y + rect.height; |
| return result; |
| } |
| |
| static ui::NativeTheme::State WebButtonStateToGfx( |
| int part, int state, ui::NativeTheme::ButtonExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| // Native buttons have a different focus style. |
| extra->is_focused = false; |
| extra->has_border = false; |
| extra->background_color = ui::NativeTheme::instance()->GetSystemColor( |
| ui::NativeTheme::kColorId_ButtonBackgroundColor); |
| |
| if (part == BP_PUSHBUTTON) { |
| switch (state) { |
| case PBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case PBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case PBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case PBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case PBS_DEFAULTED: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = true; |
| break; |
| case PBS_DEFAULTED_ANIMATING: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| } |
| } else if (part == BP_RADIOBUTTON) { |
| switch (state) { |
| case RBS_UNCHECKEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_UNCHECKEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_UNCHECKEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_UNCHECKEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_CHECKEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_CHECKEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_CHECKEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case RBS_CHECKEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| } else if (part == BP_CHECKBOX) { |
| switch (state) { |
| case CBS_UNCHECKEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_UNCHECKEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_UNCHECKEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_UNCHECKEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_CHECKEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_CHECKEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_CHECKEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_CHECKEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = true; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_MIXEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = true; |
| extra->is_default = false; |
| break; |
| case CBS_MIXEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = true; |
| extra->is_default = false; |
| break; |
| case CBS_MIXEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = true; |
| extra->is_default = false; |
| break; |
| case CBS_MIXEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = true; |
| extra->is_default = false; |
| break; |
| case CBS_IMPLICITNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_IMPLICITHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_IMPLICITPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_IMPLICITDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_EXCLUDEDNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_EXCLUDEDHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_EXCLUDEDPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CBS_EXCLUDEDDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| } else if (part == BP_GROUPBOX) { |
| switch (state) { |
| case GBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case GBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| } else if (part == BP_COMMANDLINK) { |
| switch (state) { |
| case CMDLS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLS_DEFAULTED: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = true; |
| break; |
| case CMDLS_DEFAULTED_ANIMATING: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| } else if (part == BP_COMMANDLINKGLYPH) { |
| switch (state) { |
| case CMDLGS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLGS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLGS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLGS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = false; |
| break; |
| case CMDLGS_DEFAULTED: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->checked = false; |
| extra->indeterminate = false; |
| extra->is_default = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintButton( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect) { |
| ui::NativeTheme::Part native_part = ui::NativeTheme::kPushButton; |
| switch (part) { |
| case BP_PUSHBUTTON: |
| native_part = ui::NativeTheme::kPushButton; |
| break; |
| case BP_CHECKBOX: |
| native_part = ui::NativeTheme::kCheckbox; |
| break; |
| case BP_RADIOBUTTON: |
| native_part = ui::NativeTheme::kRadio; |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebButtonStateToGfx(part, state, |
| &extra.button); |
| extra.button.classic_state = classic_state; |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebListMenuStateToGfx(int part, int state) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| |
| switch (part) { |
| case CP_DROPDOWNBUTTON: |
| switch (state) { |
| case CBXS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| break; |
| case CBXS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| break; |
| case CBXS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| break; |
| case CBXS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintMenuList( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect) { |
| ui::NativeTheme::Part native_part = ui::NativeTheme::kMenuList; |
| switch (part) { |
| case CP_DROPDOWNBUTTON: |
| native_part = ui::NativeTheme::kMenuList; |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| ui::NativeTheme::State native_state = WebListMenuStateToGfx(part, state); |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::ExtraParams extra; |
| extra.menu_list.classic_state = classic_state; |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebScrollbarArrowStateToGfx( |
| int state, ui::NativeTheme::Part* part, |
| ui::NativeTheme::ScrollbarArrowExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (state) { |
| case ABS_UPNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *part = ui::NativeTheme::kScrollbarUpArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_UPHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarUpArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_UPPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *part = ui::NativeTheme::kScrollbarUpArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_UPDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *part = ui::NativeTheme::kScrollbarUpArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_DOWNNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *part = ui::NativeTheme::kScrollbarDownArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_DOWNHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarDownArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_DOWNPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *part = ui::NativeTheme::kScrollbarDownArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_DOWNDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *part = ui::NativeTheme::kScrollbarDownArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_LEFTNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *part = ui::NativeTheme::kScrollbarLeftArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_LEFTHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarLeftArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_LEFTPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *part = ui::NativeTheme::kScrollbarLeftArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_LEFTDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *part = ui::NativeTheme::kScrollbarLeftArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_RIGHTNORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *part = ui::NativeTheme::kScrollbarRightArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_RIGHTHOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarRightArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_RIGHTPRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *part = ui::NativeTheme::kScrollbarRightArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_RIGHTDISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *part = ui::NativeTheme::kScrollbarRightArrow; |
| extra->is_hovering = false; |
| break; |
| case ABS_UPHOVER: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarUpArrow; |
| extra->is_hovering = true; |
| break; |
| case ABS_DOWNHOVER: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarDownArrow; |
| extra->is_hovering = true; |
| break; |
| case ABS_LEFTHOVER: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarLeftArrow; |
| extra->is_hovering = true; |
| break; |
| case ABS_RIGHTHOVER: |
| gfx_state = ui::NativeTheme::kHovered; |
| *part = ui::NativeTheme::kScrollbarRightArrow; |
| extra->is_hovering = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintScrollbarArrow( |
| WebCanvas* canvas, int state, int classic_state, const WebRect& rect) { |
| ui::NativeTheme::Part native_part; |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebScrollbarArrowStateToGfx( |
| state, &native_part, &extra.scrollbar_arrow); |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebScrollbarThumbStateToGfx( |
| int state, ui::NativeTheme::ScrollbarThumbExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (state) { |
| case SCRBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->is_hovering = false; |
| break; |
| case SCRBS_HOVER: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->is_hovering = true; |
| break; |
| case SCRBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->is_hovering = false; |
| break; |
| case SCRBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->is_hovering = false; |
| break; |
| case SCRBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->is_hovering = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintScrollbarThumb( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect) { |
| ui::NativeTheme::Part native_part; |
| if (part == SBP_THUMBBTNHORZ) { |
| native_part = ui::NativeTheme::kScrollbarHorizontalThumb; |
| } else if (part == SBP_THUMBBTNVERT) { |
| native_part = ui::NativeTheme::kScrollbarVerticalThumb; |
| } else if (part == SBP_GRIPPERHORZ) { |
| native_part = ui::NativeTheme::kScrollbarHorizontalGripper; |
| } else if (part == SBP_GRIPPERVERT) { |
| native_part = ui::NativeTheme::kScrollbarVerticalGripper; |
| } else { |
| NOTREACHED() << "Invalid part: " << part; |
| } |
| |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebScrollbarThumbStateToGfx( |
| state, &extra.scrollbar_thumb); |
| |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebScrollbarTrackStateToGfx( |
| int part, int state, ui::NativeTheme::Part* gfx_part, |
| ui::NativeTheme::ScrollbarTrackExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (part) { |
| case SBP_LOWERTRACKHORZ: |
| switch (state) { |
| case SCRBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_HOVER: |
| case SCRBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| case SBP_UPPERTRACKHORZ: |
| switch (state) { |
| case SCRBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_HOVER: |
| case SCRBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack; |
| extra->is_upper = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| case SBP_LOWERTRACKVERT: |
| switch (state) { |
| case SCRBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_HOVER: |
| case SCRBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = false; |
| break; |
| case SCRBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| case SBP_UPPERTRACKVERT: |
| switch (state) { |
| case SCRBS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_HOVER: |
| case SCRBS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = true; |
| break; |
| case SCRBS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack; |
| extra->is_upper = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintScrollbarTrack( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect, const WebRect& align_rect) { |
| ui::NativeTheme::Part native_part; |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebScrollbarTrackStateToGfx( |
| part, state, &native_part, &extra.scrollbar_track); |
| extra.scrollbar_track.classic_state = classic_state; |
| extra.scrollbar_track.track_x = align_rect.x; |
| extra.scrollbar_track.track_y = align_rect.y; |
| extra.scrollbar_track.track_width = align_rect.width; |
| extra.scrollbar_track.track_height = align_rect.height; |
| |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebSpinButtonStateToGfx( |
| int part, int state, ui::NativeTheme::InnerSpinButtonExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (part) { |
| case SPNP_UP: |
| switch (state) { |
| case UPS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->spin_up = true; |
| extra->read_only = false; |
| break; |
| case UPS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->spin_up = true; |
| extra->read_only = false; |
| break; |
| case UPS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->spin_up = true; |
| extra->read_only = false; |
| break; |
| case UPS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->spin_up = true; |
| extra->read_only = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| case SPNP_DOWN: |
| switch (state) { |
| case DNS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->spin_up = false; |
| extra->read_only = false; |
| break; |
| case DNS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->spin_up = false; |
| extra->read_only = false; |
| break; |
| case DNS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->spin_up = false; |
| extra->read_only = false; |
| break; |
| case DNS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->spin_up = false; |
| extra->read_only = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintSpinButton( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect) { |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebSpinButtonStateToGfx( |
| part, state, &extra.inner_spin); |
| extra.inner_spin.classic_state = classic_state; |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| ui::NativeTheme::instance()->Paint(canvas, |
| ui::NativeTheme::kInnerSpinButton, |
| native_state, |
| gfx_rect, |
| extra); |
| } |
| |
| static ui::NativeTheme::State WebTextFieldStateToGfx( |
| int part, int state, ui::NativeTheme::TextFieldExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (part) { |
| case EP_EDITTEXT: |
| switch (state) { |
| case ETS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->is_read_only = false; |
| extra->is_focused = false; |
| break; |
| case ETS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| extra->is_read_only = false; |
| extra->is_focused = false; |
| break; |
| case ETS_SELECTED: |
| gfx_state = ui::NativeTheme::kPressed; |
| extra->is_read_only = false; |
| extra->is_focused = false; |
| break; |
| case ETS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| extra->is_read_only = false; |
| extra->is_focused = false; |
| break; |
| case ETS_FOCUSED: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->is_read_only = false; |
| extra->is_focused = true; |
| break; |
| case ETS_READONLY: |
| gfx_state = ui::NativeTheme::kNormal; |
| extra->is_read_only = true; |
| extra->is_focused = false; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintTextField( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect, WebColor color, bool fill_content_area, |
| bool draw_edges) { |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebTextFieldStateToGfx( |
| part, state, &extra.text_field); |
| extra.text_field.fill_content_area = fill_content_area; |
| extra.text_field.draw_edges = draw_edges; |
| extra.text_field.background_color = color; |
| extra.text_field.classic_state = classic_state; |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| |
| ui::NativeTheme::instance()->Paint(canvas, |
| ui::NativeTheme::kTextField, native_state, gfx_rect, extra); |
| } |
| |
| static ui::NativeTheme::State WebTrackbarStateToGfx( |
| int part, |
| int state, |
| ui::NativeTheme::TrackbarExtraParams* extra) { |
| ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal; |
| switch (state) { |
| case TUS_NORMAL: |
| gfx_state = ui::NativeTheme::kNormal; |
| break; |
| case TUS_HOT: |
| gfx_state = ui::NativeTheme::kHovered; |
| break; |
| case TUS_PRESSED: |
| gfx_state = ui::NativeTheme::kPressed; |
| break; |
| case TUS_DISABLED: |
| gfx_state = ui::NativeTheme::kDisabled; |
| break; |
| default: |
| NOTREACHED() << "Invalid state: " << state; |
| break; |
| } |
| |
| switch (part) { |
| case TKP_TRACK: |
| case TKP_THUMBBOTTOM: |
| extra->vertical = false; |
| break; |
| case TKP_TRACKVERT: |
| case TKP_THUMBVERT: |
| extra->vertical = true; |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| |
| return gfx_state; |
| } |
| |
| void WebThemeEngineImpl::paintTrackbar( |
| WebCanvas* canvas, int part, int state, int classic_state, |
| const WebRect& rect) { |
| ui::NativeTheme::Part native_part = ui::NativeTheme::kTrackbarTrack; |
| switch (part) { |
| case TKP_TRACK: |
| case TKP_TRACKVERT: |
| native_part = ui::NativeTheme::kTrackbarTrack; |
| break; |
| case TKP_THUMBBOTTOM: |
| case TKP_THUMBVERT: |
| native_part = ui::NativeTheme::kTrackbarThumb; |
| break; |
| default: |
| NOTREACHED() << "Invalid part: " << part; |
| break; |
| } |
| |
| ui::NativeTheme::ExtraParams extra; |
| ui::NativeTheme::State native_state = WebTrackbarStateToGfx(part, state, |
| &extra.trackbar); |
| gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height); |
| extra.trackbar.classic_state = classic_state; |
| ui::NativeTheme::instance()->Paint(canvas, native_part, |
| native_state, gfx_rect, extra); |
| } |
| |
| void WebThemeEngineImpl::paintProgressBar( |
| WebCanvas* canvas, const WebRect& barRect, const WebRect& valueRect, |
| bool determinate, double animatedSeconds) |
| { |
| gfx::Rect gfx_rect(barRect.x, barRect.y, barRect.width, barRect.height); |
| ui::NativeTheme::ExtraParams extra; |
| extra.progress_bar.animated_seconds = animatedSeconds; |
| extra.progress_bar.determinate = determinate; |
| extra.progress_bar.value_rect_x = valueRect.x; |
| extra.progress_bar.value_rect_y = valueRect.y; |
| extra.progress_bar.value_rect_width = valueRect.width; |
| extra.progress_bar.value_rect_height = valueRect.height; |
| ui::NativeTheme::instance()->Paint(canvas, ui::NativeTheme::kProgressBar, |
| ui::NativeTheme::kNormal, gfx_rect, |
| extra); |
| } |
| |
| WebSize WebThemeEngineImpl::getSize(int part) { |
| switch (part) { |
| case SBP_ARROWBTN: { |
| gfx::Size size = ui::NativeTheme::instance()->GetPartSize( |
| ui::NativeTheme::kScrollbarUpArrow, |
| ui::NativeTheme::kNormal, |
| ui::NativeTheme::ExtraParams()); |
| // GetPartSize returns a size of (0, 0) when not using a themed style |
| // (i.e. Windows Classic). Returning a non-zero size in this context |
| // creates repaint conflicts, particularly in the window titlebar area |
| // which significantly degrades performance. Fallback to using a system |
| // metric if required. |
| if (size.width() == 0) { |
| int width = static_cast<int>(GetSystemMetrics(SM_CXVSCROLL) / |
| gfx::win::GetDeviceScaleFactor()); |
| size = gfx::Size(width, width); |
| } |
| return WebSize(size.width(), size.height()); |
| } |
| default: |
| NOTREACHED() << "Unhandled part: " << part; |
| } |
| return WebSize(); |
| } |
| |
| } // namespace webkit_glue |