diff options
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 13 | ||||
| -rw-r--r-- | src/Editor.cxx | 65 | ||||
| -rw-r--r-- | src/Editor.h | 5 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 61 | 
4 files changed, 91 insertions, 53 deletions
| diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 2e0291eeb..a873f1ada 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -156,6 +156,7 @@ private:  	virtual void Initialise();  	virtual void Finalise();  	virtual void DisplayCursor(Window::Cursor c); +	virtual bool DragThreshold(Point ptStart, Point ptNow);  	virtual void StartDrag();  	int TargetAsUTF8(char *text);  	int EncodedFromUTF8(char *utf8, char *encoded); @@ -788,8 +789,18 @@ void ScintillaGTK::DisplayCursor(Window::Cursor c) {  		wText.SetCursor(static_cast<Window::Cursor>(cursorMode));  } +bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) { +#if GTK_MAJOR_VERSION < 2 +	return Editor::DragThreshold(ptStart, ptNow); +#else +	return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)), +		ptStart.x, ptStart.y, ptNow.x, ptNow.y); +#endif +} +  void ScintillaGTK::StartDrag() {  	dragWasDropped = false; +	inDragDrop = ddDragging;  	static const GtkTargetEntry targets[] = {  	    { "UTF8_STRING", 0, TARGET_UTF8_STRING },  	    { "STRING", 0, TARGET_STRING }, @@ -2345,7 +2356,6 @@ gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context,                                   gint x, gint y, guint dragtime) {  	ScintillaGTK *sciThis = ScintillaFromWidget(widget);  	Point npt(x, y); -	sciThis->inDragDrop = true;  	sciThis->SetDragPosition(sciThis->PositionFromLocation(npt));  	GdkDragAction preferredAction = context->suggested_action;  	if (context->actions == static_cast<GdkDragAction> @@ -2369,6 +2379,7 @@ void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {  		sciThis->SetEmptySelection(sciThis->posDrag);  	sciThis->SetDragPosition(invalidPosition);  	//Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped); +	sciThis->inDragDrop = ddNone;  }  gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/, diff --git a/src/Editor.cxx b/src/Editor.cxx index addfedf6e..8a2000090 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -362,7 +362,7 @@ Editor::Editor() {  	dwelling = false;  	ptMouseLast.x = 0;  	ptMouseLast.y = 0; -	inDragDrop = false; +	inDragDrop = ddNone;  	dropWentOutside = false;  	posDrag = invalidPosition;  	posDrop = invalidPosition; @@ -5000,6 +5000,13 @@ void Editor::DisplayCursor(Window::Cursor c) {  		wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));  } +bool Editor::DragThreshold(Point ptStart, Point ptNow) { +	int xMove = ptStart.x - ptNow.x; +	int yMove = ptStart.y - ptNow.y; +	int distanceSquared = xMove * xMove + yMove * yMove; +	return distanceSquared > 16; +} +  void Editor::StartDrag() {  	// Always handled by subclasses  	//SetMouseCapture(true); @@ -5007,8 +5014,8 @@ void Editor::StartDrag() {  }  void Editor::DropAt(int position, const char *value, bool moving, bool rectangular) { -	//Platform::DebugPrintf("DropAt %d\n", inDragDrop); -	if (inDragDrop) +	//Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position); +	if (inDragDrop == ddDragging)  		dropWentOutside = false;  	int positionWasInSelection = PositionInSelection(position); @@ -5016,7 +5023,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul  	bool positionOnEdgeOfSelection =  	    (position == SelectionStart()) || (position == SelectionEnd()); -	if ((!inDragDrop) || !(0 == positionWasInSelection) || +	if ((inDragDrop != ddDragging) || !(0 == positionWasInSelection) ||  	        (positionOnEdgeOfSelection && !moving)) {  		int selStart = SelectionStart(); @@ -5025,7 +5032,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul  		pdoc->BeginUndoAction();  		int positionAfterDeletion = position; -		if (inDragDrop && moving) { +		if ((inDragDrop == ddDragging) && moving) {  			// Remove dragged out text  			if (rectangular || selType == selLines) {  				SelectionLineIterator lineIterator(this); @@ -5059,7 +5066,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul  			}  			pdoc->EndUndoAction();  		} -	} else if (inDragDrop) { +	} else if (inDragDrop == ddDragging) {  		SetEmptySelection(position);  	}  } @@ -5161,11 +5168,11 @@ void Editor::DwellEnd(bool mouseMoved) {  }  void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) { -	//Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt); +	//Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);  	ptMouseLast = pt;  	int newPos = PositionFromLocation(pt);  	newPos = MovePositionOutsideChar(newPos, currentPos - newPos); -	inDragDrop = false; +	inDragDrop = ddNone;  	moveExtendsSelection = false;  	bool processed = NotifyMarginClick(pt, shift, ctrl, alt); @@ -5250,16 +5257,14 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b  				NotifyHotSpotClicked(newPos, shift, ctrl, alt);  			}  			if (!shift) { -				inDragDrop = PointInSelection(pt) && !SelectionEmpty(); +				if (PointInSelection(pt) && !SelectionEmpty()) +					inDragDrop = ddInitial; +				else +					inDragDrop = ddNone;  			} -			if (inDragDrop) { -				SetMouseCapture(false); -				SetDragPosition(newPos); -				CopySelectionRange(&drag); -				StartDrag(); -			} else { +			SetMouseCapture(true); +			if (inDragDrop != ddInitial) {  				SetDragPosition(invalidPosition); -				SetMouseCapture(true);  				if (!shift) {  					SetEmptySelection(newPos);  				} @@ -5328,6 +5333,20 @@ void Editor::ButtonMove(Point pt) {  	if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) {  		DwellEnd(true);  	} + +	int movePos = PositionFromLocation(pt); +	movePos = MovePositionOutsideChar(movePos, currentPos - movePos); + +	if (inDragDrop == ddInitial) { +		if (DragThreshold(ptMouseLast, pt)) { +			SetMouseCapture(false); +			SetDragPosition(movePos); +			CopySelectionRange(&drag); +			StartDrag(); +		} +		return; +	} +  	ptMouseLast = pt;  	//Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);  	if (HaveMouseCapture()) { @@ -5339,8 +5358,6 @@ void Editor::ButtonMove(Point pt) {  		autoScrollTimer.ticksToWait = autoScrollDelay;  		// Adjust selection -		int movePos = PositionFromLocation(pt); -		movePos = MovePositionOutsideChar(movePos, currentPos - movePos);  		if (posDrag >= 0) {  			SetDragPosition(movePos);  		} else { @@ -5416,7 +5433,13 @@ void Editor::ButtonMove(Point pt) {  }  void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { -	//Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture()); +	//Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop); +	int newPos = PositionFromLocation(pt); +	newPos = MovePositionOutsideChar(newPos, currentPos - newPos); +	if (inDragDrop == ddInitial) { +		inDragDrop = ddNone; +		SetEmptySelection(newPos); +	}  	if (HaveMouseCapture()) {  		if (PointInSelMargin(pt)) {  			DisplayCursor(Window::cursorReverseArrow); @@ -5429,7 +5452,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {  		int newPos = PositionFromLocation(pt);  		newPos = MovePositionOutsideChar(newPos, currentPos - newPos);  		NotifyIndicatorClick(false, newPos, false, false, false); -		if (inDragDrop) { +		if (inDragDrop == ddDragging) {  			int selStart = SelectionStart();  			int selEnd = SelectionEnd();  			if (selStart < selEnd) { @@ -5468,7 +5491,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {  		if (selType == selStream) {  			SetLastXChosen();  		} -		inDragDrop = false; +		inDragDrop = ddNone;  		EnsureCaretVisible(false);  	}  } diff --git a/src/Editor.h b/src/Editor.h index 04bf21958..ef061e46f 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -246,7 +246,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	bool dwelling;  	enum { selChar, selWord, selLine } selectionType;  	Point ptMouseLast; -	bool inDragDrop; +	enum { ddNone, ddInitial, ddDragging } inDragDrop;  	bool dropWentOutside;  	int posDrag;  	int posDrop; @@ -415,7 +415,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);  	void ClearSelection();  	void ClearAll(); -    	void ClearDocumentStyle(); +	void ClearDocumentStyle();  	void Cut();  	void PasteRectangular(int pos, const char *ptr, int len);  	virtual void Copy() = 0; @@ -489,6 +489,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	void CopyText(int length, const char *text);  	void SetDragPosition(int newPos);  	virtual void DisplayCursor(Window::Cursor c); +	virtual bool DragThreshold(Point ptStart, Point ptNow);  	virtual void StartDrag();  	void DropAt(int position, const char *value, bool moving, bool rectangular);  	/** PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after. diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 62d87fd9d..6d7f1268d 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -183,6 +183,7 @@ class ScintillaWin :  	enum { invalidTimerID, standardTimerID, idleTimerID }; +	virtual bool DragThreshold(Point ptStart, Point ptNow);  	virtual void StartDrag();  	sptr_t WndPaint(uptr_t wParam);  	sptr_t HandleComposition(uptr_t wParam, sptr_t lParam); @@ -224,6 +225,7 @@ class ScintillaWin :  	void FullPaint();  	void FullPaintDC(HDC dc);  	bool IsCompatibleDC(HDC dc); +	DWORD EffectFromState(DWORD grfKeyState);  	virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw);  	virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi); @@ -335,7 +337,15 @@ HWND ScintillaWin::MainHWND() {  	return reinterpret_cast<HWND>(wMain.GetID());  } +bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) { +	int xMove = abs(ptStart.x - ptNow.x); +	int yMove = abs(ptStart.y - ptNow.y); +	return (xMove > ::GetSystemMetrics(SM_CXDRAG)) || +		(yMove > ::GetSystemMetrics(SM_CYDRAG)); +} +  void ScintillaWin::StartDrag() { +	inDragDrop = ddDragging;  	DWORD dwEffect = 0;  	dropWentOutside = true;  	IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob); @@ -352,7 +362,7 @@ void ScintillaWin::StartDrag() {  			ClearSelection();  		}  	} -	inDragDrop = false; +	inDragDrop = ddNone;  	SetDragPosition(invalidPosition);  } @@ -696,7 +706,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam  	case WM_SETCURSOR:  		if (LoWord(lParam) == HTCLIENT) { -			if (inDragDrop) { +			if (inDragDrop == ddDragging) {  				DisplayCursor(Window::cursorUp);  			} else {  				// Display regular (drag) cursor over selection @@ -868,8 +878,8 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam  		capturedMouse = false;  		return 0; -        // These are not handled in Scintilla and its faster to dispatch them here. -        // Also moves time out to here so profile doesn't count lots of empty message calls. +	// These are not handled in Scintilla and its faster to dispatch them here. +	// Also moves time out to here so profile doesn't count lots of empty message calls.  	case WM_MOVE:  	case WM_MOUSEACTIVATE: @@ -1978,6 +1988,20 @@ bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) {  	return isCompatible;  } +DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) { +	// These are the Wordpad semantics. +	DWORD dwEffect; +	if (inDragDrop == ddDragging)	// Internal defaults to move +		dwEffect = DROPEFFECT_MOVE; +	else +		dwEffect = DROPEFFECT_COPY; +	if (grfKeyState & MK_ALT) +		dwEffect = DROPEFFECT_MOVE; +	if (grfKeyState & MK_CONTROL) +		dwEffect = DROPEFFECT_COPY; +	return dwEffect; +} +  /// Implement IUnknown  STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {  	*ppv = NULL; @@ -2020,14 +2044,7 @@ STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyStat  		return S_OK;  	} -	if (inDragDrop)	// Internal defaults to move -		*pdwEffect = DROPEFFECT_MOVE; -	else -		*pdwEffect = DROPEFFECT_COPY; -	if (grfKeyState & MK_ALT) -		*pdwEffect = DROPEFFECT_MOVE; -	if (grfKeyState & MK_CONTROL) -		*pdwEffect = DROPEFFECT_COPY; +	*pdwEffect = EffectFromState(grfKeyState);  	return S_OK;  } @@ -2037,15 +2054,8 @@ STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffe  		return S_OK;  	} -	// These are the Wordpad semantics. -	if (inDragDrop)	// Internal defaults to move -		*pdwEffect = DROPEFFECT_MOVE; -	else -		*pdwEffect = DROPEFFECT_COPY; -	if (grfKeyState & MK_ALT) -		*pdwEffect = DROPEFFECT_MOVE; -	if (grfKeyState & MK_CONTROL) -		*pdwEffect = DROPEFFECT_COPY; +	*pdwEffect = EffectFromState(grfKeyState); +  	// Update the cursor.  	POINT rpt = {pt.x, pt.y};  	::ScreenToClient(MainHWND(), &rpt); @@ -2061,14 +2071,7 @@ STDMETHODIMP ScintillaWin::DragLeave() {  STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,                                  POINTL pt, PDWORD pdwEffect) { -	if (inDragDrop)	// Internal defaults to move -		*pdwEffect = DROPEFFECT_MOVE; -	else -		*pdwEffect = DROPEFFECT_COPY; -	if (grfKeyState & MK_ALT) -		*pdwEffect = DROPEFFECT_MOVE; -	if (grfKeyState & MK_CONTROL) -		*pdwEffect = DROPEFFECT_COPY; +	*pdwEffect = EffectFromState(grfKeyState);  	if (pIDataSource == NULL)  		return E_POINTER; | 
