1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef nsNativeThemeWin_h
8 #define nsNativeThemeWin_h
9 
10 #include "nsITheme.h"
11 #include "nsCOMPtr.h"
12 #include "nsAtom.h"
13 #include "nsNativeTheme.h"
14 #include "nsThemeConstants.h"
15 #include "nsUXThemeConstants.h"
16 #include "nsUXThemeData.h"
17 #include "gfxTypes.h"
18 #include <windows.h>
19 #include "mozilla/Maybe.h"
20 #include "mozilla/TimeStamp.h"
21 #include "nsSize.h"
22 
23 class nsNativeThemeWin : private nsNativeTheme, public nsITheme {
24   virtual ~nsNativeThemeWin();
25 
26  public:
27   typedef mozilla::TimeStamp TimeStamp;
28   typedef mozilla::TimeDuration TimeDuration;
29 
30   NS_DECL_ISUPPORTS_INHERITED
31 
32   // The nsITheme interface.
33   NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
34                                   uint8_t aWidgetType, const nsRect& aRect,
35                                   const nsRect& aDirtyRect) override;
36 
37   NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
38                              uint8_t aWidgetType,
39                              nsIntMargin* aResult) override;
40 
41   virtual bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame* aFrame,
42                                 uint8_t aWidgetType,
43                                 nsIntMargin* aResult) override;
44 
45   virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame,
46                                  uint8_t aWidgetType,
47                                  nsRect* aOverflowRect) override;
48 
49   NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame,
50                                   uint8_t aWidgetType,
51                                   mozilla::LayoutDeviceIntSize* aResult,
52                                   bool* aIsOverridable) override;
53 
54   virtual Transparency GetWidgetTransparency(nsIFrame* aFrame,
55                                              uint8_t aWidgetType) override;
56 
57   NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
58                                 nsAtom* aAttribute, bool* aShouldRepaint,
59                                 const nsAttrValue* aOldValue) override;
60 
61   NS_IMETHOD ThemeChanged() override;
62 
63   bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
64                            uint8_t aWidgetType) override;
65 
66   bool WidgetIsContainer(uint8_t aWidgetType) override;
67 
68   bool ThemeDrawsFocusForWidget(uint8_t aWidgetType) override;
69 
70   bool ThemeNeedsComboboxDropmarker() override;
71 
72   virtual bool WidgetAppearanceDependsOnWindowFocus(
73       uint8_t aWidgetType) override;
74 
75   enum { eThemeGeometryTypeWindowButtons = eThemeGeometryTypeUnknown + 1 };
76   virtual ThemeGeometryType ThemeGeometryTypeForWidget(
77       nsIFrame* aFrame, uint8_t aWidgetType) override;
78 
79   virtual bool ShouldHideScrollbars() override;
80 
81   nsNativeThemeWin();
82 
83  protected:
84   mozilla::Maybe<nsUXThemeClass> GetThemeClass(uint8_t aWidgetType);
85   HANDLE GetTheme(uint8_t aWidgetType);
86   nsresult GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
87                                 int32_t& aPart, int32_t& aState);
88   nsresult ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
89                                        int32_t& aPart, int32_t& aState,
90                                        bool& aFocused);
91   nsresult ClassicDrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
92                                        uint8_t aWidgetType, const nsRect& aRect,
93                                        const nsRect& aClipRect);
94   nsresult ClassicGetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
95                                   uint8_t aWidgetType, nsIntMargin* aResult);
96   bool ClassicGetWidgetPadding(nsDeviceContext* aContext, nsIFrame* aFrame,
97                                uint8_t aWidgetType, nsIntMargin* aResult);
98   nsresult ClassicGetMinimumWidgetSize(nsIFrame* aFrame, uint8_t aWidgetType,
99                                        mozilla::LayoutDeviceIntSize* aResult,
100                                        bool* aIsOverridable);
101   bool ClassicThemeSupportsWidget(nsIFrame* aFrame, uint8_t aWidgetType);
102   void DrawCheckedRect(HDC hdc, const RECT& rc, int32_t fore, int32_t back,
103                        HBRUSH defaultBack);
104   uint32_t GetWidgetNativeDrawingFlags(uint8_t aWidgetType);
105   int32_t StandardGetState(nsIFrame* aFrame, uint8_t aWidgetType,
106                            bool wantFocused);
107   bool IsMenuActive(nsIFrame* aFrame, uint8_t aWidgetType);
108   RECT CalculateProgressOverlayRect(nsIFrame* aFrame, RECT* aWidgetRect,
109                                     bool aIsVertical, bool aIsIndeterminate,
110                                     bool aIsClassic);
111   void DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType, HANDLE aTheme,
112                                HDC aHdc, int aPart, int aState,
113                                RECT* aWidgetRect, RECT* aClipRect);
114 
115   nsresult GetCachedWidgetBorder(nsIFrame* aFrame, HANDLE aTheme,
116                                  nsUXThemeClass aThemeClass,
117                                  uint8_t aWidgetType, int32_t aPart,
118                                  int32_t aState, nsIntMargin* aResult);
119 
120   nsresult GetCachedMinimumWidgetSize(nsIFrame* aFrame, HANDLE aTheme,
121                                       nsUXThemeClass aThemeClass,
122                                       uint8_t aWidgetType, int32_t aPart,
123                                       int32_t aState, THEMESIZE aSizeReq,
124                                       mozilla::LayoutDeviceIntSize* aResult);
125 
126   SIZE GetCachedGutterSize(HANDLE theme);
127 
128  private:
129   TimeStamp mProgressDeterminateTimeStamp;
130   TimeStamp mProgressIndeterminateTimeStamp;
131 
132   // eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT is about 800 at the time of
133   // writing this, and nsIntMargin is 16 bytes wide, which makes this cache (1/8
134   // + 16) * 800 bytes, or about ~12KB. We could probably reduce this cache to
135   // 3KB by caching on the aWidgetType value instead, but there would be some
136   // uncacheable values, since we derive some theme parts from other arguments.
137   uint8_t
138       mBorderCacheValid[(eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT + 7) /
139                         8];
140   nsIntMargin mBorderCache[eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT];
141 
142   // See the above not for mBorderCache and friends. However
143   // mozilla::LayoutDeviceIntSize is half the size of nsIntMargin, making the
144   // cache roughly half as large. In total the caches should come to about 18KB.
145   uint8_t mMinimumWidgetSizeCacheValid
146       [(eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT + 7) / 8];
147   mozilla::LayoutDeviceIntSize
148       mMinimumWidgetSizeCache[eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT];
149 
150   bool mGutterSizeCacheValid;
151   SIZE mGutterSizeCache;
152 };
153 
154 #endif
155