gdkdnd-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  * Copyright (C) 1998-1999 Tor Lillqvist
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 /*
00022  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00023  * file for a list of people on the GTK+ Team.  See the ChangeLog
00024  * files for a list of changes.  These files are distributed with
00025  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00026  */
00027 
00028 #include "config.h"
00029 
00030 #include <string.h>
00031 
00032 /* #define OLE2_DND */
00033 
00034 #define INITGUID
00035 
00036 #include "gdkdnd.h"
00037 #include "gdkproperty.h"
00038 #include "gdkprivate.h"
00039 #include "gdkwin32.h"
00040 
00041 #ifdef OLE2_DND
00042 #include <ole2.h>
00043 #else
00044 #include <objbase.h>
00045 #endif
00046 
00047 #include <shlobj.h>
00048 #include <shlguid.h>
00049 
00050 #include <gdk/gdk.h>
00051 
00052 typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
00053 
00054 typedef enum {
00055    GDK_DRAG_STATUS_DRAG,
00056    GDK_DRAG_STATUS_MOTION_WAIT,
00057    GDK_DRAG_STATUS_ACTION_WAIT,
00058    GDK_DRAG_STATUS_DROP
00059 } GtkDragStatus;
00060 
00061 typedef enum {
00062    GDK_DRAG_SOURCE,
00063    GDK_DRAG_TARGET
00064 } GdkDragKind;
00065 
00066 #ifdef OLE2_DND
00067 
00068 #define PRINT_GUID(guid) \
00069   g_print ("guid = %.08x-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x", \
00070            ((gulong *)  guid)[0], \
00071            ((gushort *) guid)[2], \
00072            ((gushort *) guid)[3], \
00073            ((guchar *)  guid)[8], \
00074            ((guchar *)  guid)[9], \
00075            ((guchar *)  guid)[10], \
00076            ((guchar *)  guid)[11], \
00077            ((guchar *)  guid)[12], \
00078            ((guchar *)  guid)[13], \
00079            ((guchar *)  guid)[14], \
00080            ((guchar *)  guid)[15]);
00081 
00082 
00083 #endif                          /* OLE2_DND */
00084 
00085 /* Structure that holds information about a drag in progress.
00086  * this is used on both source and destination sides.
00087  */
00088 struct _GdkDragContextPrivate {
00089    GdkDragContext context;
00090 
00091    guint ref_count;
00092 
00093    guint16 last_x;              /* Coordinates from last event */
00094    guint16 last_y;
00095    HWND dest_xid;
00096    guint drag_status;           /* Current status of drag */
00097 };
00098 
00099 GdkDragContext *current_dest_drag = NULL;
00100 
00101 /* Drag Contexts */
00102 
00103 static GList *contexts;
00104 
00105 GdkDragContext *gdk_drag_context_new(void)
00106 {
00107    GdkDragContextPrivate *result;
00108 
00109    result = g_new0(GdkDragContextPrivate, 1);
00110 
00111    result->ref_count = 1;
00112 
00113    contexts = g_list_prepend(contexts, result);
00114 
00115    return (GdkDragContext *) result;
00116 }
00117 
00118 void gdk_drag_context_ref(GdkDragContext * context)
00119 {
00120    g_return_if_fail(context != NULL);
00121 
00122    ((GdkDragContextPrivate *) context)->ref_count++;
00123 }
00124 
00125 void gdk_drag_context_unref(GdkDragContext * context)
00126 {
00127    GdkDragContextPrivate *private = (GdkDragContextPrivate *) context;
00128 
00129    g_return_if_fail(context != NULL);
00130 
00131    private->ref_count--;
00132 
00133    GDK_NOTE(DND, g_print("gdk_drag_context_unref: %d%s\n",
00134                          private->ref_count,
00135                          (private->ref_count == 0 ? " freeing" : "")));
00136 
00137    if (private->ref_count == 0) {
00138       g_dataset_destroy(private);
00139 
00140       g_list_free(context->targets);
00141 
00142       if (context->source_window)
00143          gdk_window_unref(context->source_window);
00144 
00145       if (context->dest_window)
00146          gdk_window_unref(context->dest_window);
00147 
00148       contexts = g_list_remove(contexts, private);
00149       g_free(private);
00150    }
00151 }
00152 
00153 #if 0
00154 
00155 static GdkDragContext *gdk_drag_context_find(gboolean is_source,
00156                                              HWND source_xid,
00157                                              HWND dest_xid)
00158 {
00159    GList *tmp_list = contexts;
00160    GdkDragContext *context;
00161 
00162    while (tmp_list) {
00163       context = (GdkDragContext *) tmp_list->data;
00164 
00165       if ((!context->is_source == !is_source) &&
00166           ((source_xid == None) || (context->source_window &&
00167                                     (GDK_WINDOW_XWINDOW
00168                                      (context->source_window) ==
00169                                      source_xid))) && ((dest_xid == None)
00170                                                        || (context->
00171                                                            dest_window
00172                                                            &&
00173                                                            (GDK_WINDOW_XWINDOW
00174                                                             (context->
00175                                                              dest_window)
00176                                                             == dest_xid))))
00177          return context;
00178 
00179       tmp_list = tmp_list->next;
00180    }
00181 
00182    return NULL;
00183 }
00184 
00185 #endif
00186 
00187 typedef struct {
00188 #ifdef OLE2_DND
00189    IDropTarget idt;
00190 #endif
00191    GdkDragContext *context;
00192 } target_drag_context;
00193 
00194 typedef struct {
00195 #ifdef OLE2_DND
00196    IDropSource ids;
00197 #endif
00198    GdkDragContext *context;
00199 } source_drag_context;
00200 
00201 #ifdef OLE2_DND
00202 
00203 static ULONG STDMETHODCALLTYPE
00204 m_add_ref_target(IDropTarget __RPC_FAR * This)
00205 {
00206    target_drag_context *ctx = (target_drag_context *) This;
00207    GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
00208 
00209    GDK_NOTE(DND, g_print("m_add_ref_target\n"));
00210    gdk_drag_context_ref(ctx->context);
00211 
00212    return private->ref_count;
00213 }
00214 
00215 static HRESULT STDMETHODCALLTYPE
00216 m_query_interface_target(IDropTarget __RPC_FAR * This,
00217                          REFIID riid,
00218                          void __RPC_FAR * __RPC_FAR * ppvObject)
00219 {
00220    GDK_NOTE(DND, g_print("m_query_interface_target\n"));
00221 
00222    *ppvObject = NULL;
00223 
00224    PRINT_GUID(riid);
00225 
00226    if (IsEqualGUID(riid, &IID_IUnknown)) {
00227       g_print("...IUnknown\n");
00228       m_add_ref_target(This);
00229       *ppvObject = This;
00230       return S_OK;
00231    } else if (IsEqualGUID(riid, &IID_IDropTarget)) {
00232       g_print("...IDropTarget\n");
00233       m_add_ref_target(This);
00234       *ppvObject = This;
00235       return S_OK;
00236    } else {
00237       g_print("...Huh?\n");
00238       return E_NOINTERFACE;
00239    }
00240 }
00241 
00242 static ULONG STDMETHODCALLTYPE
00243 m_release_target(IDropTarget __RPC_FAR * This)
00244 {
00245    target_drag_context *ctx = (target_drag_context *) This;
00246    GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
00247 
00248    GDK_NOTE(DND, g_print("m_release_target\n"));
00249    gdk_drag_context_unref(ctx->context);
00250 
00251    if (private->ref_count == 1) {
00252       gdk_drag_context_unref(ctx->context);
00253       return 0;
00254    } else
00255       return private->ref_count - 1;
00256 }
00257 
00258 static HRESULT STDMETHODCALLTYPE
00259 m_drag_enter(IDropTarget __RPC_FAR * This,
00260              IDataObject __RPC_FAR * pDataObj,
00261              DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR * pdwEffect)
00262 {
00263    GDK_NOTE(DND, g_print("m_drag_enter\n"));
00264    return E_UNEXPECTED;
00265 }
00266 
00267 static HRESULT STDMETHODCALLTYPE
00268 m_drag_over(IDropTarget __RPC_FAR * This,
00269             DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR * pdwEffect)
00270 {
00271    GDK_NOTE(DND, g_print("m_drag_over\n"));
00272    return E_UNEXPECTED;
00273 }
00274 
00275 static HRESULT STDMETHODCALLTYPE m_drag_leave(IDropTarget __RPC_FAR * This)
00276 {
00277    GDK_NOTE(DND, g_print("m_drag_leave\n"));
00278    return E_UNEXPECTED;
00279 }
00280 
00281 static HRESULT STDMETHODCALLTYPE
00282 m_drop(IDropTarget __RPC_FAR * This,
00283        IDataObject __RPC_FAR * pDataObj,
00284        DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR * pdwEffect)
00285 {
00286    GDK_NOTE(DND, g_print("m_drop\n"));
00287    return E_UNEXPECTED;
00288 }
00289 
00290 static ULONG STDMETHODCALLTYPE
00291 m_add_ref_source(IDropSource __RPC_FAR * This)
00292 {
00293    source_drag_context *ctx = (source_drag_context *) This;
00294    GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
00295 
00296    GDK_NOTE(DND, g_print("m_add_ref_source\n"));
00297    gdk_drag_context_ref(ctx->context);
00298 
00299    return private->ref_count;
00300 }
00301 
00302 static HRESULT STDMETHODCALLTYPE
00303 m_query_interface_source(IDropSource __RPC_FAR * This,
00304                          REFIID riid,
00305                          void __RPC_FAR * __RPC_FAR * ppvObject)
00306 {
00307    GDK_NOTE(DND, g_print("m_query_interface_source\n"));
00308 
00309    *ppvObject = NULL;
00310 
00311    PRINT_GUID(riid);
00312    if (IsEqualGUID(riid, &IID_IUnknown)) {
00313       g_print("...IUnknown\n");
00314       m_add_ref_source(This);
00315       *ppvObject = This;
00316       return S_OK;
00317    } else if (IsEqualGUID(riid, &IID_IDropSource)) {
00318       g_print("...IDropSource\n");
00319       m_add_ref_source(This);
00320       *ppvObject = This;
00321       return S_OK;
00322    } else {
00323       g_print("...Huh?\n");
00324       return E_NOINTERFACE;
00325    }
00326 }
00327 
00328 static ULONG STDMETHODCALLTYPE
00329 m_release_source(IDropSource __RPC_FAR * This)
00330 {
00331    source_drag_context *ctx = (source_drag_context *) This;
00332    GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
00333 
00334    GDK_NOTE(DND, g_print("m_release_source\n"));
00335    gdk_drag_context_unref(ctx->context);
00336 
00337    if (private->ref_count == 1) {
00338       gdk_drag_context_unref(ctx->context);
00339       return 0;
00340    } else
00341       return private->ref_count - 1;
00342 }
00343 
00344 static HRESULT STDMETHODCALLTYPE
00345 m_query_continue_drag(IDropSource __RPC_FAR * This,
00346                       BOOL fEscapePressed, DWORD grfKeyState)
00347 {
00348    GDK_NOTE(DND, g_print("m_query_continue_drag\n"));
00349    return E_UNEXPECTED;
00350 }
00351 
00352 static HRESULT STDMETHODCALLTYPE
00353 m_give_feedback(IDropSource __RPC_FAR * This, DWORD dwEffect)
00354 {
00355    GDK_NOTE(DND, g_print("m_give_feedback\n"));
00356    return E_UNEXPECTED;
00357 }
00358 
00359 static HRESULT STDMETHODCALLTYPE
00360 m_query_interface_object(IDataObject __RPC_FAR * This,
00361                          REFIID riid,
00362                          void __RPC_FAR * __RPC_FAR * ppvObject)
00363 {
00364    return E_UNEXPECTED;
00365 }
00366 
00367 static ULONG STDMETHODCALLTYPE
00368 m_add_ref_object(IDataObject __RPC_FAR * This)
00369 {
00370    return E_UNEXPECTED;
00371 }
00372 
00373 static ULONG STDMETHODCALLTYPE
00374 m_release_object(IDataObject __RPC_FAR * This)
00375 {
00376    return E_UNEXPECTED;
00377 }
00378 
00379 static HRESULT STDMETHODCALLTYPE
00380 m_get_data(IDataObject __RPC_FAR * This,
00381            FORMATETC * pFormatEtc, STGMEDIUM * pMedium)
00382 {
00383    return E_UNEXPECTED;
00384 }
00385 
00386 static HRESULT STDMETHODCALLTYPE
00387 m_get_data_here(IDataObject __RPC_FAR * This,
00388                 FORMATETC * pFormatEtc, STGMEDIUM * pMedium)
00389 {
00390    return E_UNEXPECTED;
00391 }
00392 
00393 static HRESULT STDMETHODCALLTYPE
00394 m_query_get_data(IDataObject __RPC_FAR * This, FORMATETC * pFormatEtc)
00395 {
00396    return E_UNEXPECTED;
00397 }
00398 
00399 static HRESULT STDMETHODCALLTYPE
00400 m_get_canonical_format_etc(IDataObject __RPC_FAR * This,
00401                            FORMATETC * pFormatEtcIn,
00402                            FORMATETC * pFormatEtcOut)
00403 {
00404    return E_UNEXPECTED;
00405 }
00406 
00407 static HRESULT STDMETHODCALLTYPE
00408 m_set_data(IDataObject __RPC_FAR * This,
00409            FORMATETC * pFormatEtc, STGMEDIUM * pMedium, BOOL fRelease)
00410 {
00411    return E_UNEXPECTED;
00412 }
00413 
00414 static HRESULT STDMETHODCALLTYPE
00415 m_enum_format_etc(IDataObject __RPC_FAR * This,
00416                   DWORD dwDirection, IEnumFORMATETC ** ppEnumFormatEtc)
00417 {
00418    return E_UNEXPECTED;
00419 }
00420 
00421 static HRESULT STDMETHODCALLTYPE
00422 m_d_advise(IDataObject __RPC_FAR * This,
00423            FORMATETC * pFormatetc,
00424            DWORD advf, IAdviseSink * pAdvSink, DWORD * pdwConnection)
00425 {
00426    return E_UNEXPECTED;
00427 }
00428 
00429 static HRESULT STDMETHODCALLTYPE
00430 m_d_unadvise(IDataObject __RPC_FAR * This, DWORD dwConnection)
00431 {
00432    return E_UNEXPECTED;
00433 }
00434 
00435 static HRESULT STDMETHODCALLTYPE
00436 m_enum_d_advise(IDataObject __RPC_FAR * This,
00437                 IEnumSTATDATA ** ppenumAdvise)
00438 {
00439    return E_UNEXPECTED;
00440 }
00441 
00442 static IDropTargetVtbl idt_vtbl = {
00443    m_query_interface_target,
00444    m_add_ref_target,
00445    m_release_target,
00446    m_drag_enter,
00447    m_drag_over,
00448    m_drag_leave,
00449    m_drop
00450 };
00451 
00452 static IDropSourceVtbl ids_vtbl = {
00453    m_query_interface_source,
00454    m_add_ref_source,
00455    m_release_source,
00456    m_query_continue_drag,
00457    m_give_feedback
00458 };
00459 
00460 static IDataObjectVtbl ido_vtbl = {
00461    m_query_interface_object,
00462    m_add_ref_object,
00463    m_release_object,
00464    m_get_data,
00465    m_get_data_here,
00466    m_query_get_data,
00467    m_get_canonical_format_etc,
00468    m_set_data,
00469    m_enum_format_etc,
00470    m_d_advise,
00471    m_d_unadvise,
00472    m_enum_d_advise
00473 };
00474 
00475 #endif                          /* OLE2_DND */
00476 
00477 static target_drag_context *target_context_new(void)
00478 {
00479    target_drag_context *result;
00480 
00481    result = g_new0(target_drag_context, 1);
00482 
00483 #ifdef OLE2_DND
00484    result->idt.lpVtbl = &idt_vtbl;
00485 #endif
00486 
00487    result->context = gdk_drag_context_new();
00488 
00489    return result;
00490 }
00491 
00492 static source_drag_context *source_context_new(void)
00493 {
00494    source_drag_context *result;
00495 
00496    result = g_new0(source_drag_context, 1);
00497 
00498 #ifdef OLE2_DND
00499    result->ids.lpVtbl = &ids_vtbl;
00500 #endif
00501 
00502    result->context = gdk_drag_context_new();
00503 
00504    return result;
00505 }
00506 
00507 /* From MS Knowledge Base article Q130698 */
00508 
00509 /* resolve_link() fills the filename and path buffer
00510  * with relevant information
00511  * hWnd         - calling app's window handle.
00512  *
00513  * lpszLinkName - name of the link file passed into the function.
00514  *
00515  * lpszPath     - the buffer that will receive the file pathname.
00516  */
00517 
00518 static HRESULT
00519 resolve_link(HWND hWnd,
00520              LPCTSTR lpszLinkName, LPSTR lpszPath, LPSTR lpszDescription)
00521 {
00522    HRESULT hres;
00523    IShellLink *psl;
00524    WIN32_FIND_DATA wfd;
00525 
00526    /* Assume Failure to start with: */
00527    *lpszPath = 0;
00528    if (lpszDescription)
00529       *lpszDescription = 0;
00530 
00531    /* Call CoCreateInstance to obtain the IShellLink interface
00532     * pointer. This call fails if CoInitialize is not called, so it is
00533     * assumed that CoInitialize has been called.
00534     */
00535 
00536    hres = CoCreateInstance(&CLSID_ShellLink,
00537                            NULL,
00538                            CLSCTX_INPROC_SERVER,
00539                            &IID_IShellLink, (LPVOID *) & psl);
00540    if (SUCCEEDED(hres)) {
00541       IPersistFile *ppf;
00542 
00543       /* The IShellLink interface supports the IPersistFile
00544        * interface. Get an interface pointer to it.
00545        */
00546       hres = psl->lpVtbl->QueryInterface(psl,
00547                                          &IID_IPersistFile,
00548                                          (LPVOID *) & ppf);
00549       if (SUCCEEDED(hres)) {
00550          WORD wsz[MAX_PATH];
00551 
00552          /* Convert the given link name string to wide character string. */
00553          MultiByteToWideChar(CP_ACP, 0, lpszLinkName, -1, wsz, MAX_PATH);
00554          /* Load the file. */
00555          hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
00556          if (SUCCEEDED(hres)) {
00557             /* Resolve the link by calling the Resolve()
00558              * interface function.
00559              */
00560             hres = psl->lpVtbl->Resolve(psl, hWnd,
00561                                         SLR_ANY_MATCH | SLR_NO_UI);
00562             if (SUCCEEDED(hres)) {
00563                hres = psl->lpVtbl->GetPath(psl, lpszPath,
00564                                            MAX_PATH,
00565                                            (WIN32_FIND_DATA *) & wfd, 0);
00566 
00567                if (SUCCEEDED(hres) && lpszDescription != NULL) {
00568                   hres = psl->lpVtbl->GetDescription(psl,
00569                                                      lpszDescription,
00570                                                      MAX_PATH);
00571 
00572                   if (!SUCCEEDED(hres))
00573                      return FALSE;
00574                }
00575             }
00576          }
00577          ppf->lpVtbl->Release(ppf);
00578       }
00579       psl->lpVtbl->Release(psl);
00580    }
00581    return SUCCEEDED(hres);
00582 }
00583 
00584 static GdkFilterReturn
00585 gdk_dropfiles_filter(GdkXEvent * xev, GdkEvent * event, gpointer data)
00586 {
00587    GdkDragContext *context;
00588    GdkDragContextPrivate *private;
00589    static GdkAtom text_uri_list_atom = GDK_NONE;
00590    GString *result;
00591    MSG *msg = (MSG *) xev;
00592    HANDLE hdrop;
00593    POINT pt;
00594    gint nfiles, i, k;
00595    guchar fileName[MAX_PATH], linkedFile[MAX_PATH];
00596 
00597    if (text_uri_list_atom == GDK_NONE)
00598       text_uri_list_atom = gdk_atom_intern("text/uri-list", FALSE);
00599 
00600    if (msg->message == WM_DROPFILES) {
00601       GDK_NOTE(DND, g_print("WM_DROPFILES: %#x\n", msg->hwnd));
00602 
00603       context = gdk_drag_context_new();
00604       private = (GdkDragContextPrivate *) context;
00605       context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
00606       context->is_source = FALSE;
00607       context->source_window = gdk_parent_root;
00608       context->dest_window = event->any.window;
00609       gdk_window_ref(context->dest_window);
00610       /* WM_DROPFILES drops are always file names */
00611       context->targets =
00612           g_list_append(NULL, GUINT_TO_POINTER(text_uri_list_atom));
00613       current_dest_drag = context;
00614 
00615       event->dnd.type = GDK_DROP_START;
00616       event->dnd.context = current_dest_drag;
00617       gdk_drag_context_ref(current_dest_drag);
00618 
00619       hdrop = (HANDLE) msg->wParam;
00620       DragQueryPoint(hdrop, &pt);
00621       ClientToScreen(msg->hwnd, &pt);
00622 
00623       event->dnd.x_root = pt.x;
00624       event->dnd.y_root = pt.y;
00625       event->dnd.time = msg->time;
00626 
00627       nfiles = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
00628 
00629       result = g_string_new(NULL);
00630       for (i = 0; i < nfiles; i++) {
00631          g_string_append(result, "file:");
00632          DragQueryFile(hdrop, i, fileName, MAX_PATH);
00633 
00634          /* Resolve shortcuts */
00635          if (resolve_link(msg->hwnd, fileName, linkedFile, NULL)) {
00636             g_string_append(result, linkedFile);
00637             GDK_NOTE(DND, g_print("...%s link to %s\n",
00638                                   fileName, linkedFile));
00639          } else {
00640             g_string_append(result, fileName);
00641             GDK_NOTE(DND, g_print("...%s\n", fileName));
00642          }
00643          g_string_append(result, "\015\012");
00644       }
00645       gdk_sel_prop_store(gdk_parent_root, text_uri_list_atom, 8,
00646                          result->str, result->len + 1);
00647 
00648       DragFinish(hdrop);
00649 
00650       return GDK_FILTER_TRANSLATE;
00651    } else
00652       return GDK_FILTER_CONTINUE;
00653 }
00654 
00655 /*************************************************************
00656  ************************** Public API ***********************
00657  *************************************************************/
00658 
00659 void gdk_dnd_init(void)
00660 {
00661    HRESULT hres;
00662 #ifdef OLE2_DND
00663    hres = OleInitialize(NULL);
00664 
00665    if (!SUCCEEDED(hres))
00666       g_error("OleInitialize failed");
00667 #endif
00668 }
00669 
00670 void gdk_win32_dnd_exit(void)
00671 {
00672 #ifdef OLE2_DND
00673    OleUninitialize();
00674 #endif
00675 }
00676 
00677 /* Source side */
00678 
00679 static void gdk_drag_do_leave(GdkDragContext * context, guint32 time)
00680 {
00681    if (context->dest_window) {
00682       GDK_NOTE(DND, g_print("gdk_drag_do_leave\n"));
00683       gdk_window_unref(context->dest_window);
00684       context->dest_window = NULL;
00685    }
00686 }
00687 
00688 GdkDragContext *gdk_drag_begin(GdkWindow * window, GList * targets)
00689 {
00690    GList *tmp_list;
00691    source_drag_context *ctx;
00692 
00693    g_return_val_if_fail(window != NULL, NULL);
00694 
00695    GDK_NOTE(DND, g_print("gdk_drag_begin\n"));
00696 
00697    ctx = source_context_new();
00698    ctx->context->is_source = TRUE;
00699    ctx->context->source_window = window;
00700    gdk_window_ref(window);
00701 
00702    tmp_list = g_list_last(targets);
00703    ctx->context->targets = NULL;
00704    while (tmp_list) {
00705       ctx->context->targets = g_list_prepend(ctx->context->targets,
00706                                              tmp_list->data);
00707       tmp_list = tmp_list->prev;
00708    }
00709 
00710    ctx->context->actions = 0;
00711 
00712 #if 0
00713    DoDragDrop(...);
00714 #endif
00715    return ctx->context;
00716 }
00717 
00718 guint32 gdk_drag_get_protocol(guint32 xid, GdkDragProtocol * protocol)
00719 {
00720    /* This isn't used */
00721    return 0;
00722 }
00723 
00724 void
00725 gdk_drag_find_window(GdkDragContext * context,
00726                      GdkWindow * drag_window,
00727                      gint x_root,
00728                      gint y_root,
00729                      GdkWindow ** dest_window, GdkDragProtocol * protocol)
00730 {
00731    GdkDragContextPrivate *private = (GdkDragContextPrivate *) context;
00732    GdkDrawablePrivate *drag_window_private =
00733        (GdkDrawablePrivate *) drag_window;
00734    HWND recipient;
00735    POINT pt;
00736 
00737    GDK_NOTE(DND, g_print("gdk_drag_find_window: %#x +%d+%d\n",
00738                          (drag_window ? GDK_DRAWABLE_XID(drag_window) : 0),
00739                          x_root, y_root));
00740 
00741    pt.x = x_root;
00742    pt.y = y_root;
00743    recipient = WindowFromPoint(pt);
00744    if (recipient == NULL)
00745       *dest_window = NULL;
00746    else {
00747       *dest_window = gdk_window_lookup(recipient);
00748       if (*dest_window)
00749          gdk_window_ref(*dest_window);
00750       *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
00751    }
00752 }
00753 
00754 gboolean
00755 gdk_drag_motion(GdkDragContext * context,
00756                 GdkWindow * dest_window,
00757                 GdkDragProtocol protocol,
00758                 gint x_root,
00759                 gint y_root,
00760                 GdkDragAction suggested_action,
00761                 GdkDragAction possible_actions, guint32 time)
00762 {
00763    return FALSE;
00764 }
00765 
00766 void gdk_drag_drop(GdkDragContext * context, guint32 time)
00767 {
00768    g_return_if_fail(context != NULL);
00769 
00770    g_warning("gdk_drag_drop: not implemented\n");
00771 }
00772 
00773 void gdk_drag_abort(GdkDragContext * context, guint32 time)
00774 {
00775    g_return_if_fail(context != NULL);
00776 
00777    gdk_drag_do_leave(context, time);
00778 }
00779 
00780 /* Destination side */
00781 
00782 void
00783 gdk_drag_status(GdkDragContext * context,
00784                 GdkDragAction action, guint32 time)
00785 {
00786    GDK_NOTE(DND, g_print("gdk_drag_status\n"));
00787 }
00788 
00789 void gdk_drop_reply(GdkDragContext * context, gboolean ok, guint32 time)
00790 {
00791 }
00792 
00793 void
00794 gdk_drop_finish(GdkDragContext * context, gboolean success, guint32 time)
00795 {
00796 }
00797 
00798 static GdkFilterReturn
00799 gdk_destroy_filter(GdkXEvent * xev, GdkEvent * event, gpointer data)
00800 {
00801 #ifdef OLE2_DND
00802    MSG *msg = (MSG *) xev;
00803 
00804    if (msg->message == WM_DESTROY) {
00805       IDropTarget *idtp = (IDropTarget *) data;
00806 
00807       GDK_NOTE(DND,
00808                g_print("gdk_destroy_filter: WM_DESTROY: %#x\n",
00809                        msg->hwnd));
00810       RevokeDragDrop(msg->hwnd);
00811       CoLockObjectExternal(idtp, FALSE, TRUE);
00812    }
00813 #endif
00814    return GDK_FILTER_CONTINUE;
00815 }
00816 
00817 void gdk_window_register_dnd(GdkWindow * window)
00818 {
00819 #ifdef OLE2_DND
00820    target_drag_context *context;
00821    HRESULT hres;
00822 #endif
00823 
00824    g_return_if_fail(window != NULL);
00825 
00826    GDK_NOTE(DND, g_print("gdk_window_register_dnd: %#x\n",
00827                          GDK_DRAWABLE_XID(window)));
00828 
00829    /* We always claim to accept dropped files, but in fact we might not,
00830     * of course. This function is called in such a way that it cannot know
00831     * whether the window (widget) in question actually accepts files
00832     * (in gtk, data of type text/uri-list) or not.
00833     */
00834    gdk_window_add_filter(window, gdk_dropfiles_filter, NULL);
00835    DragAcceptFiles(GDK_DRAWABLE_XID(window), TRUE);
00836 
00837 #ifdef OLE2_DND
00838    /* Register for OLE2 d&d */
00839    context = target_context_new();
00840    hres = CoLockObjectExternal((IUnknown *) & context->idt, TRUE, FALSE);
00841    if (!SUCCEEDED(hres))
00842       OTHER_API_FAILED("CoLockObjectExternal");
00843    else {
00844       hres = RegisterDragDrop(GDK_DRAWABLE_XID(window), &context->idt);
00845       if (hres == DRAGDROP_E_ALREADYREGISTERED) {
00846          g_print("DRAGDROP_E_ALREADYREGISTERED\n");
00847          CoLockObjectExternal((IUnknown *) & context->idt, FALSE, FALSE);
00848       } else if (!SUCCEEDED(hres))
00849          OTHER_API_FAILED("RegisterDragDrop");
00850       else {
00851          gdk_window_add_filter(window, gdk_destroy_filter, &context->idt);
00852       }
00853    }
00854 #endif
00855 }
00856 
00857 /*************************************************************
00858  * gdk_drag_get_selection:
00859  *     Returns the selection atom for the current source window
00860  *   arguments:
00861  *
00862  *   results:
00863  *************************************************************/
00864 
00865 GdkAtom gdk_drag_get_selection(GdkDragContext * context)
00866 {
00867    if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
00868       return gdk_win32_dropfiles_atom;
00869    else if (context->protocol == GDK_DRAG_PROTO_OLE2)
00870       return gdk_ole2_dnd_atom;
00871    else
00872       return GDK_NONE;
00873 }

Generated on Tue Jul 5 14:14:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1