summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorpetasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e>2012-06-07 15:58:36 (GMT)
committerpetasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e>2012-06-07 15:58:36 (GMT)
commitecf7b7d7c1312357e11244124490df33f35c856a (patch)
tree8e2ca54a1bc5116ee5951efda476922b501619eb /unix
parentac795d6ade829b799bc7130320ac608612f5a2ee (diff)
downloadtkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.zip
tkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.tar.gz
tkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.tar.bz2
Linux (XDND) support completed\!
Diffstat (limited to 'unix')
-rw-r--r--unix/TkDND_XDND.c120
-rw-r--r--unix/tkUnixSelect.c51
2 files changed, 162 insertions, 9 deletions
diff --git a/unix/TkDND_XDND.c b/unix/TkDND_XDND.c
index 993a685..d807b66 100644
--- a/unix/TkDND_XDND.c
+++ b/unix/TkDND_XDND.c
@@ -38,6 +38,7 @@
#include "tcl.h"
#include "tk.h"
#include <string.h>
+#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/Xatom.h>
@@ -392,8 +393,8 @@ int TkDND_HandleXdndPosition(Tk_Window tkwin, XEvent *xevent) {
ActionCopy, ActionMove, ActionLink, ActionAsk, ActionPrivate,
refuse_drop, ActionDefault
};
- Time time;
- Atom action;
+/*Time time;
+ Atom action;*/
if (interp == NULL || tkwin == NULL) return False;
@@ -402,9 +403,9 @@ int TkDND_HandleXdndPosition(Tk_Window tkwin, XEvent *xevent) {
rootX = XDND_POSITION_ROOT_X(xevent);
rootY = XDND_POSITION_ROOT_Y(xevent);
/* Get the time from the event... */
- time = XDND_POSITION_TIME(xevent);
+ /* time = XDND_POSITION_TIME(xevent); */
/* Get the user action from the event... */
- action = XDND_POSITION_ACTION(xevent);
+ /* action = XDND_POSITION_ACTION(xevent); */
/* The event may have been delivered to the toplevel wrapper.
* Try to find the toplevel window... */
@@ -1032,7 +1033,21 @@ int TkDND_HandleGenericEvent(ClientData clientData, XEvent *eventPtr) {
TkDND_Dict_Put(dict, "type", "LeaveNotify");
TkDND_Dict_PutLong(dict, "time", eventPtr->xcrossing.time);
break;
- default:
+ case SelectionRequest:
+ main_window = Tk_MainWindow(interp);
+ TkDND_Dict_Put(dict, "type", "SelectionRequest");
+ TkDND_Dict_PutLong(dict, "time", eventPtr->xselectionrequest.time);
+ TkDND_Dict_PutLong(dict, "owner", eventPtr->xselectionrequest.owner);
+ TkDND_Dict_PutLong(dict, "requestor",
+ eventPtr->xselectionrequest.requestor);
+ TkDND_Dict_Put(dict, "selection",
+ Tk_GetAtomName(main_window, eventPtr->xselectionrequest.selection));
+ TkDND_Dict_Put(dict, "target",
+ Tk_GetAtomName(main_window, eventPtr->xselectionrequest.target));
+ TkDND_Dict_Put(dict, "property",
+ Tk_GetAtomName(main_window, eventPtr->xselectionrequest.property));
+ break;
+ default:
Tcl_DecrRefCount(dict);
return 0;
}
@@ -1360,6 +1375,95 @@ int TkDND_SendXdndDropObjCmd(ClientData clientData,
return TCL_OK;
}; /* TkDND_SendXdndDropObjCmd */
+int TkDND_XChangePropertyObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+ XEvent event;
+ Window target;
+ Atom property = None, type = None;
+ int format, numItems, numFields, i;
+ Display *display;
+ Tk_Window source;
+ Time time;
+ unsigned char *data = NULL;
+ Tcl_Obj **field;
+
+ if (objc != 9) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "source requestor property type format time data data_items");
+ return TCL_ERROR;
+ }
+
+ source = TkDND_TkWin(objv[1]);
+ if (!source) return TCL_ERROR;
+ if (Tcl_GetLongFromObj(interp, objv[2], (long *) &target) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ display = Tk_Display(source);
+ property = Tk_InternAtom(source, Tcl_GetString(objv[3]));
+ type = Tk_InternAtom(source, Tcl_GetString(objv[4]));
+ if (Tcl_GetIntFromObj(interp, objv[5], &format) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (format != 8 && format != 16 && format != 32) {
+ Tcl_SetResult(interp, "unsupported format: not 8, 16 or 32", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[5], &format) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetLongFromObj(interp, objv[6], (long *) &time) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[8], &numItems) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!time) time = CurrentTime;
+ switch (format) {
+ case 8:
+ data = (unsigned char *) Tcl_GetString(objv[7]);
+ break;
+ case 16: {
+ short *propPtr = (short *) Tcl_Alloc(sizeof(short)*numItems);
+ data = (unsigned char *) propPtr;
+ if (Tcl_ListObjGetElements(interp, objv[7], &numFields, &field)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 0; i < numItems; i++) {
+ char *dummy;
+ propPtr[i] = (short) strtol(Tcl_GetString(field[i]), &dummy, 0);
+ }
+ break;
+ }
+ case 32: {
+ long *propPtr = (long *) Tcl_Alloc(sizeof(long)*numItems);
+ data = (unsigned char *) propPtr;
+ if (Tcl_ListObjGetElements(interp, objv[7], &numFields, &field)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 0; i < numItems; i++) {
+ char *dummy;
+ propPtr[i] = (short) strtol(Tcl_GetString(field[i]), &dummy, 0);
+ }
+ break;
+ }
+ }
+ XChangeProperty(display, target, property, type, format, PropModeReplace,
+ (unsigned char *) data, numItems);
+ if (format > 8 && data) Tcl_Free((char *) data);
+ /* Send selection notify to requestor... */
+ event.xselection.type = SelectionNotify;
+ event.xselection.display = display;
+ event.xselection.requestor = target;
+ event.xselection.selection = Tk_InternAtom(source, "XdndSelection");
+ event.xselection.target = type;
+ event.xselection.property = property;
+ event.xselection.time = time;
+ XSendEvent(display, target, False, NoEventMask, &event);
+ return TCL_OK;
+}; /* TkDND_XChangePropertyObjCmd */
+
/*
* For C++ compilers, use extern "C"
*/
@@ -1500,6 +1604,12 @@ int DLLEXPORT Tkdnd_Init(Tcl_Interp *interp) {
return TCL_ERROR;
}
+ if (Tcl_CreateObjCommand(interp, "XChangeProperty",
+ (Tcl_ObjCmdProc*) TkDND_XChangePropertyObjCmd,
+ (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL) == NULL) {
+ return TCL_ERROR;
+ }
+
/* Create the cursors... */
TkDND_InitialiseCursors(interp);
diff --git a/unix/tkUnixSelect.c b/unix/tkUnixSelect.c
index 2baa0fb..99f208b 100644
--- a/unix/tkUnixSelect.c
+++ b/unix/tkUnixSelect.c
@@ -65,7 +65,7 @@ int TkDND_ClipboardReadProperty(Tk_Window tkwin,
}
XFree((char*)data);
- int offset = 0, format_inc = 1;
+ int offset = 0, format_inc = 1, proplen = bytes_left;
switch (*format) {
case 8:
@@ -75,10 +75,12 @@ int TkDND_ClipboardReadProperty(Tk_Window tkwin,
case 16:
format_inc = sizeof(short) / 2;
+ proplen *= sizeof(short) / 2;
break;
case 32:
format_inc = sizeof(long) / 4;
+ proplen *= sizeof(long) / 4;
break;
}
@@ -88,13 +90,46 @@ int TkDND_ClipboardReadProperty(Tk_Window tkwin,
&length, &bytes_left, &data);
if (r != Success || (type && *type == None))
break;
+ switch (*format) {
+ case 8:
+ default:
+ offset += length / (32 / *format);
+ length *= format_inc * (*format) / 8;
+ Tcl_DStringAppend(buffer, (char *) data, length);
+ break;
+ case 16: {
+ register unsigned short *propPtr = (unsigned short *) data;
+ for (; length > 0; propPtr++, length--) {
+ char buf[12];
+
+ sprintf(buf, "0x%04x", (unsigned short) *propPtr);
+ Tcl_DStringAppendElement(buffer, buf);
+ }
+ Tcl_DStringAppend(buffer, " ", 1);
+ break;
+ }
+ case 32: {
+ register unsigned long *propPtr = (unsigned long *) data;
+ for (; length > 0; propPtr++, length--) {
+ char buf[12];
- offset += length / (32 / *format);
- length *= format_inc * (*format) / 8;
- Tcl_DStringAppend(buffer, (char *) data, length);
+ sprintf(buf, "0x%x", (unsigned int) *propPtr);
+ Tcl_DStringAppendElement(buffer, buf);
+ }
+ Tcl_DStringAppend(buffer, " ", 1);
+ break;
+ }
+ }
XFree((char*)data);
}
+#if 0
+ printf("Selection details:\n");
+ printf(" type: %s\n", XGetAtomName(display, *type));
+ printf(" format: %d %s\n", *format, XGetAtomName(display, *format));
+ printf(" length: %d\n", Tcl_DStringLength(buffer));
+ printf(" data: \"%s\"\n", Tcl_DStringValue(buffer));
+#endif
if (*format == 8 && *type == Tk_InternAtom(tkwin, "COMPOUND_TEXT")) {
// convert COMPOUND_TEXT to a multibyte string
@@ -166,6 +201,14 @@ void TkDND_SelectionNotifyEventProc(ClientData clientData, XEvent *eventPtr) {
status = TkDND_ClipboardReadProperty(detail->tkwin, detail->property, 1,
detail, &size, &type, &format);
if (status) {
+#ifdef TKDND_DebugSelectionRequests
+ printf("SelectionNotify: selection: %s, target: %s, property: %s,\
+ type: %s, format: %d\n",
+ Tk_GetAtomName(detail->tkwin, eventPtr->xselection.selection),
+ Tk_GetAtomName(detail->tkwin, eventPtr->xselection.target),
+ Tk_GetAtomName(detail->tkwin, eventPtr->xselection.property),
+ Tk_GetAtomName(detail->tkwin, type), format);
+#endif /* TKDND_DebugSelectionRequests */
if (type == Tk_InternAtom(detail->tkwin, "INCR")) {
status = TkDND_ClipboardReadIncrementalProperty(detail->tkwin,
detail->property, detail);