зеркало из https://github.com/mozilla/pjs.git
Fix bug 74404: show caret drag feedback. r=brade, sr=kin
This commit is contained in:
Родитель
81e95afad3
Коммит
0fce5c3a3b
|
@ -385,6 +385,8 @@ nsHTMLEditor::InstallEventListeners()
|
|||
NS_ASSERTION(mDocWeak, "no document set on this editor");
|
||||
if (!mDocWeak) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result;
|
||||
// get a key listener
|
||||
result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
||||
|
@ -421,7 +423,8 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n");
|
|||
}
|
||||
|
||||
// get a drag listener
|
||||
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this);
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
|
||||
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), presShell, this);
|
||||
if (NS_FAILED(result)) {
|
||||
HandleEventListenerError();
|
||||
return result;
|
||||
|
@ -4216,7 +4219,8 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva
|
|||
mIMEBufferLength = aCompositionString.Length();
|
||||
|
||||
ps->GetCaret(getter_AddRefs(caretP));
|
||||
caretP->SetCaretDOMSelection(selection);
|
||||
if (caretP)
|
||||
caretP->SetCaretDOMSelection(selection);
|
||||
|
||||
// second part of 23558 fix:
|
||||
if (aCompositionString.IsEmpty())
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIPlaintextEditor.h"
|
||||
#include "nsICaret.h"
|
||||
|
||||
/** The nsTextEditorKeyListener public nsIDOMKeyListener
|
||||
* This class will delegate events to its editor according to the translation
|
||||
|
@ -207,7 +208,8 @@ public:
|
|||
/** SetEditor gives an address to the editor that will be accessed
|
||||
* @param aEditor the editor this listener calls for editing operations
|
||||
*/
|
||||
void SetEditor(nsIEditor *aEditor){mEditor = aEditor;}
|
||||
void SetEditor(nsIEditor *aEditor) { mEditor = aEditor; }
|
||||
void SetPresShell(nsIPresShell *aPresShell) { mPresShell = aPresShell; }
|
||||
|
||||
/*interfaces for addref and release and queryinterface*/
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -222,7 +224,16 @@ public:
|
|||
/*END implementations of dragevent handler interface*/
|
||||
|
||||
protected:
|
||||
|
||||
PRBool CanDrop(nsIDOMEvent* aEvent);
|
||||
|
||||
protected:
|
||||
|
||||
nsIEditor* mEditor;
|
||||
nsIPresShell* mPresShell;
|
||||
|
||||
nsCOMPtr<nsICaret> mCaret;
|
||||
PRBool mCaretDrawn;
|
||||
|
||||
};
|
||||
|
||||
|
@ -272,7 +283,8 @@ extern nsresult NS_NewEditorTextListener(nsIDOMEventListener** aInstancePtrResul
|
|||
|
||||
/** factory for the editor drag listener
|
||||
*/
|
||||
extern nsresult NS_NewEditorDragListener(nsIDOMEventListener ** aInstancePtrResult, nsIEditor *aEditor);
|
||||
extern nsresult NS_NewEditorDragListener(nsIDOMEventListener ** aInstancePtrResult, nsIPresShell* aPresShell,
|
||||
nsIEditor *aEditor);
|
||||
|
||||
/** factory for the editor composition listener
|
||||
*/
|
||||
|
|
|
@ -361,6 +361,8 @@ nsPlaintextEditor::InstallEventListeners()
|
|||
NS_ASSERTION(mDocWeak, "no document set on this editor");
|
||||
if (!mDocWeak) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result;
|
||||
// get a key listener
|
||||
result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
||||
|
@ -397,7 +399,8 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n");
|
|||
}
|
||||
|
||||
// get a drag listener
|
||||
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this);
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
|
||||
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), presShell, this);
|
||||
if (NS_FAILED(result)) {
|
||||
HandleEventListenerError();
|
||||
return result;
|
||||
|
@ -1958,7 +1961,8 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI
|
|||
mIMEBufferLength = aCompositionString.Length();
|
||||
|
||||
ps->GetCaret(getter_AddRefs(caretP));
|
||||
caretP->SetCaretDOMSelection(selection);
|
||||
if (caretP)
|
||||
caretP->SetCaretDOMSelection(selection);
|
||||
|
||||
// second part of 23558 fix:
|
||||
if (aCompositionString.IsEmpty())
|
||||
|
|
|
@ -96,6 +96,9 @@ nsCaret::nsCaret()
|
|||
, mLastCaretFrame(nsnull)
|
||||
, mLastCaretView(nsnull)
|
||||
, mLastContentOffset(0)
|
||||
#ifdef IBMBIDI
|
||||
, mKeyboardRTL(PR_FALSE)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -109,52 +112,56 @@ nsCaret::~nsCaret()
|
|||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
|
||||
{
|
||||
if (!inPresShell)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_ENSURE_ARG(inPresShell);
|
||||
|
||||
mPresShell = getter_AddRefs(NS_GetWeakReference(inPresShell)); // the presshell owns us, so no addref
|
||||
NS_ASSERTION(mPresShell, "Hey, pres shell should support weak refs");
|
||||
|
||||
nsILookAndFeel* touchyFeely;
|
||||
if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kLookAndFeelCID, nsnull, NS_GET_IID(nsILookAndFeel), (void**)&touchyFeely)))
|
||||
// get nsILookAndFeel from the pres context, which has one cached.
|
||||
nsCOMPtr<nsILookAndFeel> lookAndFeel;
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
inPresShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext)
|
||||
presContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
|
||||
if (lookAndFeel)
|
||||
{
|
||||
PRInt32 tempInt;
|
||||
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
|
||||
mCaretTwipsWidth = (nscoord)tempInt;
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
|
||||
mCaretPixelsWidth = (nscoord)tempInt;
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
|
||||
mBlinkRate = (PRUint32)tempInt;
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
|
||||
mShowDuringSelection = tempInt ? PR_TRUE : PR_FALSE;
|
||||
|
||||
NS_RELEASE(touchyFeely);
|
||||
}
|
||||
|
||||
// get the selection from the pres shell, and set ourselves up as a selection
|
||||
// listener
|
||||
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection;
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon = do_QueryReferent(mPresShell);
|
||||
if (selCon)
|
||||
{
|
||||
if (NS_SUCCEEDED(selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))))
|
||||
{
|
||||
privateSelection = do_QueryInterface(domSelection);
|
||||
privateSelection->AddSelectionListener(this);
|
||||
mDomSelectionWeak = getter_AddRefs( NS_GetWeakReference(domSelection) );
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!selCon)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!domSelection)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection);
|
||||
if (privateSelection)
|
||||
privateSelection->AddSelectionListener(this);
|
||||
mDomSelectionWeak = getter_AddRefs(NS_GetWeakReference(domSelection));
|
||||
|
||||
// set up the blink timer
|
||||
if (mVisible)
|
||||
{
|
||||
nsresult err = StartBlinking();
|
||||
if (NS_FAILED(err))
|
||||
return err;
|
||||
rv = StartBlinking();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI
|
||||
PRBool isRTL;
|
||||
mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1");
|
||||
|
@ -166,43 +173,39 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
|
|||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMPL_ADDREF(nsCaret);
|
||||
NS_IMPL_RELEASE(nsCaret);
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::QueryInterface(const nsIID& aIID,
|
||||
void** aInstancePtrResult)
|
||||
NS_IMETHODIMP nsCaret::Terminate()
|
||||
{
|
||||
// this doesn't erase the caret if it's drawn. Should it? We might not have a good
|
||||
// drawing environment during teardown.
|
||||
|
||||
KillTimer();
|
||||
mBlinkTimer = nsnull;
|
||||
|
||||
mRendContext = nsnull;
|
||||
|
||||
NS_PRECONDITION(aInstancePtrResult, "null pointer");
|
||||
if (!aInstancePtrResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// unregiser ourselves as a selection listener
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (privateSelection)
|
||||
privateSelection->RemoveSelectionListener(this);
|
||||
mDomSelectionWeak = nsnull;
|
||||
mPresShell = nsnull;
|
||||
|
||||
nsISupports* foundInterface;
|
||||
mLastCaretFrame = nsnull;
|
||||
mLastCaretView = nsnull;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
mBidiKeyboard = nsnull;
|
||||
#endif
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsISupports)))
|
||||
foundInterface = (nsISupports*)(nsICaret*)this; // whoo boy
|
||||
else if (aIID.Equals(NS_GET_IID(nsICaret)))
|
||||
foundInterface = (nsICaret*)this;
|
||||
else if (aIID.Equals(NS_GET_IID(nsISelectionListener)))
|
||||
foundInterface = (nsISelectionListener*)this;
|
||||
else
|
||||
foundInterface = nsnull;
|
||||
|
||||
nsresult status;
|
||||
if (! foundInterface)
|
||||
status = NS_NOINTERFACE;
|
||||
else
|
||||
{
|
||||
NS_ADDREF(foundInterface);
|
||||
status = NS_OK;
|
||||
}
|
||||
|
||||
*aInstancePtrResult = foundInterface;
|
||||
return status;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMPL_ISUPPORTS2(nsCaret, nsICaret, nsISelectionListener);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::GetCaretDOMSelection(nsISelection **aDOMSel)
|
||||
{
|
||||
|
@ -236,6 +239,8 @@ NS_IMETHODIMP nsCaret::SetCaretVisible(PRBool inMakeVisible)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::GetCaretVisible(PRBool *outMakeVisible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outMakeVisible);
|
||||
|
@ -259,11 +264,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!outCoordinates || !outIsCollapsed)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = aDOMSel;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
nsresult err;
|
||||
if (!domSelection)
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = aDOMSel;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!privateSelection)
|
||||
return NS_ERROR_NOT_INITIALIZED; // no selection
|
||||
|
||||
if (outView)
|
||||
|
@ -276,7 +280,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
outCoordinates->height = -1;
|
||||
*outIsCollapsed = PR_FALSE;
|
||||
|
||||
err = domSelection->GetIsCollapsed(outIsCollapsed);
|
||||
nsresult err = domSelection->GetIsCollapsed(outIsCollapsed);
|
||||
if (NS_FAILED(err))
|
||||
return err;
|
||||
|
||||
|
@ -333,7 +337,6 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
nsRect clipRect;
|
||||
nsIView *drawingView; // views are not refcounted
|
||||
|
||||
|
||||
GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView);
|
||||
if (!drawingView)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -411,6 +414,37 @@ NS_IMETHODIMP nsCaret::EraseCaret()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
|
||||
{
|
||||
if (aPixels <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// no need to optimize this, but if it gets too slow, we can check for
|
||||
// case aPixels==mCaretPixelsWidth
|
||||
mCaretPixelsWidth = aPixels;
|
||||
mCaretTwipsWidth = -1;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
|
||||
{
|
||||
mShowDuringSelection = aVisibility;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
|
||||
{
|
||||
NS_ENSURE_ARG(aNode);
|
||||
|
||||
// XXX we need to do more work here to get the correct hint.
|
||||
if (!SetupDrawingFrameAndOffset(aNode, aOffset, nsIFrameSelection::HINTLEFT))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
GetCaretRectAndInvert();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
|
@ -511,30 +545,9 @@ nsresult nsCaret::StopBlinking()
|
|||
// Get the nsIFrame and the content offset for the current caret position.
|
||||
// Returns PR_TRUE if we should go ahead and draw, PR_FALSE otherwise.
|
||||
//
|
||||
PRBool nsCaret::SetupDrawingFrameAndOffset()
|
||||
{
|
||||
if (!mDomSelectionWeak)
|
||||
return PR_FALSE;
|
||||
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!domSelection) return PR_FALSE;
|
||||
|
||||
PRBool isCollapsed = PR_FALSE;
|
||||
domSelection->GetIsCollapsed(&isCollapsed);
|
||||
if (!mShowDuringSelection && !isCollapsed) return PR_FALSE;
|
||||
|
||||
// start and end parent should be the same since we are collapsed
|
||||
nsCOMPtr<nsIDOMNode> focusNode;
|
||||
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||
if (!focusNode) return PR_FALSE;
|
||||
|
||||
PRInt32 contentOffset;
|
||||
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
|
||||
PRBool nsCaret::SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint)
|
||||
{
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(aNode);
|
||||
if (!contentNode) return PR_FALSE;
|
||||
|
||||
//get frame selection and find out what frame to use...
|
||||
|
@ -547,15 +560,11 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
|||
if (!frameSelection)
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool hintRight;
|
||||
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
|
||||
nsIFrameSelection::HINT hint;
|
||||
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||
|
||||
nsIFrame* theFrame = nsnull;
|
||||
PRInt32 theFrameOffset = 0;
|
||||
|
||||
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
||||
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, aOffset, aFrameHint, &theFrame, &theFrameOffset);
|
||||
if (NS_FAILED(rv) || !theFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -608,7 +617,7 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
|||
if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset)
|
||||
{
|
||||
/* Boundary condition, we need to know the Bidi levels of the characters before and after the cursor */
|
||||
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, contentOffset,
|
||||
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, aOffset,
|
||||
&frameBefore, &frameAfter,
|
||||
&levelBefore, &levelAfter)))
|
||||
{
|
||||
|
@ -915,10 +924,10 @@ PRBool nsCaret::MustDrawCaret()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mDrawn)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
if (mDrawn)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
if (!domSelection)
|
||||
return PR_FALSE;
|
||||
PRBool isCollapsed;
|
||||
|
@ -948,10 +957,38 @@ void nsCaret::DrawCaret()
|
|||
// if we are drawing, not erasing, then set up the frame etc.
|
||||
if (!mDrawn)
|
||||
{
|
||||
if (!SetupDrawingFrameAndOffset())
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!privateSelection) return;
|
||||
|
||||
PRBool isCollapsed = PR_FALSE;
|
||||
domSelection->GetIsCollapsed(&isCollapsed);
|
||||
if (!mShowDuringSelection && !isCollapsed)
|
||||
return;
|
||||
|
||||
PRBool hintRight;
|
||||
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
|
||||
nsIFrameSelection::HINT hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||
|
||||
// get the node and offset, which is where we want the caret to draw
|
||||
nsCOMPtr<nsIDOMNode> focusNode;
|
||||
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||
if (!focusNode)
|
||||
return;
|
||||
|
||||
PRInt32 contentOffset;
|
||||
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||
return;
|
||||
|
||||
if (!SetupDrawingFrameAndOffset(focusNode, contentOffset, hint))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GetCaretRectAndInvert();
|
||||
}
|
||||
|
||||
void nsCaret::GetCaretRectAndInvert()
|
||||
{
|
||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
||||
|
||||
nsRect frameRect;
|
||||
|
@ -978,7 +1015,7 @@ void nsCaret::DrawCaret()
|
|||
return;
|
||||
|
||||
// if the view changed, or we don't have a rendering context, make one
|
||||
// because of drawing issues, always make a new RC at the momemt. See bug 28068
|
||||
// because of drawing issues, always make a new RC at the moment. See bug 28068
|
||||
if (
|
||||
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||
PR_TRUE ||
|
||||
|
@ -1045,9 +1082,8 @@ void nsCaret::DrawCaret()
|
|||
|
||||
caretRect += mCachedFrameOffset;
|
||||
|
||||
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
||||
if(mCaretTwipsWidth < 0)
|
||||
{// need to re-compute the pixel width
|
||||
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
|
||||
{
|
||||
float tDevUnitsToTwips = 15;
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
presContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
@ -1151,6 +1187,7 @@ void nsCaret::DrawCaret()
|
|||
mRendContext->SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
||||
else
|
||||
mRendContext->SetColor(NS_RGB(255,255,255));
|
||||
|
||||
mRendContext->InvertRect(mCaretRect);
|
||||
|
||||
// Ensure the buffer is flushed (Cocoa needs this), since we're drawing
|
||||
|
@ -1162,7 +1199,7 @@ void nsCaret::DrawCaret()
|
|||
mRendContext->InvertRect(mHookRect);
|
||||
#endif
|
||||
|
||||
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
|
||||
PRBool emptyClip;
|
||||
mRendContext->PopState(emptyClip);
|
||||
|
||||
ToggleDrawnStatus();
|
||||
|
@ -1199,20 +1236,3 @@ nsresult NS_NewCaret(nsICaret** aInstancePtrResult)
|
|||
return caret->QueryInterface(NS_GET_IID(nsICaret), (void**) aInstancePtrResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
|
||||
{
|
||||
if(!aPixels)
|
||||
return NS_ERROR_FAILURE;
|
||||
else
|
||||
{ //no need to optimize this, but if it gets too slow, we can check for case aPixels==mCaretPixelsWidth
|
||||
mCaretPixelsWidth = aPixels;
|
||||
mCaretTwipsWidth = -1;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
|
||||
{
|
||||
mShowDuringSelection = aVisibility;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -34,12 +34,6 @@
|
|||
|
||||
class nsIView;
|
||||
|
||||
class nsISelectionController;
|
||||
|
||||
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
||||
#define NS_CARET_CID \
|
||||
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } };
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsCaret : public nsICaret,
|
||||
|
@ -56,6 +50,7 @@ class nsCaret : public nsICaret,
|
|||
|
||||
// nsICaret interface
|
||||
NS_IMETHOD Init(nsIPresShell *inPresShell);
|
||||
NS_IMETHOD Terminate();
|
||||
|
||||
NS_IMETHOD GetCaretDOMSelection(nsISelection **outDOMSel);
|
||||
NS_IMETHOD SetCaretDOMSelection(nsISelection *inDOMSel);
|
||||
|
@ -68,6 +63,7 @@ class nsCaret : public nsICaret,
|
|||
|
||||
NS_IMETHOD SetCaretWidth(nscoord aPixels);
|
||||
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
|
||||
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
|
||||
|
||||
//nsISelectionListener interface
|
||||
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
|
||||
|
@ -83,9 +79,10 @@ class nsCaret : public nsICaret,
|
|||
nsresult StopBlinking();
|
||||
|
||||
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView);
|
||||
PRBool SetupDrawingFrameAndOffset();
|
||||
PRBool SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint);
|
||||
PRBool MustDrawCaret();
|
||||
void DrawCaret();
|
||||
void GetCaretRectAndInvert();
|
||||
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
||||
|
||||
protected:
|
||||
|
@ -98,7 +95,7 @@ protected:
|
|||
|
||||
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
||||
|
||||
nscoord mCaretTwipsWidth; // caret width in twips
|
||||
nscoord mCaretTwipsWidth; // caret width in twips. this gets calculated laziiy
|
||||
nscoord mCaretPixelsWidth; // caret width in pixels
|
||||
|
||||
PRPackedBool mVisible; // is the caret blinking
|
||||
|
@ -114,11 +111,9 @@ protected:
|
|||
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
|
||||
PRInt32 mLastContentOffset;
|
||||
#ifdef IBMBIDI
|
||||
//---------------------------------------IBMBIDI----------------------------------------------
|
||||
nsRect mHookRect; // directional hook on the caret
|
||||
nsCOMPtr<nsIBidiKeyboard> mBidiKeyboard; // Bidi keyboard object to set and query keyboard language
|
||||
PRPackedBool mKeyboardRTL; // is the keyboard language right-to-left
|
||||
//-------------------------------------END OF IBM BIDI----------------------------------------
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -42,13 +42,15 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
struct nsRect;
|
||||
struct nsPoint;
|
||||
|
||||
class nsIRenderingContext;
|
||||
class nsIFrame;
|
||||
class nsIView;
|
||||
class nsIPresShell;
|
||||
struct nsRect;
|
||||
struct nsPoint;
|
||||
class nsISelection;
|
||||
class nsIDOMNode;
|
||||
|
||||
// IID for the nsICaret interface
|
||||
#define NS_ICARET_IID \
|
||||
|
@ -59,14 +61,15 @@ class nsICaret: public nsISupports
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICARET_IID)
|
||||
|
||||
typedef enum EViewCoordinates {
|
||||
enum EViewCoordinates {
|
||||
eTopLevelWindowCoordinates,
|
||||
eRenderingViewCoordinates,
|
||||
eClosestViewCoordinates,
|
||||
eIMECoordinates
|
||||
} EViewCoordinates;
|
||||
};
|
||||
|
||||
NS_IMETHOD Init(nsIPresShell *inPresShell) = 0;
|
||||
NS_IMETHOD Terminate() = 0;
|
||||
|
||||
NS_IMETHOD GetCaretDOMSelection(nsISelection **aDOMSel) = 0;
|
||||
NS_IMETHOD SetCaretDOMSelection(nsISelection *aDOMSel) = 0;
|
||||
|
@ -112,6 +115,16 @@ public:
|
|||
NS_IMETHOD SetCaretWidth(nscoord aPixels) = 0;
|
||||
|
||||
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibilityDuringSelection) = 0;
|
||||
|
||||
/** DrawAtPosition
|
||||
*
|
||||
* Draw the caret explicitly, at the specified node and offset.
|
||||
* To avoid drawing glitches, you should call EraseCaret()
|
||||
* after each call to DrawAtPosition().
|
||||
*
|
||||
**/
|
||||
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
|
||||
|
||||
};
|
||||
|
||||
extern nsresult NS_NewCaret(nsICaret** aInstancePtrResult);
|
||||
|
|
|
@ -1184,7 +1184,7 @@ public:
|
|||
// caret handling
|
||||
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
|
||||
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
|
||||
NS_IMETHOD SetCaretWidth(PRInt16 twips);
|
||||
NS_IMETHOD SetCaretWidth(PRInt16 aPixels);
|
||||
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
|
||||
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
|
||||
|
||||
|
@ -1776,6 +1776,11 @@ PresShell::Destroy()
|
|||
mPaintSuppressionTimer = nsnull;
|
||||
}
|
||||
|
||||
if (mCaret) {
|
||||
mCaret->Terminate();
|
||||
mCaret = nsnull;
|
||||
}
|
||||
|
||||
// release our pref style sheet, if we have one still
|
||||
ClearPreferenceStyleRules();
|
||||
|
||||
|
@ -2725,8 +2730,8 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
|
|||
|
||||
// notice that we ignore the result
|
||||
NotifyReflowObservers(NS_PRESSHELL_INITIAL_REFLOW);
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
WillCauseReflow();
|
||||
|
||||
|
@ -2901,8 +2906,9 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
|||
NotifyReflowObservers(NS_PRESSHELL_RESIZE_REFLOW);
|
||||
mViewManager->CacheWidgetChanges(PR_TRUE);
|
||||
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
WillCauseReflow();
|
||||
|
||||
if (mPresContext) {
|
||||
|
@ -3100,11 +3106,14 @@ PresShell::GetFrameManager(nsIFrameManager** aFrameManager) const
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// note that this can return a null caret, but NS_OK
|
||||
NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret)
|
||||
{
|
||||
if (!outCaret || !mCaret)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return mCaret->QueryInterface(NS_GET_IID(nsICaret), (void **)outCaret);
|
||||
NS_ENSURE_ARG_POINTER(outCaret);
|
||||
|
||||
*outCaret = mCaret;
|
||||
NS_IF_ADDREF(*outCaret);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
|
||||
|
@ -3129,17 +3138,21 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
|
|||
|
||||
NS_IMETHODIMP PresShell::SetCaretWidth(PRInt16 pixels)
|
||||
{
|
||||
return mCaret->SetCaretWidth(pixels);
|
||||
if (mCaret)
|
||||
mCaret->SetCaretWidth(pixels);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::SetCaretReadOnly(PRBool aReadOnly)
|
||||
{
|
||||
return mCaret->SetCaretReadOnly(aReadOnly);
|
||||
if (mCaret)
|
||||
mCaret->SetCaretReadOnly(aReadOnly);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::GetCaretEnabled(PRBool *aOutEnabled)
|
||||
{
|
||||
if (!aOutEnabled) { return NS_ERROR_INVALID_ARG; }
|
||||
NS_ENSURE_ARG_POINTER(aOutEnabled);
|
||||
*aOutEnabled = mCaretEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -5755,8 +5768,8 @@ PresShell::Paint(nsIView *aView,
|
|||
|
||||
if (nsnull != frame)
|
||||
{
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
// If the frame is absolutely positioned, then the 'clip' property
|
||||
// applies
|
||||
|
|
|
@ -42,13 +42,15 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
struct nsRect;
|
||||
struct nsPoint;
|
||||
|
||||
class nsIRenderingContext;
|
||||
class nsIFrame;
|
||||
class nsIView;
|
||||
class nsIPresShell;
|
||||
struct nsRect;
|
||||
struct nsPoint;
|
||||
class nsISelection;
|
||||
class nsIDOMNode;
|
||||
|
||||
// IID for the nsICaret interface
|
||||
#define NS_ICARET_IID \
|
||||
|
@ -59,14 +61,15 @@ class nsICaret: public nsISupports
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICARET_IID)
|
||||
|
||||
typedef enum EViewCoordinates {
|
||||
enum EViewCoordinates {
|
||||
eTopLevelWindowCoordinates,
|
||||
eRenderingViewCoordinates,
|
||||
eClosestViewCoordinates,
|
||||
eIMECoordinates
|
||||
} EViewCoordinates;
|
||||
};
|
||||
|
||||
NS_IMETHOD Init(nsIPresShell *inPresShell) = 0;
|
||||
NS_IMETHOD Terminate() = 0;
|
||||
|
||||
NS_IMETHOD GetCaretDOMSelection(nsISelection **aDOMSel) = 0;
|
||||
NS_IMETHOD SetCaretDOMSelection(nsISelection *aDOMSel) = 0;
|
||||
|
@ -112,6 +115,16 @@ public:
|
|||
NS_IMETHOD SetCaretWidth(nscoord aPixels) = 0;
|
||||
|
||||
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibilityDuringSelection) = 0;
|
||||
|
||||
/** DrawAtPosition
|
||||
*
|
||||
* Draw the caret explicitly, at the specified node and offset.
|
||||
* To avoid drawing glitches, you should call EraseCaret()
|
||||
* after each call to DrawAtPosition().
|
||||
*
|
||||
**/
|
||||
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
|
||||
|
||||
};
|
||||
|
||||
extern nsresult NS_NewCaret(nsICaret** aInstancePtrResult);
|
||||
|
|
|
@ -96,6 +96,9 @@ nsCaret::nsCaret()
|
|||
, mLastCaretFrame(nsnull)
|
||||
, mLastCaretView(nsnull)
|
||||
, mLastContentOffset(0)
|
||||
#ifdef IBMBIDI
|
||||
, mKeyboardRTL(PR_FALSE)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -109,52 +112,56 @@ nsCaret::~nsCaret()
|
|||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
|
||||
{
|
||||
if (!inPresShell)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_ENSURE_ARG(inPresShell);
|
||||
|
||||
mPresShell = getter_AddRefs(NS_GetWeakReference(inPresShell)); // the presshell owns us, so no addref
|
||||
NS_ASSERTION(mPresShell, "Hey, pres shell should support weak refs");
|
||||
|
||||
nsILookAndFeel* touchyFeely;
|
||||
if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kLookAndFeelCID, nsnull, NS_GET_IID(nsILookAndFeel), (void**)&touchyFeely)))
|
||||
// get nsILookAndFeel from the pres context, which has one cached.
|
||||
nsCOMPtr<nsILookAndFeel> lookAndFeel;
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
inPresShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext)
|
||||
presContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
|
||||
if (lookAndFeel)
|
||||
{
|
||||
PRInt32 tempInt;
|
||||
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
|
||||
mCaretTwipsWidth = (nscoord)tempInt;
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
|
||||
mCaretPixelsWidth = (nscoord)tempInt;
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
|
||||
mBlinkRate = (PRUint32)tempInt;
|
||||
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
|
||||
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
|
||||
mShowDuringSelection = tempInt ? PR_TRUE : PR_FALSE;
|
||||
|
||||
NS_RELEASE(touchyFeely);
|
||||
}
|
||||
|
||||
// get the selection from the pres shell, and set ourselves up as a selection
|
||||
// listener
|
||||
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection;
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon = do_QueryReferent(mPresShell);
|
||||
if (selCon)
|
||||
{
|
||||
if (NS_SUCCEEDED(selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))))
|
||||
{
|
||||
privateSelection = do_QueryInterface(domSelection);
|
||||
privateSelection->AddSelectionListener(this);
|
||||
mDomSelectionWeak = getter_AddRefs( NS_GetWeakReference(domSelection) );
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!selCon)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!domSelection)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection);
|
||||
if (privateSelection)
|
||||
privateSelection->AddSelectionListener(this);
|
||||
mDomSelectionWeak = getter_AddRefs(NS_GetWeakReference(domSelection));
|
||||
|
||||
// set up the blink timer
|
||||
if (mVisible)
|
||||
{
|
||||
nsresult err = StartBlinking();
|
||||
if (NS_FAILED(err))
|
||||
return err;
|
||||
rv = StartBlinking();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI
|
||||
PRBool isRTL;
|
||||
mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1");
|
||||
|
@ -166,43 +173,39 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
|
|||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMPL_ADDREF(nsCaret);
|
||||
NS_IMPL_RELEASE(nsCaret);
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::QueryInterface(const nsIID& aIID,
|
||||
void** aInstancePtrResult)
|
||||
NS_IMETHODIMP nsCaret::Terminate()
|
||||
{
|
||||
// this doesn't erase the caret if it's drawn. Should it? We might not have a good
|
||||
// drawing environment during teardown.
|
||||
|
||||
KillTimer();
|
||||
mBlinkTimer = nsnull;
|
||||
|
||||
mRendContext = nsnull;
|
||||
|
||||
NS_PRECONDITION(aInstancePtrResult, "null pointer");
|
||||
if (!aInstancePtrResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// unregiser ourselves as a selection listener
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (privateSelection)
|
||||
privateSelection->RemoveSelectionListener(this);
|
||||
mDomSelectionWeak = nsnull;
|
||||
mPresShell = nsnull;
|
||||
|
||||
nsISupports* foundInterface;
|
||||
mLastCaretFrame = nsnull;
|
||||
mLastCaretView = nsnull;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
mBidiKeyboard = nsnull;
|
||||
#endif
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsISupports)))
|
||||
foundInterface = (nsISupports*)(nsICaret*)this; // whoo boy
|
||||
else if (aIID.Equals(NS_GET_IID(nsICaret)))
|
||||
foundInterface = (nsICaret*)this;
|
||||
else if (aIID.Equals(NS_GET_IID(nsISelectionListener)))
|
||||
foundInterface = (nsISelectionListener*)this;
|
||||
else
|
||||
foundInterface = nsnull;
|
||||
|
||||
nsresult status;
|
||||
if (! foundInterface)
|
||||
status = NS_NOINTERFACE;
|
||||
else
|
||||
{
|
||||
NS_ADDREF(foundInterface);
|
||||
status = NS_OK;
|
||||
}
|
||||
|
||||
*aInstancePtrResult = foundInterface;
|
||||
return status;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMPL_ISUPPORTS2(nsCaret, nsICaret, nsISelectionListener);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::GetCaretDOMSelection(nsISelection **aDOMSel)
|
||||
{
|
||||
|
@ -236,6 +239,8 @@ NS_IMETHODIMP nsCaret::SetCaretVisible(PRBool inMakeVisible)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsCaret::GetCaretVisible(PRBool *outMakeVisible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outMakeVisible);
|
||||
|
@ -259,11 +264,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!outCoordinates || !outIsCollapsed)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = aDOMSel;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
nsresult err;
|
||||
if (!domSelection)
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = aDOMSel;
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!privateSelection)
|
||||
return NS_ERROR_NOT_INITIALIZED; // no selection
|
||||
|
||||
if (outView)
|
||||
|
@ -276,7 +280,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
outCoordinates->height = -1;
|
||||
*outIsCollapsed = PR_FALSE;
|
||||
|
||||
err = domSelection->GetIsCollapsed(outIsCollapsed);
|
||||
nsresult err = domSelection->GetIsCollapsed(outIsCollapsed);
|
||||
if (NS_FAILED(err))
|
||||
return err;
|
||||
|
||||
|
@ -333,7 +337,6 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
|
|||
nsRect clipRect;
|
||||
nsIView *drawingView; // views are not refcounted
|
||||
|
||||
|
||||
GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView);
|
||||
if (!drawingView)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -411,6 +414,37 @@ NS_IMETHODIMP nsCaret::EraseCaret()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
|
||||
{
|
||||
if (aPixels <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// no need to optimize this, but if it gets too slow, we can check for
|
||||
// case aPixels==mCaretPixelsWidth
|
||||
mCaretPixelsWidth = aPixels;
|
||||
mCaretTwipsWidth = -1;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
|
||||
{
|
||||
mShowDuringSelection = aVisibility;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
|
||||
{
|
||||
NS_ENSURE_ARG(aNode);
|
||||
|
||||
// XXX we need to do more work here to get the correct hint.
|
||||
if (!SetupDrawingFrameAndOffset(aNode, aOffset, nsIFrameSelection::HINTLEFT))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
GetCaretRectAndInvert();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
|
@ -511,30 +545,9 @@ nsresult nsCaret::StopBlinking()
|
|||
// Get the nsIFrame and the content offset for the current caret position.
|
||||
// Returns PR_TRUE if we should go ahead and draw, PR_FALSE otherwise.
|
||||
//
|
||||
PRBool nsCaret::SetupDrawingFrameAndOffset()
|
||||
{
|
||||
if (!mDomSelectionWeak)
|
||||
return PR_FALSE;
|
||||
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!domSelection) return PR_FALSE;
|
||||
|
||||
PRBool isCollapsed = PR_FALSE;
|
||||
domSelection->GetIsCollapsed(&isCollapsed);
|
||||
if (!mShowDuringSelection && !isCollapsed) return PR_FALSE;
|
||||
|
||||
// start and end parent should be the same since we are collapsed
|
||||
nsCOMPtr<nsIDOMNode> focusNode;
|
||||
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||
if (!focusNode) return PR_FALSE;
|
||||
|
||||
PRInt32 contentOffset;
|
||||
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
|
||||
PRBool nsCaret::SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint)
|
||||
{
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(aNode);
|
||||
if (!contentNode) return PR_FALSE;
|
||||
|
||||
//get frame selection and find out what frame to use...
|
||||
|
@ -547,15 +560,11 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
|||
if (!frameSelection)
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool hintRight;
|
||||
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
|
||||
nsIFrameSelection::HINT hint;
|
||||
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||
|
||||
nsIFrame* theFrame = nsnull;
|
||||
PRInt32 theFrameOffset = 0;
|
||||
|
||||
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
||||
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, aOffset, aFrameHint, &theFrame, &theFrameOffset);
|
||||
if (NS_FAILED(rv) || !theFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -608,7 +617,7 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
|||
if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset)
|
||||
{
|
||||
/* Boundary condition, we need to know the Bidi levels of the characters before and after the cursor */
|
||||
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, contentOffset,
|
||||
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, aOffset,
|
||||
&frameBefore, &frameAfter,
|
||||
&levelBefore, &levelAfter)))
|
||||
{
|
||||
|
@ -915,10 +924,10 @@ PRBool nsCaret::MustDrawCaret()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mDrawn)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
if (mDrawn)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
if (!domSelection)
|
||||
return PR_FALSE;
|
||||
PRBool isCollapsed;
|
||||
|
@ -948,10 +957,38 @@ void nsCaret::DrawCaret()
|
|||
// if we are drawing, not erasing, then set up the frame etc.
|
||||
if (!mDrawn)
|
||||
{
|
||||
if (!SetupDrawingFrameAndOffset())
|
||||
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
|
||||
if (!privateSelection) return;
|
||||
|
||||
PRBool isCollapsed = PR_FALSE;
|
||||
domSelection->GetIsCollapsed(&isCollapsed);
|
||||
if (!mShowDuringSelection && !isCollapsed)
|
||||
return;
|
||||
|
||||
PRBool hintRight;
|
||||
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
|
||||
nsIFrameSelection::HINT hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||
|
||||
// get the node and offset, which is where we want the caret to draw
|
||||
nsCOMPtr<nsIDOMNode> focusNode;
|
||||
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||
if (!focusNode)
|
||||
return;
|
||||
|
||||
PRInt32 contentOffset;
|
||||
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||
return;
|
||||
|
||||
if (!SetupDrawingFrameAndOffset(focusNode, contentOffset, hint))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GetCaretRectAndInvert();
|
||||
}
|
||||
|
||||
void nsCaret::GetCaretRectAndInvert()
|
||||
{
|
||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
||||
|
||||
nsRect frameRect;
|
||||
|
@ -978,7 +1015,7 @@ void nsCaret::DrawCaret()
|
|||
return;
|
||||
|
||||
// if the view changed, or we don't have a rendering context, make one
|
||||
// because of drawing issues, always make a new RC at the momemt. See bug 28068
|
||||
// because of drawing issues, always make a new RC at the moment. See bug 28068
|
||||
if (
|
||||
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||
PR_TRUE ||
|
||||
|
@ -1045,9 +1082,8 @@ void nsCaret::DrawCaret()
|
|||
|
||||
caretRect += mCachedFrameOffset;
|
||||
|
||||
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
||||
if(mCaretTwipsWidth < 0)
|
||||
{// need to re-compute the pixel width
|
||||
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
|
||||
{
|
||||
float tDevUnitsToTwips = 15;
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
presContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
@ -1151,6 +1187,7 @@ void nsCaret::DrawCaret()
|
|||
mRendContext->SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
||||
else
|
||||
mRendContext->SetColor(NS_RGB(255,255,255));
|
||||
|
||||
mRendContext->InvertRect(mCaretRect);
|
||||
|
||||
// Ensure the buffer is flushed (Cocoa needs this), since we're drawing
|
||||
|
@ -1162,7 +1199,7 @@ void nsCaret::DrawCaret()
|
|||
mRendContext->InvertRect(mHookRect);
|
||||
#endif
|
||||
|
||||
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
|
||||
PRBool emptyClip;
|
||||
mRendContext->PopState(emptyClip);
|
||||
|
||||
ToggleDrawnStatus();
|
||||
|
@ -1199,20 +1236,3 @@ nsresult NS_NewCaret(nsICaret** aInstancePtrResult)
|
|||
return caret->QueryInterface(NS_GET_IID(nsICaret), (void**) aInstancePtrResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
|
||||
{
|
||||
if(!aPixels)
|
||||
return NS_ERROR_FAILURE;
|
||||
else
|
||||
{ //no need to optimize this, but if it gets too slow, we can check for case aPixels==mCaretPixelsWidth
|
||||
mCaretPixelsWidth = aPixels;
|
||||
mCaretTwipsWidth = -1;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
|
||||
{
|
||||
mShowDuringSelection = aVisibility;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -34,12 +34,6 @@
|
|||
|
||||
class nsIView;
|
||||
|
||||
class nsISelectionController;
|
||||
|
||||
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
||||
#define NS_CARET_CID \
|
||||
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } };
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsCaret : public nsICaret,
|
||||
|
@ -56,6 +50,7 @@ class nsCaret : public nsICaret,
|
|||
|
||||
// nsICaret interface
|
||||
NS_IMETHOD Init(nsIPresShell *inPresShell);
|
||||
NS_IMETHOD Terminate();
|
||||
|
||||
NS_IMETHOD GetCaretDOMSelection(nsISelection **outDOMSel);
|
||||
NS_IMETHOD SetCaretDOMSelection(nsISelection *inDOMSel);
|
||||
|
@ -68,6 +63,7 @@ class nsCaret : public nsICaret,
|
|||
|
||||
NS_IMETHOD SetCaretWidth(nscoord aPixels);
|
||||
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
|
||||
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
|
||||
|
||||
//nsISelectionListener interface
|
||||
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
|
||||
|
@ -83,9 +79,10 @@ class nsCaret : public nsICaret,
|
|||
nsresult StopBlinking();
|
||||
|
||||
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView);
|
||||
PRBool SetupDrawingFrameAndOffset();
|
||||
PRBool SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint);
|
||||
PRBool MustDrawCaret();
|
||||
void DrawCaret();
|
||||
void GetCaretRectAndInvert();
|
||||
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
||||
|
||||
protected:
|
||||
|
@ -98,7 +95,7 @@ protected:
|
|||
|
||||
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
||||
|
||||
nscoord mCaretTwipsWidth; // caret width in twips
|
||||
nscoord mCaretTwipsWidth; // caret width in twips. this gets calculated laziiy
|
||||
nscoord mCaretPixelsWidth; // caret width in pixels
|
||||
|
||||
PRPackedBool mVisible; // is the caret blinking
|
||||
|
@ -114,11 +111,9 @@ protected:
|
|||
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
|
||||
PRInt32 mLastContentOffset;
|
||||
#ifdef IBMBIDI
|
||||
//---------------------------------------IBMBIDI----------------------------------------------
|
||||
nsRect mHookRect; // directional hook on the caret
|
||||
nsCOMPtr<nsIBidiKeyboard> mBidiKeyboard; // Bidi keyboard object to set and query keyboard language
|
||||
PRPackedBool mKeyboardRTL; // is the keyboard language right-to-left
|
||||
//-------------------------------------END OF IBM BIDI----------------------------------------
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -254,4 +254,9 @@
|
|||
#define NS_SELECTIONIMAGESERVICE_CID \
|
||||
{ 0x9d1001b1, 0xe59a, 0x456b, { 0x99, 0xdc, 0xcc, 0x3f, 0x12, 0x83, 0x23, 0x6e } }
|
||||
|
||||
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
||||
#define NS_CARET_CID \
|
||||
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } }
|
||||
|
||||
|
||||
#endif /* nsLayoutCID_h__ */
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
#include "nsITextContent.h"
|
||||
#include "nsIXBLService.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsICaret.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsPlainTextSerializer.h"
|
||||
#include "mozSanitizingSerializer.h"
|
||||
|
@ -412,6 +413,7 @@ MAKE_CTOR(CreateNewScrollBoxObject, nsIBoxObject, NS_NewScrollBoxO
|
|||
MAKE_CTOR(CreateNewTreeBoxObject, nsIBoxObject, NS_NewTreeBoxObject)
|
||||
MAKE_CTOR(CreateNewAutoCopyService, nsIAutoCopyService, NS_NewAutoCopyService)
|
||||
MAKE_CTOR(CreateSelectionImageService, nsISelectionImageService,NS_NewSelectionImageService)
|
||||
MAKE_CTOR(CreateCaret, nsICaret, NS_NewCaret)
|
||||
|
||||
MAKE_CTOR(CreateNameSpaceManager, nsINameSpaceManager, NS_GetNameSpaceManager)
|
||||
MAKE_CTOR(CreateEventListenerManager, nsIEventListenerManager, NS_NewEventListenerManager)
|
||||
|
@ -618,7 +620,12 @@ static const nsModuleComponentInfo gComponents[] = {
|
|||
{ "selection image storage",
|
||||
NS_SELECTIONIMAGESERVICE_CID,
|
||||
nsnull,
|
||||
CreateSelectionImageService},
|
||||
CreateSelectionImageService },
|
||||
|
||||
{ "caret",
|
||||
NS_CARET_CID,
|
||||
"@mozilla.org/layout/caret;1",
|
||||
CreateCaret },
|
||||
|
||||
// XXX ick
|
||||
{ "Presentation shell",
|
||||
|
|
|
@ -1184,7 +1184,7 @@ public:
|
|||
// caret handling
|
||||
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
|
||||
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
|
||||
NS_IMETHOD SetCaretWidth(PRInt16 twips);
|
||||
NS_IMETHOD SetCaretWidth(PRInt16 aPixels);
|
||||
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
|
||||
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
|
||||
|
||||
|
@ -1776,6 +1776,11 @@ PresShell::Destroy()
|
|||
mPaintSuppressionTimer = nsnull;
|
||||
}
|
||||
|
||||
if (mCaret) {
|
||||
mCaret->Terminate();
|
||||
mCaret = nsnull;
|
||||
}
|
||||
|
||||
// release our pref style sheet, if we have one still
|
||||
ClearPreferenceStyleRules();
|
||||
|
||||
|
@ -2725,8 +2730,8 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
|
|||
|
||||
// notice that we ignore the result
|
||||
NotifyReflowObservers(NS_PRESSHELL_INITIAL_REFLOW);
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
WillCauseReflow();
|
||||
|
||||
|
@ -2901,8 +2906,9 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
|||
NotifyReflowObservers(NS_PRESSHELL_RESIZE_REFLOW);
|
||||
mViewManager->CacheWidgetChanges(PR_TRUE);
|
||||
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
WillCauseReflow();
|
||||
|
||||
if (mPresContext) {
|
||||
|
@ -3100,11 +3106,14 @@ PresShell::GetFrameManager(nsIFrameManager** aFrameManager) const
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// note that this can return a null caret, but NS_OK
|
||||
NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret)
|
||||
{
|
||||
if (!outCaret || !mCaret)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return mCaret->QueryInterface(NS_GET_IID(nsICaret), (void **)outCaret);
|
||||
NS_ENSURE_ARG_POINTER(outCaret);
|
||||
|
||||
*outCaret = mCaret;
|
||||
NS_IF_ADDREF(*outCaret);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
|
||||
|
@ -3129,17 +3138,21 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
|
|||
|
||||
NS_IMETHODIMP PresShell::SetCaretWidth(PRInt16 pixels)
|
||||
{
|
||||
return mCaret->SetCaretWidth(pixels);
|
||||
if (mCaret)
|
||||
mCaret->SetCaretWidth(pixels);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::SetCaretReadOnly(PRBool aReadOnly)
|
||||
{
|
||||
return mCaret->SetCaretReadOnly(aReadOnly);
|
||||
if (mCaret)
|
||||
mCaret->SetCaretReadOnly(aReadOnly);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PresShell::GetCaretEnabled(PRBool *aOutEnabled)
|
||||
{
|
||||
if (!aOutEnabled) { return NS_ERROR_INVALID_ARG; }
|
||||
NS_ENSURE_ARG_POINTER(aOutEnabled);
|
||||
*aOutEnabled = mCaretEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -5755,8 +5768,8 @@ PresShell::Paint(nsIView *aView,
|
|||
|
||||
if (nsnull != frame)
|
||||
{
|
||||
mCaret->EraseCaret();
|
||||
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
|
||||
if (mCaret)
|
||||
mCaret->EraseCaret();
|
||||
|
||||
// If the frame is absolutely positioned, then the 'clip' property
|
||||
// applies
|
||||
|
|
Загрузка…
Ссылка в новой задаче