зеркало из https://github.com/mozilla/pjs.git
Bug 242833. Make nsDOMEvent::GetClientX/Y handle cases where a subdocument's widget is not an ancestor of the event's widget. Also forward all mouse grabbing to the root view manager of a view manager hierarchy so that subdocuments can grab the mouse when an event occurs in an outer document.
This commit is contained in:
Родитель
f8feba3ada
Коммит
1f65501541
|
@ -620,162 +620,112 @@ nsDOMEvent::GetReconversionReply(nsReconversionEventReply** aReply)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsDOMEvent::GetScreenX(PRInt32* aScreenX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aScreenX);
|
||||
nsPoint nsDOMEvent::GetScreenPoint() {
|
||||
if (!mEvent ||
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
!NS_IS_DRAG_EVENT(mEvent))) {
|
||||
*aScreenX = 0;
|
||||
return NS_OK;
|
||||
return nsPoint(0, 0);
|
||||
}
|
||||
|
||||
if (!((nsGUIEvent*)mEvent)->widget ) {
|
||||
*aScreenX = mScreenPoint.x;
|
||||
return NS_OK;
|
||||
return mScreenPoint;
|
||||
}
|
||||
|
||||
nsRect bounds, offset;
|
||||
bounds.x = mEvent->refPoint.x;
|
||||
|
||||
nsRect bounds(mEvent->refPoint, nsSize(1, 1));
|
||||
nsRect offset;
|
||||
((nsGUIEvent*)mEvent)->widget->WidgetToScreen ( bounds, offset );
|
||||
*aScreenX = offset.x;
|
||||
|
||||
return offset.TopLeft();
|
||||
}
|
||||
|
||||
NS_METHOD nsDOMEvent::GetScreenX(PRInt32* aScreenX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aScreenX);
|
||||
*aScreenX = GetScreenPoint().x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsDOMEvent::GetScreenY(PRInt32* aScreenY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aScreenY);
|
||||
if (!mEvent ||
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
!NS_IS_DRAG_EVENT(mEvent))) {
|
||||
*aScreenY = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!((nsGUIEvent*)mEvent)->widget ) {
|
||||
*aScreenY = mScreenPoint.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRect bounds, offset;
|
||||
bounds.y = mEvent->refPoint.y;
|
||||
|
||||
((nsGUIEvent*)mEvent)->widget->WidgetToScreen ( bounds, offset );
|
||||
*aScreenY = offset.y;
|
||||
|
||||
*aScreenY = GetScreenPoint().y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsDOMEvent::GetClientX(PRInt32* aClientX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClientX);
|
||||
nsPoint nsDOMEvent::GetClientPoint() {
|
||||
if (!mEvent ||
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
!NS_IS_DRAG_EVENT(mEvent)) ||
|
||||
!mPresContext) {
|
||||
*aClientX = 0;
|
||||
return NS_OK;
|
||||
return nsPoint(0, 0);
|
||||
}
|
||||
|
||||
if (!((nsGUIEvent*)mEvent)->widget ) {
|
||||
*aClientX = mClientPoint.x;
|
||||
return NS_OK;
|
||||
return mClientPoint;
|
||||
}
|
||||
|
||||
//My god, man, there *must* be a better way to do this.
|
||||
nsIWidget* rootWidget = nsnull;
|
||||
nsCOMPtr<nsIWidget> docWidget;
|
||||
nsIPresShell *presShell = mPresContext->GetPresShell();
|
||||
if (presShell) {
|
||||
nsIViewManager* vm = presShell->GetViewManager();
|
||||
if (vm) {
|
||||
vm->GetWidget(&rootWidget);
|
||||
vm->GetWidget(getter_AddRefs(docWidget));
|
||||
}
|
||||
}
|
||||
|
||||
nsPoint pt = mEvent->refPoint;
|
||||
|
||||
nsRect bounds, offset;
|
||||
offset.x = 0;
|
||||
|
||||
nsIWidget* parent = ((nsGUIEvent*)mEvent)->widget;
|
||||
//Add extra ref since loop will free one.
|
||||
NS_IF_ADDREF(parent);
|
||||
nsIWidget* tmp;
|
||||
while (rootWidget != parent && nsnull != parent) {
|
||||
nsCOMPtr<nsIWidget> eventWidget = ((nsGUIEvent*)mEvent)->widget;
|
||||
while (eventWidget && docWidget != eventWidget) {
|
||||
nsWindowType windowType;
|
||||
parent->GetWindowType(windowType);
|
||||
eventWidget->GetWindowType(windowType);
|
||||
if (windowType == eWindowType_popup)
|
||||
break;
|
||||
|
||||
parent->GetBounds(bounds);
|
||||
offset.x += bounds.x;
|
||||
tmp = parent;
|
||||
parent = tmp->GetParent();
|
||||
NS_RELEASE(tmp);
|
||||
nsRect bounds;
|
||||
eventWidget->GetBounds(bounds);
|
||||
pt += bounds.TopLeft();
|
||||
eventWidget = eventWidget->GetParent();
|
||||
}
|
||||
NS_IF_RELEASE(parent);
|
||||
NS_IF_RELEASE(rootWidget);
|
||||
|
||||
*aClientX = mEvent->refPoint.x + offset.x;
|
||||
if (eventWidget != docWidget) {
|
||||
// docWidget wasn't on the chain from the event widget to the root
|
||||
// of the widget tree (or the nearest popup). OK, so now pt is
|
||||
// relative to eventWidget; to get it relative to docWidget, we
|
||||
// need to subtract docWidget's offset from eventWidget.
|
||||
while (docWidget && docWidget != eventWidget) {
|
||||
nsWindowType windowType;
|
||||
docWidget->GetWindowType(windowType);
|
||||
if (windowType == eWindowType_popup) {
|
||||
// oh dear. the doc and the event were in different popups?
|
||||
// That shouldn't happen.
|
||||
NS_NOTREACHED("doc widget and event widget are in different popups. That's dumb.");
|
||||
break;
|
||||
}
|
||||
|
||||
nsRect bounds;
|
||||
docWidget->GetBounds(bounds);
|
||||
pt -= bounds.TopLeft();
|
||||
docWidget = docWidget->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
NS_METHOD nsDOMEvent::GetClientX(PRInt32* aClientX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClientX);
|
||||
*aClientX = GetClientPoint().x;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsDOMEvent::GetClientY(PRInt32* aClientY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClientY);
|
||||
if (!mEvent ||
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
!NS_IS_DRAG_EVENT(mEvent)) ||
|
||||
!mPresContext) {
|
||||
*aClientY = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!((nsGUIEvent*)mEvent)->widget ) {
|
||||
*aClientY = mClientPoint.y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//My god, man, there *must* be a better way to do this.
|
||||
nsIWidget* rootWidget = nsnull;
|
||||
nsIPresShell *presShell = mPresContext->GetPresShell();
|
||||
if (presShell) {
|
||||
nsIViewManager* vm = presShell->GetViewManager();
|
||||
if (vm) {
|
||||
vm->GetWidget(&rootWidget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsRect bounds, offset;
|
||||
offset.y = 0;
|
||||
|
||||
nsIWidget* parent = ((nsGUIEvent*)mEvent)->widget;
|
||||
//Add extra ref since loop will free one.
|
||||
NS_IF_ADDREF(parent);
|
||||
nsIWidget* tmp;
|
||||
while (rootWidget != parent && nsnull != parent) {
|
||||
nsWindowType windowType;
|
||||
parent->GetWindowType(windowType);
|
||||
if (windowType == eWindowType_popup)
|
||||
break;
|
||||
|
||||
parent->GetBounds(bounds);
|
||||
offset.y += bounds.y;
|
||||
tmp = parent;
|
||||
parent = tmp->GetParent();
|
||||
NS_RELEASE(tmp);
|
||||
}
|
||||
NS_IF_RELEASE(parent);
|
||||
NS_IF_RELEASE(rootWidget);
|
||||
|
||||
*aClientY = mEvent->refPoint.y + offset.y;
|
||||
*aClientY = GetClientPoint().y;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,6 +218,8 @@ protected:
|
|||
const char* GetEventName(PRUint32 aEventType);
|
||||
already_AddRefed<nsIDOMEventTarget> GetTargetFromFrame();
|
||||
void AllocateEvent(const nsAString& aEventType);
|
||||
nsPoint GetClientPoint();
|
||||
nsPoint GetScreenPoint();
|
||||
|
||||
nsEvent* mEvent;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
|
|
|
@ -2233,6 +2233,11 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBo
|
|||
|
||||
NS_IMETHODIMP nsViewManager::GrabMouseEvents(nsIView *aView, PRBool &aResult)
|
||||
{
|
||||
nsView* rootParent = RootView()->GetParent();
|
||||
if (rootParent) {
|
||||
return rootParent->GetViewManager()->GrabMouseEvents(aView, aResult);
|
||||
}
|
||||
|
||||
// Along with nsView::SetVisibility, we enforce that the mouse grabber
|
||||
// can never be a hidden view.
|
||||
if (aView && NS_STATIC_CAST(nsView*, aView)->GetVisibility()
|
||||
|
@ -2262,6 +2267,11 @@ NS_IMETHODIMP nsViewManager::GrabKeyEvents(nsIView *aView, PRBool &aResult)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::GetMouseEventGrabber(nsIView *&aView)
|
||||
{
|
||||
nsView* rootParent = RootView()->GetParent();
|
||||
if (rootParent) {
|
||||
return rootParent->GetViewManager()->GetMouseEventGrabber(aView);
|
||||
}
|
||||
|
||||
aView = mMouseGrabber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче