/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sts=2 sw=2 et cin: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
using mozilla::LinkedListElement; using mozilla::dom::Element;
class StatusBarEntry final : public LinkedListElement<RefPtr<StatusBarEntry>>, public IconLoader::Listener, public nsISupports { public: explicit StatusBarEntry(Element* aMenu);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(StatusBarEntry)
nsresult Init(); void Destroy();
// First, look at the content node's "image" attribute.
nsAutoString imageURIString; bool hasImageAttr = mMenu->GetAttr(nsGkAtoms::image, imageURIString);
nsresult rv;
nsCOMPtr<nsIURI> iconURI; if (!hasImageAttr) { // If the content node has no "image" attribute, get the // "list-style-image" property from CSS.
RefPtr<mozilla::dom::Document> document = mMenu->GetComposedDoc(); if (!document) { return NS_ERROR_FAILURE;
}
// If this menu item shouldn't have an icon, the string will be empty, // and NS_NewURI will fail.
rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString); if (NS_FAILED(rv)) return rv;
}
mIconLoader = new IconLoader(this);
if (iconURI) {
rv = mIconLoader->LoadIcon(iconURI, mMenu);
}
if (mIconData.hIcon) {
::DestroyIcon(mIconData.hIcon);
mIconData.hIcon = nullptr;
}
// To simplify things, we won't react to CSS changes to update the icon // with this implementation. We can get rid of the IconLoader at this point.
mIconLoader->Destroy();
mIconLoader = nullptr; return NS_OK;
}
nsMenuPopupFrame* popupFrame = menu->GetMenuPopup(FlushType::None); if (NS_WARN_IF(!popupFrame)) { returnTRUE;
}
nsIWidget* widget = popupFrame->GetNearestWidget();
MOZ_DIAGNOSTIC_ASSERT(widget); if (!widget) { returnTRUE;
}
HWND win = static_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
MOZ_DIAGNOSTIC_ASSERT(win); if (!win) { returnTRUE;
}
if (LOWORD(lp) == NIN_KEYSELECT && ::GetForegroundWindow() == win) { // When enter is pressed on the icon, the shell sends two NIN_KEYSELECT // notifications. This might cause us to open two windows. To work around // this, if we're already the foreground window (which happens below), // ignore this notification. returnTRUE;
}
nsPresContext* pc = popupFrame->PresContext(); const CSSIntPoint point = gfx::RoundedToInt(
LayoutDeviceIntPoint(GET_X_LPARAM(wp), GET_Y_LPARAM(wp)) /
pc->CSSToDevPixelScale());
// The menu that is being opened is a Gecko <xul:menu>, and the popup code // that manages it expects that the window that the <xul:menu> belongs to // will be in the foreground when it opens. If we don't do this, then if the // icon is clicked when the window is _not_ in the foreground, then the // opened menu will not be keyboard focusable, nor will it close on its own // if the user clicks away from the menu (at least, not until the user // focuses any window in the parent process).
::SetForegroundWindow(win);
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
pm->ShowPopupAtScreen(popupFrame->GetContent()->AsElement(), point.x,
point.y, false, nullptr);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.