diff --git a/widget/src/os2/Makefile.in b/widget/src/os2/Makefile.in index a4cd2d037489..806de04933f4 100644 --- a/widget/src/os2/Makefile.in +++ b/widget/src/os2/Makefile.in @@ -82,6 +82,6 @@ LOCAL_INCLUDES = -I. -I$(srcdir)/../xpwidgets -I$(srcdir) export:: test -d ./res || mkdir ./res - test -f ./res/aliasb.ptr || cp $(srcdir)/res/*.ptr ./res + test -f ./res/aliasb.ptr || cp $(srcdir)/res/*.* ./res ADD_TO_DEF_FILE = cat < $(srcdir)/extradefs.os2 >>$(DEF_FILE) diff --git a/widget/src/os2/nsDragService.cpp b/widget/src/os2/nsDragService.cpp index 5a7bc68bf404..01022b64778c 100644 --- a/widget/src/os2/nsDragService.cpp +++ b/widget/src/os2/nsDragService.cpp @@ -47,6 +47,8 @@ #include "nsIURL.h" #include "nsNetUtil.h" #include "nsOS2Uni.h" +#include "nsdefs.h" +#include "resource.h" // -------------------------------------------------------------------------- // helper functions @@ -64,6 +66,11 @@ int UnicodeToCodepage( const nsAString& inString, char **outText); #define DC_PREPAREITEM 0x0040; #endif +// -------------------------------------------------------------------------- +// Global data + +static HPOINTER gPtrArray[IDC_DNDCOUNT]; + // -------------------------------------------------------------------------- nsDragService::nsDragService() @@ -72,6 +79,11 @@ nsDragService::nsDragService() mDragWnd = WinCreateWindow( HWND_DESKTOP, WC_STATIC, 0, 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0); WinSubclassWindow( mDragWnd, nsDragWindowProc); + + HMODULE hModResources = NULLHANDLE; + DosQueryModFromEIP(&hModResources, NULL, 0, NULL, NULL, (ULONG) &gPtrArray); + for (int i = 0; i < IDC_DNDCOUNT; i++) + gPtrArray[i] = ::WinLoadPointer(HWND_DESKTOP, hModResources, i+IDC_DNDBASE); } // -------------------------------------------------------------------------- @@ -181,6 +193,11 @@ nsDragService::~nsDragService() { /* destructor code */ WinDestroyWindow(mDragWnd); + + for (int i = 0; i < IDC_DNDCOUNT; i++) { + WinDestroyPointer(gPtrArray[i]); + gPtrArray[i] = 0; + } } // -------------------------------------------------------------------------- @@ -223,6 +240,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports dragitem.hstrSourceName = NULLHANDLE; nsresult rv = NS_ERROR_FAILURE; + ULONG idIcon = 0; // reduce our footprint by ensuring any intermediate objects // go out of scope before the drag begins @@ -249,6 +267,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports dragitem.hstrRMF = DrgAddStrHandle(""); dragitem.hstrTargetName = DrgAddStrHandle(targetName); nsMemory::Free(targetName); + idIcon = IDC_DNDURL; } } else @@ -260,6 +279,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports dragitem.hstrRMF = DrgAddStrHandle(""); dragitem.hstrTargetName = DrgAddStrHandle(targetName); nsMemory::Free(targetName); + idIcon = IDC_DNDTEXT; } } } @@ -277,8 +297,15 @@ NS_IMETHODIMP nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, nsISupports DRAGIMAGE dragimage; memset(&dragimage, 0, sizeof(DRAGIMAGE)); dragimage.cb = sizeof(DRAGIMAGE); - dragimage.hImage = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE); dragimage.fl = DRG_ICON; + if (idIcon) + dragimage.hImage = gPtrArray[idIcon-IDC_DNDBASE]; + if (dragimage.hImage) { + dragimage.cyOffset = 8; + dragimage.cxOffset = 2; + } + else + dragimage.hImage = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE); mDoingDrag = PR_TRUE; HWND hwndDest = DrgDrag(mDragWnd, pDragInfo, &dragimage, 1, VK_BUTTON2, diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index 29d3287c7354..e6fcd8312d16 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -71,6 +71,7 @@ #include #include +#include "nsdefs.h" #include "resource.h" #ifdef DEBUG_sobotka @@ -123,7 +124,10 @@ PRBool gIsDestroyingAny = PR_FALSE; static POINTL gLastMousePoint; static LONG gLastMsgTime = 0; static LONG gLastClickCount = 0; -static LONG gLastButtonDown = 0; +static POINTS gLastButton1Down = {0,0}; + +#define XFROMMP(m) (SHORT(LOUSHORT(m))) +#define YFROMMP(m) (SHORT(HIUSHORT(m))) //////////////////////////////////////////////////// static PRBool gGlobalsInitialized = PR_FALSE; @@ -131,16 +135,6 @@ static HPOINTER gPtrArray[IDC_COUNT]; static PRBool gIsTrackPoint = PR_FALSE; static PRBool gIsDBCS = PR_FALSE; -/* Older versions of the toolkit, as well as GCC do not have this - from bsedos.h */ -extern "C" { - APIRET APIENTRY DosQueryModFromEIP(HMODULE *phMod, - ULONG *pObjNum, - ULONG BuffLen, - PCHAR pBuff, - ULONG *pOffset, - ULONG Address); -} - // The last user input event time in milliseconds. If there are any pending // native toolkit input events it returns the current time. The value is // compatible with PR_IntervalToMicroseconds(PR_IntervalNow()). @@ -1975,7 +1969,7 @@ void nsWindow::FreeNativeData(void * data, PRUint32 aDataType) { case NS_NATIVE_GRAPHIC: if (data) { - if (ReleaseDragHPS((HPS)data)) + if (!ReleaseIfDragHPS((HPS)data)) WinReleasePS((HPS)data); } break; @@ -2034,7 +2028,7 @@ NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) Update(); if (hps) - ReleaseDragHPS(hps); + ReleaseIfDragHPS(hps); return NS_OK; } @@ -2053,7 +2047,7 @@ NS_IMETHODIMP nsWindow::ScrollWidgets(PRInt32 aDx, PRInt32 aDy) Update(); // Force synchronous generation of NS_PAINT if (hps) - ReleaseDragHPS(hps); + ReleaseIfDragHPS(hps); return NS_OK; } @@ -2080,7 +2074,7 @@ NS_IMETHODIMP nsWindow::ScrollRect(nsRect &aRect, PRInt32 aDx, PRInt32 aDy) Update(); // Force synchronous generation of NS_PAINT if (hps) - ReleaseDragHPS(hps); + ReleaseIfDragHPS(hps); return NS_OK; } @@ -2478,13 +2472,14 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) if (!mIsScrollBar) WinSetCapture( HWND_DESKTOP, mWnd); result = DispatchMouseEvent( NS_MOUSE_LEFT_BUTTON_DOWN, mp1, mp2); - gLastButtonDown = 1; + // there's no need to clear this on button-up + gLastButton1Down.x = XFROMMP(mp1); + gLastButton1Down.y = YFROMMP(mp1); break; case WM_BUTTON1UP: if (!mIsScrollBar) WinSetCapture( HWND_DESKTOP, 0); // release result = DispatchMouseEvent( NS_MOUSE_LEFT_BUTTON_UP, mp1, mp2); - gLastButtonDown = 0; break; case WM_BUTTON1DBLCLK: result = DispatchMouseEvent( NS_MOUSE_LEFT_DOUBLECLICK, mp1, mp2); @@ -2494,13 +2489,11 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) if (!mIsScrollBar) WinSetCapture( HWND_DESKTOP, mWnd); result = DispatchMouseEvent( NS_MOUSE_RIGHT_BUTTON_DOWN, mp1, mp2); - gLastButtonDown = 2; break; case WM_BUTTON2UP: if (!mIsScrollBar) WinSetCapture( HWND_DESKTOP, 0); // release result = DispatchMouseEvent( NS_MOUSE_RIGHT_BUTTON_UP, mp1, mp2); - gLastButtonDown = 0; break; case WM_BUTTON2DBLCLK: result = DispatchMouseEvent( NS_MOUSE_RIGHT_DOUBLECLICK, mp1, mp2); @@ -2518,34 +2511,40 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) } break; + // if MB1 & MB2 are both pressed, perform a copy or paste; + // see how far the mouse has moved since MB1-down to determine + // the operation (this really ought to look for selected content) case WM_CHORD: - { + if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & + WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & + 0x8000) { + PRBool isCopy = FALSE; + if (abs(XFROMMP(mp1) - gLastButton1Down.x) > + (WinQuerySysValue(HWND_DESKTOP, SV_CXMOTIONSTART) / 2) || + abs(YFROMMP(mp1) - gLastButton1Down.y) > + (WinQuerySysValue(HWND_DESKTOP, SV_CYMOTIONSTART) / 2)) + isCopy = TRUE; + nsKeyEvent event; nsPoint point(0,0); + InitEvent( event, NS_KEY_PRESS, &point); - if (gLastButtonDown == 2) { - InitEvent( event, NS_KEY_PRESS, &point); - event.keyCode = NS_VK_INSERT; + event.keyCode = NS_VK_INSERT; + if (isCopy) { event.isShift = PR_FALSE; event.isControl = PR_TRUE; - event.isAlt = PR_FALSE; - event.isMeta = PR_FALSE; - event.eventStructType = NS_KEY_EVENT; - event.charCode = 0; - result = DispatchWindowEvent( &event); - } else if (gLastButtonDown == 1) { - InitEvent( event, NS_KEY_PRESS, &point); - event.keyCode = NS_VK_INSERT; + } else { event.isShift = PR_TRUE; event.isControl = PR_FALSE; - event.isAlt = PR_FALSE; - event.isMeta = PR_FALSE; - event.eventStructType = NS_KEY_EVENT; - event.charCode = 0; - result = DispatchWindowEvent( &event); } + event.isAlt = PR_FALSE; + event.isMeta = PR_FALSE; + event.eventStructType = NS_KEY_EVENT; + event.charCode = 0; + result = DispatchWindowEvent( &event); } break; + case WM_BUTTON3DOWN: result = DispatchMouseEvent( NS_MOUSE_MIDDLE_BUTTON_DOWN, mp1, mp2); break; @@ -2669,22 +2668,24 @@ PRBool nsWindow::ProcessMessage( ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT &rc) break; case DM_DRAGOVER: - result = OnDragOver(mp1, mp2, rc); + OnDragOver(mp1, mp2, rc); + result = PR_TRUE; break; case DM_DRAGLEAVE: - result = OnDragLeave(mp1, mp2); + OnDragLeave(mp1, mp2); + result = PR_TRUE; break; case DM_DROP: - result = OnDrop( mp1, mp2); + OnDrop( mp1, mp2); + result = PR_TRUE; break; - // Need to handle this method in order to keep track of whether there - // is a drag inside the window; we need to do *this* so that we can - // generate DRAGENTER messages [which os/2 doesn't provide]. + // this cancels a drag - after we do our cleanup + // pass this to the default wndproc to do its cleanup case DM_DROPHELP: - mNativeDrag = FALSE; + OnDragLeave(mp1, mp2); break; } @@ -2919,7 +2920,7 @@ PRBool nsWindow::OnPaint() WinEndPaint(hPS); if (hpsDrag) - ReleaseDragHPS(hpsDrag); + ReleaseIfDragHPS(hpsDrag); } return rc; @@ -3764,16 +3765,16 @@ PRUint32 nsWindow::GetDragStatus(PRUint32 aState, HPS * oHps) // if there's an outstanding drag hps & it matches the one // passed in, release it -HPS nsWindow::ReleaseDragHPS(HPS aHps) +PRBool nsWindow::ReleaseIfDragHPS(HPS aHps) { if (mDragHps && aHps == mDragHps) { DrgReleasePS(mDragHps); mDragHps = 0; - aHps = 0; + return PR_TRUE; } - return aHps; + return PR_FALSE; } // -------------------------------------------------------------------------- diff --git a/widget/src/os2/nsWindow.h b/widget/src/os2/nsWindow.h index 6749beacc773..2e2b99ce6968 100644 --- a/widget/src/os2/nsWindow.h +++ b/widget/src/os2/nsWindow.h @@ -301,7 +301,7 @@ protected: void ConstrainZLevel(HWND *aAfter); PRUint32 GetDragStatus(PRUint32 aState, HPS * oHps); - HPS ReleaseDragHPS(HPS hps); + PRBool ReleaseIfDragHPS(HPS hps); // Enumeration of the methods which are accessable on the PM thread enum { diff --git a/widget/src/os2/nsdefs.h b/widget/src/os2/nsdefs.h index 8f6d3c8d515f..49cc6a12b691 100644 --- a/widget/src/os2/nsdefs.h +++ b/widget/src/os2/nsdefs.h @@ -63,12 +63,16 @@ extern "C" { -PVOID APIENTRY WinQueryProperty(HWND hwnd, PCSZ pszNameOrAtom); + PVOID APIENTRY WinQueryProperty(HWND hwnd, PCSZ pszNameOrAtom); -PVOID APIENTRY WinRemoveProperty(HWND hwnd, PCSZ pszNameOrAtom); + PVOID APIENTRY WinRemoveProperty(HWND hwnd, PCSZ pszNameOrAtom); -BOOL APIENTRY WinSetProperty(HWND hwnd, PCSZ pszNameOrAtom, - PVOID pvData, ULONG ulFlags); + BOOL APIENTRY WinSetProperty(HWND hwnd, PCSZ pszNameOrAtom, + PVOID pvData, ULONG ulFlags); + + APIRET APIENTRY DosQueryModFromEIP(HMODULE *phMod, ULONG *pObjNum, + ULONG BuffLen, PCHAR pBuff, + ULONG *pOffset, ULONG Address); } #endif // NSDEFS_H diff --git a/widget/src/os2/res/dndtext.ico b/widget/src/os2/res/dndtext.ico new file mode 100644 index 000000000000..80e76e8888a2 Binary files /dev/null and b/widget/src/os2/res/dndtext.ico differ diff --git a/widget/src/os2/res/dndurl.ico b/widget/src/os2/res/dndurl.ico new file mode 100644 index 000000000000..e7aff0f0d788 Binary files /dev/null and b/widget/src/os2/res/dndurl.ico differ diff --git a/widget/src/os2/resource.h b/widget/src/os2/resource.h index c2bf9c0b3aa7..9ee9c02a58d0 100644 --- a/widget/src/os2/resource.h +++ b/widget/src/os2/resource.h @@ -46,3 +46,10 @@ #define IDC_COUNT IDC_HELP-IDC_BASE+1 +/* drag & drop icons */ +#define IDC_DNDBASE 4150 +#define IDC_DNDURL 4150 +#define IDC_DNDTEXT 4151 + +#define IDC_DNDCOUNT IDC_DNDTEXT-IDC_DNDBASE+1 + diff --git a/widget/src/os2/widget.rc b/widget/src/os2/widget.rc index 4c5ef661ad05..9bc2ea0a69fb 100644 --- a/widget/src/os2/widget.rc +++ b/widget/src/os2/widget.rc @@ -43,3 +43,6 @@ POINTER IDC_ARROWWAIT res\arrow_wait.ptr POINTER IDC_CROSS res\crosshair.ptr POINTER IDC_HELP res\help.ptr +ICON IDC_DNDURL res\dndurl.ico +ICON IDC_DNDTEXT res\dndtext.ico +