зеркало из https://github.com/mozilla/gecko-dev.git
fixed bugs 21612 ([dogfood] first click doesn't get through to text field)
and 18500 (Can't drag-select in text widget unless focussed first) This fix does NOT address other focus-related problems having to do with text controls. r=rickg a=chofmann platform testing support=kin,dcone,akkana (THANKS!)
This commit is contained in:
Родитель
67b6e72f15
Коммит
8ec5958afa
|
@ -43,6 +43,12 @@
|
|||
#include "nsIFrameManager.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMHTMLTextAreaElement.h"
|
||||
// begin includes for controllers
|
||||
#include "nsIDOMNSHTMLInputElement.h"
|
||||
#include "nsIDOMNSHTMLTextAreaElement.h"
|
||||
#include "nsIDOMXULCommandDispatcher.h"
|
||||
#include "nsIControllers.h"
|
||||
// end includes for controllers
|
||||
#include "nsIScrollbar.h"
|
||||
|
||||
#include "nsCSSRendering.h"
|
||||
|
@ -120,6 +126,48 @@ static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
|
|||
//#define NOISY
|
||||
const nscoord kSuggestedNotSet = -1;
|
||||
|
||||
/*================== global functions =========================*/
|
||||
nsIWidget * GetDeepestWidget(nsIView * aView)
|
||||
{
|
||||
|
||||
PRInt32 count;
|
||||
aView->GetChildCount(count);
|
||||
if (0 != count) {
|
||||
for (PRInt32 i=0;i<count;i++) {
|
||||
nsIView * child;
|
||||
aView->GetChild(i, child);
|
||||
nsIWidget * widget = GetDeepestWidget(child);
|
||||
if (widget) {
|
||||
return widget;
|
||||
} else {
|
||||
aView->GetWidget(widget);
|
||||
if (widget) {
|
||||
nsCOMPtr<nsIScrollbar> scrollbar(do_QueryInterface(widget));
|
||||
if (scrollbar) {
|
||||
NS_RELEASE(widget);
|
||||
} else {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void GetWidgetForView(nsIView *aView, nsIWidget *&aWidget)
|
||||
{
|
||||
aWidget = nsnull;
|
||||
nsIView *view = aView;
|
||||
while (!aWidget && view)
|
||||
{
|
||||
view->GetWidget(aWidget);
|
||||
if (!aWidget)
|
||||
view->GetParent(view);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewGfxTextControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
||||
{
|
||||
|
@ -160,6 +208,15 @@ nsGfxTextControlFrame::Init(nsIPresContext* aPresContext,
|
|||
return (nsTextControlFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxTextControlFrame::GetFrameType(nsIAtom** aType) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
|
||||
*aType = NS_NewAtom("textControlFrame");
|
||||
NS_IF_ADDREF(*aType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxTextControlFrame::GetEditor(nsIEditor **aEditor)
|
||||
|
@ -191,18 +248,42 @@ nsGfxTextControlFrame::CreateEditor()
|
|||
mDocObserver->SetFrame(this);
|
||||
NS_ADDREF(mDocObserver);
|
||||
|
||||
// create the focus listener for HTML Input content
|
||||
// create the drag listener for the content node
|
||||
if (mContent)
|
||||
{
|
||||
mListenerForContent = new nsEnderListenerForContent();
|
||||
if (!mListenerForContent) { return NS_ERROR_OUT_OF_MEMORY; }
|
||||
mListenerForContent->SetFrame(this);
|
||||
NS_ADDREF(mListenerForContent);
|
||||
|
||||
// get the DOM event receiver
|
||||
nsCOMPtr<nsIDOMEventReceiver> contentER;
|
||||
result = mContent->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(contentER));
|
||||
if NS_FAILED(result) { return result; }
|
||||
if (contentER)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDragListener> dragListenerForContent;
|
||||
mListenerForContent->QueryInterface(nsIDOMDragListener::GetIID(), getter_AddRefs(dragListenerForContent));
|
||||
if (dragListenerForContent)
|
||||
{
|
||||
result = contentER->AddEventListenerByIID(dragListenerForContent, nsIDOMDragListener::GetIID());
|
||||
if NS_FAILED(result) { return result; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create the focus listener for HTML Input display content
|
||||
if (mDisplayContent)
|
||||
{
|
||||
mFocusListenerForContent = new nsEnderFocusListenerForContent();
|
||||
if (!mFocusListenerForContent) { return NS_ERROR_OUT_OF_MEMORY; }
|
||||
mFocusListenerForContent->SetFrame(this);
|
||||
NS_ADDREF(mFocusListenerForContent);
|
||||
mFocusListenerForDisplayContent = new nsEnderFocusListenerForDisplayContent();
|
||||
if (!mFocusListenerForDisplayContent) { return NS_ERROR_OUT_OF_MEMORY; }
|
||||
mFocusListenerForDisplayContent->SetFrame(this);
|
||||
NS_ADDREF(mFocusListenerForDisplayContent);
|
||||
// get the DOM event receiver
|
||||
nsCOMPtr<nsIDOMEventReceiver> er;
|
||||
result = mDisplayContent->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(er));
|
||||
if (NS_SUCCEEDED(result) && er)
|
||||
result = er->AddEventListenerByIID(mFocusListenerForContent, nsIDOMFocusListener::GetIID());
|
||||
result = er->AddEventListenerByIID(mFocusListenerForDisplayContent, nsIDOMFocusListener::GetIID());
|
||||
// should check to see if mDisplayContent or mContent has focus and call CreateSubDoc instead if it does
|
||||
// do something with result
|
||||
}
|
||||
|
@ -229,8 +310,8 @@ nsGfxTextControlFrame::nsGfxTextControlFrame()
|
|||
mWeakReferent(this),
|
||||
mFrameConstructor(nsnull),
|
||||
mDisplayFrame(nsnull),
|
||||
mDidSetFocus(PR_FALSE)
|
||||
|
||||
mDidSetFocus(PR_FALSE),
|
||||
mPassThroughMouseEvents(eUninitialized)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -255,22 +336,44 @@ nsGfxTextControlFrame::~nsGfxTextControlFrame()
|
|||
NS_RELEASE(mTempObserver);
|
||||
}
|
||||
|
||||
if (mDisplayContent && mFocusListenerForContent)
|
||||
// remove the focus listener from the display content, if any
|
||||
if (mDisplayContent && mFocusListenerForDisplayContent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventReceiver> er;
|
||||
result = mContent->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(er));
|
||||
result = mDisplayContent->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(er));
|
||||
if (NS_SUCCEEDED(result) && er)
|
||||
{
|
||||
er->RemoveEventListenerByIID(mFocusListenerForContent, nsIDOMFocusListener::GetIID());
|
||||
er->RemoveEventListenerByIID(mFocusListenerForDisplayContent, nsIDOMFocusListener::GetIID());
|
||||
}
|
||||
mFocusListenerForContent->SetFrame(nsnull);
|
||||
NS_RELEASE(mFocusListenerForContent);
|
||||
mFocusListenerForDisplayContent->SetFrame(nsnull);
|
||||
NS_RELEASE(mFocusListenerForDisplayContent);
|
||||
}
|
||||
|
||||
// remove the drag listener from the frame's content node, if any
|
||||
if (mContent && mListenerForContent)
|
||||
{
|
||||
// checking errors below does not good, I'm in a void method
|
||||
// I only check the minimum required to be sure it all works right
|
||||
nsCOMPtr<nsIDOMEventReceiver> contentER;
|
||||
result = mContent->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(contentER));
|
||||
if (NS_SUCCEEDED(result) && contentER)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDragListener> dragListenerForContent;
|
||||
mListenerForContent->QueryInterface(nsIDOMDragListener::GetIID(), getter_AddRefs(dragListenerForContent));
|
||||
if (dragListenerForContent)
|
||||
{
|
||||
contentER->RemoveEventListenerByIID(dragListenerForContent, nsIDOMDragListener::GetIID());
|
||||
}
|
||||
}
|
||||
mListenerForContent->SetFrame(nsnull);
|
||||
NS_RELEASE(mListenerForContent);
|
||||
}
|
||||
|
||||
if (mEventListener)
|
||||
{
|
||||
if (mEditor)
|
||||
{
|
||||
// remove selection listener
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result) && selection)
|
||||
|
@ -281,6 +384,7 @@ nsGfxTextControlFrame::~nsGfxTextControlFrame()
|
|||
selection->RemoveSelectionListener(selListener);
|
||||
}
|
||||
}
|
||||
// remove all other listeners from embedded document
|
||||
nsCOMPtr<nsIDOMDocument>domDoc;
|
||||
result = mEditor->GetDocument(getter_AddRefs(domDoc));
|
||||
if (NS_SUCCEEDED(result) && domDoc)
|
||||
|
@ -289,14 +393,17 @@ nsGfxTextControlFrame::~nsGfxTextControlFrame()
|
|||
result = domDoc->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(er));
|
||||
if (NS_SUCCEEDED(result) && er)
|
||||
{
|
||||
// remove key listener
|
||||
nsCOMPtr<nsIDOMKeyListener>keyListener;
|
||||
keyListener = do_QueryInterface(mEventListener);
|
||||
if (keyListener)
|
||||
er->RemoveEventListenerByIID(keyListener, nsIDOMKeyListener::GetIID());
|
||||
// remove mouse listener
|
||||
nsCOMPtr<nsIDOMMouseListener>mouseListener;
|
||||
mouseListener = do_QueryInterface(mEventListener);
|
||||
if (mouseListener)
|
||||
er->RemoveEventListenerByIID(mouseListener, nsIDOMMouseListener::GetIID());
|
||||
// remove focus listener
|
||||
nsCOMPtr<nsIDOMFocusListener>focusListener;
|
||||
focusListener = do_QueryInterface(mEventListener);
|
||||
if (focusListener)
|
||||
|
@ -333,36 +440,206 @@ NS_METHOD nsGfxTextControlFrame::HandleEvent(nsIPresContext* aPresContext,
|
|||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPresContext);
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
NS_ENSURE_ARG_POINTER(aEventStatus);
|
||||
|
||||
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aEventStatus = nsEventStatus_eConsumeDoDefault; // this is the default
|
||||
|
||||
switch (aEvent->message) {
|
||||
case NS_MOUSE_LEFT_CLICK:
|
||||
MouseClicked(aPresContext);
|
||||
break;
|
||||
|
||||
case NS_KEY_PRESS:
|
||||
if (NS_KEY_EVENT == aEvent->eventStructType) {
|
||||
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
|
||||
if (NS_VK_RETURN == keyEvent->keyCode)
|
||||
{
|
||||
EnterPressed(aPresContext);
|
||||
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
else if (NS_VK_SPACE == keyEvent->keyCode)
|
||||
{
|
||||
MouseClicked(aPresContext);
|
||||
}
|
||||
/* the handling of mouse messages here has two purposes:
|
||||
* 1) to create a subdoc if one doesn't exist on click, and to pass
|
||||
* mouse messages along to the content of the subdoc in the case
|
||||
* where we created it in response to a click.
|
||||
* 2) to call MouseClicked
|
||||
*/
|
||||
switch (aEvent->message) {
|
||||
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
||||
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||
case NS_MOUSE_RIGHT_BUTTON_DOWN:
|
||||
// don't pass through a click if we're already handling a click
|
||||
if (eGotDown != mPassThroughMouseEvents)
|
||||
{
|
||||
mPassThroughMouseEvents = eGotDown;
|
||||
if (!mWebShell) {
|
||||
NS_ENSURE_SUCCESS(CreateSubDoc(nsnull), NS_ERROR_FAILURE);
|
||||
}
|
||||
NS_ENSURE_TRUE(mWebShell, NS_ERROR_FAILURE);
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_MOUSE_LEFT_BUTTON_UP:
|
||||
case NS_MOUSE_MIDDLE_BUTTON_UP:
|
||||
case NS_MOUSE_RIGHT_BUTTON_UP:
|
||||
// only pass through the mouseUp if we're the one who handled the mouseDown
|
||||
if (eGotDown==mPassThroughMouseEvents)
|
||||
{
|
||||
mPassThroughMouseEvents = eGotUp;
|
||||
NS_ENSURE_TRUE(mWebShell, NS_ERROR_FAILURE);
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_MOUSE_LEFT_CLICK:
|
||||
case NS_MOUSE_MIDDLE_CLICK:
|
||||
case NS_MOUSE_RIGHT_CLICK:
|
||||
MouseClicked(aPresContext);
|
||||
// only pass through the mouseClick if we're the one who handled the mouseUp
|
||||
if (eGotUp==mPassThroughMouseEvents)
|
||||
{
|
||||
mPassThroughMouseEvents = eGotClick;
|
||||
NS_ENSURE_TRUE(mWebShell, NS_ERROR_FAILURE);
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_MOUSE_LEFT_DOUBLECLICK:
|
||||
case NS_MOUSE_MIDDLE_DOUBLECLICK:
|
||||
case NS_MOUSE_RIGHT_DOUBLECLICK:
|
||||
mPassThroughMouseEvents = eGotClick;
|
||||
NS_ENSURE_TRUE(mWebShell, NS_ERROR_FAILURE);
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_FALSE);
|
||||
break;
|
||||
|
||||
case NS_MOUSE_MOVE:
|
||||
// only pass through the mouseMove if we're the one who handled the mouseDown
|
||||
if (eGotDown==mPassThroughMouseEvents)
|
||||
{
|
||||
if (mWebShell) {
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_DRAGDROP_ENTER:
|
||||
case NS_DRAGDROP_OVER:
|
||||
case NS_DRAGDROP_DROP:
|
||||
case NS_DRAGDROP_EXIT:
|
||||
// currently unused
|
||||
break;
|
||||
|
||||
case NS_DRAGDROP_GESTURE:
|
||||
// this currently seems to have no effect
|
||||
NS_ENSURE_TRUE(mWebShell, NS_ERROR_FAILURE);
|
||||
return RedispatchMouseEventToSubDoc(aPresContext, aEvent, aEventStatus, PR_FALSE);
|
||||
break;
|
||||
|
||||
case NS_KEY_PRESS:
|
||||
if (NS_KEY_EVENT == aEvent->eventStructType) {
|
||||
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
|
||||
if (NS_VK_RETURN == keyEvent->keyCode)
|
||||
{
|
||||
EnterPressed(aPresContext);
|
||||
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
break;
|
||||
else if (NS_VK_SPACE == keyEvent->keyCode)
|
||||
{
|
||||
MouseClicked(aPresContext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxTextControlFrame::RedispatchMouseEventToSubDoc(nsIPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus,
|
||||
PRBool aAdjustForView)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPresContext);
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
NS_ENSURE_ARG_POINTER(aEventStatus);
|
||||
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
NS_ENSURE_SUCCESS(mWebShell->GetContentViewer(getter_AddRefs(viewer)), NS_ERROR_FAILURE);
|
||||
if (viewer)
|
||||
{
|
||||
nsCOMPtr<nsIDocumentViewer> docv;
|
||||
viewer->QueryInterface(kIDocumentViewerIID, getter_AddRefs(docv));
|
||||
if (docv)
|
||||
{
|
||||
nsCOMPtr<nsIPresContext> cx;
|
||||
NS_ENSURE_SUCCESS(docv->GetPresContext(*(getter_AddRefs(cx))), NS_ERROR_FAILURE);
|
||||
if (cx)
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
NS_ENSURE_SUCCESS(cx->GetShell(getter_AddRefs(shell)), NS_ERROR_FAILURE);
|
||||
if (shell)
|
||||
{
|
||||
nsIFrame * rootFrame;
|
||||
NS_ENSURE_SUCCESS(shell->GetRootFrame(&rootFrame), NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
NS_ENSURE_SUCCESS(shell->GetViewManager(getter_AddRefs(vm)), NS_ERROR_FAILURE);
|
||||
if (vm)
|
||||
{
|
||||
// create a new mouse event
|
||||
nsMouseEvent event;
|
||||
event = *((nsMouseEvent*)aEvent);
|
||||
// if we're told to, translate the event point based on the view of this text control
|
||||
if (PR_TRUE==aAdjustForView)
|
||||
{
|
||||
nsIView * view = nsnull;
|
||||
GetView(aPresContext, &view);
|
||||
NS_ASSERTION(view, "text control frame has no view");
|
||||
if (!view) { return NS_ERROR_NULL_POINTER;}
|
||||
nsRect viewBounds;
|
||||
view->GetBounds(viewBounds);
|
||||
event.point.x -= viewBounds.x;
|
||||
event.point.y -= viewBounds.y;
|
||||
}
|
||||
// translate the event point based on this frame's border and padding
|
||||
nsSize size;
|
||||
GetSize(size);
|
||||
nsRect subBounds;
|
||||
nsMargin border;
|
||||
nsMargin padding;
|
||||
border.SizeTo(0, 0, 0, 0);
|
||||
padding.SizeTo(0, 0, 0, 0);
|
||||
const nsStyleSpacing* spacing;
|
||||
GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
||||
spacing->CalcBorderFor(this, border);
|
||||
spacing->CalcPaddingFor(this, padding);
|
||||
CalcSizeOfSubDocInTwips(border, padding, size, subBounds);
|
||||
event.point.x -= (border.left + padding.left);
|
||||
if (0>event.point.x) {
|
||||
event.point.x = 0;
|
||||
}
|
||||
else if (event.point.x > subBounds.width) {
|
||||
event.point.x = subBounds.width-1;
|
||||
}
|
||||
event.point.y -= (border.top + padding.top);
|
||||
if (0>event.point.y) {
|
||||
event.point.y = 0;
|
||||
}
|
||||
else if (event.point.y > subBounds.height) {
|
||||
event.point.x = subBounds.height-1;
|
||||
}
|
||||
|
||||
// translate the event point to pixels for consumption by the embedded view manager
|
||||
nsCOMPtr<nsIDeviceContext> dc;
|
||||
aPresContext->GetDeviceContext(getter_AddRefs(dc));
|
||||
NS_ASSERTION(dc, "text control frame has no dc");
|
||||
if (!dc) { return NS_ERROR_NULL_POINTER;}
|
||||
float t2p;
|
||||
dc->GetAppUnitsToDevUnits(t2p);
|
||||
|
||||
event.point.x = NSTwipsToIntPixels(event.point.x, t2p);
|
||||
event.point.y = NSTwipsToIntPixels(event.point.y, t2p);
|
||||
NS_ENSURE_SUCCESS(vm->DispatchEvent(&event, aEventStatus), NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxTextControlFrame::EnterPressed(nsIPresContext* aPresContext)
|
||||
|
@ -1035,36 +1312,6 @@ NS_IMETHODIMP nsGfxTextControlFrame::GetProperty(nsIAtom* aName, nsString& aValu
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIWidget * GetDeepestWidget(nsIView * aView)
|
||||
{
|
||||
|
||||
PRInt32 count;
|
||||
aView->GetChildCount(count);
|
||||
if (0 != count) {
|
||||
for (PRInt32 i=0;i<count;i++) {
|
||||
nsIView * child;
|
||||
aView->GetChild(i, child);
|
||||
nsIWidget * widget = GetDeepestWidget(child);
|
||||
if (widget) {
|
||||
return widget;
|
||||
} else {
|
||||
aView->GetWidget(widget);
|
||||
if (widget) {
|
||||
nsCOMPtr<nsIScrollbar> scrollbar(do_QueryInterface(widget));
|
||||
if (scrollbar) {
|
||||
NS_RELEASE(widget);
|
||||
} else {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
void nsGfxTextControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
|
||||
{
|
||||
// !! IF REMOVING THIS ANY CODE HERE
|
||||
|
@ -1169,16 +1416,14 @@ nsGfxTextControlFrame::CreateWebShell(nsIPresContext* aPresContext,
|
|||
float t2p;
|
||||
aPresContext->GetTwipsToPixels(&t2p);
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
rv = aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
|
||||
// create, init, set the parent of the view
|
||||
nsIView* view;
|
||||
rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, kIViewIID,
|
||||
(void **)&view);
|
||||
if (NS_OK != rv) {
|
||||
NS_ASSERTION(0, "Could not create view for nsHTMLFrame");
|
||||
return rv;
|
||||
}
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
|
||||
nsIView* parView;
|
||||
nsPoint origin;
|
||||
|
@ -1192,8 +1437,10 @@ nsGfxTextControlFrame::CreateWebShell(nsIPresContext* aPresContext,
|
|||
nsCOMPtr<nsIViewManager> viewMan;
|
||||
presShell->GetViewManager(getter_AddRefs(viewMan));
|
||||
rv = view->Init(viewMan, viewBounds, parView);
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
viewMan->InsertChild(parView, view, 0);
|
||||
rv = view->CreateWidget(kCChildCID);
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
SetView(aPresContext, view);
|
||||
|
||||
// if the visibility is hidden, reflect that in the view
|
||||
|
@ -1215,12 +1462,13 @@ nsGfxTextControlFrame::CreateWebShell(nsIPresContext* aPresContext,
|
|||
NSToCoordRound((aSize.width - border.right) * t2p),
|
||||
NSToCoordRound((aSize.height - border.bottom) * t2p));
|
||||
|
||||
mWebShell->Init(widget->GetNativeData(NS_NATIVE_WIDGET),
|
||||
webBounds.x, webBounds.y,
|
||||
webBounds.width, webBounds.height,
|
||||
nsScrollPreference_kAuto, // auto scrolling
|
||||
PR_FALSE // turn off plugin hosting
|
||||
);
|
||||
rv = mWebShell->Init(widget->GetNativeData(NS_NATIVE_WIDGET),
|
||||
webBounds.x, webBounds.y,
|
||||
webBounds.width, webBounds.height,
|
||||
nsScrollPreference_kAuto, // auto scrolling
|
||||
PR_FALSE // turn off plugin hosting
|
||||
);
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
NS_RELEASE(widget);
|
||||
|
||||
#ifdef NEW_WEBSHELL_INTERFACES
|
||||
|
@ -1745,7 +1993,6 @@ nsGfxTextControlFrame::Reflow(nsIPresContext* aPresContext,
|
|||
subBoundsInPixels.y = NSToCoordRound(subBounds.y * t2p);
|
||||
subBoundsInPixels.width = NSToCoordRound(subBounds.width * t2p);
|
||||
subBoundsInPixels.height = NSToCoordRound(subBounds.height * t2p);
|
||||
|
||||
if (eReflowReason_Initial == aReflowState.reason)
|
||||
{
|
||||
if (!mWebShell)
|
||||
|
@ -1870,13 +2117,6 @@ nsGfxTextControlFrame::Reflow(nsIPresContext* aPresContext,
|
|||
#endif
|
||||
webShellWin->SetPositionAndSize(subBoundsInPixels.x, subBoundsInPixels.y,
|
||||
subBoundsInPixels.width, subBoundsInPixels.height, PR_FALSE);
|
||||
|
||||
#ifdef NOISY
|
||||
printf("webshell set to (%d, %d, %d %d)\n",
|
||||
borderPadding.left, borderPadding.top,
|
||||
(aDesiredSize.width - (borderPadding.left + borderPadding.right)),
|
||||
(aDesiredSize.height - (borderPadding.top + borderPadding.bottom)));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2053,32 +2293,6 @@ nsGfxTextControlFrame::GetFirstFrameForType(const nsString& aTag, nsIPresShell *
|
|||
return result;
|
||||
}
|
||||
|
||||
// XXX: this really should use a content iterator over the whole document
|
||||
// looking for the first and last editable text nodes
|
||||
nsresult
|
||||
nsGfxTextControlFrame::SelectAllTextContent(nsIDOMNode *aBodyNode, nsIDOMSelection *aSelection)
|
||||
{
|
||||
if (!aBodyNode || !aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
nsCOMPtr<nsIDOMNode>firstChild, lastChild;
|
||||
nsresult result = aBodyNode->GetFirstChild(getter_AddRefs(firstChild));
|
||||
if ((NS_SUCCEEDED(result)) && firstChild)
|
||||
{
|
||||
result = aBodyNode->GetLastChild(getter_AddRefs(lastChild));
|
||||
if ((NS_SUCCEEDED(result)) && lastChild)
|
||||
{
|
||||
aSelection->Collapse(firstChild, 0);
|
||||
nsCOMPtr<nsIDOMCharacterData>text = do_QueryInterface(lastChild);
|
||||
if (text)
|
||||
{
|
||||
PRUint32 length;
|
||||
text->GetLength(&length);
|
||||
aSelection->Extend(lastChild, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// XXX: wouldn't it be nice to get this from the style context!
|
||||
PRBool nsGfxTextControlFrame::IsSingleLineTextControl() const
|
||||
{
|
||||
|
@ -2517,6 +2731,33 @@ nsGfxTextControlFrame::InternalContentChanged()
|
|||
|
||||
// Have the content handle the event, propogating it according to normal DOM rules.
|
||||
nsresult result = mContent->HandleDOMEvent(mFramePresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
|
||||
|
||||
// update commands via controllers interface, if present
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> textInputDOMElement = do_QueryInterface(mContent);
|
||||
if (textInputDOMElement) {
|
||||
result = textInputDOMElement->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textAreaDOMElement = do_QueryInterface(mContent);
|
||||
if (textAreaDOMElement) {
|
||||
result = textAreaDOMElement->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
if (controllers)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXULCommandDispatcher> commandDispatcher;
|
||||
result = controllers->GetCommandDispatcher(getter_AddRefs(commandDispatcher));
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
if (commandDispatcher)
|
||||
{
|
||||
nsAutoString commandString("furby");
|
||||
result = commandDispatcher->UpdateCommands(commandString);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2945,6 +3186,8 @@ nsEnderEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/*================== nsIKeyListener =========================*/
|
||||
|
||||
nsresult
|
||||
nsEnderEventListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
|
@ -3111,17 +3354,7 @@ nsEnderEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
return result;
|
||||
}
|
||||
|
||||
void GetWidgetForView(nsIView *aView, nsIWidget *&aWidget)
|
||||
{
|
||||
aWidget = nsnull;
|
||||
nsIView *view = aView;
|
||||
while (!aWidget && view)
|
||||
{
|
||||
view->GetWidget(aWidget);
|
||||
if (!aWidget)
|
||||
view->GetParent(view);
|
||||
}
|
||||
}
|
||||
/*=============== nsIMouseListener ======================*/
|
||||
|
||||
nsresult
|
||||
nsEnderEventListener::DispatchMouseEvent(nsIDOMMouseEvent *aEvent, PRInt32 aEventType)
|
||||
|
@ -3348,6 +3581,7 @@ nsEnderEventListener::MouseDblClick(nsIDOMEvent* aEvent)
|
|||
nsresult
|
||||
nsEnderEventListener::MouseOver(nsIDOMEvent* aEvent)
|
||||
{
|
||||
/*
|
||||
nsCOMPtr<nsIDOMMouseEvent>mouseEvent;
|
||||
mouseEvent = do_QueryInterface(aEvent);
|
||||
if (!mouseEvent) { //non-key event passed in. bad things.
|
||||
|
@ -3363,6 +3597,8 @@ nsEnderEventListener::MouseOver(nsIDOMEvent* aEvent)
|
|||
}
|
||||
|
||||
return result;
|
||||
*/
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -3384,6 +3620,7 @@ nsEnderEventListener::MouseOut(nsIDOMEvent* aEvent)
|
|||
return result;
|
||||
}
|
||||
|
||||
/*=============== nsIFocusListener ======================*/
|
||||
|
||||
nsresult
|
||||
nsEnderEventListener::Focus(nsIDOMEvent* aEvent)
|
||||
|
@ -3530,14 +3767,14 @@ nsEnderEventListener::NotifySelectionChanged()
|
|||
|
||||
|
||||
/*******************************************************************************
|
||||
* nsEnderFocusListenerForContent
|
||||
* nsEnderFocusListenerForDisplayContent
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMPL_ADDREF(nsEnderFocusListenerForContent);
|
||||
NS_IMPL_RELEASE(nsEnderFocusListenerForContent);
|
||||
NS_IMPL_ADDREF(nsEnderFocusListenerForDisplayContent);
|
||||
NS_IMPL_RELEASE(nsEnderFocusListenerForDisplayContent);
|
||||
|
||||
nsresult
|
||||
nsEnderFocusListenerForContent::QueryInterface(const nsIID& aIID,
|
||||
nsEnderFocusListenerForDisplayContent::QueryInterface(const nsIID& aIID,
|
||||
void** aInstancePtr)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtr, "null pointer");
|
||||
|
@ -3557,25 +3794,25 @@ nsEnderFocusListenerForContent::QueryInterface(const nsIID& aIID,
|
|||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
nsEnderFocusListenerForContent::nsEnderFocusListenerForContent() :
|
||||
nsEnderFocusListenerForDisplayContent::nsEnderFocusListenerForDisplayContent() :
|
||||
mFrame(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsEnderFocusListenerForContent::~nsEnderFocusListenerForContent()
|
||||
nsEnderFocusListenerForDisplayContent::~nsEnderFocusListenerForDisplayContent()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEnderFocusListenerForContent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
nsEnderFocusListenerForDisplayContent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEnderFocusListenerForContent::Focus(nsIDOMEvent* aEvent)
|
||||
nsEnderFocusListenerForDisplayContent::Focus(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mFrame)
|
||||
{
|
||||
|
@ -3585,16 +3822,16 @@ nsEnderFocusListenerForContent::Focus(nsIDOMEvent* aEvent)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsEnderFocusListenerForContent::Blur (nsIDOMEvent* aEvent)
|
||||
nsEnderFocusListenerForDisplayContent::Blur (nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEnderFocusListenerForContent::SetFrame(nsGfxTextControlFrame *aFrame)
|
||||
nsEnderFocusListenerForDisplayContent::SetFrame(nsGfxTextControlFrame *aFrame)
|
||||
{
|
||||
mFrame = aFrame;
|
||||
mFrame = aFrame; // frames are not ref counted
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3714,3 +3951,118 @@ EnderTempObserver::SetFrame(nsGfxTextControlFrame *aFrame)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* nsEnderListenerForContent
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMPL_ADDREF(nsEnderListenerForContent);
|
||||
NS_IMPL_RELEASE(nsEnderListenerForContent);
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::QueryInterface(const nsIID& aIID,
|
||||
void** aInstancePtr)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtr, "null pointer");
|
||||
if (nsnull == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) {
|
||||
*aInstancePtr = (void*) ((nsIDOMMouseListener*)this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMDragListener))) {
|
||||
*aInstancePtr = (void*) ((nsIDOMDragListener*)this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*) ((nsISupports*)((nsIDOMFocusListener*)this));
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
nsEnderListenerForContent::nsEnderListenerForContent() :
|
||||
mFrame(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsEnderListenerForContent::~nsEnderListenerForContent()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
printf("frame forContent generic HandleEvent\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* XXX:
|
||||
drag events should be forwarded to the editor's own drag event listener?
|
||||
*/
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::DragGesture(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
printf("frame forContent DragGesture\n");
|
||||
// ...figure out if a drag should be started...
|
||||
|
||||
// ...until we have this implemented, just eat the drag event so it
|
||||
// ...doesn't leak out into the rest of the app/handlers.
|
||||
aDragEvent->PreventBubble();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::DragEnter(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
printf("frame forContent DragEnter\n");
|
||||
// see nsTextEditorDragListener
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::DragOver(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
printf("frame forContent DragOver\n");
|
||||
// see nsTextEditorDragListener
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::DragExit(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
printf("frame forContent DragExit\n");
|
||||
// see nsTextEditorDragListener
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsEnderListenerForContent::DragDrop(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
printf("frame forContent DragDrop\n");
|
||||
// see nsTextEditorDragListener
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEnderListenerForContent::SetFrame(nsGfxTextControlFrame *aFrame)
|
||||
{
|
||||
mFrame = aFrame; // frames are not ref counted
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMDragListener.h"
|
||||
#include "nsIDOMFocusListener.h"
|
||||
#include "nsIDOMSelectionListener.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include "nsITextContent.h"
|
||||
#include "nsHTMLValue.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIViewManager.h"
|
||||
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
|
||||
|
@ -299,16 +301,16 @@ protected:
|
|||
|
||||
|
||||
/******************************************************************************
|
||||
* nsEnderFocusListenerForContent
|
||||
* used to watch for focus notifications on the text control frame's content
|
||||
* nsEnderFocusListenerForDisplayContent
|
||||
* used to watch for focus notifications on the text control frame's display content
|
||||
******************************************************************************/
|
||||
|
||||
class nsEnderFocusListenerForContent : public nsIDOMFocusListener
|
||||
class nsEnderFocusListenerForDisplayContent : public nsIDOMFocusListener
|
||||
{
|
||||
public:
|
||||
|
||||
/** the default destructor */
|
||||
virtual ~nsEnderFocusListenerForContent();
|
||||
virtual ~nsEnderFocusListenerForDisplayContent();
|
||||
|
||||
/*interfaces for addref and release and queryinterface*/
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -321,12 +323,50 @@ public:
|
|||
|
||||
NS_IMETHOD SetFrame(nsGfxTextControlFrame *aFrame);
|
||||
|
||||
nsEnderFocusListenerForContent();
|
||||
nsEnderFocusListenerForDisplayContent();
|
||||
|
||||
protected:
|
||||
nsGfxTextControlFrame *mFrame; // not ref counted
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* nsEnderListenerForContent
|
||||
* used to watch for drag notifications on the text control frame's content
|
||||
******************************************************************************/
|
||||
|
||||
class nsEnderListenerForContent :
|
||||
public nsIDOMDragListener
|
||||
{
|
||||
public:
|
||||
|
||||
/** the default destructor */
|
||||
virtual ~nsEnderListenerForContent();
|
||||
|
||||
/*interfaces for addref and release and queryinterface*/
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/** nsIDOMDragListener interfaces
|
||||
* @see nsIDOMDragListener
|
||||
*/
|
||||
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
|
||||
virtual nsresult DragEnter(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragOver(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragExit(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragDrop(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragGesture(nsIDOMEvent* aDragEvent);
|
||||
/* END interfaces from nsIDOMDragListener*/
|
||||
|
||||
NS_IMETHOD SetFrame(nsGfxTextControlFrame *aFrame);
|
||||
|
||||
nsEnderListenerForContent();
|
||||
|
||||
protected:
|
||||
nsGfxTextControlFrame *mFrame; // not ref counted
|
||||
nsCOMPtr<nsIViewManager> mViewManager;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* nsGfxTextControlFrame
|
||||
* frame that represents an HTML text input element
|
||||
|
@ -343,6 +383,7 @@ private:
|
|||
typedef nsFormControlFrame Inherited;
|
||||
|
||||
public:
|
||||
|
||||
/** constructor */
|
||||
nsGfxTextControlFrame();
|
||||
|
||||
|
@ -361,6 +402,8 @@ public:
|
|||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
/** debug method to dump frames
|
||||
* @see nsIFrame
|
||||
|
@ -518,7 +561,13 @@ protected:
|
|||
|
||||
NS_IMETHOD GetFirstFrameForType(const nsString& aTag, nsIPresShell *aPresShell, nsIDOMDocument *aDOMDoc, nsIFrame **aResult);
|
||||
|
||||
NS_IMETHOD SelectAllTextContent(nsIDOMNode *aBodyNode, nsIDOMSelection *aSelection);
|
||||
/** create an event based on aEvent and pass it to the sub document mWebShell
|
||||
* via the sub document's view manager.
|
||||
*/
|
||||
NS_IMETHOD RedispatchMouseEventToSubDoc(nsIPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus,
|
||||
PRBool aAdjustForView);
|
||||
|
||||
virtual PRBool IsSingleLineTextControl() const;
|
||||
|
||||
|
@ -574,8 +623,9 @@ protected:
|
|||
nsCWeakReferent mWeakReferent; // so this obj can be used as a weak ptr
|
||||
|
||||
// listeners
|
||||
nsCOMPtr<nsIEnderEventListener> mEventListener; // ref counted
|
||||
nsEnderFocusListenerForContent *mFocusListenerForContent; // ref counted
|
||||
nsCOMPtr<nsIEnderEventListener> mEventListener; // ref counted
|
||||
nsEnderFocusListenerForDisplayContent *mFocusListenerForDisplayContent; // ref counted
|
||||
nsEnderListenerForContent *mListenerForContent; // ref counted
|
||||
|
||||
nsCSSFrameConstructor *mFrameConstructor;
|
||||
nsIFrame *mDisplayFrame;
|
||||
|
@ -587,6 +637,17 @@ protected:
|
|||
|
||||
PRBool mDidSetFocus; // init false,
|
||||
|
||||
// the PassThroughState is used to manage a tiny state machine so
|
||||
// only the proper messages get passed through
|
||||
enum PassThroughState
|
||||
{
|
||||
eUninitialized,
|
||||
eGotDown, // with my bad self
|
||||
eGotUp,
|
||||
eGotClick
|
||||
};
|
||||
PassThroughState mPassThroughMouseEvents;
|
||||
|
||||
private: // frames are not refcounted
|
||||
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
|
||||
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче