diff --git a/graphics/x11drv/oembitmap.c b/graphics/x11drv/oembitmap.c index 4acf0313ca7..cac3d34e138 100644 --- a/graphics/x11drv/oembitmap.c +++ b/graphics/x11drv/oembitmap.c @@ -198,7 +198,7 @@ static char **OBM_Icons_Data[OIC_LAST-OIC_FIRST+1] = #define OCR_BASE1 (OCR_BASE0 + OCR_LAST0 - OCR_FIRST0 + 1) #define OCR_FIRST2 OCR_SIZE -#define OCR_LAST2 OCR_SIZENS +#define OCR_LAST2 OCR_SIZEALL #define OCR_BASE2 (OCR_BASE1 + OCR_LAST1 - OCR_FIRST1 + 1) #define OCR_FIRST3 OCR_NO @@ -229,8 +229,8 @@ static char **OBM_Cursors_Data[NB_CURSORS] = ocr_sizenesw, /* OCR_SIZENESW */ ocr_sizewe, /* OCR_SIZEWE */ ocr_sizens, /* OCR_SIZENS */ + ocr_size, /* OCR_SIZEALL */ /* Re-used the same one as OCR_SIZE for now */ #if 0 - ocr_sizeall, /* OCR_SIZEALL */ ocr_icocur /* OCR_ICOCUR */ #endif ocr_no, /* OCR_NO */ diff --git a/include/ole2.h b/include/ole2.h index d80ff9c004c..3acb26e1dbe 100644 --- a/include/ole2.h +++ b/include/ole2.h @@ -5,13 +5,9 @@ #ifndef __WINE_OLE2_H #define __WINE_OLE2_H +#include "oleidl.h" #include "wintypes.h" -/* to be implemented */ -/* FIXME: this should be defined somewhere in oleidl.h instead, should it be repeated here ? */ -typedef LPVOID LPDROPTARGET; - - /* OLE version */ #define rmm 23 #define rup 639 @@ -27,11 +23,23 @@ typedef struct tagOleMenuGroupWidths *LPOLEMENUGROUPWIDTHS32; typedef HGLOBAL32 HOLEMENU32; -HRESULT WINAPI RegisterDragDrop16(HWND16,LPVOID); -HRESULT WINAPI RegisterDragDrop32(HWND32,LPVOID); +/* + * API declarations + */ +HRESULT WINAPI RegisterDragDrop16(HWND16,LPDROPTARGET); +HRESULT WINAPI RegisterDragDrop32(HWND32,LPDROPTARGET); #define RegisterDragDrop WINELIB_NAME(RegisterDragDrop) HRESULT WINAPI RevokeDragDrop16(HWND16); HRESULT WINAPI RevokeDragDrop32(HWND32); #define RevokeDragDrop WINELIB_NAME(RevokeDragDrop) +HRESULT WINAPI DoDragDrop16(LPDATAOBJECT, + LPDROPSOURCE, + DWORD, + DWORD*); +HRESULT WINAPI DoDragDrop32(LPDATAOBJECT, + LPDROPSOURCE, + DWORD, + DWORD*); +#define DoDragDrop WINELIB_NAME(DoDragDrop) #endif /* __WINE_OLE2_H */ diff --git a/include/oleidl.h b/include/oleidl.h new file mode 100644 index 00000000000..b515b9384e8 --- /dev/null +++ b/include/oleidl.h @@ -0,0 +1,21 @@ +#ifndef __WINE_OLEIDL_H +#define __WINE_OLEIDL_H + + +#include "wine/obj_base.h" + +/* the following depend only on obj_base.h */ +#include "wine/obj_storage.h" + +/* the following depend on obj_storage.h */ +#include "wine/obj_moniker.h" + +/* the following depend on obj_moniker */ +#include "wine/obj_dataobject.h" + +/* the following depend on obj_dataobject.h */ +#include "wine/obj_dragdrop.h" + + +#endif /* __WINE_OLEIDL_H */ + diff --git a/include/shlguid.h b/include/shlguid.h index 6ce12a1d63d..86410c99575 100644 --- a/include/shlguid.h +++ b/include/shlguid.h @@ -50,7 +50,5 @@ DEFINE_GUID (IID_IDockingWindowFrame, 0x47D2657AL, 0x7B27, 0x11D0, 0x8C, 0xA9, 0 DEFINE_GUID (IID_MyComputer, 0x20D04FE0L, 0x3AEA, 0x1069, 0xA2, 0xD8, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D); DEFINE_SHLGUID(IID_IEnumOLEVERB, 0x00000104L, 0, 0); DEFINE_SHLGUID(IID_IViewObject, 0x0000010DL, 0, 0); -DEFINE_SHLGUID(IID_IDropSource, 0x00000121L, 0, 0); -DEFINE_SHLGUID(IID_IDropTarget, 0x00000122L, 0, 0); #endif /* __WINE_SHLGUID_H */ diff --git a/include/shlobj.h b/include/shlobj.h index 653c8c2aba6..5d0859839e8 100644 --- a/include/shlobj.h +++ b/include/shlobj.h @@ -389,13 +389,6 @@ typedef enum tagSHCONTF SHCONTF_INCLUDEHIDDEN = 128 /* for hidden/system objects */ } SHCONTF; -/* from oleidl.h */ -#define DROPEFFECT_NONE 0 -#define DROPEFFECT_COPY 1 -#define DROPEFFECT_MOVE 2 -#define DROPEFFECT_LINK 4 -#define DROPEFFECT_SCROLL 0x80000000 - /* IShellFolder::GetAttributesOf flags */ #define SFGAO_CANCOPY DROPEFFECT_COPY /* Objects can be copied */ #define SFGAO_CANMOVE DROPEFFECT_MOVE /* Objects can be moved */ diff --git a/include/windef.h b/include/windef.h index 8301cf7c567..a1bbf3b7284 100644 --- a/include/windef.h +++ b/include/windef.h @@ -28,4 +28,15 @@ #pragma pack(4) + +/* + * POINTL structure. Used in some OLE calls. + */ +typedef struct _POINTL +{ + LONG x; + LONG y; +} POINTL; + + #endif /* __INCLUDE_WINDEF_H */ diff --git a/include/wine/obj_dragdrop.h b/include/wine/obj_dragdrop.h new file mode 100644 index 00000000000..2e6dba5f857 --- /dev/null +++ b/include/wine/obj_dragdrop.h @@ -0,0 +1,80 @@ +/* + * Defines the COM interfaces and APIs related to OLE Drag and Drop. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_DRAGDROP_H +#define __WINE_WINE_OBJ_DRAGDROP_H + +#include "winnt.h" +#include "windef.h" + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IDropSource, 0x00000121L, 0, 0); +typedef struct IDropSource IDropSource,*LPDROPSOURCE; + +DEFINE_OLEGUID(IID_IDropTarget, 0x00000122L, 0, 0); +typedef struct IDropTarget IDropTarget,*LPDROPTARGET; + +/***************************************************************************** + * DROPEFFECT enumeration + */ +#define DROPEFFECT_NONE 0 +#define DROPEFFECT_COPY 1 +#define DROPEFFECT_MOVE 2 +#define DROPEFFECT_LINK 4 +#define DROPEFFECT_SCROLL 0x80000000 + +/***************************************************************************** + * IDropSource interface + */ +#define ICOM_INTERFACE IDropSource +ICOM_BEGIN(IDropSource,IUnknown) + ICOM_METHOD2(HRESULT, QueryContinueDrag, BOOL32, fEscapePressed, DWORD, grfKeyState); + ICOM_METHOD1(HRESULT, GiveFeedback, DWORD, dwEffect); +ICOM_END(IDropSource) +#undef ICOM_INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDropSource_QueryInterface(p,a,b) ICOM_ICALL2(IUnknown,QueryInterface,p,a,b) +#define IDropSource_AddRef(p) ICOM_ICALL (IUnknown,AddRef,p) +#define IDropSource_Release(p) ICOM_ICALL (IUnknown,Release,p) +/*** IDropTarget methods ***/ +#define IDropSource_QueryContinueDrag(p,a,b) ICOM_CALL2(QueryContinueDrag,p,a,b) +#define IDropSource_GiveFeedback(p,a) ICOM_CALL1(GiveFeedback,p,a) +#endif + +/***************************************************************************** + * IDropTarget interface + */ +#define ICOM_INTERFACE IDropTarget +ICOM_BEGIN(IDropTarget,IUnknown) + ICOM_METHOD4(HRESULT, DragEnter, IDataObject*, pDataObjhect, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect); + ICOM_METHOD3(HRESULT, DragOver, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect); + ICOM_METHOD(HRESULT, DragLeave); + ICOM_METHOD4(HRESULT, Drop, IDataObject*, pDataObjhect, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect); +ICOM_END(IDropTarget) +#undef ICOM_INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDropTarget_QueryInterface(p,a,b) ICOM_ICALL2(IUnknown,QueryInterface,p,a,b) +#define IDropTarget_AddRef(p) ICOM_ICALL (IUnknown,AddRef,p) +#define IDropTarget_Release(p) ICOM_ICALL (IUnknown,Release,p) +/*** IDropTarget methods ***/ +#define IDropTarget_DragEnter(p,a,b,c,d) ICOM_CALL4(DragEnter,p,a,b,c,d) +#define IDropTarget_DragOver(p,a,b,c) ICOM_CALL3(DragOver,p,a,b,c) +#define IDropTarget_DragLeave(p) ICOM_CALL(DragLeave,p) +#define IDropTarget_Drop(p,a,b,c,d) ICOM_CALL4(Drop,p,a,b,c,d) +#endif + +#endif /* __WINE_WINE_OBJ_DRAGDROP_H */ + + + + + diff --git a/include/winerror.h b/include/winerror.h index 2772c7c3e60..8cad5aa2ddb 100644 --- a/include/winerror.h +++ b/include/winerror.h @@ -264,6 +264,9 @@ extern int WIN32_LastError; /* Drag and Drop */ #define DRAGDROP_S_DROP 0x00040100L #define DRAGDROP_S_CANCEL 0x00040101L +#define DRAGDROP_E_NOTREGISTERED 0x80040100L +#define DRAGDROP_E_ALREADYREGISTERED 0x80040101L +#define DRAGDROP_S_USEDEFAULTCURSORS 0x00040102L #define E_UNEXPECTED 0x8000FFFF @@ -290,6 +293,7 @@ extern int WIN32_LastError; #define CO_E_OBJISREG 0x800401FB #define OLE_E_ENUM_NOMORE 0x80040002 +#define OLE_S_USEREG 0x00040000 #define CLASS_E_NOAGGREGATION 0x80040110 #define CLASS_E_CLASSNOTAVAILABLE 0x80040111 #define E_ACCESSDENIED 0x80070005 diff --git a/include/wintypes.h b/include/wintypes.h index b4a64304e78..038ad9633d4 100644 --- a/include/wintypes.h +++ b/include/wintypes.h @@ -485,13 +485,6 @@ DECL_WINELIB_TYPE(POINT) DECL_WINELIB_TYPE(PPOINT) DECL_WINELIB_TYPE(LPPOINT) -typedef struct tagPOINTL -{ - LONG x; - LONG y; -} POINTL, *PPOINTL, *LPPOINTL; - - #define CONV_POINT16TO32(p16,p32) \ ((p32)->x = (INT32)(p16)->x, (p32)->y = (INT32)(p16)->y) #define CONV_POINT32TO16(p32,p16) \ diff --git a/ole/ole2.c b/ole/ole2.c index 5fa154d81a8..b9c0f383079 100644 --- a/ole/ole2.c +++ b/ole/ole2.c @@ -2,8 +2,11 @@ * OLE2 library * * Copyright 1995 Martin von Loewis + * Copyright 1999 Francis Beaudet */ +#include + #include "windows.h" #include "winerror.h" #include "ole2.h" @@ -17,15 +20,73 @@ #include "wine/obj_moniker.h" /****************************************************************************** - * These are static/global variables that the OLE module uses to maintain - * it's state. + * These are static/global variables and internal data structures that the + * OLE module uses to maintain it's state. */ +typedef struct tagDropTargetNode +{ + HWND32 hwndTarget; + IDropTarget* dropTarget; + struct tagDropTargetNode* prevDropTarget; + struct tagDropTargetNode* nextDropTarget; +} DropTargetNode; + +typedef struct tagTrackerWindowInfo +{ + IDataObject* dataObject; + IDropSource* dropSource; + DWORD dwOKEffect; + DWORD* pdwEffect; + BOOL32 trackingDone; + HRESULT returnValue; + + BOOL32 escPressed; + HWND32 curDragTargetHWND; + IDropTarget* curDragTarget; +} TrackerWindowInfo; /* * This is the lock count on the OLE library. It is controlled by the * OLEInitialize/OLEUninitialize methods. */ -static ULONG s_OLEModuleLockCount = 0; +static ULONG OLE_moduleLockCount = 0; + +/* + * Name of our registered window class. + */ +static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32"; + +/* + * This is the head of the Drop target container. + */ +static DropTargetNode* targetListHead = NULL; + +/****************************************************************************** + * These are the prototypes of the utility methods used for OLE Drag n Drop + */ +static void OLEDD_Initialize(); +static void OLEDD_UnInitialize(); +static void OLEDD_InsertDropTarget( + DropTargetNode* nodeToAdd); +static DropTargetNode* OLEDD_ExtractDropTarget( + HWND32 hwndOfTarget); +static DropTargetNode* OLEDD_FindDropTarget( + HWND32 hwndOfTarget); +static LRESULT WINAPI OLEDD_DragTrackerWindowProc( + HWND32 hwnd, + UINT32 uMsg, + WPARAM32 wParam, + LPARAM lParam); +static void OLEDD_TrackMouseMove( + TrackerWindowInfo* trackerInfo, + POINT32 mousePos, + DWORD keyState); +static void OLEDD_TrackStateChange( + TrackerWindowInfo* trackerInfo, + POINT32 mousePos, + DWORD keyState); +static DWORD OLEDD_GetButtonState(); + /****************************************************************************** * OleBuildVersion [OLE2.1] @@ -65,18 +126,23 @@ HRESULT WINAPI OleInitialize(LPVOID reserved) * Object linking and Embedding * In-place activation */ - if (s_OLEModuleLockCount==0) + if (OLE_moduleLockCount==0) { /* * Initialize the libraries. */ TRACE(ole, "() - Initializing the OLE libraries\n"); + + /* + * Drag and Drop + */ + OLEDD_Initialize(); } /* * Then, we increase the lock count on the OLE module. */ - s_OLEModuleLockCount++; + OLE_moduleLockCount++; return hr; } @@ -101,17 +167,22 @@ void WINAPI OleUninitialize(void) /* * Decrease the lock count on the OLE module. */ - s_OLEModuleLockCount--; + OLE_moduleLockCount--; /* * If we hit the bottom of the lock stack, free the libraries. */ - if (s_OLEModuleLockCount==0) + if (OLE_moduleLockCount==0) { /* * Actually free the libraries. */ TRACE(ole, "() - Freeing the last reference count\n"); + + /* + * Drag and Drop + */ + OLEDD_UnInitialize(); } /* @@ -175,9 +246,41 @@ HRESULT WINAPI RegisterDragDrop16( */ HRESULT WINAPI RegisterDragDrop32( HWND32 hwnd, - LPDROPTARGET pDropTarget -) { - FIXME(ole,"(0x%04x,%p),stub!\n",hwnd,pDropTarget); + LPDROPTARGET pDropTarget) +{ + DropTargetNode* dropTargetInfo; + + TRACE(ole,"(0x%x,%p)\n", hwnd, pDropTarget); + + /* + * First, check if the window is already registered. + */ + dropTargetInfo = OLEDD_FindDropTarget(hwnd); + + if (dropTargetInfo!=NULL) + return DRAGDROP_E_ALREADYREGISTERED; + + /* + * If it's not there, we can add it. We first create a node for it. + */ + dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode)); + + if (dropTargetInfo==NULL) + return E_OUTOFMEMORY; + + dropTargetInfo->hwndTarget = hwnd; + dropTargetInfo->prevDropTarget = NULL; + dropTargetInfo->nextDropTarget = NULL; + + /* + * Don't forget that this is an interface pointer, need to nail it down since + * we keep a copy of it. + */ + dropTargetInfo->dropTarget = pDropTarget; + IDropTarget_AddRef(dropTargetInfo->dropTarget); + + OLEDD_InsertDropTarget(dropTargetInfo); + return S_OK; } @@ -195,9 +298,30 @@ HRESULT WINAPI RevokeDragDrop16( * RevokeDragDrop32 (OLE32.141) */ HRESULT WINAPI RevokeDragDrop32( - HWND32 hwnd -) { - FIXME(ole,"(0x%04x),stub!\n",hwnd); + HWND32 hwnd) +{ + DropTargetNode* dropTargetInfo; + + TRACE(ole,"(0x%x)\n", hwnd); + + /* + * First, check if the window is already registered. + */ + dropTargetInfo = OLEDD_ExtractDropTarget(hwnd); + + /* + * If it ain't in there, it's an error. + */ + if (dropTargetInfo==NULL) + return DRAGDROP_E_NOTREGISTERED; + + /* + * If it's in there, clean-up it's used memory and + * references + */ + IDropTarget_Release(dropTargetInfo->dropTarget); + HeapFree(GetProcessHeap(), 0, dropTargetInfo); + return S_OK; } @@ -218,10 +342,679 @@ HRESULT WINAPI OleRegGetUserType32( */ HRESULT WINAPI DoDragDrop32 ( IDataObject *pDataObject, /* ptr to the data obj */ - IDataObject *pDropSource, /* ptr to the source obj */ + IDropSource* pDropSource, /* ptr to the source obj */ DWORD dwOKEffect, /* effects allowed by the source */ DWORD *pdwEffect) /* ptr to effects of the source */ { - FIXME(ole,"(DataObject %p, DropSource %p): stub!\n", pDataObject, pDropSource); - return DRAGDROP_S_DROP; + TrackerWindowInfo trackerInfo; + HWND32 hwndTrackWindow; + MSG32 msg; + + TRACE(ole,"(DataObject %p, DropSource %p)\n", pDataObject, pDropSource); + + /* + * Setup the drag n drop tracking window. + */ + trackerInfo.dataObject = pDataObject; + trackerInfo.dropSource = pDropSource; + trackerInfo.dwOKEffect = dwOKEffect; + trackerInfo.pdwEffect = pdwEffect; + trackerInfo.trackingDone = FALSE; + trackerInfo.escPressed = FALSE; + trackerInfo.curDragTargetHWND = 0; + trackerInfo.curDragTarget = 0; + + hwndTrackWindow = CreateWindow32A(OLEDD_DRAGTRACKERCLASS, + "TrackerWindow", + WS_POPUP, + CW_USEDEFAULT32, CW_USEDEFAULT32, + CW_USEDEFAULT32, CW_USEDEFAULT32, + 0, + 0, + 0, + (LPVOID)&trackerInfo); + + if (hwndTrackWindow!=0) + { + /* + * Capture the mouse input + */ + SetCapture32(hwndTrackWindow); + + /* + * Pump messages. All mouse input should go the the capture window. + */ + while (!trackerInfo.trackingDone && GetMessage32A(&msg, 0, 0, 0) ) + { + if ( (msg.message >= WM_KEYFIRST) && + (msg.message <= WM_KEYFIRST) ) + { + /* + * When keyboard messages are sent to windows on this thread, we + * want to ignore notify the drop source that the state changed. + * in the case of the Escape key, we also notify the drop source + * we give it a special meaning. + */ + if ( (msg.message==WM_KEYDOWN) && + (msg.wParam==VK_ESCAPE) ) + { + trackerInfo.escPressed = TRUE; + } + + /* + * Notify the drop source. + */ + OLEDD_TrackStateChange(&trackerInfo, + msg.pt, + OLEDD_GetButtonState()); + } + else + { + /* + * Dispatch the messages only when it's not a keyboard message. + */ + DispatchMessage32A(&msg); + } + } + + /* + * Destroy the temporary window. + */ + DestroyWindow32(hwndTrackWindow); + + return trackerInfo.returnValue; + } + + return E_FAIL; } + +/*********************************************************************** + * OleQueryLinkFromData32 [OLE32.118] + */ +HRESULT WINAPI OleQueryLinkFromData32( + IDataObject* pSrcDataObject) +{ + FIXME(ole,"(%p),stub!\n", pSrcDataObject); + return S_OK; +} + +/*********************************************************************** + * OleRegGetMiscStatus32 [OLE32.121] + */ +HRESULT WINAPI OleRegGetMiscStatus32( + REFCLSID clsid, + DWORD dwAspect, + DWORD* pdwStatus) +{ + FIXME(ole,"(),stub!\n"); + return REGDB_E_CLASSNOTREG; +} + +/*********************************************************************** + * OleGetClipboard32 [OLE32.105] + */ +HRESULT WINAPI OleGetClipboard32( + IDataObject** ppDataObj) +{ + FIXME(ole,"(%p),stub!\n", ppDataObj); + + if (ppDataObj) + *ppDataObj=0; + + return E_FAIL; +} + +/*** + * OLEDD_Initialize() + * + * Initializes the OLE drag and drop data structures. + */ +static void OLEDD_Initialize() +{ + WNDCLASS32A wndClass; + + ZeroMemory (&wndClass, sizeof(WNDCLASS32A)); + wndClass.style = CS_GLOBALCLASS; + wndClass.lpfnWndProc = (WNDPROC32)OLEDD_DragTrackerWindowProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = sizeof(TrackerWindowInfo*); + wndClass.hCursor = 0; + wndClass.hbrBackground = 0; + wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS; + + RegisterClass32A (&wndClass); +} + +/*** + * OLEDD_UnInitialize() + * + * Releases the OLE drag and drop data structures. + */ +static void OLEDD_UnInitialize() +{ + /* + * Simply empty the list. + */ + while (targetListHead!=NULL) + { + RevokeDragDrop32(targetListHead->hwndTarget); + } +} + +/*** + * OLEDD_InsertDropTarget() + * + * Insert the target node in the tree. + */ +static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd) +{ + DropTargetNode* curNode; + DropTargetNode** parentNodeLink; + + /* + * Iterate the tree to find the insertion point. + */ + curNode = targetListHead; + parentNodeLink = &targetListHead; + + while (curNode!=NULL) + { + if (nodeToAdd->hwndTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + parentNodeLink = &curNode->prevDropTarget; + curNode = curNode->prevDropTarget; + } + else if (nodeToAdd->hwndTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + parentNodeLink = &curNode->nextDropTarget; + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. It shouldn't have been there + */ + assert(FALSE); + return; + } + } + + /* + * If we get here, we have found a spot for our item. The parentNodeLink + * pointer points to the pointer that we have to modify. + * The curNode should be NULL. We just have to establish the link and Voila! + */ + assert(curNode==NULL); + assert(parentNodeLink!=NULL); + assert(*parentNodeLink==NULL); + + *parentNodeLink=nodeToAdd; +} + +/*** + * OLEDD_ExtractDropTarget() + * + * Removes the target node from the tree. + */ +static DropTargetNode* OLEDD_ExtractDropTarget(HWND32 hwndOfTarget) +{ + DropTargetNode* curNode; + DropTargetNode** parentNodeLink; + + /* + * Iterate the tree to find the insertion point. + */ + curNode = targetListHead; + parentNodeLink = &targetListHead; + + while (curNode!=NULL) + { + if (hwndOfTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + parentNodeLink = &curNode->prevDropTarget; + curNode = curNode->prevDropTarget; + } + else if (hwndOfTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + parentNodeLink = &curNode->nextDropTarget; + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. Detach it from it's parent and + * re-insert it's kids in the tree. + */ + assert(parentNodeLink!=NULL); + assert(*parentNodeLink==curNode); + + /* + * We arbitrately re-attach the left sub-tree to the parent. + */ + *parentNodeLink = curNode->prevDropTarget; + + /* + * And we re-insert the right subtree + */ + if (curNode->nextDropTarget!=NULL) + { + OLEDD_InsertDropTarget(curNode->nextDropTarget); + } + + /* + * The node we found is still a valid node once we complete + * the unlinking of the kids. + */ + curNode->nextDropTarget=NULL; + curNode->prevDropTarget=NULL; + + return curNode; + } + } + + /* + * If we get here, the node is not in the tree + */ + return NULL; +} + +/*** + * OLEDD_FindDropTarget() + * + * Finds information about the drop target. + */ +static DropTargetNode* OLEDD_FindDropTarget(HWND32 hwndOfTarget) +{ + DropTargetNode* curNode; + + /* + * Iterate the tree to find the HWND value. + */ + curNode = targetListHead; + + while (curNode!=NULL) + { + if (hwndOfTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + curNode = curNode->prevDropTarget; + } + else if (hwndOfTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. + */ + return curNode; + } + } + + /* + * If we get here, the item is not in the list + */ + return NULL; +} + +/*** + * OLEDD_DragTrackerWindowProc() + * + * This method is the WindowProcedure of the drag n drop tracking + * window. During a drag n Drop operation, an invisible window is created + * to receive the user input and act upon it. This procedure is in charge + * of this behavior. + */ +static LRESULT WINAPI OLEDD_DragTrackerWindowProc( + HWND32 hwnd, + UINT32 uMsg, + WPARAM32 wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: + { + LPCREATESTRUCT32A createStruct = (LPCREATESTRUCT32A)lParam; + + SetWindowLong32A(hwnd, 0, (LONG)createStruct->lpCreateParams); + + + break; + } + case WM_MOUSEMOVE: + { + TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLong32A(hwnd, 0); + POINT32 mousePos; + + /* + * Get the current mouse position in screen coordinates. + */ + mousePos.x = LOWORD(lParam); + mousePos.y = HIWORD(lParam); + ClientToScreen32(hwnd, &mousePos); + + /* + * Track the movement of the mouse. + */ + OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam); + + break; + } + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { + TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLong32A(hwnd, 0); + POINT32 mousePos; + + /* + * Get the current mouse position in screen coordinates. + */ + mousePos.x = LOWORD(lParam); + mousePos.y = HIWORD(lParam); + ClientToScreen32(hwnd, &mousePos); + + /* + * Notify everyone that the button state changed + * TODO: Check if the "escape" key was pressed. + */ + OLEDD_TrackStateChange(trackerInfo, mousePos, wParam); + + break; + } + } + + /* + * This is a window proc after all. Let's call the default. + */ + return DefWindowProc32A (hwnd, uMsg, wParam, lParam); +} + +/*** + * OLEDD_TrackMouseMove() + * + * This method is invoked while a drag and drop operation is in effect. + * it will generate the appropriate callbacks in the drop source + * and drop target. It will also provide the expected feedback to + * the user. + * + * params: + * trackerInfo - Pointer to the structure identifying the + * drag & drop operation that is currently + * active. + * mousePos - Current position of the mouse in screen + * coordinates. + * keyState - Contains the state of the shift keys and the + * mouse buttons (MK_LBUTTON and the like) + */ +static void OLEDD_TrackMouseMove( + TrackerWindowInfo* trackerInfo, + POINT32 mousePos, + DWORD keyState) +{ + HWND32 hwndNewTarget = 0; + HRESULT hr = S_OK; + + /* + * Get the handle of the window under the mouse + */ + hwndNewTarget = WindowFromPoint32(mousePos); + + /* + * If we are hovering over the same target as before, send the + * DragOver notification + */ + if ( (trackerInfo->curDragTarget != 0) && + (trackerInfo->curDragTargetHWND==hwndNewTarget) ) + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be in the target + * window's coordinate space. However, the tests I made tell me the + * coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_DragOver(trackerInfo->curDragTarget, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + } + else +{ + DropTargetNode* newDropTargetNode = 0; + + /* + * If we changed window, we have to notify our old target and check for + * the new one. + */ + if (trackerInfo->curDragTarget!=0) + { + IDropTarget_DragLeave(trackerInfo->curDragTarget); + } + + /* + * Make sure we're hovering over a window. + */ + if (hwndNewTarget!=0) + { + /* + * Find-out if there is a drag target under the mouse + */ + newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget); + + trackerInfo->curDragTargetHWND = hwndNewTarget; + trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0; + + /* + * If there is, notify it that we just dragged-in + */ + if (trackerInfo->curDragTarget!=0) + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be in the target + * window's coordinate space. However, the tests I made tell me the + * coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_DragEnter(trackerInfo->curDragTarget, + trackerInfo->dataObject, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + } + } + else + { + /* + * The mouse is not over a window so we don't track anything. + */ + trackerInfo->curDragTargetHWND = 0; + trackerInfo->curDragTarget = 0; + } + } + + /* + * Now that we have done that, we have to tell the source to give + * us feedback on the work being done by the target. If we don't + * have a target, simulate no effect. + */ + if (trackerInfo->curDragTarget==0) + { + *trackerInfo->pdwEffect = DROPEFFECT_NONE; + } + + hr = IDropSource_GiveFeedback(trackerInfo->dropSource, + *trackerInfo->pdwEffect); + + /* + * When we ask for feedback from the drop source, sometimes it will + * do all the necessary work and sometimes it will not handle it + * when that's the case, we must display the standard drag and drop + * cursors. + */ + if (hr==DRAGDROP_S_USEDEFAULTCURSORS) + { + if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) || + (*trackerInfo->pdwEffect & DROPEFFECT_COPY) || + (*trackerInfo->pdwEffect & DROPEFFECT_LINK) ) + { + SetCursor32(LoadCursor32A(0, IDC_SIZEALL32A)); + } + else + { + SetCursor32(LoadCursor32A(0, IDC_NO32A)); + } + } +} + +/*** + * OLEDD_TrackStateChange() + * + * This method is invoked while a drag and drop operation is in effect. + * It is used to notify the drop target/drop source callbacks when + * the state of the keyboard or mouse button change. + * + * params: + * trackerInfo - Pointer to the structure identifying the + * drag & drop operation that is currently + * active. + * mousePos - Current position of the mouse in screen + * coordinates. + * keyState - Contains the state of the shift keys and the + * mouse buttons (MK_LBUTTON and the like) + */ +static void OLEDD_TrackStateChange( + TrackerWindowInfo* trackerInfo, + POINT32 mousePos, + DWORD keyState) +{ + /* + * Ask the drop source what to do with the operation. + */ + trackerInfo->returnValue = IDropSource_QueryContinueDrag( + trackerInfo->dropSource, + trackerInfo->escPressed, + keyState); + + /* + * All the return valued will stop the operation except the S_OK + * return value. + */ + if (trackerInfo->returnValue!=S_OK) + { + /* + * Make sure the message loop in DoDragDrop stops + */ + trackerInfo->trackingDone = TRUE; + + /* + * Release the mouse in case the drop target decides to show a popup + * or a menu or something. + */ + ReleaseCapture(); + + /* + * If we end-up over a target, drop the object in the target or + * inform the target that the operation was cancelled. + */ + if (trackerInfo->curDragTarget!=0) + { + switch (trackerInfo->returnValue) + { + /* + * If the source wants us to complete the operation, we tell + * the drop target that we just dropped the object in it. + */ + case DRAGDROP_S_DROP: + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be + * in the target window's coordinate space. However, the tests + * I made tell me the coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_Drop(trackerInfo->curDragTarget, + trackerInfo->dataObject, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + break; + } + /* + * If the source told us that we should cancel, fool the drop + * target by telling it that the mouse left it's window. + */ + case DRAGDROP_S_CANCEL: + IDropTarget_DragLeave(trackerInfo->curDragTarget); + break; + } + } + } +} + +/*** + * OLEDD_GetButtonState() + * + * This method will use the current state of the keyboard to build + * a button state mask equivalent to the one passed in the + * WM_MOUSEMOVE wParam. + */ +static DWORD OLEDD_GetButtonState() +{ + BYTE keyboardState[256]; + DWORD keyMask = 0; + + GetKeyboardState(keyboardState); + + if ( (keyboardState[VK_SHIFT] & 0x80) !=0) + keyMask |= MK_SHIFT; + + if ( (keyboardState[VK_CONTROL] & 0x80) !=0) + keyMask |= MK_CONTROL; + + if ( (keyboardState[VK_LBUTTON] & 0x80) !=0) + keyMask |= MK_LBUTTON; + + if ( (keyboardState[VK_RBUTTON] & 0x80) !=0) + keyMask |= MK_RBUTTON; + + if ( (keyboardState[VK_MBUTTON] & 0x80) !=0) + keyMask |= MK_MBUTTON; + + return keyMask; +} + + diff --git a/relay32/ole32.spec b/relay32/ole32.spec index 736f060782c..c7b4fdfa7ad 100644 --- a/relay32/ole32.spec +++ b/relay32/ole32.spec @@ -105,7 +105,7 @@ type win32 102 stub OleDuplicateData 103 stub OleFlushClipboard 104 stub OleGetAutoConvert -105 stub OleGetClipboard +105 stdcall OleGetClipboard(ptr) OleGetClipboard32 106 stub OleGetIconOfClass 107 stub OleGetIconOfFile 108 stdcall OleInitialize(ptr) OleInitialize @@ -118,10 +118,10 @@ type win32 115 stub OleMetafilePictFromIconAndLabel 116 stub OleNoteObjectVisible 117 stub OleQueryCreateFromData -118 stub OleQueryLinkFromData +118 stdcall OleQueryLinkFromData(ptr) OleQueryLinkFromData32 119 stub OleRegEnumFormatEtc 120 stub OleRegEnumVerbs -121 stub OleRegGetMiscStatus +121 stdcall OleRegGetMiscStatus(ptr long ptr) OleRegGetMiscStatus32 122 stdcall OleRegGetUserType(long long ptr) OleRegGetUserType32 123 stub OleRun 124 stub OleSave