r=pedemont, sr=blizzard (platform specific), a=mkaply
Code from Rich Walsh - OS/2 drag drop improvements
This commit is contained in:
mkaply%us.ibm.com 2003-10-22 21:57:01 +00:00
Родитель a41430bfac
Коммит 5d0e41cca4
9 изменённых файлов: 96 добавлений и 54 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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("<DRM_OS2FILE,DRF_UNKNOWN>");
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("<DRM_OS2FILE,DRF_TEXT>");
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,

Просмотреть файл

@ -71,6 +71,7 @@
#include <stdlib.h>
#include <ctype.h>
#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;
}
// --------------------------------------------------------------------------

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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

Двоичные данные
widget/src/os2/res/dndtext.ico Normal file

Двоичный файл не отображается.

Двоичные данные
widget/src/os2/res/dndurl.ico Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -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

Просмотреть файл

@ -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