Bug 406730. Track window activation status and set an 'active' attribute on the XUL root so we can style window contents based on activation status. Also provide active+inactive colors to Cocoa chrome drawing and use them based on 'main' state. Patch by Markus Strange, r=josh,sr=roc,a=mconnor

This commit is contained in:
roc+@cs.cmu.edu 2008-05-02 04:32:50 -07:00
parent 511fa9f073
commit 38e56fa13d
11 changed files with 176 additions and 58 deletions

View File

@ -79,6 +79,7 @@ GK_ATOM(accesskey, "accesskey")
GK_ATOM(acronym, "acronym")
GK_ATOM(action, "action")
GK_ATOM(active, "active")
GK_ATOM(activetitlebarcolor, "activetitlebarcolor")
GK_ATOM(actuate, "actuate")
GK_ATOM(address, "address")
GK_ATOM(after, "after")
@ -405,6 +406,7 @@ GK_ATOM(img, "img")
GK_ATOM(implementation, "implementation")
GK_ATOM(implements, "implements")
GK_ATOM(import, "import")
GK_ATOM(inactivetitlebarcolor, "inactivetitlebarcolor")
GK_ATOM(include, "include")
GK_ATOM(includes, "includes")
GK_ATOM(increment, "increment")
@ -842,7 +844,6 @@ GK_ATOM(thead, "thead")
GK_ATOM(thumb, "thumb")
GK_ATOM(title, "title")
GK_ATOM(titlebar, "titlebar")
GK_ATOM(titlebarcolor, "titlebarcolor")
GK_ATOM(titletip, "titletip")
GK_ATOM(toggled, "toggled")
GK_ATOM(token, "token")

View File

@ -1143,9 +1143,10 @@ nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
HideWindowChrome(aValue && NS_LITERAL_STRING("true").Equals(*aValue));
}
// titlebarcolor is settable on any root node (windows, dialogs, etc)
// (in)activetitlebarcolor is settable on any root node (windows, dialogs, etc)
nsIDocument *document = GetCurrentDoc();
if (aName == nsGkAtoms::titlebarcolor &&
if ((aName == nsGkAtoms::activetitlebarcolor ||
aName == nsGkAtoms::inactivetitlebarcolor) &&
document && document->GetRootContent() == this) {
nscolor color = NS_RGBA(0, 0, 0, 0);
@ -1153,7 +1154,7 @@ nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
attrValue.ParseColor(*aValue, document);
attrValue.GetColorValue(color);
SetTitlebarColor(color);
SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor);
}
if (aName == nsGkAtoms::src && document) {
@ -1396,10 +1397,11 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
HideWindowChrome(PR_FALSE);
}
if (aName == nsGkAtoms::titlebarcolor &&
if ((aName == nsGkAtoms::activetitlebarcolor ||
aName == nsGkAtoms::inactivetitlebarcolor) &&
doc && doc->GetRootContent() == this) {
// Use 0, 0, 0, 0 as the "none" color.
SetTitlebarColor(NS_RGBA(0, 0, 0, 0));
SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
}
// If the accesskey attribute is removed, unregister it here
@ -2453,7 +2455,7 @@ nsXULElement::HideWindowChrome(PRBool aShouldHide)
}
void
nsXULElement::SetTitlebarColor(nscolor aColor)
nsXULElement::SetTitlebarColor(nscolor aColor, PRBool aActive)
{
nsIDocument* doc = GetCurrentDoc();
if (!doc || doc->GetRootContent() != this) {
@ -2468,7 +2470,7 @@ nsXULElement::SetTitlebarColor(nscolor aColor)
nsCOMPtr<nsIWidget> mainWidget;
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
if (mainWidget) {
mainWidget->SetWindowTitlebarColor(aColor);
mainWidget->SetWindowTitlebarColor(aColor, aActive);
}
}
}

View File

@ -726,7 +726,7 @@ protected:
nsresult HideWindowChrome(PRBool aShouldHide);
void SetTitlebarColor(nscolor aColor);
void SetTitlebarColor(nscolor aColor, PRBool aActive);
const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;

View File

@ -2223,11 +2223,11 @@ nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
nsGlobalWindow* outer = GetOuterWindowInternal();
// if the window is deactivated while in full screen mode,
// restore OS chrome, and hide it again upon re-activation
if (outer && outer->mFullScreen) {
if (aVisitor.mEvent->message == NS_DEACTIVATE ||
aVisitor.mEvent->message == NS_ACTIVATE) {
if (aVisitor.mEvent->message == NS_DEACTIVATE ||
aVisitor.mEvent->message == NS_ACTIVATE) {
// if the window is deactivated while in full screen mode,
// restore OS chrome, and hide it again upon re-activation
if (outer && outer->mFullScreen) {
nsCOMPtr<nsIFullScreen> fullScreen =
do_GetService("@mozilla.org/browser/fullscreen;1");
if (fullScreen) {
@ -2237,6 +2237,51 @@ nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
fullScreen->HideAllOSChrome();
}
}
// Set / unset the "active" attribute on the documentElement
// of the top level window
nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
NS_ENSURE_TRUE(mainWidget, nsnull);
// Get the top level widget (if the main widget is a sheet, this will
// be the sheet's top (non-sheet) parent).
nsCOMPtr<nsIWidget> topLevelWidget = mainWidget->GetSheetWindowParent();
if (!topLevelWidget)
topLevelWidget = mainWidget;
// Get the top level widget's nsGlobalWindow
nsCOMPtr<nsIDOMWindowInternal> topLevelWindow;
if (topLevelWidget == mainWidget) {
topLevelWindow = static_cast<nsIDOMWindowInternal *>(this);
} else {
// This is a workaround for the following problem:
// When a window with an open sheet loses focus, only the sheet window
// receives the NS_DEACTIVATE event. However, it's not the sheet that
// should lose the "active" attribute, but the containing top level window.
void* clientData;
topLevelWidget->GetClientData(clientData); // clientData is nsXULWindow
nsISupports* data = static_cast<nsISupports*>(clientData);
nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(data));
topLevelWindow = do_GetInterface(req);
}
if (topLevelWindow) {
// Only set the attribute if the document is a XUL document and the
// window is a chrome window
nsCOMPtr<nsIDOMDocument> domDoc;
topLevelWindow->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(topLevelWindow);
if (xulDoc && chromeWin) {
nsCOMPtr<nsIContent> rootElem = doc->GetRootContent();
if (aVisitor.mEvent->message == NS_ACTIVATE)
rootElem->SetAttr(kNameSpaceID_None, nsGkAtoms::active,
NS_LITERAL_STRING("true"), PR_TRUE);
else
rootElem->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, PR_TRUE);
}
}
}
if (aVisitor.mEvent->message == NS_RESIZE_EVENT) {

View File

@ -7,12 +7,12 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="unifiedWindow">
<content titlebarcolor="#C9C9C9"/>
<content activetitlebarcolor="#C9C9C9" inactivetitlebarcolor="#E4E4E4"/>
</binding>
<binding id="unifiedDialog"
extends="chrome://global/content/bindings/dialog.xml#dialog">
<content titlebarcolor="#C9C9C9">
<content activetitlebarcolor="#C9C9C9" inactivetitlebarcolor="#E4E4E4">
<xul:vbox class="box-inherit dialog-content-box" flex="1">
<children/>
</xul:vbox>
@ -32,7 +32,7 @@
<binding id="unifiedWizard"
extends="chrome://global/content/bindings/wizard.xml#wizard">
<content titlebarcolor="#C9C9C9">
<content activetitlebarcolor="#C9C9C9" inactivetitlebarcolor="#E4E4E4">
<xul:hbox class="wizard-header" anonid="Header"/>
<xul:deck class="wizard-page-box" flex="1" anonid="Deck">
<children includes="wizardpage"/>
@ -50,7 +50,8 @@
closebuttonaccesskey="&preferencesCloseButton.accesskey;"
role="dialog"
title="&preferencesDefaultTitleMac.title;"
titlebarcolor="#bbbbbb">
activetitlebarcolor="#BBBBBB"
inactivetitlebarcolor="#E4E4E4">
<xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
<xul:hbox flex="1" class="paneDeckContainer">

View File

@ -95,10 +95,10 @@ typedef nsEventStatus (*PR_CALLBACK EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_PLUGIN_PORT_CG 101
#endif
// a6593177-ba36-400e-8812-a0d36b3af17b
// 9151e8c9-a1cc-44e9-a70d-afb3956d4e13
#define NS_IWIDGET_IID \
{ 0xa6593177, 0xba36, 0x400e, \
{ 0x88, 0x12, 0xa0, 0xd3, 0x6b, 0x3a, 0xf1, 0x7b } }
{ 0x9151e8c9, 0xa1cc, 0x44e9, \
{ 0xa7, 0x0d, 0xaf, 0xb3, 0x95, 0x6d, 0x4e, 0x13 } }
// Hide the native window systems real window type so as to avoid
// including native window system types and APIs. This is necessary
@ -379,6 +379,16 @@ class nsIWidget : public nsISupports {
*/
virtual nsIWidget* GetParent(void) = 0;
/**
* Return the top (non-sheet) parent of this Widget if it's a sheet,
* or nsnull if this isn't a sheet (or some other error occurred).
* Sheets are only supported on some platforms (currently only OS X).
*
* @return the top (non-sheet) parent widget or nsnull
*
*/
virtual nsIWidget* GetSheetWindowParent(void) = 0;
/**
* Return the first child of this widget. Will return null if
* there are no children.
@ -1027,12 +1037,15 @@ class nsIWidget : public nsISupports {
* Ignored on any platform that does not support it. Ignored by widgets that
* do not represent windows.
*
* @param aColor The color to set the title bar background to. Alpha values
* other than fully transparent (0) are respected if possible
* on the platform. An alpha of 0 will cause the window to
* draw with the default style for the platform.
* @param aColor The color to set the title bar background to. Alpha values
* other than fully transparent (0) are respected if possible
* on the platform. An alpha of 0 will cause the window to
* draw with the default style for the platform.
*
* @param aActive Whether the color should be applied to active or inactive
* windows.
*/
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor) = 0;
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, PRBool aActive) = 0;
/**
* Get the Thebes surface associated with this widget.

View File

@ -121,19 +121,22 @@ typedef struct _nsCocoaWindowList {
// and for background of the window.
@interface TitlebarAndBackgroundColor : NSColor
{
NSColor *mTitlebarColor;
NSColor *mActiveTitlebarColor;
NSColor *mInactiveTitlebarColor;
NSColor *mBackgroundColor;
NSWindow *mWindow; // [WEAK] (we are owned by the window)
float mTitlebarHeight;
}
- (id)initWithTitlebarColor:(NSColor*)aTitlebarColor
andBackgroundColor:(NSColor*)aBackgroundColor
forWindow:(NSWindow*)aWindow;
- (id)initWithActiveTitlebarColor:(NSColor*)aActiveTitlebarColor
inactiveTitlebarColor:(NSColor*)aInactiveTitlebarColor
backgroundColor:(NSColor*)aBackgroundColor
forWindow:(NSWindow*)aWindow;
// Pass nil here to get the default appearance.
- (void)setTitlebarColor:(NSColor*)aColor;
- (NSColor*)titlebarColor;
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
- (NSColor*)activeTitlebarColor;
- (NSColor*)inactiveTitlebarColor;
- (void)setBackgroundColor:(NSColor*)aColor;
- (NSColor*)backgroundColor;
@ -147,8 +150,9 @@ typedef struct _nsCocoaWindowList {
{
TitlebarAndBackgroundColor *mColor;
}
- (void)setTitlebarColor:(NSColor*)aColor;
- (NSColor*)titlebarColor;
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
- (NSColor*)activeTitlebarColor;
- (NSColor*)inactiveTitlebarColor;
// This method is also available on NSWindows (via a category), and is the
// preferred way to check the background color of a window.
- (NSColor*)windowBackgroundColor;
@ -198,6 +202,7 @@ public:
nsNativeWidget aNativeWindow = nsnull);
NS_IMETHOD Show(PRBool aState);
virtual nsIWidget* GetSheetWindowParent(void);
NS_IMETHOD AddMouseListener(nsIMouseListener * aListener);
NS_IMETHOD AddEventListener(nsIEventListener * aListener);
NS_IMETHOD Enable(PRBool aState);
@ -242,7 +247,7 @@ public:
NS_IMETHOD GetAttention(PRInt32 aCycleCount);
NS_IMETHOD GetHasTransparentBackground(PRBool& aTransparent);
NS_IMETHOD SetHasTransparentBackground(PRBool aTransparent);
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor);
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, PRBool aActive);
virtual gfxASurface* GetThebesSurface();

View File

@ -442,6 +442,17 @@ NS_IMETHODIMP nsCocoaWindow::Destroy()
}
nsIWidget* nsCocoaWindow::GetSheetWindowParent(void)
{
if (mWindowType != eWindowType_sheet)
return nsnull;
nsCocoaWindow *parent = static_cast<nsCocoaWindow*>(mParent);
while (parent && (parent->mWindowType == eWindowType_sheet))
parent = static_cast<nsCocoaWindow*>(parent->mParent);
return parent;
}
void* nsCocoaWindow::GetNativeData(PRUint32 aDataType)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
@ -1289,7 +1300,7 @@ NS_IMETHODIMP nsCocoaWindow::GetAttention(PRInt32 aCycleCount)
}
NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor)
NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, PRBool aActive)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
@ -1304,7 +1315,7 @@ NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor)
// If they pass a color with a complete transparent alpha component, use the
// native titlebar appearance.
if (NS_GET_A(aColor) == 0) {
[(ToolbarWindow*)mWindow setTitlebarColor:nil];
[(ToolbarWindow*)mWindow setTitlebarColor:nil forActiveWindow:(BOOL)aActive];
} else {
// Transform from sRGBA to monitor RGBA. This seems like it would make trying
// to match the system appearance lame, so probably we just shouldn't color
@ -1316,7 +1327,8 @@ NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor)
[(ToolbarWindow*)mWindow setTitlebarColor:[NSColor colorWithDeviceRed:NS_GET_R(aColor)/255.0
green:NS_GET_G(aColor)/255.0
blue:NS_GET_B(aColor)/255.0
alpha:NS_GET_A(aColor)/255.0]];
alpha:NS_GET_A(aColor)/255.0]
forActiveWindow:(BOOL)aActive];
}
return NS_OK;
@ -1638,9 +1650,10 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
aStyle = aStyle | NSTexturedBackgroundWindowMask;
if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) {
mColor = [[TitlebarAndBackgroundColor alloc] initWithTitlebarColor:nil
andBackgroundColor:[NSColor whiteColor]
forWindow:self];
mColor = [[TitlebarAndBackgroundColor alloc] initWithActiveTitlebarColor:nil
inactiveTitlebarColor:nil
backgroundColor:[NSColor whiteColor]
forWindow:self];
// Call the superclass's implementation, to avoid our guard method below.
[super setBackgroundColor:mColor];
@ -1692,21 +1705,31 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
// Pass nil here to get the default appearance.
- (void)setTitlebarColor:(NSColor*)aColor
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mColor setTitlebarColor:aColor];
[mColor setTitlebarColor:aColor forActiveWindow:aActive];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSColor*)titlebarColor
- (NSColor*)activeTitlebarColor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
return [mColor titlebarColor];
return [mColor activeTitlebarColor];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (NSColor*)inactiveTitlebarColor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
return [mColor inactiveTitlebarColor];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -1795,14 +1818,16 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
// the titlebar area.
@implementation TitlebarAndBackgroundColor
- (id)initWithTitlebarColor:(NSColor*)aTitlebarColor
andBackgroundColor:(NSColor*)aBackgroundColor
forWindow:(NSWindow*)aWindow
- (id)initWithActiveTitlebarColor:(NSColor*)aActiveTitlebarColor
inactiveTitlebarColor:(NSColor*)aInactiveTitlebarColor
backgroundColor:(NSColor*)aBackgroundColor
forWindow:(NSWindow*)aWindow
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ((self = [super init])) {
mTitlebarColor = [aTitlebarColor retain];
mActiveTitlebarColor = [aActiveTitlebarColor retain];
mInactiveTitlebarColor = [aInactiveTitlebarColor retain];
mBackgroundColor = [aBackgroundColor retain];
mWindow = aWindow; // weak ref to avoid a cycle
NSRect frameRect = [aWindow frame];
@ -1821,7 +1846,8 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mTitlebarColor release];
[mActiveTitlebarColor release];
[mInactiveTitlebarColor release];
[mBackgroundColor release];
[super dealloc];
@ -1871,10 +1897,10 @@ void patternDraw(void* aInfo, CGContextRef aContext)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
TitlebarAndBackgroundColor *color = (TitlebarAndBackgroundColor*)aInfo;
NSColor *titlebarColor = [color titlebarColor];
NSColor *backgroundColor = [color backgroundColor];
NSWindow *window = [color window];
BOOL isMain = [window isMainWindow];
NSColor *titlebarColor = isMain ? [color activeTitlebarColor] : [color inactiveTitlebarColor];
// Remember: this context is NOT flipped, so the origin is in the bottom left.
float titlebarHeight = [color titlebarHeight];
@ -1951,20 +1977,31 @@ void patternDraw(void* aInfo, CGContextRef aContext)
// Pass nil here to get the default appearance.
- (void)setTitlebarColor:(NSColor*)aColor
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mTitlebarColor autorelease];
mTitlebarColor = [aColor retain];
if (aActive) {
[mActiveTitlebarColor autorelease];
mActiveTitlebarColor = [aColor retain];
} else {
[mInactiveTitlebarColor autorelease];
mInactiveTitlebarColor = [aColor retain];
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSColor*)titlebarColor
- (NSColor*)activeTitlebarColor
{
return mTitlebarColor;
return mActiveTitlebarColor;
}
- (NSColor*)inactiveTitlebarColor
{
return mInactiveTitlebarColor;
}

View File

@ -291,6 +291,16 @@ nsIWidget* nsBaseWidget::GetParent(void)
return nsnull;
}
//-------------------------------------------------------------------------
//
// Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
//
//-------------------------------------------------------------------------
nsIWidget* nsBaseWidget::GetSheetWindowParent(void)
{
return nsnull;
}
//-------------------------------------------------------------------------
//
// Add a child to the list of children
@ -847,7 +857,7 @@ nsBaseWidget::EndSecureKeyboardInput()
}
NS_IMETHODIMP
nsBaseWidget::SetWindowTitlebarColor(nscolor aColor)
nsBaseWidget::SetWindowTitlebarColor(nscolor aColor, PRBool aActive)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -82,6 +82,7 @@ public:
NS_IMETHOD Destroy();
NS_IMETHOD SetParent(nsIWidget* aNewParent);
virtual nsIWidget* GetParent(void);
virtual nsIWidget* GetSheetWindowParent(void);
virtual void AddChild(nsIWidget* aChild);
virtual void RemoveChild(nsIWidget* aChild);
@ -131,7 +132,7 @@ public:
NS_IMETHOD SetIcon(const nsAString &anIconSpec);
NS_IMETHOD BeginSecureKeyboardInput();
NS_IMETHOD EndSecureKeyboardInput();
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor);
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, PRBool aActive);
virtual void ConvertToDeviceCoordinates(nscoord &aX,nscoord &aY) {}
virtual void FreeNativeData(void * data, PRUint32 aDataType) {}
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);

View File

@ -176,6 +176,9 @@ NS_IMETHODIMP nsXULWindow::GetInterface(const nsIID& aIID, void** aSink)
if (NS_FAILED(rv)) return rv;
return mAuthPrompter->QueryInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
return GetWindowDOMWindow(reinterpret_cast<nsIDOMWindowInternal**>(aSink));
}
if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) &&
NS_SUCCEEDED(EnsureContentTreeOwner()) &&
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))