Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Unified Diff: ui/base/native_theme/native_theme_win.cc

Issue 10387121: Revert 136996 - ui: Move NativeTheme files into ui/base/native_theme/ directory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/native_theme/native_theme_win.h ('k') | ui/base/native_theme/native_theme_win_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/native_theme/native_theme_win.cc
===================================================================
--- ui/base/native_theme/native_theme_win.cc (revision 137002)
+++ ui/base/native_theme/native_theme_win.cc (working copy)
@@ -1,1779 +0,0 @@
-// 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 "ui/base/native_theme/native_theme_win.h"
-
-#include <windows.h>
-#include <uxtheme.h>
-#include <vsstyle.h>
-#include <vssym32.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/scoped_handle.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/win/scoped_gdi_object.h"
-#include "base/win/scoped_hdc.h"
-#include "base/win/scoped_select_object.h"
-#include "base/win/windows_version.h"
-#include "skia/ext/platform_canvas.h"
-#include "skia/ext/skia_utils_win.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColorPriv.h"
-#include "third_party/skia/include/core/SkShader.h"
-#include "ui/gfx/color_utils.h"
-#include "ui/gfx/gdi_util.h"
-#include "ui/gfx/rect.h"
-
-namespace {
-
-// TODO: Obtain the correct colors using GetSysColor.
-// Theme colors returned by GetSystemColor().
-const SkColor kInvalidColorIdColor = SkColorSetRGB(255, 0, 128);
-// Dialogs:
-const SkColor kDialogBackgroundColor = SkColorSetRGB(200, 200, 200);
-// FocusableBorder (should be unused on Win):
-const SkColor kFocusedBorderColor= SkColorSetRGB(0x4D, 0x90, 0xFE);
-const SkColor kUnfocusedBorderColor = SkColorSetRGB(0xD9, 0xD9, 0xD9);
-// TextButton:
-const SkColor kTextButtonBackgroundColor = SkColorSetRGB(0xde, 0xde, 0xde);
-const SkColor kTextButtonEnabledColor = SkColorSetRGB(6, 45, 117);
-const SkColor kTextButtonDisabledColor = SkColorSetRGB(161, 161, 146);
-const SkColor kTextButtonHighlightColor = SkColorSetARGB(200, 255, 255, 255);
-const SkColor kTextButtonHoverColor = kTextButtonEnabledColor;
-// MenuItem:
-const SkColor kEnabledMenuItemForegroundColor = kTextButtonEnabledColor;
-const SkColor kDisabledMenuItemForegroundColor = kTextButtonDisabledColor;
-const SkColor kFocusedMenuItemBackgroundColor = SkColorSetRGB(246, 249, 253);
-const SkColor kMenuSeparatorColor = SkColorSetARGB(50, 0, 0, 0);
-// Label:
-const SkColor kLabelEnabledColor = color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
-const SkColor kLabelDisabledColor = color_utils::GetSysSkColor(COLOR_GRAYTEXT);
-const SkColor kLabelBackgroundColor = color_utils::GetSysSkColor(COLOR_WINDOW);
-// Textfield:
-const SkColor kTextfieldDefaultColor = SK_ColorBLACK;
-const SkColor kTextfieldDefaultBackground = SK_ColorWHITE;
-const SkColor kTextfieldSelectionColor = SK_ColorWHITE;
-const SkColor kTextfieldSelectionBackgroundFocused =
- SkColorSetRGB(0x1D, 0x90, 0xFF);
-const SkColor kTextfieldSelectionBackgroundUnfocused = SK_ColorLTGRAY;
-
-SkColor WinColorToSkColor(COLORREF color) {
- return SkColorSetRGB(GetRValue(color), GetGValue(color), GetBValue(color));
-}
-
-void SetCheckerboardShader(SkPaint* paint, const RECT& align_rect) {
- // Create a 2x2 checkerboard pattern using the 3D face and highlight colors.
- SkColor face = skia::COLORREFToSkColor(GetSysColor(COLOR_3DFACE));
- SkColor highlight = skia::COLORREFToSkColor(GetSysColor(COLOR_3DHILIGHT));
- SkColor buffer[] = { face, highlight, highlight, face };
- // Confusing bit: we first create a temporary bitmap with our desired pattern,
- // then copy it to another bitmap. The temporary bitmap doesn't take
- // ownership of the pixel data, and so will point to garbage when this
- // function returns. The copy will copy the pixel data into a place owned by
- // the bitmap, which is in turn owned by the shader, etc., so it will live
- // until we're done using it.
- SkBitmap temp_bitmap;
- temp_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
- temp_bitmap.setPixels(buffer);
- SkBitmap bitmap;
- temp_bitmap.copyTo(&bitmap, temp_bitmap.config());
- SkShader* shader = SkShader::CreateBitmapShader(bitmap,
- SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode);
-
- // Align the pattern with the upper corner of |align_rect|.
- SkMatrix matrix;
- matrix.setTranslate(SkIntToScalar(align_rect.left),
- SkIntToScalar(align_rect.top));
- shader->setLocalMatrix(matrix);
- SkSafeUnref(paint->setShader(shader));
-}
-
-// <-a->
-// [ ***** ]
-// ____ | |
-// <-a-> <------b----->
-// a: object_width
-// b: frame_width
-// *: animating object
-//
-// - the animation goes from "[" to "]" repeatedly.
-// - the animation offset is at first "|"
-//
-int ComputeAnimationProgress(int frame_width,
- int object_width,
- int pixels_per_second,
- double animated_seconds) {
- int animation_width = frame_width + object_width;
- double interval = static_cast<double>(animation_width) / pixels_per_second;
- double ratio = fmod(animated_seconds, interval) / interval;
- return static_cast<int>(animation_width * ratio) - object_width;
-}
-
-RECT InsetRect(const RECT* rect, int size) {
- gfx::Rect result(*rect);
- result.Inset(size, size);
- return result.ToRECT();
-}
-
-} // namespace
-
-namespace ui {
-
-bool NativeThemeWin::IsThemingActive() const {
- if (is_theme_active_)
- return !!is_theme_active_();
- return false;
-}
-
-HRESULT NativeThemeWin::GetThemeColor(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- SkColor* color) const {
- HANDLE handle = GetThemeHandle(theme);
- if (handle && get_theme_color_) {
- COLORREF color_ref;
- if (get_theme_color_(handle, part_id, state_id, prop_id, &color_ref) ==
- S_OK) {
- *color = skia::COLORREFToSkColor(color_ref);
- return S_OK;
- }
- }
- return E_NOTIMPL;
-}
-
-SkColor NativeThemeWin::GetThemeColorWithDefault(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- int default_sys_color) const {
- SkColor color;
- if (GetThemeColor(theme, part_id, state_id, prop_id, &color) != S_OK)
- color = skia::COLORREFToSkColor(GetSysColor(default_sys_color));
- return color;
-}
-
-gfx::Size NativeThemeWin::GetThemeBorderSize(ThemeName theme) const {
- // For simplicity use the wildcard state==0, part==0, since it works
- // for the cases we currently depend on.
- int border;
- if (GetThemeInt(theme, 0, 0, TMT_BORDERSIZE, &border) == S_OK)
- return gfx::Size(border, border);
- else
- return gfx::Size(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
-}
-
-void NativeThemeWin::DisableTheming() const {
- if (!set_theme_properties_)
- return;
- set_theme_properties_(0);
-}
-
-void NativeThemeWin::CloseHandles() const {
- if (!close_theme_)
- return;
-
- for (int i = 0; i < LAST; ++i) {
- if (theme_handles_[i]) {
- close_theme_(theme_handles_[i]);
- theme_handles_[i] = NULL;
- }
- }
-}
-
-bool NativeThemeWin::IsClassicTheme(ThemeName name) const {
- if (!theme_dll_)
- return true;
-
- return !GetThemeHandle(name);
-}
-
-// static
-const NativeTheme* NativeTheme::instance() {
- return NativeThemeWin::instance();
-}
-
-// static
-const NativeThemeWin* NativeThemeWin::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeWin, s_native_theme, ());
- return &s_native_theme;
-}
-
-NativeThemeWin::NativeThemeWin()
- : theme_dll_(LoadLibrary(L"uxtheme.dll")),
- draw_theme_(NULL),
- draw_theme_ex_(NULL),
- get_theme_color_(NULL),
- get_theme_content_rect_(NULL),
- get_theme_part_size_(NULL),
- open_theme_(NULL),
- close_theme_(NULL),
- set_theme_properties_(NULL),
- is_theme_active_(NULL),
- get_theme_int_(NULL) {
- if (theme_dll_) {
- draw_theme_ = reinterpret_cast<DrawThemeBackgroundPtr>(
- GetProcAddress(theme_dll_, "DrawThemeBackground"));
- draw_theme_ex_ = reinterpret_cast<DrawThemeBackgroundExPtr>(
- GetProcAddress(theme_dll_, "DrawThemeBackgroundEx"));
- get_theme_color_ = reinterpret_cast<GetThemeColorPtr>(
- GetProcAddress(theme_dll_, "GetThemeColor"));
- get_theme_content_rect_ = reinterpret_cast<GetThemeContentRectPtr>(
- GetProcAddress(theme_dll_, "GetThemeBackgroundContentRect"));
- get_theme_part_size_ = reinterpret_cast<GetThemePartSizePtr>(
- GetProcAddress(theme_dll_, "GetThemePartSize"));
- open_theme_ = reinterpret_cast<OpenThemeDataPtr>(
- GetProcAddress(theme_dll_, "OpenThemeData"));
- close_theme_ = reinterpret_cast<CloseThemeDataPtr>(
- GetProcAddress(theme_dll_, "CloseThemeData"));
- set_theme_properties_ = reinterpret_cast<SetThemeAppPropertiesPtr>(
- GetProcAddress(theme_dll_, "SetThemeAppProperties"));
- is_theme_active_ = reinterpret_cast<IsThemeActivePtr>(
- GetProcAddress(theme_dll_, "IsThemeActive"));
- get_theme_int_ = reinterpret_cast<GetThemeIntPtr>(
- GetProcAddress(theme_dll_, "GetThemeInt"));
- }
- memset(theme_handles_, 0, sizeof(theme_handles_));
-}
-
-NativeThemeWin::~NativeThemeWin() {
- if (theme_dll_) {
- // todo (cpu): fix this soon. Making a call to CloseHandles() here breaks
- // certain tests and the reliability bots.
- // CloseHandles();
- FreeLibrary(theme_dll_);
- }
-}
-
-gfx::Size NativeThemeWin::GetPartSize(Part part,
- State state,
- const ExtraParams& extra) const {
- SIZE size;
- int part_id = GetWindowsPart(part, state, extra);
- int state_id = GetWindowsState(part, state, extra);
-
- HDC hdc = GetDC(NULL);
- HRESULT hr = GetThemePartSize(GetThemeName(part), hdc, part_id, state_id,
- NULL, TS_TRUE, &size);
- ReleaseDC(NULL, hdc);
-
- if (FAILED(hr)) {
- // TODO(rogerta): For now, we need to support radio buttons and checkboxes
- // when theming is not enabled. Support for other parts can be added
- // if/when needed.
- switch (part) {
- case kCheckbox:
- case kRadio:
- // TODO(rogerta): I was not able to find any API to get the default
- // size of these controls, so determined these values empirically.
- size.cx = 13;
- size.cy = 13;
- break;
- default:
- size.cx = 0;
- size.cy = 0;
- break;
- }
- }
-
- return gfx::Size(size.cx, size.cy);
-}
-
-void NativeThemeWin::Paint(SkCanvas* canvas,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ExtraParams& extra) const {
- if (!skia::SupportsPlatformPaint(canvas)) {
- // This block will only get hit with --enable-accelerated-drawing flag.
- PaintToNonPlatformCanvas(canvas, part, state, rect, extra);
- return;
- }
-
- skia::ScopedPlatformPaint scoped_platform_paint(canvas);
- HDC hdc = scoped_platform_paint.GetPlatformSurface();
-
- switch (part) {
- case kCheckbox:
- PaintCheckbox(hdc, part, state, rect, extra.button);
- break;
- case kRadio:
- PaintRadioButton(hdc, part, state, rect, extra.button);
- break;
- case kPushButton:
- PaintPushButton(hdc, part, state, rect, extra.button);
- break;
- case kMenuPopupArrow:
- PaintMenuArrow(hdc, state, rect, extra.menu_arrow);
- break;
- case kMenuPopupGutter:
- PaintMenuGutter(hdc, rect);
- break;
- case kMenuPopupSeparator:
- PaintMenuSeparator(hdc, rect, extra.menu_separator);
- break;
- case kMenuPopupBackground:
- PaintMenuBackground(hdc, rect);
- break;
- case kMenuCheck:
- PaintMenuCheck(hdc, state, rect, extra.menu_check);
- break;
- case kMenuCheckBackground:
- PaintMenuCheckBackground(hdc, state, rect);
- break;
- case kMenuItemBackground:
- PaintMenuItemBackground(hdc, state, rect, extra.menu_item);
- break;
- case kMenuList:
- PaintMenuList(hdc, state, rect, extra.menu_list);
- break;
- case kScrollbarDownArrow:
- case kScrollbarUpArrow:
- case kScrollbarLeftArrow:
- case kScrollbarRightArrow:
- PaintScrollbarArrow(hdc, part, state, rect, extra.scrollbar_arrow);
- break;
- case kScrollbarHorizontalTrack:
- case kScrollbarVerticalTrack:
- PaintScrollbarTrack(canvas, hdc, part, state, rect,
- extra.scrollbar_track);
- break;
- case kScrollbarHorizontalThumb:
- case kScrollbarVerticalThumb:
- case kScrollbarHorizontalGripper:
- case kScrollbarVerticalGripper:
- PaintScrollbarThumb(hdc, part, state, rect, extra.scrollbar_thumb);
- break;
- case kInnerSpinButton:
- PaintSpinButton(hdc, part, state, rect, extra.inner_spin);
- break;
- case kTrackbarThumb:
- case kTrackbarTrack:
- PaintTrackbar(canvas, hdc, part, state, rect, extra.trackbar);
- break;
- case kProgressBar:
- PaintProgressBar(hdc, rect, extra.progress_bar);
- break;
- case kWindowResizeGripper:
- PaintWindowResizeGripper(hdc, rect);
- break;
- case kTabPanelBackground:
- PaintTabPanelBackground(hdc, rect);
- break;
- case kTextField:
- PaintTextField(hdc, part, state, rect, extra.text_field);
- break;
-
- case kSliderTrack:
- case kSliderThumb:
- default:
- // While transitioning NativeThemeWin to the single Paint() entry point,
- // unsupported parts will DCHECK here.
- NOTREACHED();
- }
-}
-
-SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
- switch (color_id) {
-
- // Dialogs
- case kColorId_DialogBackground:
- // TODO(benrg): Should this use the new Windows theme functions? The old
- // code in DialogClientView::OnPaint used GetSysColor(COLOR_3DFACE).
- return WinColorToSkColor(GetSysColor(COLOR_3DFACE));
-
- // TextButton
- case kColorId_TextButtonBackgroundColor:
- return kTextButtonBackgroundColor;
- case kColorId_TextButtonEnabledColor:
- return kTextButtonEnabledColor;
- case kColorId_TextButtonDisabledColor:
- return kTextButtonDisabledColor;
- case kColorId_TextButtonHighlightColor:
- return kTextButtonHighlightColor;
- case kColorId_TextButtonHoverColor:
- return kTextButtonHoverColor;
-
- // MenuItem
- case kColorId_EnabledMenuItemForegroundColor:
- return kEnabledMenuItemForegroundColor;
- case kColorId_DisabledMenuItemForegroundColor:
- return kDisabledMenuItemForegroundColor;
- case kColorId_FocusedMenuItemBackgroundColor:
- return kFocusedMenuItemBackgroundColor;
- case kColorId_MenuSeparatorColor:
- return kMenuSeparatorColor;
-
- // Label
- case kColorId_LabelEnabledColor:
- return kLabelEnabledColor;
- case kColorId_LabelDisabledColor:
- return kLabelDisabledColor;
- case kColorId_LabelBackgroundColor:
- return kLabelBackgroundColor;
-
- // Textfield
- case kColorId_TextfieldDefaultColor:
- return kTextfieldDefaultColor;
- case kColorId_TextfieldDefaultBackground:
- return kTextfieldDefaultBackground;
- case kColorId_TextfieldSelectionColor:
- return kTextfieldSelectionColor;
- case kColorId_TextfieldSelectionBackgroundFocused:
- return kTextfieldSelectionBackgroundFocused;
- case kColorId_TextfieldSelectionBackgroundUnfocused:
- return kTextfieldSelectionBackgroundUnfocused;
-
- default:
- NOTREACHED() << "Invalid color_id: " << color_id;
- break;
- }
- return kInvalidColorIdColor;
-}
-
-void NativeThemeWin::PaintToNonPlatformCanvas(SkCanvas* canvas,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ExtraParams& extra) const {
- // TODO(asvitkine): This path is pretty inefficient - for each paint operation
- // it creates a new offscreen bitmap Skia canvas. This can
- // be sped up by doing it only once per part/state and
- // keeping a cache of the resulting bitmaps.
-
- // Create an offscreen canvas that is backed by an HDC.
- scoped_ptr<SkCanvas> offscreen_canvas(
- skia::CreateBitmapCanvas(rect.width(), rect.height(), false));
- DCHECK(offscreen_canvas.get());
- DCHECK(skia::SupportsPlatformPaint(offscreen_canvas.get()));
-
- // Some of the Windows theme drawing operations do not write correct alpha
- // values for fully-opaque pixels; instead the pixels get alpha 0. This is
- // especially a problem on Windows XP or when using the Classic theme.
- //
- // To work-around this, mark all pixels with a placeholder value, to detect
- // which pixels get touched by the paint operation. After paint, set any
- // pixels that have alpha 0 to opaque and placeholders to fully-transparent.
- const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0);
- offscreen_canvas->clear(placeholder);
-
- // Offset destination rects to have origin (0,0).
- gfx::Rect adjusted_rect(rect.size());
- ExtraParams adjusted_extra(extra);
- switch (part) {
- case kProgressBar:
- adjusted_extra.progress_bar.value_rect_x = 0;
- adjusted_extra.progress_bar.value_rect_y = 0;
- break;
- case kScrollbarHorizontalTrack:
- case kScrollbarVerticalTrack:
- adjusted_extra.scrollbar_track.track_x = 0;
- adjusted_extra.scrollbar_track.track_y = 0;
- break;
- default: break;
- }
- // Draw the theme controls using existing HDC-drawing code.
- Paint(offscreen_canvas.get(), part, state, adjusted_rect, adjusted_extra);
-
- // Copy the pixels to a bitmap that has ref-counted pixel storage, which is
- // necessary to have when drawing to a SkPicture.
- const SkBitmap& hdc_bitmap =
- offscreen_canvas->getDevice()->accessBitmap(false);
- SkBitmap bitmap;
- hdc_bitmap.copyTo(&bitmap, SkBitmap::kARGB_8888_Config);
-
- // Post-process the pixels to fix up the alpha values (see big comment above).
- const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder);
- const int pixel_count = rect.width() * rect.height();
- SkPMColor* pixels = bitmap.getAddr32(0, 0);
- for (int i = 0; i < pixel_count; i++) {
- if (pixels[i] == placeholder_value) {
- // Pixel wasn't touched - make it fully transparent.
- pixels[i] = SkPackARGB32(0, 0, 0, 0);
- } else if (SkGetPackedA32(pixels[i]) == 0) {
- // Pixel was touched but has incorrect alpha of 0, make it fully opaque.
- pixels[i] = SkPackARGB32(0xFF,
- SkGetPackedR32(pixels[i]),
- SkGetPackedG32(pixels[i]),
- SkGetPackedB32(pixels[i]));
- }
- }
-
- // Draw the offscreen bitmap to the destination canvas.
- canvas->drawBitmap(bitmap, rect.x(), rect.y());
-}
-
-HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name,
- HDC hdc,
- int part_id,
- int state_id,
- RECT* rect,
- int ts,
- SIZE* size) const {
- HANDLE handle = GetThemeHandle(theme_name);
- if (handle && get_theme_part_size_)
- return get_theme_part_size_(handle, hdc, part_id, state_id, rect, ts, size);
-
- return E_NOTIMPL;
-}
-
-HRESULT NativeThemeWin::PaintButton(HDC hdc,
- State state,
- const ButtonExtraParams& extra,
- int part_id,
- int state_id,
- RECT* rect) const {
- HANDLE handle = GetThemeHandle(BUTTON);
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, rect, NULL);
-
- // Adjust classic_state based on part, state, and extras.
- int classic_state = extra.classic_state;
- switch (part_id) {
- case BP_CHECKBOX:
- classic_state |= DFCS_BUTTONCHECK;
- break;
- case BP_RADIOBUTTON:
- classic_state |= DFCS_BUTTONRADIO;
- break;
- case BP_PUSHBUTTON:
- classic_state |= DFCS_BUTTONPUSH;
- break;
- default:
- NOTREACHED() << "Unknown part_id: " << part_id;
- break;
- }
-
- switch (state) {
- case kDisabled:
- classic_state |= DFCS_INACTIVE;
- break;
- case kPressed:
- classic_state |= DFCS_PUSHED;
- break;
- case kNormal:
- case kHovered:
- break;
- default:
- NOTREACHED() << "Unknown state: " << state;
- break;
- }
-
- if (extra.checked)
- classic_state |= DFCS_CHECKED;
-
- // Draw it manually.
- // All pressed states have both low bits set, and no other states do.
- const bool focused = ((state_id & ETS_FOCUSED) == ETS_FOCUSED);
- const bool pressed = ((state_id & PBS_PRESSED) == PBS_PRESSED);
- if ((BP_PUSHBUTTON == part_id) && (pressed || focused)) {
- // BP_PUSHBUTTON has a focus rect drawn around the outer edge, and the
- // button itself is shrunk by 1 pixel.
- HBRUSH brush = GetSysColorBrush(COLOR_3DDKSHADOW);
- if (brush) {
- FrameRect(hdc, rect, brush);
- InflateRect(rect, -1, -1);
- }
- }
- DrawFrameControl(hdc, rect, DFC_BUTTON, classic_state);
-
- // Draw the focus rectangle (the dotted line box) only on buttons. For radio
- // and checkboxes, we let webkit draw the focus rectangle (orange glow).
- if ((BP_PUSHBUTTON == part_id) && focused) {
- // The focus rect is inside the button. The exact number of pixels depends
- // on whether we're in classic mode or using uxtheme.
- if (handle && get_theme_content_rect_) {
- get_theme_content_rect_(handle, hdc, part_id, state_id, rect, rect);
- } else {
- InflateRect(rect, -GetSystemMetrics(SM_CXEDGE),
- -GetSystemMetrics(SM_CYEDGE));
- }
- DrawFocusRect(hdc, rect);
- }
-
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintMenuSeparator(
- HDC hdc,
- const gfx::Rect& rect,
- const MenuSeparatorExtraParams& extra) const {
- RECT rect_win = rect.ToRECT();
- if (!extra.has_gutter)
- rect_win.top = rect.y() + rect.height() / 3 + 1;
-
- HANDLE handle = GetThemeHandle(MENU);
- if (handle && draw_theme_) {
- // Delta is needed for non-classic to move separator up slightly.
- --rect_win.top;
- --rect_win.bottom;
- return draw_theme_(handle, hdc, MENU_POPUPSEPARATOR, MPI_NORMAL, &rect_win,
- NULL);
- }
-
- DrawEdge(hdc, &rect_win, EDGE_ETCHED, BF_TOP);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintMenuGutter(HDC hdc,
- const gfx::Rect& rect) const {
- RECT rect_win = rect.ToRECT();
- HANDLE handle = GetThemeHandle(MENU);
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPGUTTER, MPI_NORMAL, &rect_win,
- NULL);
- return E_NOTIMPL;
-}
-
-HRESULT NativeThemeWin::PaintMenuArrow(HDC hdc,
- State state,
- const gfx::Rect& rect,
- const MenuArrowExtraParams& extra)
- const {
- int state_id = MSM_NORMAL;
- if (state == kDisabled)
- state_id = MSM_DISABLED;
-
- HANDLE handle = GetThemeHandle(MENU);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- if (extra.pointing_right) {
- return draw_theme_(handle, hdc, MENU_POPUPSUBMENU, state_id, &rect_win,
- NULL);
- } else {
- // There is no way to tell the uxtheme API to draw a left pointing arrow;
- // it doesn't have a flag equivalent to DFCS_MENUARROWRIGHT. But they
- // are needed for RTL locales on Vista. So use a memory DC and mirror
- // the region with GDI's StretchBlt.
- gfx::Rect r(rect);
- base::win::ScopedCreateDC mem_dc(CreateCompatibleDC(hdc));
- base::win::ScopedBitmap mem_bitmap(CreateCompatibleBitmap(hdc, r.width(),
- r.height()));
- base::win::ScopedSelectObject select_bitmap(mem_dc, mem_bitmap);
- // Copy and horizontally mirror the background from hdc into mem_dc. Use
- // a negative-width source rect, starting at the rightmost pixel.
- StretchBlt(mem_dc, 0, 0, r.width(), r.height(),
- hdc, r.right()-1, r.y(), -r.width(), r.height(), SRCCOPY);
- // Draw the arrow.
- RECT theme_rect = {0, 0, r.width(), r.height()};
- HRESULT result = draw_theme_(handle, mem_dc, MENU_POPUPSUBMENU,
- state_id, &theme_rect, NULL);
- // Copy and mirror the result back into mem_dc.
- StretchBlt(hdc, r.x(), r.y(), r.width(), r.height(),
- mem_dc, r.width()-1, 0, -r.width(), r.height(), SRCCOPY);
- return result;
- }
- }
-
- // For some reason, Windows uses the name DFCS_MENUARROWRIGHT to indicate a
- // left pointing arrow. This makes the following 'if' statement slightly
- // counterintuitive.
- UINT pfc_state;
- if (extra.pointing_right)
- pfc_state = DFCS_MENUARROW;
- else
- pfc_state = DFCS_MENUARROWRIGHT;
- return PaintFrameControl(hdc, rect, DFC_MENU, pfc_state, extra.is_selected,
- state);
-}
-
-HRESULT NativeThemeWin::PaintMenuBackground(HDC hdc,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(MENU);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- HRESULT result = draw_theme_(handle, hdc, MENU_POPUPBACKGROUND, 0,
- &rect_win, NULL);
- FrameRect(hdc, &rect_win, GetSysColorBrush(COLOR_3DSHADOW));
- return result;
- }
-
- FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_MENU));
- DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintMenuCheck(
- HDC hdc,
- State state,
- const gfx::Rect& rect,
- const MenuCheckExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(MENU);
- int state_id;
- if (extra.is_radio) {
- state_id = state == kDisabled ? MC_BULLETDISABLED : MC_BULLETNORMAL;
- } else {
- state_id = state == kDisabled ? MC_CHECKMARKDISABLED : MC_CHECKMARKNORMAL;
- }
-
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPCHECK, state_id, &rect_win, NULL);
-
- return PaintFrameControl(hdc, rect, DFC_MENU,
- extra.is_radio ? DFCS_MENUBULLET : DFCS_MENUCHECK,
- extra.is_selected, state);
-}
-
-HRESULT NativeThemeWin::PaintMenuCheckBackground(HDC hdc,
- State state,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(MENU);
- int state_id = state == kDisabled ? MCB_DISABLED : MCB_NORMAL;
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPCHECKBACKGROUND, state_id,
- &rect_win, NULL);
- // Nothing to do for background.
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintMenuItemBackground(
- HDC hdc,
- State state,
- const gfx::Rect& rect,
- const MenuItemExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(MENU);
- RECT rect_win = rect.ToRECT();
- int state_id;
- switch (state) {
- case kNormal:
- state_id = MPI_NORMAL;
- break;
- case kDisabled:
- state_id = extra.is_selected ? MPI_DISABLEDHOT : MPI_DISABLED;
- break;
- case kHovered:
- state_id = MPI_HOT;
- break;
- default:
- NOTREACHED() << "Invalid state " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPITEM, state_id, &rect_win, NULL);
-
- if (extra.is_selected)
- FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_HIGHLIGHT));
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintPushButton(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = PBS_DISABLED;
- break;
- case kHovered:
- state_id = PBS_HOT;
- break;
- case kNormal:
- state_id = extra.is_default ? PBS_DEFAULTED : PBS_NORMAL;
- break;
- case kPressed:
- state_id = PBS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_PUSHBUTTON, state_id, &rect_win);
-}
-
-HRESULT NativeThemeWin::PaintRadioButton(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = extra.checked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
- break;
- case kHovered:
- state_id = extra.checked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
- break;
- case kNormal:
- state_id = extra.checked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
- break;
- case kPressed:
- state_id = extra.checked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_RADIOBUTTON, state_id, &rect_win);
-}
-
-HRESULT NativeThemeWin::PaintCheckbox(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = extra.checked ? CBS_CHECKEDDISABLED :
- extra.indeterminate ? CBS_MIXEDDISABLED :
- CBS_UNCHECKEDDISABLED;
- break;
- case kHovered:
- state_id = extra.checked ? CBS_CHECKEDHOT :
- extra.indeterminate ? CBS_MIXEDHOT :
- CBS_UNCHECKEDHOT;
- break;
- case kNormal:
- state_id = extra.checked ? CBS_CHECKEDNORMAL :
- extra.indeterminate ? CBS_MIXEDNORMAL :
- CBS_UNCHECKEDNORMAL;
- break;
- case kPressed:
- state_id = extra.checked ? CBS_CHECKEDPRESSED :
- extra.indeterminate ? CBS_MIXEDPRESSED :
- CBS_UNCHECKEDPRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_CHECKBOX, state_id, &rect_win);
-}
-
-HRESULT NativeThemeWin::PaintMenuList(HDC hdc,
- State state,
- const gfx::Rect& rect,
- const MenuListExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(MENULIST);
- RECT rect_win = rect.ToRECT();
- int state_id;
- switch (state) {
- case kNormal:
- state_id = CBXS_NORMAL;
- break;
- case kDisabled:
- state_id = CBXS_DISABLED;
- break;
- case kHovered:
- state_id = CBXS_HOT;
- break;
- case kPressed:
- state_id = CBXS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, CP_DROPDOWNBUTTON, state_id, &rect_win,
- NULL);
-
- // Draw it manually.
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL,
- DFCS_SCROLLCOMBOBOX | extra.classic_state);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintScrollbarArrow(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarArrowExtraParams& extra) const {
- static const int state_id_matrix[4][kMaxState] = {
- ABS_DOWNDISABLED, ABS_DOWNHOT, ABS_DOWNNORMAL, ABS_DOWNPRESSED,
- ABS_LEFTDISABLED, ABS_LEFTHOT, ABS_LEFTNORMAL, ABS_LEFTPRESSED,
- ABS_RIGHTDISABLED, ABS_RIGHTHOT, ABS_RIGHTNORMAL, ABS_RIGHTPRESSED,
- ABS_UPDISABLED, ABS_UPHOT, ABS_UPNORMAL, ABS_UPPRESSED
- };
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- int index = part - kScrollbarDownArrow;
- DCHECK(index >=0 && index < 4);
- int state_id = state_id_matrix[index][state];
-
- // Hovering means that the cursor is over the scroolbar, but not over the
- // specific arrow itself. We don't want to show it "hot" mode, but only
- // in "hover" mode.
- if (state == kHovered && extra.is_hovering) {
- switch (part) {
- case kScrollbarDownArrow:
- state_id = ABS_DOWNHOVER;
- break;
- case kScrollbarLeftArrow:
- state_id = ABS_LEFTHOVER;
- break;
- case kScrollbarRightArrow:
- state_id = ABS_RIGHTHOVER;
- break;
- case kScrollbarUpArrow:
- state_id = ABS_UPHOVER;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- }
-
- return draw_theme_(handle, hdc, SBP_ARROWBTN, state_id, &rect_win, NULL);
- }
-
- int classic_state = DFCS_SCROLLDOWN;
- switch (part) {
- case kScrollbarDownArrow:
- classic_state = DFCS_SCROLLDOWN;
- break;
- case kScrollbarLeftArrow:
- classic_state = DFCS_SCROLLLEFT;
- break;
- case kScrollbarRightArrow:
- classic_state = DFCS_SCROLLRIGHT;
- break;
- case kScrollbarUpArrow:
- classic_state = DFCS_SCROLLUP;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- switch (state) {
- case kDisabled:
- classic_state |= DFCS_INACTIVE;
- break;
- case kHovered:
- classic_state |= DFCS_HOT;
- break;
- case kNormal:
- break;
- case kPressed:
- classic_state |= DFCS_PUSHED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, classic_state);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintScrollbarThumb(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarThumbExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- int part_id;
- int state_id;
-
- switch (part) {
- case NativeTheme::kScrollbarHorizontalThumb:
- part_id = SBP_THUMBBTNHORZ;
- break;
- case NativeTheme::kScrollbarVerticalThumb:
- part_id = SBP_THUMBBTNVERT;
- break;
- case NativeTheme::kScrollbarHorizontalGripper:
- part_id = SBP_GRIPPERHORZ;
- break;
- case NativeTheme::kScrollbarVerticalGripper:
- part_id = SBP_GRIPPERVERT;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
-
- switch (state) {
- case kDisabled:
- state_id = SCRBS_DISABLED;
- break;
- case kHovered:
- state_id = extra.is_hovering ? SCRBS_HOVER : SCRBS_HOT;
- break;
- case kNormal:
- state_id = SCRBS_NORMAL;
- break;
- case kPressed:
- state_id = SCRBS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
-
- // Draw it manually.
- if ((part_id == SBP_THUMBBTNHORZ) || (part_id == SBP_THUMBBTNVERT))
- DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT | BF_MIDDLE);
- // Classic mode doesn't have a gripper.
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintScrollbarTrack(
- SkCanvas* canvas,
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarTrackExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- int part_id;
- int state_id;
-
- switch (part) {
- case NativeTheme::kScrollbarHorizontalTrack:
- part_id = extra.is_upper ? SBP_UPPERTRACKHORZ : SBP_LOWERTRACKHORZ;
- break;
- case NativeTheme::kScrollbarVerticalTrack:
- part_id = extra.is_upper ? SBP_UPPERTRACKVERT : SBP_LOWERTRACKVERT;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
-
- switch (state) {
- case kDisabled:
- state_id = SCRBS_DISABLED;
- break;
- case kHovered:
- state_id = SCRBS_HOVER;
- break;
- case kNormal:
- state_id = SCRBS_NORMAL;
- break;
- case kPressed:
- state_id = SCRBS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
-
- // Draw it manually.
- const DWORD colorScrollbar = GetSysColor(COLOR_SCROLLBAR);
- const DWORD color3DFace = GetSysColor(COLOR_3DFACE);
- if ((colorScrollbar != color3DFace) &&
- (colorScrollbar != GetSysColor(COLOR_WINDOW))) {
- FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_SCROLLBAR + 1));
- } else {
- SkPaint paint;
- RECT align_rect = gfx::Rect(extra.track_x, extra.track_y, extra.track_width,
- extra.track_height).ToRECT();
- SetCheckerboardShader(&paint, align_rect);
- canvas->drawIRect(skia::RECTToSkIRect(rect_win), paint);
- }
- if (extra.classic_state & DFCS_PUSHED)
- InvertRect(hdc, &rect_win);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintSpinButton(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const InnerSpinButtonExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SPIN);
- RECT rect_win = rect.ToRECT();
- int part_id = extra.spin_up ? SPNP_UP : SPNP_DOWN;
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = extra.spin_up ? UPS_DISABLED : DNS_DISABLED;
- break;
- case kHovered:
- state_id = extra.spin_up ? UPS_HOT : DNS_HOT;
- break;
- case kNormal:
- state_id = extra.spin_up ? UPS_NORMAL : DNS_NORMAL;
- break;
- case kPressed:
- state_id = extra.spin_up ? UPS_PRESSED : DNS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, extra.classic_state);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintTrackbar(
- SkCanvas* canvas,
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const TrackbarExtraParams& extra) const {
- int part_id = part == kTrackbarTrack ? TKP_TRACK : TKP_THUMBBOTTOM;
- if (extra.vertical)
- part_id = part == kTrackbarTrack ? TKP_TRACKVERT : TKP_THUMBVERT;
-
- int state_id = 0;
- switch (state) {
- case kDisabled:
- state_id = TUS_DISABLED;
- break;
- case kHovered:
- state_id = TUS_HOT;
- break;
- case kNormal:
- state_id = TUS_NORMAL;
- break;
- case kPressed:
- state_id = TUS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state " << state;
- break;
- }
-
- // Make the channel be 4 px thick in the center of the supplied rect. (4 px
- // matches what XP does in various menus; GetThemePartSize() doesn't seem to
- // return good values here.)
- RECT rect_win = rect.ToRECT();
- RECT channel_rect = rect.ToRECT();
- const int channel_thickness = 4;
- if (part_id == TKP_TRACK) {
- channel_rect.top +=
- ((channel_rect.bottom - channel_rect.top - channel_thickness) / 2);
- channel_rect.bottom = channel_rect.top + channel_thickness;
- } else if (part_id == TKP_TRACKVERT) {
- channel_rect.left +=
- ((channel_rect.right - channel_rect.left - channel_thickness) / 2);
- channel_rect.right = channel_rect.left + channel_thickness;
- } // else this isn't actually a channel, so |channel_rect| == |rect|.
-
- HANDLE handle = GetThemeHandle(TRACKBAR);
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &channel_rect, NULL);
-
- // Classic mode, draw it manually.
- if ((part_id == TKP_TRACK) || (part_id == TKP_TRACKVERT)) {
- DrawEdge(hdc, &channel_rect, EDGE_SUNKEN, BF_RECT);
- } else if (part_id == TKP_THUMBVERT) {
- DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE);
- } else {
- // Split rect into top and bottom pieces.
- RECT top_section = rect.ToRECT();
- RECT bottom_section = rect.ToRECT();
- top_section.bottom -= ((bottom_section.right - bottom_section.left) / 2);
- bottom_section.top = top_section.bottom;
- DrawEdge(hdc, &top_section, EDGE_RAISED,
- BF_LEFT | BF_TOP | BF_RIGHT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
-
- // Split triangular piece into two diagonals.
- RECT& left_half = bottom_section;
- RECT right_half = bottom_section;
- right_half.left += ((bottom_section.right - bottom_section.left) / 2);
- left_half.right = right_half.left;
- DrawEdge(hdc, &left_half, EDGE_RAISED,
- BF_DIAGONAL_ENDTOPLEFT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
- DrawEdge(hdc, &right_half, EDGE_RAISED,
- BF_DIAGONAL_ENDBOTTOMLEFT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
-
- // If the button is pressed, draw hatching.
- if (extra.classic_state & DFCS_PUSHED) {
- SkPaint paint;
- SetCheckerboardShader(&paint, rect_win);
-
- // Fill all three pieces with the pattern.
- canvas->drawIRect(skia::RECTToSkIRect(top_section), paint);
-
- SkScalar left_triangle_top = SkIntToScalar(left_half.top);
- SkScalar left_triangle_right = SkIntToScalar(left_half.right);
- SkPath left_triangle;
- left_triangle.moveTo(SkIntToScalar(left_half.left), left_triangle_top);
- left_triangle.lineTo(left_triangle_right, left_triangle_top);
- left_triangle.lineTo(left_triangle_right,
- SkIntToScalar(left_half.bottom));
- left_triangle.close();
- canvas->drawPath(left_triangle, paint);
-
- SkScalar right_triangle_left = SkIntToScalar(right_half.left);
- SkScalar right_triangle_top = SkIntToScalar(right_half.top);
- SkPath right_triangle;
- right_triangle.moveTo(right_triangle_left, right_triangle_top);
- right_triangle.lineTo(SkIntToScalar(right_half.right),
- right_triangle_top);
- right_triangle.lineTo(right_triangle_left,
- SkIntToScalar(right_half.bottom));
- right_triangle.close();
- canvas->drawPath(right_triangle, paint);
- }
- }
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintProgressBar(
- HDC hdc,
- const gfx::Rect& rect,
- const ProgressBarExtraParams& extra) const {
- // There is no documentation about the animation speed, frame-rate, nor
- // size of moving overlay of the indeterminate progress bar.
- // So we just observed real-world programs and guessed following parameters.
- const int kDeteminateOverlayPixelsPerSecond = 300;
- const int kDeteminateOverlayWidth = 120;
- const int kIndeterminateOverlayPixelsPerSecond = 175;
- const int kVistaIndeterminateOverlayWidth = 120;
- const int kXPIndeterminateOverlayWidth = 55;
- // The thickness of the bar frame inside |value_rect|
- const int kXPBarPadding = 3;
-
- RECT bar_rect = rect.ToRECT();
- RECT value_rect = gfx::Rect(extra.value_rect_x,
- extra.value_rect_y,
- extra.value_rect_width,
- extra.value_rect_height).ToRECT();
-
- bool pre_vista = base::win::GetVersion() < base::win::VERSION_VISTA;
- HANDLE handle = GetThemeHandle(PROGRESS);
- if (handle && draw_theme_ && draw_theme_ex_) {
- draw_theme_(handle, hdc, PP_BAR, 0, &bar_rect, NULL);
-
- int bar_width = bar_rect.right - bar_rect.left;
- if (extra.determinate) {
- // TODO(morrita): this RTL guess can be wrong.
- // We should pass the direction from WebKit side.
- bool is_rtl = (bar_rect.right == value_rect.right &&
- bar_rect.left != value_rect.left);
- // We should care the direction here because PP_CNUNK painting
- // is asymmetric.
- DTBGOPTS value_draw_options;
- value_draw_options.dwSize = sizeof(DTBGOPTS);
- value_draw_options.dwFlags = is_rtl ? DTBG_MIRRORDC : 0;
- value_draw_options.rcClip = bar_rect;
-
- if (pre_vista) {
- // On XP, progress bar is chunk-style and has no glossy effect.
- // We need to shrink destination rect to fit the part inside the bar
- // with an appropriate margin.
- RECT shrunk_value_rect = InsetRect(&value_rect, kXPBarPadding);
- draw_theme_ex_(handle, hdc, PP_CHUNK, 0,
- &shrunk_value_rect, &value_draw_options);
- } else {
- // On Vista or later, the progress bar part has a
- // single-block value part. It also has glossy effect.
- // And the value part has exactly same height as the bar part
- // so we don't need to shrink the rect.
- draw_theme_ex_(handle, hdc, PP_FILL, 0,
- &value_rect, &value_draw_options);
-
- int dx = ComputeAnimationProgress(bar_width,
- kDeteminateOverlayWidth,
- kDeteminateOverlayPixelsPerSecond,
- extra.animated_seconds);
- RECT overlay_rect = value_rect;
- overlay_rect.left += dx;
- overlay_rect.right = overlay_rect.left + kDeteminateOverlayWidth;
- draw_theme_(handle, hdc, PP_MOVEOVERLAY, 0, &overlay_rect, &value_rect);
- }
- } else {
- // A glossy overlay for indeterminate progress bar has small pause
- // after each animation. We emulate this by adding an invisible margin
- // the animation has to traverse.
- int width_with_margin = bar_width + kIndeterminateOverlayPixelsPerSecond;
- int overlay_width = pre_vista ?
- kXPIndeterminateOverlayWidth : kVistaIndeterminateOverlayWidth;
- int dx = ComputeAnimationProgress(width_with_margin,
- overlay_width,
- kIndeterminateOverlayPixelsPerSecond,
- extra.animated_seconds);
- RECT overlay_rect = bar_rect;
- overlay_rect.left += dx;
- overlay_rect.right = overlay_rect.left + overlay_width;
- if (pre_vista) {
- RECT shrunk_rect = InsetRect(&overlay_rect, kXPBarPadding);
- RECT shrunk_bar_rect = InsetRect(&bar_rect, kXPBarPadding);
- draw_theme_(handle, hdc, PP_CHUNK, 0, &shrunk_rect, &shrunk_bar_rect);
- } else {
- draw_theme_(handle, hdc, PP_MOVEOVERLAY, 0, &overlay_rect, &bar_rect);
- }
- }
-
- return S_OK;
- }
-
- HBRUSH bg_brush = GetSysColorBrush(COLOR_BTNFACE);
- HBRUSH fg_brush = GetSysColorBrush(COLOR_BTNSHADOW);
- FillRect(hdc, &bar_rect, bg_brush);
- FillRect(hdc, &value_rect, fg_brush);
- DrawEdge(hdc, &bar_rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintWindowResizeGripper(HDC hdc,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(STATUS);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- // Paint the status bar gripper. There doesn't seem to be a
- // standard gripper in Windows for the space between
- // scrollbars. This is pretty close, but it's supposed to be
- // painted over a status bar.
- return draw_theme_(handle, hdc, SP_GRIPPER, 0, &rect_win, NULL);
- }
-
- // Draw a windows classic scrollbar gripper.
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintTabPanelBackground(HDC hdc,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(TAB);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, TABP_BODY, 0, &rect_win, NULL);
-
- // Classic just renders a flat color background.
- FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1));
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintTextField(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const TextFieldExtraParams& extra) const {
- int part_id = EP_EDITTEXT;
- int state_id = ETS_NORMAL;
- switch (state) {
- case kNormal:
- if (extra.is_read_only) {
- state_id = ETS_READONLY;
- } else if (extra.is_focused) {
- state_id = ETS_FOCUSED;
- } else {
- state_id = ETS_NORMAL;
- }
- break;
- case kHovered:
- state_id = ETS_HOT;
- break;
- case kPressed:
- state_id = ETS_SELECTED;
- break;
- case kDisabled:
- state_id = ETS_DISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- RECT rect_win = rect.ToRECT();
- return PaintTextField(hdc, part_id, state_id, extra.classic_state,
- &rect_win,
- skia::SkColorToCOLORREF(extra.background_color),
- extra.fill_content_area, extra.draw_edges);
-}
-
-HRESULT NativeThemeWin::PaintTextField(HDC hdc,
- int part_id,
- int state_id,
- int classic_state,
- RECT* rect,
- COLORREF color,
- bool fill_content_area,
- bool draw_edges) const {
- // TODO(ojan): http://b/1210017 Figure out how to give the ability to
- // exclude individual edges from being drawn.
-
- HANDLE handle = GetThemeHandle(TEXTFIELD);
- // TODO(mpcomplete): can we detect if the color is specified by the user,
- // and if not, just use the system color?
- // CreateSolidBrush() accepts a RGB value but alpha must be 0.
- HBRUSH bg_brush = CreateSolidBrush(color);
- HRESULT hr;
- // DrawThemeBackgroundEx was introduced in XP SP2, so that it's possible
- // draw_theme_ex_ is NULL and draw_theme_ is non-null.
- if (handle && (draw_theme_ex_ || (draw_theme_ && draw_edges))) {
- if (draw_theme_ex_) {
- static const DTBGOPTS omit_border_options = {
- sizeof(DTBGOPTS),
- DTBG_OMITBORDER,
- { 0, 0, 0, 0 }
- };
- const DTBGOPTS* draw_opts = draw_edges ? NULL : &omit_border_options;
- hr = draw_theme_ex_(handle, hdc, part_id, state_id, rect, draw_opts);
- } else {
- hr = draw_theme_(handle, hdc, part_id, state_id, rect, NULL);
- }
-
- // TODO(maruel): Need to be fixed if get_theme_content_rect_ is NULL.
- if (fill_content_area && get_theme_content_rect_) {
- RECT content_rect;
- hr = get_theme_content_rect_(handle, hdc, part_id, state_id, rect,
- &content_rect);
- FillRect(hdc, &content_rect, bg_brush);
- }
- } else {
- // Draw it manually.
- if (draw_edges)
- DrawEdge(hdc, rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
-
- if (fill_content_area) {
- FillRect(hdc, rect, (classic_state & DFCS_INACTIVE) ?
- reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1) : bg_brush);
- }
- hr = S_OK;
- }
- DeleteObject(bg_brush);
- return hr;
-}
-
-// static
-NativeThemeWin::ThemeName NativeThemeWin::GetThemeName(Part part) {
- ThemeName name;
- switch (part) {
- case kCheckbox:
- case kRadio:
- case kPushButton:
- name = BUTTON;
- break;
- case kInnerSpinButton:
- name = SPIN;
- break;
- case kMenuCheck:
- case kMenuPopupGutter:
- case kMenuList:
- case kMenuPopupArrow:
- case kMenuPopupSeparator:
- name = MENU;
- break;
- case kProgressBar:
- name = PROGRESS;
- break;
- case kScrollbarDownArrow:
- case kScrollbarLeftArrow:
- case kScrollbarRightArrow:
- case kScrollbarUpArrow:
- case kScrollbarHorizontalThumb:
- case kScrollbarVerticalThumb:
- case kScrollbarHorizontalTrack:
- case kScrollbarVerticalTrack:
- name = SCROLLBAR;
- break;
- case kSliderTrack:
- case kSliderThumb:
- name = TRACKBAR;
- break;
- case kTextField:
- name = TEXTFIELD;
- break;
- case kWindowResizeGripper:
- name = STATUS;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- return name;
-}
-
-// static
-int NativeThemeWin::GetWindowsPart(Part part,
- State state,
- const ExtraParams& extra) {
- int part_id;
- switch (part) {
- case kCheckbox:
- part_id = BP_CHECKBOX;
- break;
- case kMenuCheck:
- part_id = MENU_POPUPCHECK;
- break;
- case kMenuPopupArrow:
- part_id = MENU_POPUPSUBMENU;
- break;
- case kMenuPopupGutter:
- part_id = MENU_POPUPGUTTER;
- break;
- case kMenuPopupSeparator:
- part_id = MENU_POPUPSEPARATOR;
- break;
- case kPushButton:
- part_id = BP_PUSHBUTTON;
- break;
- case kRadio:
- part_id = BP_RADIOBUTTON;
- break;
- case kWindowResizeGripper:
- part_id = SP_GRIPPER;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- return part_id;
-}
-
-int NativeThemeWin::GetWindowsState(Part part,
- State state,
- const ExtraParams& extra) {
- int state_id;
- switch (part) {
- case kCheckbox:
- switch (state) {
- case kNormal:
- state_id = CBS_UNCHECKEDNORMAL;
- break;
- case kHovered:
- state_id = CBS_UNCHECKEDHOT;
- break;
- case kPressed:
- state_id = CBS_UNCHECKEDPRESSED;
- break;
- case kDisabled:
- state_id = CBS_UNCHECKEDDISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- case kMenuCheck:
- switch (state) {
- case kNormal:
- case kHovered:
- case kPressed:
- state_id = extra.menu_check.is_radio ? MC_BULLETNORMAL
- : MC_CHECKMARKNORMAL;
- break;
- case kDisabled:
- state_id = extra.menu_check.is_radio ? MC_BULLETDISABLED
- : MC_CHECKMARKDISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- case kMenuPopupArrow:
- case kMenuPopupGutter:
- case kMenuPopupSeparator:
- switch (state) {
- case kNormal:
- state_id = MBI_NORMAL;
- break;
- case kHovered:
- state_id = MBI_HOT;
- break;
- case kPressed:
- state_id = MBI_PUSHED;
- break;
- case kDisabled:
- state_id = MBI_DISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- case kPushButton:
- switch (state) {
- case kNormal:
- state_id = PBS_NORMAL;
- break;
- case kHovered:
- state_id = PBS_HOT;
- break;
- case kPressed:
- state_id = PBS_PRESSED;
- break;
- case kDisabled:
- state_id = PBS_DISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- case kRadio:
- switch (state) {
- case kNormal:
- state_id = RBS_UNCHECKEDNORMAL;
- break;
- case kHovered:
- state_id = RBS_UNCHECKEDHOT;
- break;
- case kPressed:
- state_id = RBS_UNCHECKEDPRESSED;
- break;
- case kDisabled:
- state_id = RBS_UNCHECKEDDISABLED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- case kWindowResizeGripper:
- switch (state) {
- case kNormal:
- case kHovered:
- case kPressed:
- case kDisabled:
- state_id = 1; // gripper has no windows state
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- return state_id;
-}
-
-HRESULT NativeThemeWin::GetThemeInt(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- int *value) const {
- HANDLE handle = GetThemeHandle(theme);
- if (handle && get_theme_int_)
- return get_theme_int_(handle, part_id, state_id, prop_id, value);
- return E_NOTIMPL;
-}
-
-HRESULT NativeThemeWin::PaintFrameControl(HDC hdc,
- const gfx::Rect& rect,
- UINT type,
- UINT state,
- bool is_selected,
- State control_state) const {
- const int width = rect.width();
- const int height = rect.height();
-
- // DrawFrameControl for menu arrow/check wants a monochrome bitmap.
- base::win::ScopedBitmap mask_bitmap(CreateBitmap(width, height, 1, 1, NULL));
-
- if (mask_bitmap == NULL)
- return E_OUTOFMEMORY;
-
- base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(NULL));
- base::win::ScopedSelectObject select_bitmap(bitmap_dc, mask_bitmap);
- RECT local_rect = { 0, 0, width, height };
- DrawFrameControl(bitmap_dc, &local_rect, type, state);
-
- // We're going to use BitBlt with a b&w mask. This results in using the dest
- // dc's text color for the black bits in the mask, and the dest dc's
- // background color for the white bits in the mask. DrawFrameControl draws the
- // check in black, and the background in white.
- int bg_color_key;
- int text_color_key;
- switch (control_state) {
- case NativeTheme::kHovered:
- bg_color_key = COLOR_HIGHLIGHT;
- text_color_key = COLOR_HIGHLIGHTTEXT;
- break;
- case NativeTheme::kNormal:
- bg_color_key = COLOR_MENU;
- text_color_key = COLOR_MENUTEXT;
- break;
- case NativeTheme::kDisabled:
- bg_color_key = is_selected ? COLOR_HIGHLIGHT : COLOR_MENU;
- text_color_key = COLOR_GRAYTEXT;
- break;
- default:
- NOTREACHED();
- bg_color_key = COLOR_MENU;
- text_color_key = COLOR_MENUTEXT;
- break;
- }
- COLORREF old_bg_color = SetBkColor(hdc, GetSysColor(bg_color_key));
- COLORREF old_text_color = SetTextColor(hdc, GetSysColor(text_color_key));
- BitBlt(hdc, rect.x(), rect.y(), width, height, bitmap_dc, 0, 0, SRCCOPY);
- SetBkColor(hdc, old_bg_color);
- SetTextColor(hdc, old_text_color);
-
- return S_OK;
-}
-
-HANDLE NativeThemeWin::GetThemeHandle(ThemeName theme_name) const {
- if (!open_theme_ || theme_name < 0 || theme_name >= LAST)
- return 0;
-
- if (theme_handles_[theme_name])
- return theme_handles_[theme_name];
-
- // Not found, try to load it.
- HANDLE handle = 0;
- switch (theme_name) {
- case BUTTON:
- handle = open_theme_(NULL, L"Button");
- break;
- case LIST:
- handle = open_theme_(NULL, L"Listview");
- break;
- case MENU:
- handle = open_theme_(NULL, L"Menu");
- break;
- case MENULIST:
- handle = open_theme_(NULL, L"Combobox");
- break;
- case SCROLLBAR:
- handle = open_theme_(NULL, L"Scrollbar");
- break;
- case STATUS:
- handle = open_theme_(NULL, L"Status");
- break;
- case TAB:
- handle = open_theme_(NULL, L"Tab");
- break;
- case TEXTFIELD:
- handle = open_theme_(NULL, L"Edit");
- break;
- case TRACKBAR:
- handle = open_theme_(NULL, L"Trackbar");
- break;
- case WINDOW:
- handle = open_theme_(NULL, L"Window");
- break;
- case PROGRESS:
- handle = open_theme_(NULL, L"Progress");
- break;
- case SPIN:
- handle = open_theme_(NULL, L"Spin");
- break;
- default:
- NOTREACHED();
- }
- theme_handles_[theme_name] = handle;
- return handle;
-}
-
-} // namespace ui
« no previous file with comments | « ui/base/native_theme/native_theme_win.h ('k') | ui/base/native_theme/native_theme_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698