X11 drag-and-drop support (files only)
svn: r4957
This commit is contained in:
parent
7225c5f60e
commit
7b185d5ae4
|
@ -455,14 +455,14 @@ static void abandoned_clip(void *_cb)
|
|||
cb->in_progress = -1;
|
||||
}
|
||||
|
||||
char *wxClipboard::GetClipboardData(char *format, long *length, long time)
|
||||
char *wxClipboard::GetClipboardData(char *format, long *length, long time, int alt_sel)
|
||||
{
|
||||
if (clipOwner) {
|
||||
if (clipOwner && !alt_sel) {
|
||||
if (clipOwner->formats->Member(format))
|
||||
return wxsGetDataInEventspace(clipOwner, format, length);
|
||||
else
|
||||
return NULL;
|
||||
} else if (cbString) {
|
||||
} else if (cbString && !alt_sel) {
|
||||
if (!strcmp(format, "TEXT"))
|
||||
return copystring(cbString);
|
||||
else
|
||||
|
@ -482,7 +482,7 @@ char *wxClipboard::GetClipboardData(char *format, long *length, long time)
|
|||
receivedString = NULL;
|
||||
receivedTargets = NULL;
|
||||
|
||||
XtGetSelectionValue(getClipWindow, is_sel ? XA_PRIMARY : xa_clipboard,
|
||||
XtGetSelectionValue(getClipWindow, alt_sel ? alt_sel : (is_sel ? XA_PRIMARY : xa_clipboard),
|
||||
xa_targets, wxGetTargets, (XtPointer)saferef, time);
|
||||
|
||||
start_time = scheme_get_inexact_milliseconds();
|
||||
|
@ -517,7 +517,7 @@ char *wxClipboard::GetClipboardData(char *format, long *length, long time)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
XtGetSelectionValue(getClipWindow, is_sel ? XA_PRIMARY : xa_clipboard,
|
||||
XtGetSelectionValue(getClipWindow, alt_sel ? alt_sel : (is_sel ? XA_PRIMARY : xa_clipboard),
|
||||
xa, wxGetSelection, (XtPointer)saferef, 0);
|
||||
|
||||
start_time = scheme_get_inexact_milliseconds();
|
||||
|
|
|
@ -63,7 +63,7 @@ class wxClipboard : public wxObject
|
|||
wxBitmap *GetClipboardBitmap(long time);
|
||||
|
||||
/* Get data from the clipboard */
|
||||
char *GetClipboardData(char *format, long *length, long time);
|
||||
char *GetClipboardData(char *format, long *length, long time, int alt_sel = 0);
|
||||
|
||||
/* Get the clipboard client directly. Will be NULL if clipboard data
|
||||
is a string, or if some other application owns the clipboard.
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define Uses_wxItem
|
||||
#define Uses_wxCanvas
|
||||
#define Uses_wxApp
|
||||
#define Uses_wxClipboard
|
||||
#include "wx.h"
|
||||
#define Uses_ScrollWinWidget
|
||||
#define Uses_Scrollbar
|
||||
|
@ -49,6 +50,8 @@
|
|||
#define Uses_ScrollbarWidget
|
||||
#include "widgets.h"
|
||||
|
||||
#include "xdnd.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/keysym.h> // needed for IsFunctionKey, etc.
|
||||
#ifdef WX_USE_XFT
|
||||
|
@ -60,11 +63,17 @@ static Atom utf8_atom = 0, net_wm_name_atom, net_wm_icon_name_atom;
|
|||
extern void wxSetSensitive(Widget, Bool enabled);
|
||||
extern int wxLocaleStringToChar(char *str, int slen);
|
||||
extern int wxUTF8StringToChar(char *str, int slen);
|
||||
extern wxWindow *wxLocationToWindow(int x, int y);
|
||||
|
||||
static wxWindow *grabbing_panel;
|
||||
static Time grabbing_panel_time;
|
||||
static Bool grabbing_panel_regsitered;
|
||||
|
||||
#include "xdnd.c"
|
||||
|
||||
static int dnd_inited = 0;
|
||||
static DndClass dnd;
|
||||
|
||||
#ifndef NO_XMB_LOOKUP_STRING
|
||||
static XIM the_im;
|
||||
#endif
|
||||
|
@ -146,7 +155,9 @@ wxWindow::~wxWindow(void)
|
|||
// destroy widgets
|
||||
wxSetSensitive(X->frame, TRUE);
|
||||
|
||||
*saferef = NULL; /* MATTHEW */
|
||||
*saferef = NULL;
|
||||
|
||||
dndTarget = NULL; /* just in case */
|
||||
|
||||
if (X->frame) XtDestroyWidget(X->frame); X->frame = X->handle = X->scroll = NULL;
|
||||
DELETE_OBJ constraints; constraints = NULL;
|
||||
|
@ -1397,6 +1408,91 @@ void wxWindow::FrameEventHandler(Widget w,
|
|||
if (win->OnClose())
|
||||
win->Show(FALSE);
|
||||
}
|
||||
if (dnd_inited) {
|
||||
if (xev->xclient.message_type == dnd.XdndEnter) {
|
||||
/* Ok... */
|
||||
} else if (xev->xclient.message_type == dnd.XdndPosition) {
|
||||
wxWindow *target = NULL;
|
||||
|
||||
/* Find immediate target window: */
|
||||
{
|
||||
Display *dpy = XtDisplay(w);
|
||||
Screen *scn = XtScreen(w);
|
||||
Window root = RootWindowOfScreen(scn);
|
||||
Window xwin = XtWindow(w);
|
||||
Window child = 0;
|
||||
int cx, cy;
|
||||
cx = XDND_POSITION_ROOT_X(xev);
|
||||
cy = XDND_POSITION_ROOT_Y(xev);
|
||||
while (1) {
|
||||
if (XTranslateCoordinates(dpy, root, xwin, cx, cy,
|
||||
&cx, &cy, &child)) {
|
||||
if (!child)
|
||||
break;
|
||||
else {
|
||||
root = xwin;
|
||||
xwin = child;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (xwin) {
|
||||
Widget cw;
|
||||
cw = XtWindowToWidget(dpy, xwin);
|
||||
if (cw) {
|
||||
target = win->FindChildByWidget(cw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Does this window (if found) accept drops? Or maybe a parent? */
|
||||
while (target && !target->drag_accept) {
|
||||
if (wxSubType(target->__type, wxTYPE_FRAME)
|
||||
|| wxSubType(target->__type, wxTYPE_DIALOG_BOX)) {
|
||||
target = NULL;
|
||||
break;
|
||||
} else {
|
||||
target = target->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
xdnd_send_status(&dnd, XDND_ENTER_SOURCE_WIN(xev), xev->xclient.window,
|
||||
!!target,
|
||||
0, 0, 0, 10, 10, dnd.XdndActionPrivate);
|
||||
|
||||
win->dndTarget = target;
|
||||
} else if (xev->xclient.message_type == dnd.XdndDrop) {
|
||||
if (win->dndTarget) {
|
||||
wxWindow *target = win->dndTarget;
|
||||
win->dndTarget = NULL;
|
||||
if (!xdnd_convert_selection(&dnd, XDND_DROP_SOURCE_WIN(xev), xev->xclient.window, dnd.text_uri_list)) {
|
||||
long len;
|
||||
char *data;
|
||||
data = wxTheClipboard->GetClipboardData("text/uri-list", &len, XDND_DROP_TIME(xev), dnd.XdndSelection);
|
||||
if (data) {
|
||||
/* If file://... prefix (then drop it) */
|
||||
if (!strncmp(data, "file://", 7)) {
|
||||
int i = 7;
|
||||
char *data2;
|
||||
while ((i < len) && (data[i] != '/')) {
|
||||
i++;
|
||||
}
|
||||
if (i < len) {
|
||||
data2 = new WXGC_ATOMIC char[len - i + 1];
|
||||
memcpy(data2, data + i, len - i);
|
||||
data2[len - i] = 0;
|
||||
target->OnDropFile(data2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xdnd_send_finished(&dnd, XDND_DROP_SOURCE_WIN(xev), XtWindow(w), 0);
|
||||
} else if (xev->xclient.message_type == dnd.XdndLeave) {
|
||||
win->dndTarget = NULL;
|
||||
xdnd_send_finished(&dnd, XDND_LEAVE_SOURCE_WIN(xev), XtWindow(w), 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CreateNotify:
|
||||
break;
|
||||
|
@ -2256,3 +2352,64 @@ long wxWindow::GetWindowHandle()
|
|||
{
|
||||
return (long)X->handle;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// drag & drop
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void wxWindow::DragAcceptFiles(Bool accept)
|
||||
{
|
||||
wxWindow *p;
|
||||
|
||||
if (!drag_accept == !accept)
|
||||
return;
|
||||
|
||||
drag_accept = accept;
|
||||
|
||||
if (!dnd_inited) {
|
||||
xdnd_init(&dnd, wxAPP_DISPLAY);
|
||||
dnd_inited = 1;
|
||||
}
|
||||
|
||||
/* Declare drag-and-drop possible at this
|
||||
window's top-level frame: */
|
||||
|
||||
p = this;
|
||||
while (p) {
|
||||
if (wxSubType(p->__type, wxTYPE_FRAME)
|
||||
|| wxSubType(p->__type, wxTYPE_DIALOG_BOX))
|
||||
break;
|
||||
p = p->GetParent();
|
||||
}
|
||||
|
||||
{
|
||||
Atom l[2];
|
||||
l[0] = dnd.text_uri_list;
|
||||
l[1] = 0;
|
||||
xdnd_set_dnd_aware(&dnd, XtWindow(p->X->frame), l);
|
||||
}
|
||||
}
|
||||
|
||||
wxWindow *wxWindow::FindChildByWidget(Widget w)
|
||||
{
|
||||
wxChildNode *node, *next;
|
||||
wxWindow *r;
|
||||
|
||||
if ((w == X->frame)
|
||||
|| (w == X->handle))
|
||||
return this;
|
||||
|
||||
|
||||
for (node = children->First(); node; node = next) {
|
||||
wxWindow *child;
|
||||
next = node->Next();
|
||||
child = (wxWindow*)(node->Data());
|
||||
if (child) {
|
||||
r = child->FindChildByWidget(w);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ public:
|
|||
// miscellaneous
|
||||
virtual void AllowDoubleClick(Bool allow) { allow_dclicks = allow; }
|
||||
virtual void CaptureMouse(void);
|
||||
virtual void DragAcceptFiles(Bool accept) { drag_accept = accept; }
|
||||
virtual void DragAcceptFiles(Bool accept);
|
||||
virtual void Enable(Bool enable);
|
||||
virtual void EnablePainting(Bool enable) { painting_enabled = enable; }
|
||||
virtual void Fit(void) {}
|
||||
|
@ -196,6 +196,7 @@ protected:
|
|||
static Status LookupKey(int unshifted, int unalted,
|
||||
Widget w, wxWindow *win, XEvent *xev, KeySym *_keysym, char *s, int *_len);
|
||||
void RegisterAll(Widget ww);
|
||||
wxWindow *FindChildByWidget(Widget w);
|
||||
# endif
|
||||
protected:
|
||||
friend void wxXSetBusyCursor(wxWindow *, wxCursor *);
|
||||
|
@ -224,6 +225,8 @@ protected:
|
|||
|
||||
wxWindow **saferef; /* indirection for safety in callbacks */
|
||||
|
||||
wxWindow *dndTarget; /* set between XdndPosition and XdndDrop/XdndLeave */
|
||||
|
||||
long misc_flags;
|
||||
|
||||
unsigned long current_state;
|
||||
|
|
402
src/wxxt/src/Windows/xdnd.c
Normal file
402
src/wxxt/src/Windows/xdnd.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
xdnd.c, xdnd.h - C program library for handling the Xdnd protocol
|
||||
|
||||
Copyright (C) 1998 Paul Sheer
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
http://www.cco.caltech.edu/~jafl/xdnd/
|
||||
|
||||
Further info can also be obtained by emailing the author at,
|
||||
psheer@obsidian.co.za
|
||||
|
||||
Released 1998-08-07
|
||||
*/
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "xdnd.h"
|
||||
|
||||
|
||||
// #define DND_DEBUG
|
||||
#define dnd_version_at_least(a,b) ((a) <= (b))
|
||||
|
||||
#ifdef DND_DEBUG
|
||||
#define dnd_debug(a,b...) printf("%s: %d: " a "\n", __FILE__, __LINE__ , ## b)
|
||||
#else
|
||||
|
||||
#ifdef NeXT_RUNTIME
|
||||
#define dnd_debug //
|
||||
#else /* !NeXT_RUNTIME */
|
||||
#define dnd_debug(a,b...)
|
||||
#endif /* NeXT_RUNTIME */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void
|
||||
xdnd_reset(DndClass * dnd)
|
||||
{
|
||||
dnd->stage = XDND_DROP_STAGE_IDLE;
|
||||
dnd->dragging_version = 0;
|
||||
dnd->internal_drag = 0;
|
||||
dnd->want_position = 0;
|
||||
dnd->ready_to_drop = 0;
|
||||
dnd->will_accept = 0;
|
||||
dnd->rectangle.x = dnd->rectangle.y = 0;
|
||||
dnd->rectangle.width = dnd->rectangle.height = 0;
|
||||
dnd->dropper_window = 0;
|
||||
dnd->dragger_window = 0;
|
||||
dnd->dragger_typelist = 0;
|
||||
dnd->desired_type = 0;
|
||||
dnd->time = 0;
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_init(DndClass * dnd, Display * display)
|
||||
{
|
||||
memset (dnd, 0, sizeof (*dnd));
|
||||
|
||||
dnd->display = display;
|
||||
dnd->root_window = DefaultRootWindow (display);
|
||||
dnd->version = XDND_VERSION;
|
||||
dnd->XdndAware = XInternAtom (dnd->display, "XdndAware", False);
|
||||
dnd->XdndSelection = XInternAtom (dnd->display, "XdndSelection", False);
|
||||
dnd->XdndEnter = XInternAtom (dnd->display, "XdndEnter", False);
|
||||
dnd->XdndLeave = XInternAtom (dnd->display, "XdndLeave", False);
|
||||
dnd->XdndPosition = XInternAtom (dnd->display, "XdndPosition", False);
|
||||
dnd->XdndDrop = XInternAtom (dnd->display, "XdndDrop", False);
|
||||
dnd->XdndFinished = XInternAtom (dnd->display, "XdndFinished", False);
|
||||
dnd->XdndStatus = XInternAtom (dnd->display, "XdndStatus", False);
|
||||
dnd->XdndActionCopy = XInternAtom (dnd->display, "XdndActionCopy", False);
|
||||
dnd->XdndActionMove = XInternAtom (dnd->display, "XdndActionMove", False);
|
||||
dnd->XdndActionLink = XInternAtom (dnd->display, "XdndActionLink", False);
|
||||
dnd->XdndActionAsk = XInternAtom (dnd->display, "XdndActionAsk", False);
|
||||
dnd->XdndActionPrivate=XInternAtom(dnd->display,"XdndActionPrivate",False);
|
||||
dnd->XdndTypeList = XInternAtom (dnd->display, "XdndTypeList", False);
|
||||
dnd->XdndActionList = XInternAtom (dnd->display, "XdndActionList", False);
|
||||
dnd->XdndActionDescription = XInternAtom(dnd->display,
|
||||
"XdndActionDescription", False);
|
||||
dnd->text_uri_list = XInternAtom(dnd->display, "text/uri-list", False);
|
||||
xdnd_reset(dnd);
|
||||
}
|
||||
|
||||
static int
|
||||
array_length(Atom * a)
|
||||
{ // typelist is a null terminated array
|
||||
int n = 0;
|
||||
|
||||
while (a[n])
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist)
|
||||
{
|
||||
XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) &dnd->version, 1);
|
||||
if (typelist)
|
||||
{
|
||||
int n = array_length (typelist);
|
||||
if (n)
|
||||
XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32,
|
||||
PropModeAppend, (unsigned char *) typelist, n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_set_dnd_unaware (DndClass * dnd, Window window)
|
||||
{
|
||||
XDeleteProperty (dnd->display, window, dnd->XdndAware);
|
||||
}
|
||||
|
||||
int
|
||||
xdnd_is_dnd_aware(DndClass *dnd, Window window, int *version, Atom *typelist)
|
||||
{
|
||||
Atom actual;
|
||||
int format;
|
||||
unsigned long count, remaining;
|
||||
unsigned char *data = 0;
|
||||
Atom *types, *t;
|
||||
int result = 1;
|
||||
|
||||
*version = 0;
|
||||
XGetWindowProperty (dnd->display, window, dnd->XdndAware,
|
||||
0, 0x8000000L, False, XA_ATOM, &actual, &format,
|
||||
&count, &remaining, &data);
|
||||
|
||||
if (actual != XA_ATOM || format != 32 || count == 0 || !data)
|
||||
{
|
||||
dnd_debug("XGetWindowProperty failed in xdnd_is_dnd_aware - XdndAware = %ld", dnd->XdndAware);
|
||||
if (data)
|
||||
XFree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
types = (Atom *) data;
|
||||
*version = dnd->version < types[0] ? dnd->version : types[0]; // minimum
|
||||
dnd_debug ("Using XDND version %d", *version);
|
||||
if (count > 1)
|
||||
{
|
||||
result = 0;
|
||||
for (t = typelist; *t; t++)
|
||||
{
|
||||
unsigned long j;
|
||||
for (j = 1; j < count; j++)
|
||||
{
|
||||
if (types[j] == *t)
|
||||
{
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_enter(DndClass *dnd, Window window, Window from, Atom *typelist)
|
||||
{
|
||||
XEvent xevent;
|
||||
int n, i;
|
||||
|
||||
n = array_length (typelist);
|
||||
|
||||
memset(&xevent, 0, sizeof (xevent));
|
||||
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndEnter;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_ENTER_SOURCE_WIN (&xevent) = from;
|
||||
XDND_ENTER_THREE_TYPES_SET (&xevent, n > XDND_THREE);
|
||||
XDND_ENTER_VERSION_SET (&xevent, dnd->version);
|
||||
for (i = 0; i < n && i < XDND_THREE; i++)
|
||||
{
|
||||
XDND_ENTER_TYPE (&xevent, i) = typelist[i];
|
||||
}
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_position(DndClass *dnd, Window window, Window from, Atom action,
|
||||
int x, int y, unsigned long time)
|
||||
{
|
||||
XEvent xevent;
|
||||
|
||||
memset (&xevent, 0, sizeof (xevent));
|
||||
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndPosition;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_POSITION_SOURCE_WIN (&xevent) = from;
|
||||
XDND_POSITION_ROOT_SET (&xevent, x, y);
|
||||
if (dnd_version_at_least (dnd->dragging_version, 1))
|
||||
XDND_POSITION_TIME (&xevent) = time;
|
||||
if (dnd_version_at_least (dnd->dragging_version, 2))
|
||||
XDND_POSITION_ACTION (&xevent) = action;
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_status(DndClass *dnd, Window window, Window from, int will_accept,
|
||||
int want_position, int x, int y, int w, int h, Atom action)
|
||||
{
|
||||
XEvent xevent;
|
||||
|
||||
memset (&xevent, 0, sizeof (xevent));
|
||||
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndStatus;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_STATUS_TARGET_WIN (&xevent) = from;
|
||||
XDND_STATUS_WILL_ACCEPT_SET (&xevent, will_accept);
|
||||
if (will_accept)
|
||||
XDND_STATUS_WANT_POSITION_SET (&xevent, want_position);
|
||||
if (want_position)
|
||||
XDND_STATUS_RECT_SET (&xevent, x, y, w, h);
|
||||
if (dnd_version_at_least (dnd->dragging_version, 2))
|
||||
if (will_accept)
|
||||
XDND_STATUS_ACTION (&xevent) = action;
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_leave(DndClass *dnd, Window window, Window from)
|
||||
{
|
||||
XEvent xevent;
|
||||
|
||||
memset(&xevent, 0, sizeof (xevent));
|
||||
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndLeave;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_LEAVE_SOURCE_WIN (&xevent) = from;
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_drop(DndClass *dnd, Window window, Window from, unsigned long time)
|
||||
{
|
||||
XEvent xevent;
|
||||
|
||||
memset (&xevent, 0, sizeof (xevent));
|
||||
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndDrop;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_DROP_SOURCE_WIN (&xevent) = from;
|
||||
if (dnd_version_at_least (dnd->dragging_version, 1))
|
||||
XDND_DROP_TIME (&xevent) = time;
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_send_finished(DndClass * dnd, Window window, Window from, int error)
|
||||
{
|
||||
XEvent xevent;
|
||||
memset (&xevent, 0, sizeof (xevent));
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dnd->display;
|
||||
xevent.xclient.window = window;
|
||||
xevent.xclient.message_type = dnd->XdndFinished;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_FINISHED_TARGET_WIN (&xevent) = from;
|
||||
|
||||
XSendEvent (dnd->display, window, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
int
|
||||
xdnd_convert_selection(DndClass *dnd, Window window, Window requester, Atom type)
|
||||
{
|
||||
if (window != XGetSelectionOwner (dnd->display, dnd->XdndSelection))
|
||||
{
|
||||
dnd_debug ("xdnd_convert_selection(): XGetSelectionOwner failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
XConvertSelection (dnd->display, dnd->XdndSelection, type,
|
||||
dnd->Xdnd_NON_PROTOCOL_ATOM, requester, CurrentTime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xdnd_set_selection_owner(DndClass * dnd, Window window, Atom type)
|
||||
{
|
||||
if (!XSetSelectionOwner(dnd->display,dnd->XdndSelection,window,CurrentTime))
|
||||
{
|
||||
dnd_debug ("xdnd_set_selection_owner(): XSetSelectionOwner failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_selection_send(DndClass * dnd, XSelectionRequestEvent * request,
|
||||
unsigned char *data, int length)
|
||||
{
|
||||
XEvent xevent;
|
||||
|
||||
dnd_debug (" requestor = %ld", request->requestor);
|
||||
dnd_debug (" property = %ld", request->property);
|
||||
dnd_debug (" length = %d", length);
|
||||
|
||||
XChangeProperty (dnd->display, request->requestor, request->property,
|
||||
request->target, 8, PropModeReplace, data, length);
|
||||
|
||||
xevent.xselection.type = SelectionNotify;
|
||||
xevent.xselection.property = request->property;
|
||||
xevent.xselection.display = request->display;
|
||||
xevent.xselection.requestor = request->requestor;
|
||||
xevent.xselection.selection = request->selection;
|
||||
xevent.xselection.target = request->target;
|
||||
xevent.xselection.time = request->time;
|
||||
|
||||
XSendEvent (dnd->display, request->requestor, 0, 0, &xevent);
|
||||
}
|
||||
|
||||
//
|
||||
// Unused
|
||||
//
|
||||
|
||||
void
|
||||
xdnd_set_type_list(DndClass * dnd, Window window, Atom * typelist)
|
||||
{
|
||||
int n = array_length (typelist);
|
||||
|
||||
XChangeProperty (dnd->display, window, dnd->XdndTypeList, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) typelist, n);
|
||||
}
|
||||
|
||||
void
|
||||
xdnd_get_type_list(DndClass * dnd, Window window, Atom ** typelist)
|
||||
{
|
||||
Atom type, *a, *tl;
|
||||
int format;
|
||||
unsigned long i, count, remaining;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
*typelist = 0;
|
||||
|
||||
XGetWindowProperty (dnd->display, window, dnd->XdndTypeList,
|
||||
0, 0x8000000L, False, XA_ATOM, &type, &format, &count, &remaining, &data);
|
||||
|
||||
if (type != XA_ATOM || format != 32 || count == 0 || !data)
|
||||
{
|
||||
if (data)
|
||||
XFree (data);
|
||||
dnd_debug ("XGetWindowProperty failed in xdnd_get_type_list - dnd->XdndTypeList = %ld", dnd->XdndTypeList);
|
||||
return;
|
||||
}
|
||||
tl = (Atom *)(new WXGC_ATOMIC char[(count + 1) * sizeof (Atom)]);
|
||||
*typelist = tl;
|
||||
a = (Atom *) data;
|
||||
for (i = 0; i < count; i++)
|
||||
(*typelist)[i] = a[i];
|
||||
(*typelist)[count] = 0;
|
||||
|
||||
XFree (data);
|
||||
}
|
135
src/wxxt/src/Windows/xdnd.h
Normal file
135
src/wxxt/src/Windows/xdnd.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
xdnd.c, xdnd.h - C program library for handling the Xdnd protocol
|
||||
|
||||
Copyright (C) 1998 Paul Sheer
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
Further info can also be obtained by emailing the author at,
|
||||
psheer@obsidian.co.za
|
||||
*/
|
||||
|
||||
#ifndef _X_DND_H
|
||||
#define _X_DND_H
|
||||
|
||||
#define XDND_VERSION 3
|
||||
|
||||
/* XdndEnter */
|
||||
#define XDND_THREE 3
|
||||
#define XDND_ENTER_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||
#define XDND_ENTER_THREE_TYPES(e) (((e)->xclient.data.l[1] & 0x1UL) == 0)
|
||||
#define XDND_ENTER_THREE_TYPES_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL)
|
||||
#define XDND_ENTER_VERSION(e) ((e)->xclient.data.l[1] >> 24)
|
||||
#define XDND_ENTER_VERSION_SET(e,v) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~(0xFF << 24)) | ((v) << 24)
|
||||
#define XDND_ENTER_TYPE(e,i) ((e)->xclient.data.l[2 + i]) /* i => (0, 1, 2) */
|
||||
|
||||
/* XdndPosition */
|
||||
#define XDND_POSITION_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||
#define XDND_POSITION_ROOT_X(e) ((e)->xclient.data.l[2] >> 16)
|
||||
#define XDND_POSITION_ROOT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFUL)
|
||||
#define XDND_POSITION_ROOT_SET(e,x,y) (e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL)
|
||||
#define XDND_POSITION_TIME(e) ((e)->xclient.data.l[3])
|
||||
#define XDND_POSITION_ACTION(e) ((e)->xclient.data.l[4])
|
||||
|
||||
/* XdndStatus */
|
||||
#define XDND_STATUS_TARGET_WIN(e) ((e)->xclient.data.l[0])
|
||||
#define XDND_STATUS_WILL_ACCEPT(e) ((e)->xclient.data.l[1] & 0x1L)
|
||||
#define XDND_STATUS_WILL_ACCEPT_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL)
|
||||
#define XDND_STATUS_WANT_POSITION(e) ((e)->xclient.data.l[1] & 0x2UL)
|
||||
#define XDND_STATUS_WANT_POSITION_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x2UL) | (((b) == 0) ? 0 : 0x2UL)
|
||||
#define XDND_STATUS_RECT_X(e) ((e)->xclient.data.l[2] >> 16)
|
||||
#define XDND_STATUS_RECT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFL)
|
||||
#define XDND_STATUS_RECT_WIDTH(e) ((e)->xclient.data.l[3] >> 16)
|
||||
#define XDND_STATUS_RECT_HEIGHT(e) ((e)->xclient.data.l[3] & 0xFFFFL)
|
||||
#define XDND_STATUS_RECT_SET(e,x,y,w,h) {(e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL); (e)->xclient.data.l[3] = ((w) << 16) | ((h) & 0xFFFFUL); }
|
||||
#define XDND_STATUS_ACTION(e) ((e)->xclient.data.l[4])
|
||||
|
||||
/* XdndLeave */
|
||||
#define XDND_LEAVE_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||
|
||||
/* XdndDrop */
|
||||
#define XDND_DROP_SOURCE_WIN(e) ((e)->xclient.data.l[0])
|
||||
#define XDND_DROP_TIME(e) ((e)->xclient.data.l[2])
|
||||
|
||||
/* XdndFinished */
|
||||
#define XDND_FINISHED_TARGET_WIN(e) ((e)->xclient.data.l[0])
|
||||
|
||||
typedef struct _DndClass DndClass;
|
||||
|
||||
struct _DndClass {
|
||||
|
||||
Display *display;
|
||||
|
||||
Atom XdndAware;
|
||||
Atom XdndSelection;
|
||||
Atom XdndEnter;
|
||||
Atom XdndLeave;
|
||||
Atom XdndPosition;
|
||||
Atom XdndDrop;
|
||||
Atom XdndFinished;
|
||||
Atom XdndStatus;
|
||||
Atom XdndActionCopy;
|
||||
Atom XdndActionMove;
|
||||
Atom XdndActionLink;
|
||||
Atom XdndActionAsk;
|
||||
Atom XdndActionPrivate;
|
||||
Atom XdndTypeList;
|
||||
Atom XdndActionList;
|
||||
Atom XdndActionDescription;
|
||||
Atom Xdnd_NON_PROTOCOL_ATOM;
|
||||
Atom version;
|
||||
Atom text_uri_list;
|
||||
Window root_window;
|
||||
|
||||
#define XDND_DROP_STAGE_IDLE 0
|
||||
#define XDND_DRAG_STAGE_DRAGGING 1
|
||||
#define XDND_DRAG_STAGE_ENTERED 2
|
||||
#define XDND_DROP_STAGE_CONVERTING 3
|
||||
#define XDND_DROP_STAGE_ENTERED 4
|
||||
int stage;
|
||||
int dragging_version;
|
||||
int internal_drag;
|
||||
int want_position;
|
||||
int ready_to_drop;
|
||||
int will_accept;
|
||||
XRectangle rectangle;
|
||||
Window dropper_window, dragger_window;
|
||||
Atom *dragger_typelist;
|
||||
Atom desired_type;
|
||||
Atom supported_action;
|
||||
Time time;
|
||||
/* drop position from last XdndPosition */
|
||||
int x, y;
|
||||
|
||||
/* block for only this many seconds on not receiving a XdndFinished from target, default : 10 */
|
||||
int time_out;
|
||||
};
|
||||
|
||||
void xdnd_init (DndClass * dnd, Display * display);
|
||||
void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist);
|
||||
void xdnd_set_dnd_unaware (DndClass * dnd, Window window);
|
||||
int xdnd_is_dnd_aware (DndClass * dnd, Window window, int *version, Atom * typelist);
|
||||
void xdnd_set_type_list (DndClass * dnd, Window window, Atom * typelist);
|
||||
void xdnd_send_enter (DndClass * dnd, Window window, Window from, Atom * typelist);
|
||||
void xdnd_send_position (DndClass * dnd, Window window, Window from, Atom action, int x, int y, unsigned long etime);
|
||||
void xdnd_send_status (DndClass * dnd, Window window, Window from, int will_accept,
|
||||
int want_position, int x, int y, int w, int h, Atom action);
|
||||
void xdnd_send_leave (DndClass * dnd, Window window, Window from);
|
||||
void xdnd_send_drop (DndClass * dnd, Window window, Window from, unsigned long etime);
|
||||
void xdnd_send_finished (DndClass * dnd, Window window, Window from, int error);
|
||||
int xdnd_convert_selection (DndClass * dnd, Window window, Window requester, Atom type);
|
||||
void xdnd_selection_send (DndClass * dnd, XSelectionRequestEvent * request, unsigned char *data, int length);
|
||||
|
||||
#endif /* !_X_DND_H */
|
Loading…
Reference in New Issue
Block a user