Bug 303404. Crash when hitting escape in context menu for a menu item. r=dbaron, sr=neil
This commit is contained in:
Родитель
52277d9aec
Коммит
49f3d10eb4
|
@ -1,790 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsNativeThemeGTK.h"
|
||||
#include "nsThemeConstants.h"
|
||||
#include "nsDrawingSurfaceGTK.h"
|
||||
#include "nsDeviceContextGTK.h"
|
||||
#include "gtkdrawing.h"
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsILookAndFeel.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsTransform2D.h"
|
||||
#include "nsIMenuFrame.h"
|
||||
#include "nsIMenuParent.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#include <gdk/gdkprivate.h>
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsNativeThemeGTK, nsITheme, nsIObserver)
|
||||
|
||||
static int gLastXError;
|
||||
|
||||
nsNativeThemeGTK::nsNativeThemeGTK()
|
||||
{
|
||||
if (moz_gtk_init() != MOZ_GTK_SUCCESS) {
|
||||
memset(mDisabledWidgetTypes, 0xff, sizeof(mDisabledWidgetTypes));
|
||||
return;
|
||||
}
|
||||
|
||||
// We have to call moz_gtk_shutdown before the event loop stops running.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
obsServ->AddObserver(this, "quit-application", PR_FALSE);
|
||||
|
||||
mInputCheckedAtom = do_GetAtom("_moz-input-checked");
|
||||
mInputAtom = do_GetAtom("input");
|
||||
mCurPosAtom = do_GetAtom("curpos");
|
||||
mMaxPosAtom = do_GetAtom("maxpos");
|
||||
mMenuActiveAtom = do_GetAtom("_moz-menuactive");
|
||||
|
||||
memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
|
||||
memset(mSafeWidgetStates, 0, sizeof(mSafeWidgetStates));
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
// Look up the symbol for gtk_style_get_prop_experimental
|
||||
PRLibrary* gtkLibrary;
|
||||
PRFuncPtr stylePropFunc = PR_FindFunctionSymbolAndLibrary("gtk_style_get_prop_experimental", >kLibrary);
|
||||
if (stylePropFunc) {
|
||||
moz_gtk_enable_style_props((style_prop_t) stylePropFunc);
|
||||
PR_UnloadLibrary(gtkLibrary);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsNativeThemeGTK::~nsNativeThemeGTK() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
if (!nsCRT::strcmp(aTopic, "quit-application")) {
|
||||
moz_gtk_shutdown();
|
||||
} else {
|
||||
NS_NOTREACHED("unexpected topic");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeThemeGTK::RefreshWidgetWindow(nsIFrame* aFrame)
|
||||
{
|
||||
nsIPresShell *shell = GetPresShell(aFrame);
|
||||
if (!shell)
|
||||
return;
|
||||
|
||||
nsIViewManager* vm = shell->GetViewManager();
|
||||
if (!vm)
|
||||
return;
|
||||
|
||||
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
|
||||
static PRBool IsWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
|
||||
return aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7));
|
||||
}
|
||||
|
||||
static void SetWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
|
||||
aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7));
|
||||
}
|
||||
|
||||
static inline PRUint16
|
||||
GetWidgetStateKey(PRUint8 aWidgetType, GtkWidgetState *aWidgetState)
|
||||
{
|
||||
return (aWidgetState->active |
|
||||
aWidgetState->focused << 1 |
|
||||
aWidgetState->inHover << 2 |
|
||||
aWidgetState->disabled << 3 |
|
||||
aWidgetState->isDefault << 4 |
|
||||
aWidgetType << 5);
|
||||
}
|
||||
|
||||
static PRBool IsWidgetStateSafe(PRUint8* aSafeVector,
|
||||
PRUint8 aWidgetType,
|
||||
GtkWidgetState *aWidgetState)
|
||||
{
|
||||
PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
|
||||
return aSafeVector[key >> 3] & (1 << (key & 7));
|
||||
}
|
||||
|
||||
static void SetWidgetStateSafe(PRUint8 *aSafeVector,
|
||||
PRUint8 aWidgetType,
|
||||
GtkWidgetState *aWidgetState)
|
||||
{
|
||||
PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
|
||||
aSafeVector[key >> 3] |= (1 << (key & 7));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
|
||||
GtkThemeWidgetType& aGtkWidgetType,
|
||||
GtkWidgetState* aState,
|
||||
gint* aWidgetFlags)
|
||||
{
|
||||
if (aState) {
|
||||
if (!aFrame) {
|
||||
// reset the entire struct to zero
|
||||
memset(aState, 0, sizeof(GtkWidgetState));
|
||||
} else {
|
||||
|
||||
// for dropdown textfields, look at the parent frame (textbox or menulist)
|
||||
if (aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD)
|
||||
aFrame = aFrame->GetParent();
|
||||
|
||||
// For XUL checkboxes and radio buttons, the state of the parent
|
||||
// determines our state.
|
||||
if (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO ||
|
||||
aWidgetType == NS_THEME_CHECKBOX_LABEL ||
|
||||
aWidgetType == NS_THEME_RADIO_LABEL) {
|
||||
if (aWidgetFlags) {
|
||||
nsIAtom* atom = nsnull;
|
||||
|
||||
if (aFrame) {
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (content->IsContentOfType(nsIContent::eXUL)) {
|
||||
aFrame = aFrame->GetParent();
|
||||
if (aWidgetType == NS_THEME_CHECKBOX_LABEL ||
|
||||
aWidgetType == NS_THEME_RADIO_LABEL)
|
||||
aFrame = aFrame->GetParent();
|
||||
}
|
||||
else if (content->Tag() == mInputAtom)
|
||||
atom = mInputCheckedAtom;
|
||||
}
|
||||
|
||||
if (!atom)
|
||||
atom = (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_CHECKBOX_LABEL) ? mCheckedAtom : mSelectedAtom;
|
||||
*aWidgetFlags = CheckBooleanAttr(aFrame, atom);
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
|
||||
|
||||
aState->disabled = IsDisabled(aFrame);
|
||||
aState->active = (eventState & NS_EVENT_STATE_ACTIVE) == NS_EVENT_STATE_ACTIVE;
|
||||
aState->focused = (eventState & NS_EVENT_STATE_FOCUS) == NS_EVENT_STATE_FOCUS;
|
||||
aState->inHover = (eventState & NS_EVENT_STATE_HOVER) == NS_EVENT_STATE_HOVER;
|
||||
aState->isDefault = FALSE; // XXX fix me
|
||||
aState->canDefault = FALSE; // XXX fix me
|
||||
|
||||
// For these widget types, some element (either a child or parent)
|
||||
// actually has element focus, so we check the focused attribute
|
||||
// to see whether to draw in the focused state.
|
||||
if (aWidgetType == NS_THEME_TEXTFIELD ||
|
||||
aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD ||
|
||||
aWidgetType == NS_THEME_RADIO_CONTAINER ||
|
||||
aWidgetType == NS_THEME_RADIO_LABEL ||
|
||||
aWidgetType == NS_THEME_RADIO) {
|
||||
aState->focused = IsFocused(aFrame);
|
||||
}
|
||||
|
||||
if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL ||
|
||||
aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) {
|
||||
// for scrollbars we need to go up two to go from the thumb to
|
||||
// the slider to the actual scrollbar object
|
||||
nsIFrame *tmpFrame = aFrame->GetParent()->GetParent();
|
||||
|
||||
aState->curpos = CheckIntAttr(tmpFrame, mCurPosAtom);
|
||||
aState->maxpos = CheckIntAttr(tmpFrame, mMaxPosAtom);
|
||||
}
|
||||
|
||||
// menu item state is determined by the attribute "_moz-menuactive",
|
||||
// and not by the mouse hovering (accessibility). as a special case,
|
||||
// menus which are children of a menu bar are only marked as prelight
|
||||
// if they are open, not on normal hover.
|
||||
|
||||
if (aWidgetType == NS_THEME_MENUITEM ||
|
||||
aWidgetType == NS_THEME_CHECKMENUITEM ||
|
||||
aWidgetType == NS_THEME_RADIOMENUITEM) {
|
||||
PRBool isTopLevel = PR_FALSE;
|
||||
nsIMenuFrame *menuFrame;
|
||||
CallQueryInterface(aFrame, &menuFrame);
|
||||
|
||||
if (menuFrame) {
|
||||
nsIMenuParent *menuParent;
|
||||
menuFrame->GetMenuParent(&menuParent);
|
||||
if (menuParent)
|
||||
menuParent->IsMenuBar(isTopLevel);
|
||||
}
|
||||
|
||||
if (isTopLevel) {
|
||||
PRBool isOpen;
|
||||
menuFrame->MenuIsOpen(isOpen);
|
||||
aState->inHover = isOpen;
|
||||
} else {
|
||||
aState->inHover = CheckBooleanAttr(aFrame, mMenuActiveAtom);
|
||||
}
|
||||
|
||||
aState->active = FALSE;
|
||||
|
||||
if (aWidgetType == NS_THEME_CHECKMENUITEM ||
|
||||
aWidgetType == NS_THEME_RADIOMENUITEM) {
|
||||
if (aFrame) {
|
||||
nsAutoString attr;
|
||||
nsresult res = aFrame->GetContent()->GetAttr(kNameSpaceID_None, mCheckedAtom, attr);
|
||||
if (res == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
(res != NS_CONTENT_ATTR_NOT_THERE && attr.IsEmpty()))
|
||||
*aWidgetFlags = FALSE;
|
||||
else
|
||||
*aWidgetFlags = attr.EqualsIgnoreCase("true");
|
||||
} else {
|
||||
*aWidgetFlags = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (aWidgetType) {
|
||||
case NS_THEME_BUTTON:
|
||||
case NS_THEME_TOOLBAR_BUTTON:
|
||||
case NS_THEME_TOOLBAR_DUAL_BUTTON:
|
||||
if (aWidgetFlags)
|
||||
*aWidgetFlags = (aWidgetType == NS_THEME_BUTTON) ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE;
|
||||
aGtkWidgetType = MOZ_GTK_BUTTON;
|
||||
break;
|
||||
case NS_THEME_CHECKBOX:
|
||||
case NS_THEME_RADIO:
|
||||
aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
||||
if (aWidgetFlags)
|
||||
*aWidgetFlags = GtkArrowType(aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP);
|
||||
aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
||||
aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
||||
aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
||||
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
||||
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
|
||||
break;
|
||||
case NS_THEME_TOOLBAR_GRIPPER:
|
||||
aGtkWidgetType = MOZ_GTK_GRIPPER;
|
||||
break;
|
||||
case NS_THEME_TEXTFIELD:
|
||||
case NS_THEME_DROPDOWN_TEXTFIELD:
|
||||
aGtkWidgetType = MOZ_GTK_ENTRY;
|
||||
break;
|
||||
case NS_THEME_DROPDOWN:
|
||||
aGtkWidgetType = MOZ_GTK_DROPDOWN;
|
||||
break;
|
||||
case NS_THEME_DROPDOWN_TEXT:
|
||||
return PR_FALSE; // nothing to do, but prevents the bg from being drawn
|
||||
case NS_THEME_DROPDOWN_BUTTON:
|
||||
aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW;
|
||||
break;
|
||||
case NS_THEME_CHECKBOX_CONTAINER:
|
||||
aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER;
|
||||
break;
|
||||
case NS_THEME_RADIO_CONTAINER:
|
||||
aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER;
|
||||
break;
|
||||
case NS_THEME_CHECKBOX_LABEL:
|
||||
aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL;
|
||||
break;
|
||||
case NS_THEME_RADIO_LABEL:
|
||||
aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL;
|
||||
break;
|
||||
case NS_THEME_TOOLBAR:
|
||||
aGtkWidgetType = MOZ_GTK_TOOLBAR;
|
||||
break;
|
||||
case NS_THEME_TOOLTIP:
|
||||
aGtkWidgetType = MOZ_GTK_TOOLTIP;
|
||||
break;
|
||||
case NS_THEME_STATUSBAR_PANEL:
|
||||
aGtkWidgetType = MOZ_GTK_FRAME;
|
||||
break;
|
||||
case NS_THEME_PROGRESSBAR:
|
||||
case NS_THEME_PROGRESSBAR_VERTICAL:
|
||||
aGtkWidgetType = MOZ_GTK_PROGRESSBAR;
|
||||
break;
|
||||
case NS_THEME_PROGRESSBAR_CHUNK:
|
||||
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
||||
aGtkWidgetType = MOZ_GTK_PROGRESS_CHUNK;
|
||||
break;
|
||||
case NS_THEME_TAB_PANELS:
|
||||
aGtkWidgetType = MOZ_GTK_TABPANELS;
|
||||
break;
|
||||
case NS_THEME_TAB:
|
||||
case NS_THEME_TAB_LEFT_EDGE:
|
||||
case NS_THEME_TAB_RIGHT_EDGE:
|
||||
{
|
||||
if (aWidgetFlags) {
|
||||
*aWidgetFlags = 0;
|
||||
|
||||
if (aWidgetType == NS_THEME_TAB &&
|
||||
CheckBooleanAttr(aFrame, mSelectedAtom))
|
||||
*aWidgetFlags |= MOZ_GTK_TAB_SELECTED;
|
||||
else if (aWidgetType == NS_THEME_TAB_LEFT_EDGE)
|
||||
*aWidgetFlags |= MOZ_GTK_TAB_BEFORE_SELECTED;
|
||||
|
||||
if (aFrame->GetContent()->HasAttr(kNameSpaceID_None, mFirstTabAtom))
|
||||
*aWidgetFlags |= MOZ_GTK_TAB_FIRST;
|
||||
}
|
||||
|
||||
aGtkWidgetType = MOZ_GTK_TAB;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_MENUBAR:
|
||||
aGtkWidgetType = MOZ_GTK_MENUBAR;
|
||||
break;
|
||||
case NS_THEME_MENUPOPUP:
|
||||
aGtkWidgetType = MOZ_GTK_MENUPOPUP;
|
||||
break;
|
||||
case NS_THEME_MENUITEM:
|
||||
aGtkWidgetType = MOZ_GTK_MENUITEM;
|
||||
break;
|
||||
case NS_THEME_CHECKMENUITEM:
|
||||
aGtkWidgetType = MOZ_GTK_CHECKMENUITEM;
|
||||
break;
|
||||
case NS_THEME_RADIOMENUITEM:
|
||||
aGtkWidgetType = MOZ_GTK_RADIOMENUITEM;
|
||||
break;
|
||||
case NS_THEME_WINDOW:
|
||||
case NS_THEME_DIALOG:
|
||||
aGtkWidgetType = MOZ_GTK_WINDOW;
|
||||
break;
|
||||
default:
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
NativeThemeErrorHandler(Display* dpy, XErrorEvent* error) {
|
||||
gLastXError = error->error_code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
{
|
||||
GtkWidgetState state;
|
||||
GtkThemeWidgetType gtkWidgetType;
|
||||
gint flags;
|
||||
if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, &state,
|
||||
&flags))
|
||||
return NS_OK;
|
||||
|
||||
nsDrawingSurfaceGTK* surface;
|
||||
aContext->GetDrawingSurface((nsIDrawingSurface**)&surface);
|
||||
GdkWindow* window = (GdkWindow*) surface->GetDrawable();
|
||||
|
||||
nsTransform2D* transformMatrix;
|
||||
aContext->GetCurrentTransform(transformMatrix);
|
||||
|
||||
nsRect tr(aRect);
|
||||
transformMatrix->TransformCoord(&tr.x, &tr.y, &tr.width, &tr.height);
|
||||
GdkRectangle gdk_rect = {tr.x, tr.y, tr.width, tr.height};
|
||||
|
||||
nsRect cr(aClipRect);
|
||||
transformMatrix->TransformCoord(&cr.x, &cr.y, &cr.width, &cr.height);
|
||||
GdkRectangle gdk_clip = {cr.x, cr.y, cr.width, cr.height};
|
||||
|
||||
NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType),
|
||||
"Trying to render an unsafe widget!");
|
||||
|
||||
PRBool safeState = IsWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
|
||||
XErrorHandler oldHandler = nsnull;
|
||||
if (!safeState) {
|
||||
gLastXError = 0;
|
||||
oldHandler = XSetErrorHandler(NativeThemeErrorHandler);
|
||||
}
|
||||
|
||||
moz_gtk_widget_paint(gtkWidgetType, window, &gdk_rect, &gdk_clip, &state,
|
||||
flags);
|
||||
|
||||
if (!safeState) {
|
||||
gdk_flush();
|
||||
XSetErrorHandler(oldHandler);
|
||||
|
||||
if (gLastXError) {
|
||||
#ifdef DEBUG
|
||||
printf("GTK theme failed for widget type %d, error was %d, state was "
|
||||
"[active=%d,focused=%d,inHover=%d,disabled=%d]\n",
|
||||
aWidgetType, gLastXError, state.active, state.focused,
|
||||
state.inHover, state.disabled);
|
||||
#endif
|
||||
NS_WARNING("GTK theme failed; disabling unsafe widget");
|
||||
SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType);
|
||||
// force refresh of the window, because the widget was not
|
||||
// successfully drawn it must be redrawn using the default look
|
||||
RefreshWidgetWindow(aFrame);
|
||||
} else {
|
||||
SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::GetWidgetBorder(nsIDeviceContext* aContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType, nsMargin* aResult)
|
||||
{
|
||||
aResult->top = aResult->left = 0;
|
||||
switch (aWidgetType) {
|
||||
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
||||
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
||||
{
|
||||
MozGtkScrollbarMetrics metrics;
|
||||
moz_gtk_get_scrollbar_metrics(&metrics);
|
||||
aResult->top = aResult->left = metrics.trough_border;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_TOOLBOX:
|
||||
// gtk has no toolbox equivalent. So, although we map toolbox to
|
||||
// gtk's 'toolbar' for purposes of painting the widget background,
|
||||
// we don't use the toolbar border for toolbox.
|
||||
break;
|
||||
case NS_THEME_TOOLBAR_DUAL_BUTTON:
|
||||
// TOOLBAR_DUAL_BUTTON is an interesting case. We want a border to draw
|
||||
// around the entire button + dropdown, and also an inner border if you're
|
||||
// over the button part. But, we want the inner button to be right up
|
||||
// against the edge of the outer button so that the borders overlap.
|
||||
// To make this happen, we draw a button border for the outer button,
|
||||
// but don't reserve any space for it.
|
||||
break;
|
||||
default:
|
||||
{
|
||||
GtkThemeWidgetType gtkWidgetType;
|
||||
if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nsnull,
|
||||
nsnull))
|
||||
moz_gtk_get_widget_border(gtkWidgetType, &aResult->left,
|
||||
&aResult->top);
|
||||
}
|
||||
}
|
||||
|
||||
aResult->right = aResult->left;
|
||||
aResult->bottom = aResult->top;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
|
||||
nsIFrame* aFrame, PRUint8 aWidgetType,
|
||||
nsMargin* aResult)
|
||||
{
|
||||
if (aWidgetType == NS_THEME_BUTTON_FOCUS ||
|
||||
aWidgetType == NS_THEME_TOOLBAR_BUTTON ||
|
||||
aWidgetType == NS_THEME_TOOLBAR_DUAL_BUTTON) {
|
||||
aResult->SizeTo(0, 0, 0, 0);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::GetMinimumWidgetSize(nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame, PRUint8 aWidgetType,
|
||||
nsSize* aResult, PRBool* aIsOverridable)
|
||||
{
|
||||
aResult->width = aResult->height = 0;
|
||||
*aIsOverridable = PR_TRUE;
|
||||
|
||||
switch (aWidgetType) {
|
||||
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
||||
{
|
||||
MozGtkScrollbarMetrics metrics;
|
||||
moz_gtk_get_scrollbar_metrics(&metrics);
|
||||
|
||||
aResult->width = metrics.slider_width;
|
||||
aResult->height = metrics.stepper_size;
|
||||
*aIsOverridable = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
||||
{
|
||||
MozGtkScrollbarMetrics metrics;
|
||||
moz_gtk_get_scrollbar_metrics(&metrics);
|
||||
|
||||
aResult->width = metrics.stepper_size;
|
||||
aResult->height = metrics.slider_width;
|
||||
*aIsOverridable = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
||||
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
||||
{
|
||||
MozGtkScrollbarMetrics metrics;
|
||||
moz_gtk_get_scrollbar_metrics(&metrics);
|
||||
|
||||
if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL) {
|
||||
aResult->width = metrics.slider_width;
|
||||
aResult->height = metrics.min_slider_size;
|
||||
} else {
|
||||
aResult->width = metrics.min_slider_size;
|
||||
aResult->height = metrics.slider_width;
|
||||
}
|
||||
|
||||
*aIsOverridable = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_DROPDOWN_BUTTON:
|
||||
{
|
||||
moz_gtk_get_dropdown_arrow_size(&aResult->width, &aResult->height);
|
||||
*aIsOverridable = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case NS_THEME_CHECKBOX:
|
||||
case NS_THEME_RADIO:
|
||||
{
|
||||
gint indicator_size, indicator_spacing;
|
||||
|
||||
if (aWidgetType == NS_THEME_CHECKBOX) {
|
||||
moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
|
||||
} else {
|
||||
moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
|
||||
}
|
||||
|
||||
// Include space for the indicator and the padding around it.
|
||||
aResult->width = indicator_size + 3 * indicator_spacing;
|
||||
aResult->height = indicator_size + 2 * indicator_spacing;
|
||||
*aIsOverridable = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_THEME_CHECKBOX_CONTAINER:
|
||||
case NS_THEME_RADIO_CONTAINER:
|
||||
case NS_THEME_CHECKBOX_LABEL:
|
||||
case NS_THEME_RADIO_LABEL:
|
||||
case NS_THEME_BUTTON:
|
||||
case NS_THEME_TOOLBAR_BUTTON:
|
||||
{
|
||||
// Just include our border, and let the box code augment the size.
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dc;
|
||||
aContext->GetDeviceContext(*getter_AddRefs(dc));
|
||||
|
||||
nsMargin border;
|
||||
nsNativeThemeGTK::GetWidgetBorder(dc, aFrame, aWidgetType, &border);
|
||||
aResult->width = border.left + border.right;
|
||||
aResult->height = border.top + border.bottom;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
|
||||
nsIAtom* aAttribute, PRBool* aShouldRepaint)
|
||||
{
|
||||
// Some widget types just never change state.
|
||||
if (aWidgetType == NS_THEME_TOOLBOX ||
|
||||
aWidgetType == NS_THEME_TOOLBAR ||
|
||||
aWidgetType == NS_THEME_STATUSBAR ||
|
||||
aWidgetType == NS_THEME_STATUSBAR_PANEL ||
|
||||
aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
|
||||
aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
|
||||
aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
|
||||
aWidgetType == NS_THEME_PROGRESSBAR ||
|
||||
aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
|
||||
aWidgetType == NS_THEME_MENUBAR ||
|
||||
aWidgetType == NS_THEME_MENUPOPUP ||
|
||||
aWidgetType == NS_THEME_TOOLTIP ||
|
||||
aWidgetType == NS_THEME_WINDOW ||
|
||||
aWidgetType == NS_THEME_DIALOG) {
|
||||
*aShouldRepaint = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXXdwh Not sure what can really be done here. Can at least guess for
|
||||
// specific widgets that they're highly unlikely to have certain states.
|
||||
// For example, a toolbar doesn't care about any states.
|
||||
if (!aAttribute) {
|
||||
// Hover/focus/active changed. Always repaint.
|
||||
*aShouldRepaint = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
// Check the attribute to see if it's relevant.
|
||||
// disabled, checked, dlgtype, default, etc.
|
||||
*aShouldRepaint = PR_FALSE;
|
||||
if (aAttribute == mDisabledAtom || aAttribute == mCheckedAtom ||
|
||||
aAttribute == mSelectedAtom || aAttribute == mFocusedAtom ||
|
||||
aAttribute == mMenuActiveAtom)
|
||||
*aShouldRepaint = PR_TRUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::ThemeChanged()
|
||||
{
|
||||
nsDeviceContextGTK::ClearCachedSystemFonts();
|
||||
|
||||
memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType)
|
||||
{
|
||||
if (aFrame) {
|
||||
// For now don't support HTML.
|
||||
if (aFrame->GetContent()->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType))
|
||||
return PR_FALSE;
|
||||
|
||||
switch (aWidgetType) {
|
||||
case NS_THEME_BUTTON:
|
||||
case NS_THEME_BUTTON_FOCUS:
|
||||
case NS_THEME_RADIO:
|
||||
case NS_THEME_CHECKBOX:
|
||||
case NS_THEME_TOOLBOX: // N/A
|
||||
case NS_THEME_TOOLBAR:
|
||||
case NS_THEME_TOOLBAR_BUTTON:
|
||||
case NS_THEME_TOOLBAR_DUAL_BUTTON: // so we can override the border with 0
|
||||
// case NS_THEME_TOOLBAR_DUAL_BUTTON_DROPDOWN:
|
||||
// case NS_THEME_TOOLBAR_SEPARATOR:
|
||||
case NS_THEME_TOOLBAR_GRIPPER:
|
||||
case NS_THEME_STATUSBAR:
|
||||
case NS_THEME_STATUSBAR_PANEL:
|
||||
// case NS_THEME_RESIZER: (n/a for gtk)
|
||||
// case NS_THEME_LISTBOX:
|
||||
// case NS_THEME_LISTBOX_LISTITEM:
|
||||
// case NS_THEME_TREEVIEW:
|
||||
// case NS_THEME_TREEVIEW_TREEITEM:
|
||||
// case NS_THEME_TREEVIEW_TWISTY:
|
||||
// case NS_THEME_TREEVIEW_LINE:
|
||||
// case NS_THEME_TREEVIEW_HEADER:
|
||||
// case NS_THEME_TREEVIEW_HEADER_CELL:
|
||||
// case NS_THEME_TREEVIEW_HEADER_SORTARROW:
|
||||
// case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
||||
case NS_THEME_PROGRESSBAR:
|
||||
case NS_THEME_PROGRESSBAR_CHUNK:
|
||||
case NS_THEME_PROGRESSBAR_VERTICAL:
|
||||
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
||||
case NS_THEME_TAB:
|
||||
// case NS_THEME_TAB_PANEL:
|
||||
case NS_THEME_TAB_LEFT_EDGE:
|
||||
case NS_THEME_TAB_RIGHT_EDGE:
|
||||
case NS_THEME_TAB_PANELS:
|
||||
case NS_THEME_TOOLTIP:
|
||||
// case NS_THEME_SPINNER:
|
||||
// case NS_THEME_SPINNER_UP_BUTTON:
|
||||
// case NS_THEME_SPINNER_DOWN_BUTTON:
|
||||
// case NS_THEME_SCROLLBAR: (n/a for gtk)
|
||||
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
||||
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
||||
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
||||
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
||||
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
||||
// case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: (n/a for gtk)
|
||||
// case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: (n/a for gtk)
|
||||
case NS_THEME_TEXTFIELD:
|
||||
// case NS_THEME_TEXTFIELD_CARET:
|
||||
case NS_THEME_DROPDOWN_BUTTON:
|
||||
case NS_THEME_DROPDOWN_TEXTFIELD:
|
||||
// case NS_THEME_SLIDER:
|
||||
// case NS_THEME_SLIDER_THUMB:
|
||||
// case NS_THEME_SLIDER_THUMB_START:
|
||||
// case NS_THEME_SLIDER_THUMB_END:
|
||||
// case NS_THEME_SLIDER_TICK:
|
||||
case NS_THEME_CHECKBOX_CONTAINER:
|
||||
case NS_THEME_RADIO_CONTAINER:
|
||||
case NS_THEME_CHECKBOX_LABEL:
|
||||
case NS_THEME_RADIO_LABEL:
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
case NS_THEME_MENUBAR:
|
||||
case NS_THEME_MENUPOPUP:
|
||||
case NS_THEME_MENUITEM:
|
||||
case NS_THEME_CHECKMENUITEM:
|
||||
case NS_THEME_RADIOMENUITEM:
|
||||
case NS_THEME_WINDOW:
|
||||
case NS_THEME_DIALOG:
|
||||
case NS_THEME_DROPDOWN:
|
||||
case NS_THEME_DROPDOWN_TEXT:
|
||||
#endif
|
||||
return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsNativeThemeGTK::WidgetIsContainer(PRUint8 aWidgetType)
|
||||
{
|
||||
// XXXdwh At some point flesh all of this out.
|
||||
if (aWidgetType == NS_THEME_DROPDOWN_BUTTON ||
|
||||
aWidgetType == NS_THEME_RADIO ||
|
||||
aWidgetType == NS_THEME_CHECKBOX)
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
|
@ -38,9 +38,9 @@
|
|||
#ifndef nsIMenuFrame_h___
|
||||
#define nsIMenuFrame_h___
|
||||
|
||||
// {6A4CDE51-6C05-11d3-BB50-00104B7B7DEB}
|
||||
// {2281EFC8-A8BA-4a73-8CF7-DB4EECA5EAEC}
|
||||
#define NS_IMENUFRAME_IID \
|
||||
{ 0x6a4cde51, 0x6c05, 0x11d3, { 0xbb, 0x50, 0x0, 0x10, 0x4b, 0x7b, 0x7d, 0xeb } }
|
||||
{ 0x2281efc8, 0xa8ba, 0x4a73, { 0x8c, 0xf7, 0xdb, 0x4e, 0xec, 0xa5, 0xea, 0xec } };
|
||||
|
||||
class nsIMenuParent;
|
||||
class nsIDOMElement;
|
||||
|
@ -73,8 +73,8 @@ public:
|
|||
NS_IMETHOD ShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, PRBool& aHandledFlag) = 0;
|
||||
NS_IMETHOD KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag) = 0;
|
||||
|
||||
NS_IMETHOD GetMenuParent(nsIMenuParent** aMenuParent) = 0;
|
||||
NS_IMETHOD GetMenuChild(nsIFrame** aResult) = 0;
|
||||
virtual nsIMenuParent *GetMenuParent() = 0;
|
||||
virtual nsIFrame *GetMenuChild() = 0;
|
||||
|
||||
NS_IMETHOD GetRadioGroupName(nsString &aName) = 0;
|
||||
NS_IMETHOD GetMenuType(nsMenuType &aType) = 0;
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
#define nsIMenuParent_h___
|
||||
|
||||
|
||||
// {D407BF61-3EFA-11d3-97FA-00400553EEF0}
|
||||
// {81C0BF71-9F50-4f4d-8B6A-D6B233C100C2}
|
||||
#define NS_IMENUPARENT_IID \
|
||||
{ 0xd407bf61, 0x3efa, 0x11d3, { 0x97, 0xfa, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
|
||||
{ 0x81c0bf71, 0x9f50, 0x4f4d, { 0x8b, 0x6a, 0xd6, 0xb2, 0x33, 0xc1, 0x0, 0xc2 } };
|
||||
|
||||
class nsIMenuFrame;
|
||||
class nsIDOMKeyEvent;
|
||||
|
@ -139,10 +139,10 @@ class nsIMenuParent : public nsISupports {
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMENUPARENT_IID)
|
||||
|
||||
NS_IMETHOD GetCurrentMenuItem(nsIMenuFrame** aMenuItem) = 0;
|
||||
virtual nsIMenuFrame *GetCurrentMenuItem() = 0;
|
||||
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem) = 0;
|
||||
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
|
||||
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
|
||||
virtual nsIMenuFrame *GetNextMenuItem(nsIMenuFrame* aStart) = 0;
|
||||
virtual nsIMenuFrame *GetPreviousMenuItem(nsIMenuFrame* aStart) = 0;
|
||||
|
||||
NS_IMETHOD SetActive(PRBool aActiveFlag) = 0;
|
||||
NS_IMETHOD GetIsActive(PRBool& isActive) = 0;
|
||||
|
|
|
@ -280,8 +280,7 @@ nsMenuBarFrame::ToggleMenuActiveState()
|
|||
// Set the active menu to be the top left item (e.g., the File menu).
|
||||
// We use an attribute called "menuactive" to track the current
|
||||
// active menu.
|
||||
nsIMenuFrame* firstFrame;
|
||||
GetNextMenuItem(nsnull, &firstFrame);
|
||||
nsIMenuFrame* firstFrame = GetNextMenuItem(nsnull);
|
||||
if (firstFrame) {
|
||||
firstFrame->SelectMenu(PR_TRUE);
|
||||
|
||||
|
@ -328,10 +327,11 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
if ( shortcutKey.Equals(Substring(&letter, &letter+1),
|
||||
nsCaseInsensitiveStringComparator()) ) {
|
||||
// We match!
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
if (menuFrame)
|
||||
return menuFrame.get();
|
||||
return nsnull;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame))) {
|
||||
menuFrame = nsnull;
|
||||
}
|
||||
return menuFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,11 +405,9 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
|||
|
||||
if NS_DIRECTION_IS_INLINE(theDirection) {
|
||||
|
||||
nsIMenuFrame* nextItem;
|
||||
|
||||
if (theDirection == eNavigationDirection_End)
|
||||
GetNextMenuItem(mCurrentMenu, &nextItem);
|
||||
else GetPreviousMenuItem(mCurrentMenu, &nextItem);
|
||||
nsIMenuFrame* nextItem = (theDirection == eNavigationDirection_End) ?
|
||||
GetNextMenuItem(mCurrentMenu) :
|
||||
GetPreviousMenuItem(mCurrentMenu);
|
||||
|
||||
SetCurrentMenuItem(nextItem);
|
||||
if (nextItem) {
|
||||
|
@ -430,8 +428,8 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(mPresContext->PresShell(), this, nsnull, &immediateParent);
|
||||
|
@ -453,10 +451,10 @@ nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
|||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
@ -467,22 +465,21 @@ nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
|||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
*aResult = aStart;
|
||||
return NS_OK;
|
||||
return aStart;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(mPresContext->PresShell(), this, nsnull, &immediateParent);
|
||||
|
@ -505,10 +502,10 @@ nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult
|
|||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
@ -519,25 +516,23 @@ nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult
|
|||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
*aResult = aStart;
|
||||
return NS_OK;
|
||||
return aStart;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMenuBarFrame::GetCurrentMenuItem(nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuBarFrame::GetCurrentMenuItem()
|
||||
{
|
||||
*aResult = mCurrentMenu;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
return mCurrentMenu;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -68,10 +68,10 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMenuParentInterface
|
||||
NS_IMETHOD GetCurrentMenuItem(nsIMenuFrame** aResult);
|
||||
virtual nsIMenuFrame* GetCurrentMenuItem();
|
||||
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem);
|
||||
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
|
||||
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
|
||||
virtual nsIMenuFrame* GetNextMenuItem(nsIMenuFrame* aStart);
|
||||
virtual nsIMenuFrame* GetPreviousMenuItem(nsIMenuFrame* aStart);
|
||||
NS_IMETHOD SetActive(PRBool aActiveFlag);
|
||||
NS_IMETHOD GetIsActive(PRBool& isActive) { isActive = IsActive(); return NS_OK; };
|
||||
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) { isMenuBar = PR_TRUE; return NS_OK; };
|
||||
|
|
|
@ -69,11 +69,10 @@ nsMenuDismissalListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuDismissalListener::GetCurrentMenuParent(nsIMenuParent** aMenuParent)
|
||||
nsIMenuParent*
|
||||
nsMenuDismissalListener::GetCurrentMenuParent()
|
||||
{
|
||||
*aMenuParent = mMenuParent;
|
||||
NS_IF_ADDREF(*aMenuParent);
|
||||
return mMenuParent;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -149,9 +148,13 @@ nsMenuDismissalListener::GetSubmenuWidgetChain(nsISupportsArray **_retval)
|
|||
// move up the chain
|
||||
nsIFrame* currAsFrame = nsnull;
|
||||
if ( NS_SUCCEEDED(CallQueryInterface(curr, &currAsFrame)) ) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame ( do_QueryInterface(currAsFrame->GetParent()) );
|
||||
nsIMenuFrame *menuFrame = nsnull;
|
||||
nsIFrame *parentFrame = currAsFrame->GetParent();
|
||||
if (parentFrame) {
|
||||
CallQueryInterface(parentFrame, &menuFrame);
|
||||
}
|
||||
if ( menuFrame ) {
|
||||
menuFrame->GetMenuParent ( &curr ); // Advance to next parent
|
||||
curr = menuFrame->GetMenuParent (); // Advance to next parent
|
||||
}
|
||||
else {
|
||||
// we are a menuParent but not a menuFrame. This is probably the case
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
NS_IMETHOD EnableListener(PRBool aEnabled);
|
||||
void SetCurrentMenuParent(nsIMenuParent* aMenuParent);
|
||||
void GetCurrentMenuParent(nsIMenuParent** aMenuParent);
|
||||
nsIMenuParent* GetCurrentMenuParent();
|
||||
|
||||
NS_IMETHOD Unregister();
|
||||
|
||||
|
|
|
@ -335,8 +335,7 @@ nsMenuFrame::Destroy(nsPresContext* aPresContext)
|
|||
{
|
||||
// are we our menu parent's current menu item?
|
||||
if (mMenuParent) {
|
||||
nsIMenuFrame *curItem = nsnull;
|
||||
mMenuParent->GetCurrentMenuItem(&curItem);
|
||||
nsIMenuFrame *curItem = mMenuParent->GetCurrentMenuItem();
|
||||
if (curItem == this) {
|
||||
// yes; tell it that we're going away
|
||||
mMenuParent->SetCurrentMenuItem(nsnull);
|
||||
|
@ -1261,9 +1260,7 @@ nsMenuFrame::SelectFirstItem()
|
|||
nsIFrame* frame = mPopupFrames.FirstChild();
|
||||
if (frame) {
|
||||
nsMenuPopupFrame* popup = (nsMenuPopupFrame*)frame;
|
||||
nsIMenuFrame* result;
|
||||
popup->GetNextMenuItem(nsnull, &result);
|
||||
popup->SetCurrentMenuItem(result);
|
||||
popup->SetCurrentMenuItem(popup->GetNextMenuItem(nsnull));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1955,8 +1952,7 @@ nsMenuFrame::GetActiveChild(nsIDOMElement** aResult)
|
|||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIMenuFrame* menuFrame;
|
||||
menuPopup->GetCurrentMenuItem(&menuFrame);
|
||||
nsIMenuFrame* menuFrame = menuPopup->GetCurrentMenuItem();
|
||||
|
||||
if (!menuFrame) {
|
||||
*aResult = nsnull;
|
||||
|
@ -1992,9 +1988,10 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
|||
mPresContext->PresShell()->GetPrimaryFrameFor(child, &kid);
|
||||
if (!kid)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(kid));
|
||||
if (!menuFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsIMenuFrame *menuFrame;
|
||||
nsresult rv = CallQueryInterface(kid, &menuFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
menuPopup->SetCurrentMenuItem(menuFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -150,8 +150,8 @@ public:
|
|||
|
||||
NS_IMETHOD SetParent(const nsIFrame* aParent);
|
||||
|
||||
NS_IMETHOD GetMenuParent(nsIMenuParent** aResult) { *aResult = mMenuParent; return NS_OK; };
|
||||
NS_IMETHOD GetMenuChild(nsIFrame** aResult) { *aResult = mPopupFrames.FirstChild(); return NS_OK; }
|
||||
virtual nsIMenuParent *GetMenuParent() { return mMenuParent; };
|
||||
virtual nsIFrame *GetMenuChild() { return mPopupFrames.FirstChild(); }
|
||||
NS_IMETHOD GetRadioGroupName(nsString &aName) { aName = mGroupName; return NS_OK; };
|
||||
NS_IMETHOD GetMenuType(nsMenuType &aType) { aType = mType; return NS_OK; };
|
||||
NS_IMETHOD MarkChildrenStyleChange();
|
||||
|
|
|
@ -186,7 +186,10 @@ nsMenuListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
}
|
||||
else if (theChar == NS_VK_ESCAPE) {
|
||||
// Close one level.
|
||||
// Prevents us from getting destroyed by Escape(), we need to return to ourselves
|
||||
NS_ADDREF_THIS();
|
||||
mMenuParent->Escape(handled);
|
||||
NS_RELEASE_THIS();
|
||||
if (!handled)
|
||||
mMenuParent->DismissChain();
|
||||
}
|
||||
|
|
|
@ -1130,8 +1130,8 @@ static void GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame*
|
|||
aShell->FrameConstructor()->GetInsertionPoint(aFrame, child, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuPopupFrame::GetNextMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(mPresContext->PresShell(), this, nsnull, &immediateParent);
|
||||
|
@ -1153,10 +1153,10 @@ nsMenuPopupFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
|||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
@ -1167,22 +1167,21 @@ nsMenuPopupFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
|||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
*aResult = aStart;
|
||||
return NS_OK;
|
||||
return aStart;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuPopupFrame::GetPreviousMenuItem(nsIMenuFrame* aStart)
|
||||
{
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
GetInsertionPoint(mPresContext->PresShell(), this, nsnull, &immediateParent);
|
||||
|
@ -1205,10 +1204,10 @@ nsMenuPopupFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResu
|
|||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
@ -1219,25 +1218,23 @@ nsMenuPopupFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResu
|
|||
while (currFrame && currFrame != startFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidItem(currFrame->GetContent())) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
*aResult = menuFrame.get();
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
nsIMenuFrame *menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(currFrame, &menuFrame)))
|
||||
menuFrame = nsnull;
|
||||
return menuFrame;
|
||||
}
|
||||
|
||||
currFrame = frames.GetPrevSiblingFor(currFrame);
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
*aResult = aStart;
|
||||
return NS_OK;
|
||||
return aStart;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMenuPopupFrame::GetCurrentMenuItem(nsIMenuFrame** aResult)
|
||||
/* virtual */ nsIMenuFrame*
|
||||
nsMenuPopupFrame::GetCurrentMenuItem()
|
||||
{
|
||||
*aResult = mCurrentMenu;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
return mCurrentMenu;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMenuPopupFrame::ConsumeOutsideClicks(PRBool& aConsumeOutsideClicks)
|
||||
|
@ -1359,8 +1356,7 @@ NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
|
|||
{
|
||||
// When a context menu is open, the current menu is locked, and no change
|
||||
// to the menu is allowed.
|
||||
nsCOMPtr<nsIMenuParent> contextMenu;
|
||||
GetContextMenu(getter_AddRefs(contextMenu));
|
||||
nsIMenuParent *contextMenu = GetContextMenu();
|
||||
if (contextMenu)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -1409,8 +1405,7 @@ nsMenuPopupFrame::Escape(PRBool& aHandledFlag)
|
|||
mIncrementalString.Truncate();
|
||||
|
||||
// See if we have a context menu open.
|
||||
nsCOMPtr<nsIMenuParent> contextMenu;
|
||||
GetContextMenu(getter_AddRefs(contextMenu));
|
||||
nsIMenuParent* contextMenu = GetContextMenu();
|
||||
if (contextMenu) {
|
||||
// Get the context menu parent.
|
||||
nsIFrame* childFrame;
|
||||
|
@ -1450,8 +1445,7 @@ nsMenuPopupFrame::Enter()
|
|||
mIncrementalString.Truncate();
|
||||
|
||||
// See if we have a context menu open.
|
||||
nsCOMPtr<nsIMenuParent> contextMenu;
|
||||
GetContextMenu(getter_AddRefs(contextMenu));
|
||||
nsIMenuParent *contextMenu = GetContextMenu();
|
||||
if (contextMenu)
|
||||
return contextMenu->Enter();
|
||||
|
||||
|
@ -1462,24 +1456,19 @@ nsMenuPopupFrame::Enter()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuPopupFrame::GetContextMenu(nsIMenuParent** aContextMenu)
|
||||
nsIMenuParent*
|
||||
nsMenuPopupFrame::GetContextMenu()
|
||||
{
|
||||
*aContextMenu = nsnull;
|
||||
if (mIsContextMenu || !nsMenuFrame::sDismissalListener)
|
||||
return;
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIMenuParent> menuParent;
|
||||
nsMenuFrame::sDismissalListener->GetCurrentMenuParent(getter_AddRefs(menuParent));
|
||||
nsIMenuParent *menuParent = nsMenuFrame::sDismissalListener->GetCurrentMenuParent();
|
||||
if (!menuParent)
|
||||
return;
|
||||
return nsnull;
|
||||
|
||||
PRBool isContextMenu;
|
||||
menuParent->GetIsContextMenu(isContextMenu);
|
||||
if (isContextMenu) {
|
||||
*aContextMenu = menuParent;
|
||||
NS_ADDREF(*aContextMenu);
|
||||
}
|
||||
return isContextMenu ? menuParent : nsnull;
|
||||
}
|
||||
|
||||
nsIMenuFrame*
|
||||
|
@ -1582,25 +1571,25 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, PRBool& doActi
|
|||
if (StringBeginsWith(textKey, incrementalString,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
// mIncrementalString is a prefix of textKey
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
if (menuFrame) {
|
||||
nsIMenuFrame* menuFrame;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(currFrame, &menuFrame))) {
|
||||
// There is one match
|
||||
matchCount++;
|
||||
if (isShortcut) {
|
||||
// There is one shortcut-key match
|
||||
matchShortcutCount++;
|
||||
// Record the matched item. If there is only one matched shortcut item, do it
|
||||
frameShortcut = menuFrame.get();
|
||||
frameShortcut = menuFrame;
|
||||
}
|
||||
if (!foundActive) {
|
||||
// It's a first candidate item located before/on the current item
|
||||
if (!frameBefore)
|
||||
frameBefore = menuFrame.get();
|
||||
frameBefore = menuFrame;
|
||||
}
|
||||
else {
|
||||
// It's a first candidate item located after the current item
|
||||
if (!frameAfter)
|
||||
frameAfter = menuFrame.get();
|
||||
frameAfter = menuFrame;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1614,8 +1603,9 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, PRBool& doActi
|
|||
if (stringLength > 1) {
|
||||
// If there is more than one char typed, the current item has highest priority,
|
||||
// otherwise the item next to current has highest priority
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
|
||||
if (menuFrame && menuFrame.get() == frameBefore) {
|
||||
nsIMenuFrame* menuFrame;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(currFrame, &menuFrame)) &&
|
||||
menuFrame == frameBefore) {
|
||||
return frameBefore;
|
||||
}
|
||||
}
|
||||
|
@ -1681,8 +1671,7 @@ NS_IMETHODIMP
|
|||
nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
||||
{
|
||||
// See if we have a context menu open.
|
||||
nsCOMPtr<nsIMenuParent> contextMenu;
|
||||
GetContextMenu(getter_AddRefs(contextMenu));
|
||||
nsIMenuParent *contextMenu = GetContextMenu();
|
||||
if (contextMenu)
|
||||
return contextMenu->KeyboardNavigation(aKeyCode, aHandledFlag);
|
||||
|
||||
|
@ -1696,8 +1685,7 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
|||
// We've been opened, but we haven't had anything selected.
|
||||
// We can handle End, but our parent handles Start.
|
||||
if (theDirection == eNavigationDirection_End) {
|
||||
nsIMenuFrame* nextItem;
|
||||
GetNextMenuItem(nsnull, &nextItem);
|
||||
nsIMenuFrame* nextItem = GetNextMenuItem(nsnull);
|
||||
if (nextItem) {
|
||||
aHandledFlag = PR_TRUE;
|
||||
SetCurrentMenuItem(nextItem);
|
||||
|
@ -1737,13 +1725,13 @@ nsMenuPopupFrame::KeyboardNavigation(PRUint32 aKeyCode, PRBool& aHandledFlag)
|
|||
nsIMenuFrame* nextItem;
|
||||
|
||||
if (theDirection == eNavigationDirection_Before)
|
||||
GetPreviousMenuItem(mCurrentMenu, &nextItem);
|
||||
nextItem = GetPreviousMenuItem(mCurrentMenu);
|
||||
else if (theDirection == eNavigationDirection_After)
|
||||
GetNextMenuItem(mCurrentMenu, &nextItem);
|
||||
nextItem = GetNextMenuItem(mCurrentMenu);
|
||||
else if (theDirection == eNavigationDirection_First)
|
||||
GetNextMenuItem(nsnull, &nextItem);
|
||||
nextItem = GetNextMenuItem(nsnull);
|
||||
else
|
||||
GetPreviousMenuItem(nsnull, &nextItem);
|
||||
nextItem = GetPreviousMenuItem(nsnull);
|
||||
|
||||
if (nextItem) {
|
||||
aHandledFlag = PR_TRUE;
|
||||
|
@ -1771,11 +1759,7 @@ nsMenuPopupFrame::GetParentPopup(nsIMenuParent** aMenuParent)
|
|||
if (frame) {
|
||||
nsIFrame* grandparent = frame->GetParent();
|
||||
if (grandparent ) {
|
||||
nsCOMPtr<nsIMenuParent> menuParent = do_QueryInterface(grandparent);
|
||||
if (menuParent) {
|
||||
*aMenuParent = menuParent.get();
|
||||
NS_ADDREF(*aMenuParent);
|
||||
}
|
||||
CallQueryInterface(grandparent, aMenuParent);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1795,8 +1779,8 @@ nsMenuPopupFrame::HideChain()
|
|||
|
||||
nsIFrame* frame = GetParent();
|
||||
if (frame) {
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(frame);
|
||||
if (!menuFrame) {
|
||||
nsIMenuFrame* menuFrame;
|
||||
if (NS_FAILED(CallQueryInterface(frame, &menuFrame))) {
|
||||
nsIPopupSetFrame* popupSetFrame = GetPopupSetFrame(mPresContext);
|
||||
if (popupSetFrame)
|
||||
// Hide the popup.
|
||||
|
@ -1808,8 +1792,7 @@ nsMenuPopupFrame::HideChain()
|
|||
menuFrame->SelectMenu(PR_FALSE);
|
||||
|
||||
// Get the parent.
|
||||
nsCOMPtr<nsIMenuParent> menuParent;
|
||||
menuFrame->GetMenuParent(getter_AddRefs(menuParent));
|
||||
nsIMenuParent *menuParent = menuFrame->GetMenuParent();
|
||||
if (menuParent)
|
||||
menuParent->HideChain();
|
||||
}
|
||||
|
@ -1852,8 +1835,7 @@ nsMenuPopupFrame::DismissChain()
|
|||
menuFrame->OpenMenu(PR_FALSE);
|
||||
|
||||
// Get the parent.
|
||||
nsIMenuParent* menuParent;
|
||||
menuFrame->GetMenuParent(&menuParent);
|
||||
nsIMenuParent* menuParent = menuFrame->GetMenuParent();
|
||||
if (menuParent)
|
||||
menuParent->DismissChain();
|
||||
}
|
||||
|
@ -2055,26 +2037,15 @@ nsMenuPopupFrame::Notify(nsITimer* aTimer)
|
|||
// Walk through all of the sub-menus of this menu item until we get to the
|
||||
// last sub-menu, then check if that sub-menu has an active menu item. If it
|
||||
// does, then keep that menu open. If it doesn't, close menu and its sub-menus.
|
||||
nsIFrame* child;
|
||||
mTimerMenu->GetMenuChild(&child);
|
||||
nsCOMPtr<nsIMenuFrame> currentMenuItem = nsnull;
|
||||
|
||||
nsCOMPtr<nsIMenuParent> menuParent = do_QueryInterface(child);
|
||||
while (menuParent)
|
||||
nsIFrame* child = mTimerMenu->GetMenuChild();
|
||||
nsIMenuFrame *currentMenuItem = nsnull;
|
||||
nsIMenuParent *menuParent;
|
||||
while (child && NS_SUCCEEDED(CallQueryInterface(child, &menuParent)))
|
||||
{
|
||||
// get the selected menu item for this sub-menu
|
||||
menuParent->GetCurrentMenuItem(getter_AddRefs(currentMenuItem));
|
||||
menuParent = nsnull;
|
||||
if (currentMenuItem)
|
||||
{
|
||||
// this sub-menu has a selected menu item - does that item open a sub-menu?
|
||||
currentMenuItem->GetMenuChild(&child);
|
||||
if (child) {
|
||||
// the selected menu item opens a sub-menu - move down
|
||||
// to that sub-menu and then go through the loop again
|
||||
menuParent = do_QueryInterface(child);
|
||||
}
|
||||
} // if item is selected
|
||||
currentMenuItem = menuParent->GetCurrentMenuItem();
|
||||
// if this sub-menu has a selected menu item, does that item open a sub-menu?
|
||||
child = currentMenuItem ? currentMenuItem->GetMenuChild() : nsnull;
|
||||
} // while we're not at the last submenu
|
||||
|
||||
if (currentMenuItem)
|
||||
|
|
|
@ -84,10 +84,10 @@ public:
|
|||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
// nsIMenuParentInterface
|
||||
NS_IMETHOD GetCurrentMenuItem(nsIMenuFrame** aResult);
|
||||
virtual nsIMenuFrame* GetCurrentMenuItem();
|
||||
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem);
|
||||
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
|
||||
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
|
||||
virtual nsIMenuFrame* GetNextMenuItem(nsIMenuFrame* aStart);
|
||||
virtual nsIMenuFrame* GetPreviousMenuItem(nsIMenuFrame* aStart);
|
||||
NS_IMETHOD SetActive(PRBool aActiveFlag) { return NS_OK; }; // We don't care.
|
||||
NS_IMETHOD GetIsActive(PRBool& isActive) { isActive = PR_FALSE; return NS_OK; };
|
||||
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) { isMenuBar = PR_FALSE; return NS_OK; };
|
||||
|
@ -161,7 +161,7 @@ public:
|
|||
PRBool IsValidItem(nsIContent* aContent);
|
||||
PRBool IsDisabled(nsIContent* aContent);
|
||||
|
||||
void GetContextMenu(nsIMenuParent** aContextMenu);
|
||||
nsIMenuParent* GetContextMenu();
|
||||
|
||||
NS_IMETHOD KillCloseTimer();
|
||||
|
||||
|
|
|
@ -177,8 +177,7 @@ nsPopupSetFrame::Destroy(nsPresContext* aPresContext)
|
|||
if (mPopupList) {
|
||||
// Try to hide any active popups
|
||||
if (nsMenuFrame::sDismissalListener) {
|
||||
nsCOMPtr<nsIMenuParent> menuParent;
|
||||
nsMenuFrame::sDismissalListener->GetCurrentMenuParent(getter_AddRefs(menuParent));
|
||||
nsIMenuParent *menuParent = nsMenuFrame::sDismissalListener->GetCurrentMenuParent();
|
||||
nsIFrame* frame;
|
||||
CallQueryInterface(menuParent, &frame);
|
||||
// Rollup popups, but only if they're ours
|
||||
|
@ -419,12 +418,13 @@ nsPopupSetFrame::HidePopup(nsIFrame* aPopup)
|
|||
mPresContext->PresShell()->GetPrimaryFrameFor(entry->mElementContent,
|
||||
&popupFrame);
|
||||
if (popupFrame) {
|
||||
nsCOMPtr<nsIMenuParent> menuParent(do_QueryInterface(popupFrame));
|
||||
if (menuParent)
|
||||
nsIMenuParent *menuParent;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) {
|
||||
menuParent->HideChain();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -450,12 +450,13 @@ nsPopupSetFrame::DestroyPopup(nsIFrame* aPopup, PRBool aDestroyEntireChain)
|
|||
mPresContext->PresShell()->GetPrimaryFrameFor(entry->mElementContent,
|
||||
&popupFrame);
|
||||
if (popupFrame) {
|
||||
nsCOMPtr<nsIMenuParent> menuParent(do_QueryInterface(popupFrame));
|
||||
if (menuParent)
|
||||
nsIMenuParent *menuParent;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) {
|
||||
menuParent->DismissChain();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear things out for next time
|
||||
entry->mCreateHandlerSucceeded = PR_FALSE;
|
||||
|
|
Загрузка…
Ссылка в новой задаче