// 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