diff options
author | petasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e> | 2012-06-07 15:58:36 (GMT) |
---|---|---|
committer | petasis <petasis@f3661a36-4baa-549a-d6c7-40e0ffef350e> | 2012-06-07 15:58:36 (GMT) |
commit | ecf7b7d7c1312357e11244124490df33f35c856a (patch) | |
tree | 8e2ca54a1bc5116ee5951efda476922b501619eb /unix | |
parent | ac795d6ade829b799bc7130320ac608612f5a2ee (diff) | |
download | tkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.zip tkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.tar.gz tkdnd-ecf7b7d7c1312357e11244124490df33f35c856a.tar.bz2 |
Linux (XDND) support completed\!
Diffstat (limited to 'unix')
-rw-r--r-- | unix/TkDND_XDND.c | 120 | ||||
-rw-r--r-- | unix/tkUnixSelect.c | 51 |
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); |