зеркало из https://github.com/mozilla/gecko-dev.git
Bug 364508, add api to synthesize events at the widget level, r+sr=roc
This commit is contained in:
Родитель
36d8e5b47b
Коммит
7d5c0e2d30
|
@ -45,7 +45,7 @@
|
|||
* getInterface on a DOMWindow.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(cc7f4216-ad89-4687-a793-980662bd10bd)]
|
||||
[scriptable, uuid(76cdfff8-6f13-43e8-9ed4-36066cd83742)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -81,4 +81,49 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
* Force an immediate redraw of this window.
|
||||
*/
|
||||
void redraw();
|
||||
|
||||
/** Synthesize a mouse event for a window. The event types supported
|
||||
* are:
|
||||
* mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu
|
||||
*
|
||||
* Events are sent in coordinates offset by aX and aY from the window.
|
||||
*
|
||||
* Note that additional events may be fired as a result of this call. For
|
||||
* instance, typically a click event will be fired as a result of a
|
||||
* mousedown and mouseup in sequence.
|
||||
*
|
||||
* Normally at this level of events, the mouseover and mouseout events are
|
||||
* only fired when the window is entered or exited. For inter-element
|
||||
* mouseover and mouseout events, a movemove event fired on the new element
|
||||
* should be sufficient to generate the correct over and out events as well.
|
||||
*
|
||||
* @param aType event type
|
||||
* @param aX x offset
|
||||
* @param aY y offset
|
||||
* @param aButton button to synthesize
|
||||
* @param aClickCount number of clicks that have been performed
|
||||
* @param aModifiers modifiers pressed, using constants defined in nsIDOMNSEvent
|
||||
*/
|
||||
void sendMouseEvent(in AString aType,
|
||||
in long aX,
|
||||
in long aY,
|
||||
in long aButton,
|
||||
in long aClickCount,
|
||||
in long aModifiers);
|
||||
|
||||
/**
|
||||
* Synthesize a key event to the window. The event types supported are:
|
||||
* keydown, keyup, keypress
|
||||
*
|
||||
* Key events generally end up being sent to the focused node.
|
||||
*
|
||||
* @param aType event type
|
||||
* @param aKeyCode key code
|
||||
* @param aCharCode character code
|
||||
* @param aModifiers modifiers pressed, using constants defined in nsIDOMNSEvent
|
||||
*/
|
||||
void sendKeyEvent(in AString aType,
|
||||
in long aKeyCode,
|
||||
in long aCharCode,
|
||||
in long aModifiers);
|
||||
};
|
||||
|
|
|
@ -39,14 +39,19 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
|
||||
#include "nsDOMWindowUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFocusController.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_GTK2
|
||||
#include <gdk/gdkx.h>
|
||||
|
@ -155,3 +160,111 @@ nsDOMWindowUtils::Redraw()
|
|||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SendMouseEvent(const nsAString& aType,
|
||||
PRInt32 aX,
|
||||
PRInt32 aY,
|
||||
PRInt32 aButton,
|
||||
PRInt32 aClickCount,
|
||||
PRInt32 aModifiers)
|
||||
{
|
||||
PRBool hasCap = PR_FALSE;
|
||||
if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled("UniversalXPConnect", &hasCap))
|
||||
|| !hasCap)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
// get the widget to send the event to
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 msg;
|
||||
if (aType.EqualsLiteral("mousedown"))
|
||||
msg = NS_MOUSE_BUTTON_DOWN;
|
||||
else if (aType.EqualsLiteral("mouseup"))
|
||||
msg = NS_MOUSE_BUTTON_UP;
|
||||
else if (aType.EqualsLiteral("mousemove"))
|
||||
msg = NS_MOUSE_MOVE;
|
||||
else if (aType.EqualsLiteral("mouseover"))
|
||||
msg = NS_MOUSE_ENTER;
|
||||
else if (aType.EqualsLiteral("mouseout"))
|
||||
msg = NS_MOUSE_EXIT;
|
||||
else if (aType.EqualsLiteral("contextmenu"))
|
||||
msg = NS_CONTEXTMENU;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsMouseEvent event(PR_TRUE, msg, widget, nsMouseEvent::eReal);
|
||||
event.isShift = (aModifiers & nsIDOMNSEvent::SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isControl = (aModifiers & nsIDOMNSEvent::CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isAlt = (aModifiers & nsIDOMNSEvent::ALT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isMeta = (aModifiers & nsIDOMNSEvent::META_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.button = aButton;
|
||||
event.widget = widget;
|
||||
|
||||
event.clickCount = aClickCount;
|
||||
event.time = PR_IntervalNow();
|
||||
event.refPoint.x = aX;
|
||||
event.refPoint.y = aY;
|
||||
|
||||
nsEventStatus status;
|
||||
return widget->DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
|
||||
PRInt32 aKeyCode,
|
||||
PRInt32 aCharCode,
|
||||
PRInt32 aModifiers)
|
||||
{
|
||||
PRBool hasCap = PR_FALSE;
|
||||
if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled("UniversalXPConnect", &hasCap))
|
||||
|| !hasCap)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
// get the widget to send the event to
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 msg;
|
||||
if (aType.EqualsLiteral("keydown"))
|
||||
msg = NS_KEY_DOWN;
|
||||
else if (aType.EqualsLiteral("keyup"))
|
||||
msg = NS_KEY_UP;
|
||||
else if (aType.EqualsLiteral("keypress"))
|
||||
msg = NS_KEY_PRESS;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsKeyEvent event(PR_TRUE, msg, widget);
|
||||
event.isShift = (aModifiers & nsIDOMNSEvent::SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isControl = (aModifiers & nsIDOMNSEvent::CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isAlt = (aModifiers & nsIDOMNSEvent::ALT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
event.isMeta = (aModifiers & nsIDOMNSEvent::META_MASK) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
event.keyCode = aKeyCode;
|
||||
event.charCode = aCharCode;
|
||||
event.refPoint.x = event.refPoint.y = 0;
|
||||
event.time = PR_IntervalNow();
|
||||
|
||||
nsEventStatus status;
|
||||
return widget->DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
nsDOMWindowUtils::GetWidget()
|
||||
{
|
||||
if (mWindow) {
|
||||
nsIDocShell *docShell = mWindow->GetDocShell();
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
if (presShell)
|
||||
return presShell->GetRootFrame()->GetWindow();
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
|
|
@ -53,4 +53,6 @@ public:
|
|||
|
||||
protected:
|
||||
nsRefPtr<nsGlobalWindow> mWindow;
|
||||
|
||||
nsIWidget* GetWidget();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче