Bug 621762 - Change the way native windows are notified about toolbars. r=roc, a=betaN

This commit is contained in:
Markus Stange 2011-01-11 14:03:16 +01:00
parent bdd22ccfb0
commit e20afb330c
11 changed files with 113 additions and 141 deletions

View File

@ -102,24 +102,7 @@ public:
const nsRect& aDirtyRect) = 0;
/**
* Notifies the theme engine that a particular themed widget exists
* at the given rectangle within the window aWindow.
* For certain appearance values (currently only
* NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
* called during every paint to a window, for every themed widget of
* the right type within the
* window, except for themed widgets which are transformed or have
* effects applied to them (e.g. CSS opacity or filters).
* Note that a DrawWidgetBackground for the widget might not be called
* during the paint, since ThebesLayers can cache rendered content.
* This could sometimes be called during display list construction
* outside of painting.
* If called during painting, it will be called before we actually
* paint anything.
*
* @param aWidgetType the -moz-appearance value for the themed widget
* @param aRect the device-pixel rect within aWindow for the themed
* widget
* XXX Unused. This is only here because the interface is frozen for 2.0.
*/
virtual void RegisterWidgetGeometry(nsIWidget* aWindow,
PRUint8 aWidgetType,

View File

@ -261,6 +261,17 @@ nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
return;
}
// If we're finished building display list items for painting of the outermost
// pres shell, notify the widget about any toolbars we've encountered.
if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
nsIWidget* widget = aReferenceFrame->GetNearestWidget();
if (widget) {
nsIWidget_MOZILLA_2_0_BRANCH* widget2 =
static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget);
widget2->UpdateThemeGeometries(CurrentPresShellState()->mThemeGeometries);
}
}
// Unmark and pop off the frames marked for display in this pres shell.
PRUint32 firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
for (PRUint32 i = firstFrameForShell;
@ -715,19 +726,9 @@ void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
}
static void
RegisterThemeWidgetGeometry(nsIFrame* aFrame)
RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
nsITheme* theme = presContext->GetTheme();
if (!theme)
return;
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
nsIWidget* widget = displayRoot->GetNearestWidget();
// If the display root doesn't have a widget, just bail. Something
// weird is going on, maybe we're printing?
if (!widget)
return;
for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
// Bail out if we're in a transformed subtree
@ -739,9 +740,8 @@ RegisterThemeWidgetGeometry(nsIFrame* aFrame)
}
nsRect borderBox(aFrame->GetOffsetTo(displayRoot), aFrame->GetSize());
theme->RegisterWidgetGeometry(widget,
aFrame->GetStyleDisplay()->mAppearance,
borderBox.ToNearestPixels(presContext->AppUnitsPerDevPixel()));
aBuilder->RegisterThemeGeometry(aFrame->GetStyleDisplay()->mAppearance,
borderBox.ToNearestPixels(aFrame->PresContext()->AppUnitsPerDevPixel()));
}
nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
@ -753,11 +753,11 @@ nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency);
// Perform necessary RegisterWidgetGeometry
// Perform necessary RegisterThemeGeometry
if (mIsThemed &&
(disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
disp->mAppearance == NS_THEME_TOOLBAR)) {
RegisterThemeWidgetGeometry(aFrame);
RegisterThemeGeometry(aBuilder, aFrame);
}
}

View File

@ -127,6 +127,7 @@ class nsDisplayListBuilder {
public:
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
@ -371,7 +372,29 @@ public:
(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
GetIncludeAllOutOfFlows();
}
/**
* Notifies the builder that a particular themed widget exists
* at the given rectangle within the currently built display list.
* For certain appearance values (currently only
* NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
* called during every display list construction, for every themed widget of
* the right type within the display list, except for themed widgets which
* are transformed or have effects applied to them (e.g. CSS opacity or
* filters).
*
* @param aWidgetType the -moz-appearance value for the themed widget
* @param aRect the device-pixel rect relative to the widget's displayRoot
* for the themed widget
*/
void RegisterThemeGeometry(PRUint8 aWidgetType,
const nsIntRect& aRect) {
if (mIsPaintingToWindow) {
ThemeGeometry geometry(aWidgetType, aRect);
CurrentPresShellState()->mThemeGeometries.AppendElement(geometry);
}
}
/**
* Allocate memory in our arena. It will only be freed when this display list
* builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
@ -434,6 +457,7 @@ private:
nsIFrame* mCaretFrame;
PRUint32 mFirstFrameMarkedForDisplay;
PRPackedBool mIsBackgroundOnly;
nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
};
PresShellState* CurrentPresShellState() {
NS_ASSERTION(mPresShellStates.Length() > 0,

View File

@ -262,6 +262,19 @@ class nsIWidget : public nsISupports {
public:
typedef mozilla::layers::LayerManager LayerManager;
// Used in UpdateThemeGeometries.
struct ThemeGeometry {
// The -moz-appearance value for the themed widget
PRUint8 mWidgetType;
// The device-pixel rect within the window for the themed widget
nsIntRect mRect;
ThemeGeometry(PRUint8 aWidgetType, const nsIntRect& aRect)
: mWidgetType(aWidgetType)
, mRect(aRect)
{ }
};
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
nsIWidget()
@ -1407,6 +1420,20 @@ class nsIWidget_MOZILLA_2_0_BRANCH : public nsIWidget {
* @param aRect Current widget rect that is being drawn.
*/
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) = 0;
/**
* Called when Gecko knows which themed widgets exist in this window.
* The passed array contains an entry for every themed widget of the right
* type (currently only NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and
* NS_THEME_TOOLBAR) within the window, except for themed widgets which are
* transformed or have effects applied to them (e.g. CSS opacity or
* filters).
* This could sometimes be called during display list construction
* outside of painting.
* If called during painting, it will be called before we actually
* paint anything.
*/
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget_MOZILLA_2_0_BRANCH, NS_IWIDGET_MOZILLA_2_0_BRANCH_IID)

View File

@ -395,6 +395,8 @@ public:
virtual gfxASurface* GetThebesSurface();
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
NS_IMETHOD BeginSecureKeyboardInput();
NS_IMETHOD EndSecureKeyboardInput();

View File

@ -71,6 +71,7 @@
#include "nsIMenuRollup.h"
#include "nsIDOMSimpleGestureEvent.h"
#include "nsIPluginInstance.h"
#include "nsThemeConstants.h"
#include "nsDragService.h"
#include "nsClipboard.h"
@ -189,9 +190,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
+ (NSEvent*)makeNewCocoaEventWithType:(NSEventType)type fromEvent:(NSEvent*)theEvent;
- (float)beginMaybeResetUnifiedToolbar;
- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight;
- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
#if USE_CLICK_HOLD_CONTEXTMENU
@ -2086,6 +2084,27 @@ nsChildView::DrawOver(LayerManager* aManager, nsIntRect aRect)
}
}
void
nsChildView::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
{
NSWindow* win = [mView window];
if (!win || ![win isKindOfClass:[ToolbarWindow class]])
return;
float unifiedToolbarHeight = 0;
nsIntRect topPixelStrip(0, 0, [win frame].size.width, 1);
for (PRUint32 i = 0; i < aThemeGeometries.Length(); ++i) {
const ThemeGeometry& g = aThemeGeometries[i];
if ((g.mWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
g.mWidgetType == NS_THEME_TOOLBAR) &&
g.mRect.Contains(topPixelStrip)) {
unifiedToolbarHeight = g.mRect.YMost();
}
}
[(ToolbarWindow*)win setUnifiedToolbarHeight:unifiedToolbarHeight];
}
NS_IMETHODIMP
nsChildView::BeginSecureKeyboardInput()
{
@ -2598,27 +2617,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// Whenever we paint a toplevel window, we will be notified of any
// unified toolbar in the window via
// nsNativeThemeCocoa::RegisterWidgetGeometry.
- (float)beginMaybeResetUnifiedToolbar
{
if (![[self window] isKindOfClass:[ToolbarWindow class]] ||
[self superview] != [[self window] contentView])
return 0.0;
return [(ToolbarWindow*)[self window] beginMaybeResetUnifiedToolbar];
}
- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight
{
if (![[self window] isKindOfClass:[ToolbarWindow class]] ||
[self superview] != [[self window] contentView])
return;
[(ToolbarWindow*)[self window] endMaybeResetUnifiedToolbar:aOldHeight];
}
-(void)update
{
if (mGLContext) {
@ -2635,8 +2633,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
// gecko to paint it
- (void)drawRect:(NSRect)aRect
{
float oldHeight = [self beginMaybeResetUnifiedToolbar];
CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
[self drawRect:aRect inContext:cgContext];
@ -2645,8 +2641,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
if ([[self window] isKindOfClass:[BaseWindow class]]) {
[(BaseWindow*)[self window] deferredInvalidateShadow];
}
[self endMaybeResetUnifiedToolbar:oldHeight];
}
- (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext

View File

@ -183,15 +183,12 @@ struct UnifiedGradientInfo {
{
TitlebarAndBackgroundColor *mColor;
float mUnifiedToolbarHeight;
BOOL mInUnifiedToolbarReset;
NSColor *mBackgroundColor;
}
// Pass nil here to get the default appearance.
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
- (void)notifyToolbarAt:(float)aY height:(float)aHeight;
- (void)setUnifiedToolbarHeight:(float)aHeight;
- (float)unifiedToolbarHeight;
- (float)beginMaybeResetUnifiedToolbar;
- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight;
- (float)titlebarHeight;
- (NSRect)titlebarRect;
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;

View File

@ -2193,15 +2193,15 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
// Drawing the unified gradient in the titlebar and the toolbar works like this:
// 1) In the style sheet we set the toolbar's -moz-appearance to -moz-mac-unified-toolbar.
// 2) When the toolbar is visible and we paint the application chrome
// window in nsChildView::drawRect, Gecko calls
// nsNativeThemeCocoa::RegisterWidgetGeometry for the widget type
// window, the array that Gecko passes nsChildView::UpdateThemeGeometries
// will contain an entry for the widget type NS_THEME_TOOLBAR or
// NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR.
// 3) This finds the toolbar frame's ToolbarWindow and passes the toolbar
// frame's height to setUnifiedToolbarHeight.
// 4) If the toolbar height has changed, a titlebar redraw is triggered by
// [self display] and the upper part of the unified gradient is drawn in the
// titlebar.
// 5) DrawUnifiedToolbar draws the lower part of the unified gradient in the toolbar.
// 3) nsChildView::UpdateThemeGeometries finds the toolbar frame's ToolbarWindow
// and passes the toolbar frame's height to setUnifiedToolbarHeight.
// 4) If the toolbar height has changed, a titlebar redraw is triggered and the
// upper part of the unified gradient is drawn in the titlebar.
// 5) The lower part of the unified gradient in the toolbar is drawn during
// normal window content painting in nsNativeThemeCocoa::DrawUnifiedToolbar.
//
// Whenever the unified gradient is drawn in the titlebar or the toolbar, both
// titlebar height and toolbar height must be known in order to construct the
@ -2224,7 +2224,6 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
mBackgroundColor = [NSColor whiteColor];
mUnifiedToolbarHeight = 0.0f;
mInUnifiedToolbarReset = NO;
// setBottomCornerRounded: is a private API call, so we check to make sure
// we respond to it just in case.
@ -2268,20 +2267,6 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
return mBackgroundColor;
}
// This is called by nsNativeThemeCocoa.mm's RegisterWidgetGeometry.
// We need to know the toolbar's height in order to draw the correct
// unified gradient in the titlebar.
- (void)notifyToolbarAt:(float)aY height:(float)aHeight
{
// Ignore unexpected notifications about the toolbar height
if (!mInUnifiedToolbarReset)
return;
if (aY <= 0.0 && aY + aHeight > mUnifiedToolbarHeight) {
mUnifiedToolbarHeight = aY + aHeight;
}
}
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect
{
[self setTitlebarNeedsDisplayInRect:aRect sync:NO];
@ -2322,27 +2307,20 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
return frameRect.size.height - [self contentRectForFrameRect:frameRect].size.height;
}
- (float)beginMaybeResetUnifiedToolbar
- (void)setUnifiedToolbarHeight:(float)aHeight
{
mInUnifiedToolbarReset = YES;
float old = mUnifiedToolbarHeight;
mUnifiedToolbarHeight = 0.0;
return old;
}
if ([self drawsContentsIntoWindowFrame] || aHeight == mUnifiedToolbarHeight)
return;
- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight
{
if (mInUnifiedToolbarReset) {
mInUnifiedToolbarReset = NO;
if (mUnifiedToolbarHeight == aOldHeight)
return;
mUnifiedToolbarHeight = aHeight;
[self setContentBorderThickness:mUnifiedToolbarHeight forEdge:NSMaxYEdge];
// Update sheet positioning hint.
[self setContentBorderThickness:mUnifiedToolbarHeight forEdge:NSMaxYEdge];
// Since this function is only called inside painting, the repaint needs to
// be synchronous.
[self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:YES];
}
// Redraw the title bar. If we're inside painting, we'll do it right now,
// otherwise we'll just invalidate it.
BOOL needSyncRedraw = ([NSView focusView] != nil);
[self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw];
}
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState

View File

@ -67,9 +67,6 @@ public:
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect);
virtual void RegisterWidgetGeometry(nsIWidget* aWindow,
PRUint8 aWidgetType,
const nsIntRect& aRect);
NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,

View File

@ -1519,25 +1519,6 @@ nsNativeThemeCocoa::DrawResizer(CGContextRef cgContext, const HIRect& aRect,
NS_OBJC_END_TRY_ABORT_BLOCK;
}
static PRBool
IsWindowSpanningToolbar(nsIWidget* aWindow,
PRUint8 aWidgetType,
const nsIntRect& aRect,
ToolbarWindow** aCocoaWindow)
{
nsIWidget* topLevelWidget = aWindow->GetTopLevelWidget();
if (!topLevelWidget)
return PR_FALSE;
NSWindow* win = (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
if (!win || ![win isKindOfClass:[ToolbarWindow class]])
return PR_FALSE;
*aCocoaWindow = (ToolbarWindow*)win;
return (aWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
aWidgetType == NS_THEME_TOOLBAR) &&
aRect.x == 0 && aRect.width == [win frame].size.width;
}
NS_IMETHODIMP
nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
PRUint8 aWidgetType, const nsRect& aRect,
@ -1982,18 +1963,6 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void
nsNativeThemeCocoa::RegisterWidgetGeometry(nsIWidget* aWindow,
PRUint8 aWidgetType,
const nsIntRect& aRect)
{
ToolbarWindow* cocoaWindow;
if (IsWindowSpanningToolbar(aWindow, aWidgetType, aRect, &cocoaWindow) &&
![cocoaWindow drawsContentsIntoWindowFrame]) {
[cocoaWindow notifyToolbarAt:aRect.y height:aRect.height];
}
}
nsIntMargin
nsNativeThemeCocoa::RTLAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame)
{

View File

@ -119,6 +119,7 @@ public:
virtual LayerManager* GetLayerManager(LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
bool* aAllowRetaining = nsnull);
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) {}
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
virtual gfxASurface* GetThebesSurface();
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);