From 212ea7c4a4dcf5734f20dcf3c2bb1242268a1c5d Mon Sep 17 00:00:00 2001 From: "brettw%gmail.com" Date: Tue, 15 Nov 2005 02:00:32 +0000 Subject: [PATCH] bug 271498: context menus should appear at cursor when using the keyboard r=bryner sr=roc git-svn-id: svn://10.0.0.236/trunk@184629 18797224-902f-48f8-a5cc-f745e15eee43 --- .../events/src/nsEventListenerManager.cpp | 149 ++++++++++++++++-- .../events/src/nsEventListenerManager.h | 3 + 2 files changed, 140 insertions(+), 12 deletions(-) diff --git a/mozilla/content/events/src/nsEventListenerManager.cpp b/mozilla/content/events/src/nsEventListenerManager.cpp index e8ddd0dc502..d86fe61bc7c 100644 --- a/mozilla/content/events/src/nsEventListenerManager.cpp +++ b/mozilla/content/events/src/nsEventListenerManager.cpp @@ -39,6 +39,8 @@ #include "nsGUIEvent.h" #include "nsDOMEvent.h" #include "nsEventListenerManager.h" +#include "nsICaret.h" +#include "nsIFrameSelection.h" #include "nsIDOMNSEvent.h" #include "nsIDOMEventListener.h" #include "nsIDOMMouseListener.h" @@ -57,6 +59,7 @@ #include "nsIDOMMutationListener.h" #include "nsIDOMUIListener.h" #include "nsIDOMPageTransitionListener.h" +#include "nsITextControlFrame.h" #ifdef MOZ_SVG #include "nsIDOMSVGListener.h" #include "nsIDOMSVGZoomListener.h" @@ -2239,26 +2242,148 @@ nsEventListenerManager::FixContextMenuEvent(nsPresContext* aPresContext, if (aEvent->message == NS_CONTEXTMENU_KEY) NS_IF_RELEASE(((nsGUIEvent*)aEvent)->widget); // nulls out widget ret = NS_NewDOMMouseEvent(aDOMEvent, aPresContext, NS_STATIC_CAST(nsInputEvent*, aEvent)); + NS_ENSURE_SUCCESS(ret, ret); } - if (NS_SUCCEEDED(ret)) { - // update the target - if (currentFocus) { - // Reset event coordinates relative to focused frame in view - nsPoint targetPt; - GetCoordinatesFor(currentFocus, aPresContext, shell, targetPt); - aEvent->refPoint.x = targetPt.x; - aEvent->refPoint.y = targetPt.y; + // see if we should use the caret position for the popup + PRBool useCaretPosition = PR_FALSE; + nsPoint caretPoint; + if (aEvent->message == NS_CONTEXTMENU_KEY) { + useCaretPosition = PrepareToUseCaretPosition(((nsGUIEvent*)aEvent)->widget, + shell, caretPoint); + } - currentTarget = do_QueryInterface(currentFocus); - nsCOMPtr pEvent(do_QueryInterface(*aDOMEvent)); - pEvent->SetTarget(currentTarget); - } + if (useCaretPosition) { + aEvent->refPoint.x = caretPoint.x; + aEvent->refPoint.y = caretPoint.y; + } else if (currentFocus) { + // Reset event coordinates relative to focused frame in view + nsPoint targetPt; + GetCoordinatesFor(currentFocus, aPresContext, shell, targetPt); + aEvent->refPoint.x = targetPt.x; + aEvent->refPoint.y = targetPt.y; + + currentTarget = do_QueryInterface(currentFocus); + nsCOMPtr pEvent(do_QueryInterface(*aDOMEvent)); + pEvent->SetTarget(currentTarget); } return ret; } +// nsEventListenerManager::PrepareToUseCaretPosition +// +// This checks to see if we should use the caret position for popup context +// menus. Returns true if the caret position should be used, and the window +// coordinates of that position are placed into WindowX/Y. This function +// will also scroll the window as needed to make the caret visible. +// +// The event widget should be the widget that generated the event, and +// whose coordinate system the resulting event's refPoint should be +// relative to. + +PRBool +nsEventListenerManager::PrepareToUseCaretPosition(nsIWidget* aEventWidget, + nsIPresShell* aShell, + nsPoint& aTargetPt) +{ + nsresult rv; + + // check caret visibility + nsCOMPtr caret; + rv = aShell->GetCaret(getter_AddRefs(caret)); + NS_ENSURE_SUCCESS(rv, PR_FALSE); + + PRBool caretVisible = PR_FALSE; + rv = caret->GetCaretVisible(&caretVisible); + if (NS_FAILED(rv) || ! caretVisible) + return PR_FALSE; + + // caret selection + nsCOMPtr domSelection; + rv = caret->GetCaretDOMSelection(getter_AddRefs(domSelection)); + NS_ENSURE_SUCCESS(rv, PR_FALSE); + + // since the match could be an anonymous textnode inside a + //