Bug 295285 - onpopupshowing does not expose accesskeys (event.shiftKey) r=enn

This commit is contained in:
Jan Varga 2011-07-09 09:41:32 +02:00
Родитель 73fb32b307
Коммит c4cdffded8
4 изменённых файлов: 78 добавлений и 12 удалений

Просмотреть файл

@ -767,6 +767,9 @@ protected:
// root prescontext's root frame.
nsIntPoint mCachedMousePoint;
// cached modifiers
PRInt8 mCachedModifiers;
// set to the currently active menu bar, if any
nsMenuBarFrame* mActiveMenuBar;

Просмотреть файл

@ -73,6 +73,11 @@
#include "nsIObserverService.h"
#include "mozilla/Services.h"
#define FLAG_ALT 0x01
#define FLAG_CONTROL 0x02
#define FLAG_SHIFT 0x04
#define FLAG_META 0x08
const nsNavigationDirection DirectionFromKeyCodeTable[2][6] = {
{
eNavigationDirection_Last, // NS_VK_END
@ -140,6 +145,7 @@ NS_IMPL_ISUPPORTS4(nsXULPopupManager,
nsXULPopupManager::nsXULPopupManager() :
mRangeOffset(0),
mCachedMousePoint(0, 0),
mCachedModifiers(0),
mActiveMenuBar(nsnull),
mPopups(nsnull),
mNoHidePanels(nsnull),
@ -462,6 +468,8 @@ nsXULPopupManager::InitTriggerEvent(nsIDOMEvent* aEvent, nsIContent* aPopup,
}
}
mCachedModifiers = 0;
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aEvent);
if (uiEvent) {
uiEvent->GetRangeParent(getter_AddRefs(mRangeParent));
@ -475,6 +483,22 @@ nsXULPopupManager::InitTriggerEvent(nsIDOMEvent* aEvent, nsIContent* aPopup,
nsEvent* event;
event = privateEvent->GetInternalNSEvent();
if (event) {
if (event->eventStructType == NS_MOUSE_EVENT ||
event->eventStructType == NS_KEY_EVENT) {
nsInputEvent* inputEvent = static_cast<nsInputEvent*>(event);
if (inputEvent->isAlt) {
mCachedModifiers |= FLAG_ALT;
}
if (inputEvent->isControl) {
mCachedModifiers |= FLAG_CONTROL;
}
if (inputEvent->isShift) {
mCachedModifiers |= FLAG_SHIFT;
}
if (inputEvent->isMeta) {
mCachedModifiers |= FLAG_META;
}
}
nsIDocument* doc = aPopup->GetCurrentDoc();
if (doc) {
nsIPresShell* presShell = doc->GetShell();
@ -1187,10 +1211,19 @@ nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup,
}
event.refPoint = mCachedMousePoint;
event.isAlt = !!(mCachedModifiers & FLAG_ALT);
event.isControl = !!(mCachedModifiers & FLAG_CONTROL);
event.isShift = !!(mCachedModifiers & FLAG_SHIFT);
event.isMeta = !!(mCachedModifiers & FLAG_META);
nsEventDispatcher::Dispatch(popup, presContext, &event, nsnull, &status);
mCachedMousePoint = nsIntPoint(0, 0);
mOpeningPopup = nsnull;
mCachedModifiers = 0;
// if a panel, blur whatever has focus so that the panel can take the focus.
// This is done after the popupshowing event in case that event is cancelled.
// Using noautofocus="true" will disable this behaviour, which is needed for

Просмотреть файл

@ -3,6 +3,22 @@ var gTrigger = null;
var gIsMenu = false;
var gScreenX = -1, gScreenY = -1;
var gCachedEvent = null;
var gCachedEvent2 = null;
function cacheEvent(modifiers)
{
var cachedEvent = null;
var mouseFn = function(event) {
cachedEvent = event;
}
window.addEventListener("mousedown", mouseFn, false);
synthesizeMouse(document.documentElement, 0, 0, modifiers);
window.removeEventListener("mousedown", mouseFn, false);
return cachedEvent;
}
function runTests()
{
@ -15,17 +31,13 @@ function runTests()
gIsMenu = gTrigger.boxObject instanceof Components.interfaces.nsIMenuBoxObject;
var mouseFn = function(event) {
gScreenX = event.screenX;
gScreenY = event.screenY;
// cache the event so that we can use it in calls to openPopup
gCachedEvent = event;
}
// a hacky way to get the screen position of the document. Cache the event
// so that we can use it in calls to openPopup.
gCachedEvent = cacheEvent({ shiftKey: true });
gScreenX = gCachedEvent.screenX;
gScreenY = gCachedEvent.screenY;
gCachedEvent2 = cacheEvent({ altKey: true, ctrlKey: true, shiftKey: true, metaKey: true });
// a hacky way to get the screen position of the document
window.addEventListener("mousedown", mouseFn, false);
synthesizeMouse(document.documentElement, 0, 0, { });
window.removeEventListener("mousedown", mouseFn, false);
startPopupTests(popupTests);
}
@ -254,7 +266,7 @@ var popupTests = [
// can be used to override the popup's position. This test also passes an
// event to openPopup to check the trigger node.
testname: "open popup anchored with override",
events: [ "popupshowing thepopup", "popupshown thepopup" ],
events: [ "popupshowing thepopup 0010", "popupshown thepopup" ],
test: function(testname, step) {
// attribute overrides the position passed in
gMenuPopup.setAttribute("position", "end_after");
@ -403,7 +415,7 @@ var popupTests = [
},
{
testname: "open context popup at screen",
events: [ "popupshowing thepopup", "popupshown thepopup" ],
events: [ "popupshowing thepopup 0010", "popupshown thepopup" ],
test: function(testname, step) {
gExpectedTriggerNode = gCachedEvent.target;
gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent);
@ -558,6 +570,14 @@ var popupTests = [
checkActive(gMenuPopup, "", testname);
}
},
{
testname: "open context popup at screen with all modifiers set",
events: [ "popupshowing thepopup 1111", "popupshown thepopup" ],
autohide: "thepopup",
test: function(testname, step) {
gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent2);
}
},
{
testname: "open popup with open property",
events: [ "popupshowing thepopup", "popupshown thepopup" ],

Просмотреть файл

@ -133,6 +133,16 @@ function eventOccurred(event)
matches = eventitem[0] == event.type && eventitem[1] == event.target.id;
}
var modifiersMask = eventitem[2];
if (modifiersMask) {
var m = "";
m += event.altKey ? '1' : '0';
m += event.ctrlKey ? '1' : '0';
m += event.shiftKey ? '1' : '0';
m += event.metaKey ? '1' : '0';
is(m, modifiersMask, test.testname + " modifiers mask matches");
}
var expectedState;
switch (event.type) {
case "popupshowing": expectedState = "showing"; break;