mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 12:28:22 +01:00
drag and drop!
selection code rewrite! textfield with new selection code! etc etc
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
#include <WUtil.h>
|
#include <WUtil.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#define WINGS_H_VERSION 991003
|
#define WINGS_H_VERSION 20000402
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -170,7 +170,7 @@ typedef enum {
|
|||||||
WTNoTabsBevelBorder,
|
WTNoTabsBevelBorder,
|
||||||
WTNoTabsLineBorder,
|
WTNoTabsLineBorder,
|
||||||
WTNoTabsNoBorder
|
WTNoTabsNoBorder
|
||||||
} WMTabViewTypes;
|
} WMTabViewType;
|
||||||
|
|
||||||
|
|
||||||
/* text movement types */
|
/* text movement types */
|
||||||
@@ -192,6 +192,18 @@ enum {
|
|||||||
WMDeleteTextEvent
|
WMDeleteTextEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* drag operations */
|
||||||
|
typedef enum {
|
||||||
|
WDOperationNone,
|
||||||
|
WDOperationCopy,
|
||||||
|
WDOperationMove,
|
||||||
|
WDOperationLink,
|
||||||
|
WDOperationAsk,
|
||||||
|
WDOperationPrivate
|
||||||
|
} WMDragOperationType;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WMGrayModeColorPanel = 1,
|
WMGrayModeColorPanel = 1,
|
||||||
WMRGBModeColorPanel = 2,
|
WMRGBModeColorPanel = 2,
|
||||||
@@ -392,8 +404,6 @@ typedef void WMCallback(void *data);
|
|||||||
|
|
||||||
|
|
||||||
/* delegate method like stuff */
|
/* delegate method like stuff */
|
||||||
typedef void WMFreeDataProc(void *data);
|
|
||||||
|
|
||||||
typedef void WMListDrawProc(WMList *lPtr, int index, Drawable d, char *text,
|
typedef void WMListDrawProc(WMList *lPtr, int index, Drawable d, char *text,
|
||||||
int state, WMRect *rect);
|
int state, WMRect *rect);
|
||||||
|
|
||||||
@@ -409,15 +419,6 @@ typedef void WMSplitViewConstrainProc(WMSplitView *sPtr, int dividerIndex,
|
|||||||
typedef WMWidget *WMMatrixCreateCellProc(WMMatrix *mPtr);
|
typedef WMWidget *WMMatrixCreateCellProc(WMMatrix *mPtr);
|
||||||
|
|
||||||
|
|
||||||
typedef Bool WMConvertSelectionProc(WMWidget *w, Atom selection, Atom target,
|
|
||||||
Atom *type, void **value, unsigned *length,
|
|
||||||
int *format);
|
|
||||||
|
|
||||||
typedef void WMLoseSelectionProc(WMWidget *w, Atom selection);
|
|
||||||
|
|
||||||
typedef void WMSelectionDoneProc(WMWidget *w, Atom selection, Atom target);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct WMBrowserDelegate {
|
typedef struct WMBrowserDelegate {
|
||||||
@@ -474,6 +475,22 @@ typedef struct WMTabViewDelegate {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef void WMSelectionCallback(WMView *view, Atom selection, Atom target,
|
||||||
|
Time timestamp, void *cdata, WMData *data);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct WMSelectionProcs {
|
||||||
|
WMData* (*convertSelection)(WMView *view, Atom selection, Atom target,
|
||||||
|
void *cdata, Atom *type);
|
||||||
|
void (*selectionLost)(WMView *view, Atom selection, void *cdata);
|
||||||
|
void (*selectionDone)(WMView *view, Atom selection, Atom target,
|
||||||
|
void *cdata);
|
||||||
|
} WMSelectionProcs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct W_DraggingInfo WMDraggingInfo;
|
typedef struct W_DraggingInfo WMDraggingInfo;
|
||||||
|
|
||||||
|
|
||||||
@@ -482,7 +499,7 @@ typedef struct W_DragSourceProcs {
|
|||||||
void (*beganDragImage)(WMView *self, WMPixmap *image, WMPoint point);
|
void (*beganDragImage)(WMView *self, WMPixmap *image, WMPoint point);
|
||||||
void (*endedDragImage)(WMView *self, WMPixmap *image, WMPoint point,
|
void (*endedDragImage)(WMView *self, WMPixmap *image, WMPoint point,
|
||||||
Bool deposited);
|
Bool deposited);
|
||||||
WMData* (*fetchDragData)(WMView *self, char *type, Bool local);
|
WMData* (*fetchDragData)(WMView *self, char *type);
|
||||||
/* Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/
|
/* Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/
|
||||||
} WMDragSourceProcs;
|
} WMDragSourceProcs;
|
||||||
|
|
||||||
@@ -492,8 +509,9 @@ typedef struct W_DragDestinationProcs {
|
|||||||
unsigned (*draggingEntered)(WMView *self, WMDraggingInfo *info);
|
unsigned (*draggingEntered)(WMView *self, WMDraggingInfo *info);
|
||||||
unsigned (*draggingUpdated)(WMView *self, WMDraggingInfo *info);
|
unsigned (*draggingUpdated)(WMView *self, WMDraggingInfo *info);
|
||||||
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
|
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
|
||||||
Bool (*prepareForDragOperation)(WMView *self, WMDraggingInfo *info);
|
char *(*prepareForDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||||
Bool (*performDragOperation)(WMView *self, WMDraggingInfo *info);
|
Bool (*performDragOperation)(WMView *self, WMDraggingInfo *info,
|
||||||
|
WMData *data);
|
||||||
void (*concludeDragOperation)(WMView *self, WMDraggingInfo *info);
|
void (*concludeDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||||
} WMDragDestinationProcs;
|
} WMDragDestinationProcs;
|
||||||
|
|
||||||
@@ -581,12 +599,16 @@ WMHandlerID WMAddInputHandler(int fd, int condition, WMInputProc *proc,
|
|||||||
|
|
||||||
void WMDeleteInputHandler(WMHandlerID handlerID);
|
void WMDeleteInputHandler(WMHandlerID handlerID);
|
||||||
|
|
||||||
Bool WMCreateSelectionHandler(WMWidget *w, Atom selection, Time timestamp,
|
|
||||||
WMConvertSelectionProc *convProc,
|
|
||||||
WMLoseSelectionProc *loseProc,
|
|
||||||
WMSelectionDoneProc *doneProc);
|
|
||||||
|
|
||||||
void WMDeleteSelectionHandler(WMWidget *widget, Atom selection);
|
|
||||||
|
Bool WMCreateSelectionHandler(WMView *view, Atom selection, Time timestamp,
|
||||||
|
WMSelectionProcs *procs, void *cdata);
|
||||||
|
|
||||||
|
void WMDeleteSelectionHandler(WMView *view, Atom selection, Time timestamp);
|
||||||
|
|
||||||
|
Bool WMRequestSelection(WMView *view, Atom selection, Atom target,
|
||||||
|
Time timestamp, WMSelectionCallback *callback,
|
||||||
|
void *cdata);
|
||||||
|
|
||||||
|
|
||||||
/* ....................................................................... */
|
/* ....................................................................... */
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "WINGs.h"
|
#include "WINGs.h"
|
||||||
|
|
||||||
#if WINGS_H_VERSION < 991003
|
#if WINGS_H_VERSION < 20000402
|
||||||
#error There_is_an_old_WINGs.h_file_somewhere_in_your_system._Please_remove_it.
|
#error There_is_an_old_WINGs.h_file_somewhere_in_your_system._Please_remove_it.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -105,9 +105,10 @@ struct W_DraggingInfo {
|
|||||||
|
|
||||||
int protocolVersion;
|
int protocolVersion;
|
||||||
|
|
||||||
|
/* should be treated as internal data */
|
||||||
|
WMView *sourceView;
|
||||||
WMView *destView;
|
WMView *destView;
|
||||||
|
|
||||||
/* only valid if in the same app.. should be treated as internal data */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -155,6 +156,7 @@ typedef struct W_Screen {
|
|||||||
|
|
||||||
Pixmap stipple;
|
Pixmap stipple;
|
||||||
|
|
||||||
|
struct W_View *dragSourceView;
|
||||||
struct W_DraggingInfo dragInfo;
|
struct W_DraggingInfo dragInfo;
|
||||||
|
|
||||||
/* colors */
|
/* colors */
|
||||||
@@ -263,6 +265,12 @@ typedef struct W_Screen {
|
|||||||
Atom xdndTypeListAtom;
|
Atom xdndTypeListAtom;
|
||||||
Atom xdndStatusAtom;
|
Atom xdndStatusAtom;
|
||||||
|
|
||||||
|
Atom xdndActionCopy;
|
||||||
|
Atom xdndActionMove;
|
||||||
|
Atom xdndActionLink;
|
||||||
|
Atom xdndActionAsk;
|
||||||
|
Atom xdndActionPrivate;
|
||||||
|
|
||||||
Atom wmStateAtom; /* WM_STATE */
|
Atom wmStateAtom; /* WM_STATE */
|
||||||
|
|
||||||
/* stuff for detecting double-clicks */
|
/* stuff for detecting double-clicks */
|
||||||
@@ -485,8 +493,6 @@ void W_RedisplayView(WMView *view);
|
|||||||
|
|
||||||
Bool W_ApplicationInitialized(void);
|
Bool W_ApplicationInitialized(void);
|
||||||
|
|
||||||
char *W_GetTextSelection(WMScreen *scr, Atom selection);
|
|
||||||
|
|
||||||
void W_HandleSelectionEvent(XEvent *event);
|
void W_HandleSelectionEvent(XEvent *event);
|
||||||
|
|
||||||
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
|
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
|
||||||
|
|||||||
@@ -118,6 +118,10 @@ typedef struct W_Connection WMConnection;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef void WMFreeDataProc(void *data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int position;
|
int position;
|
||||||
int count;
|
int count;
|
||||||
@@ -438,6 +442,10 @@ WMData* WMCreateDataWithBytes(void *bytes, unsigned length);
|
|||||||
|
|
||||||
WMData* WMCreateDataWithBytesNoCopy(void *bytes, unsigned length);
|
WMData* WMCreateDataWithBytesNoCopy(void *bytes, unsigned length);
|
||||||
|
|
||||||
|
|
||||||
|
WMData* WMCreateDataWithBytesAndDestructor(void *bytes, unsigned length,
|
||||||
|
WMFreeDataProc *destructor);
|
||||||
|
|
||||||
WMData* WMCreateDataWithData(WMData *aData);
|
WMData* WMCreateDataWithData(WMData *aData);
|
||||||
|
|
||||||
WMData* WMRetainData(WMData *aData);
|
WMData* WMRetainData(WMData *aData);
|
||||||
@@ -470,8 +478,6 @@ Bool WMIsDataEqualToData(WMData *aData, WMData *anotherData);
|
|||||||
|
|
||||||
unsigned WMGetDataLength(WMData *aData);
|
unsigned WMGetDataLength(WMData *aData);
|
||||||
|
|
||||||
unsigned WMGetDataHash(WMData *aData);
|
|
||||||
|
|
||||||
/* Adding data */
|
/* Adding data */
|
||||||
|
|
||||||
void WMAppendDataBytes(WMData *aData, void *bytes, unsigned length);
|
void WMAppendDataBytes(WMData *aData, void *bytes, unsigned length);
|
||||||
|
|||||||
78
WINGs/data.c
78
WINGs/data.c
@@ -30,6 +30,8 @@ typedef struct W_Data {
|
|||||||
unsigned growth; /* How much to grow */
|
unsigned growth; /* How much to grow */
|
||||||
void *bytes; /* Actual data */
|
void *bytes; /* Actual data */
|
||||||
unsigned retainCount;
|
unsigned retainCount;
|
||||||
|
WMFreeDataProc *destructor;
|
||||||
|
int format; /* 0, 8, 16 or 32 */
|
||||||
unsigned freeData:1; /* whether the data should be released */
|
unsigned freeData:1; /* whether the data should be released */
|
||||||
} W_Data;
|
} W_Data;
|
||||||
|
|
||||||
@@ -54,6 +56,8 @@ WMCreateDataWithCapacity(unsigned capacity) /*FOLD00*/
|
|||||||
aData->length = 0;
|
aData->length = 0;
|
||||||
aData->retainCount = 1;
|
aData->retainCount = 1;
|
||||||
aData->freeData = 1;
|
aData->freeData = 1;
|
||||||
|
aData->format = 0;
|
||||||
|
aData->destructor = NULL;
|
||||||
|
|
||||||
return aData;
|
return aData;
|
||||||
}
|
}
|
||||||
@@ -99,6 +103,28 @@ WMCreateDataWithBytesNoCopy(void *bytes, unsigned length) /*FOLD00*/
|
|||||||
aData->bytes = bytes;
|
aData->bytes = bytes;
|
||||||
aData->retainCount = 1;
|
aData->retainCount = 1;
|
||||||
aData->freeData = 0;
|
aData->freeData = 0;
|
||||||
|
aData->format = 0;
|
||||||
|
aData->destructor = NULL;
|
||||||
|
|
||||||
|
return aData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WMData*
|
||||||
|
WMCreateDataWithBytesAndDestructor(void *bytes, unsigned length,
|
||||||
|
WMFreeDataProc *destructor)
|
||||||
|
{
|
||||||
|
WMData *aData;
|
||||||
|
|
||||||
|
aData = (WMData*)wmalloc(sizeof(WMData));
|
||||||
|
aData->length = length;
|
||||||
|
aData->capacity = length;
|
||||||
|
aData->growth = length/2 > 0 ? length/2 : 1;
|
||||||
|
aData->bytes = bytes;
|
||||||
|
aData->retainCount = 1;
|
||||||
|
aData->freeData = 0;
|
||||||
|
aData->format = 0;
|
||||||
|
aData->destructor = destructor;
|
||||||
|
|
||||||
return aData;
|
return aData;
|
||||||
}
|
}
|
||||||
@@ -107,10 +133,16 @@ WMCreateDataWithBytesNoCopy(void *bytes, unsigned length) /*FOLD00*/
|
|||||||
WMData*
|
WMData*
|
||||||
WMCreateDataWithData(WMData *aData) /*FOLD00*/
|
WMCreateDataWithData(WMData *aData) /*FOLD00*/
|
||||||
{
|
{
|
||||||
if (aData->length > 0)
|
WMData *newData;
|
||||||
return WMCreateDataWithBytes(aData->bytes, aData->length);
|
if (aData->length > 0) {
|
||||||
else
|
newData = WMCreateDataWithBytes(aData->bytes, aData->length);
|
||||||
return WMCreateDataWithCapacity(0);
|
} else {
|
||||||
|
newData = WMCreateDataWithCapacity(0);
|
||||||
|
}
|
||||||
|
newData->destructor = aData->destructor;
|
||||||
|
newData->format = aData->format;
|
||||||
|
|
||||||
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -128,8 +160,12 @@ WMReleaseData(WMData *aData) /*FOLD00*/
|
|||||||
aData->retainCount--;
|
aData->retainCount--;
|
||||||
if (aData->retainCount > 0)
|
if (aData->retainCount > 0)
|
||||||
return;
|
return;
|
||||||
if (aData->bytes && aData->freeData)
|
if (aData->bytes && aData->freeData) {
|
||||||
wfree(aData->bytes);
|
if (aData->destructor != NULL)
|
||||||
|
aData->destructor(aData->bytes);
|
||||||
|
else
|
||||||
|
wfree(aData->bytes);
|
||||||
|
}
|
||||||
wfree(aData);
|
wfree(aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +194,7 @@ WMSetDataLength(WMData *aData, unsigned length) /*FOLD00*/
|
|||||||
WMSetDataCapacity(aData, length);
|
WMSetDataCapacity(aData, length);
|
||||||
}
|
}
|
||||||
if (length > aData->length) {
|
if (length > aData->length) {
|
||||||
unsigned char *dataBytes = (unsigned char *)aData->bytes;
|
unsigned char *dataBytes = (unsigned char *)aData->bytes;
|
||||||
|
|
||||||
memset(dataBytes + aData->length, 0, length - aData->length);
|
memset(dataBytes + aData->length, 0, length - aData->length);
|
||||||
}
|
}
|
||||||
@@ -166,6 +202,13 @@ WMSetDataLength(WMData *aData, unsigned length) /*FOLD00*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMSetDataFormat(WMData *aData, unsigned format)
|
||||||
|
{
|
||||||
|
aData->format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WMIncreaseDataLengthBy(WMData *aData, unsigned extraLength) /*FOLD00*/
|
WMIncreaseDataLengthBy(WMData *aData, unsigned extraLength) /*FOLD00*/
|
||||||
{
|
{
|
||||||
@@ -191,6 +234,13 @@ WMGetDataBytes(WMData *aData, void *buffer) /*FOLD00*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
WMGetDataFormat(WMData *aData)
|
||||||
|
{
|
||||||
|
return aData->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WMGetDataBytesWithLength(WMData *aData, void *buffer, unsigned length) /*FOLD00*/
|
WMGetDataBytesWithLength(WMData *aData, void *buffer, unsigned length) /*FOLD00*/
|
||||||
{
|
{
|
||||||
@@ -217,13 +267,18 @@ WMData*
|
|||||||
WMGetSubdataWithRange(WMData *aData, WMRange aRange) /*FOLD00*/
|
WMGetSubdataWithRange(WMData *aData, WMRange aRange) /*FOLD00*/
|
||||||
{
|
{
|
||||||
void *buffer;
|
void *buffer;
|
||||||
|
WMData *newData;
|
||||||
|
|
||||||
/* return an empty subdata instead if aRange.count is 0 ? */
|
/* return an empty subdata instead if aRange.count is 0 ? */
|
||||||
wassertrv(aRange.count > 0, NULL);
|
wassertrv(aRange.count > 0, NULL);
|
||||||
|
|
||||||
buffer = wmalloc(aRange.count);
|
buffer = wmalloc(aRange.count);
|
||||||
WMGetDataBytesWithRange(aData, buffer, aRange);
|
WMGetDataBytesWithRange(aData, buffer, aRange);
|
||||||
return WMCreateDataWithBytesNoCopy(buffer, aRange.count);
|
newData = WMCreateDataWithBytesNoCopy(buffer, aRange.count);
|
||||||
|
newData->destructor = aData->destructor;
|
||||||
|
newData->format = aData->format;
|
||||||
|
|
||||||
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -249,13 +304,6 @@ WMGetDataLength(WMData *aData) /*FOLD00*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
WMGetDataHash(WMData *aData) /*FOLD00*/
|
|
||||||
{
|
|
||||||
return aData->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adding data */
|
/* Adding data */
|
||||||
void
|
void
|
||||||
WMAppendDataBytes(WMData *aData, void *bytes, unsigned length) /*FOLD00*/
|
WMAppendDataBytes(WMData *aData, void *bytes, unsigned length) /*FOLD00*/
|
||||||
|
|||||||
@@ -58,14 +58,6 @@ W_SetXdndAwareProperty(WMScreen *scr, WMView *view, Atom *types, int typeCount)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WMData*
|
|
||||||
WMGetDroppedData(WMView *view, WMDraggingInfo *info)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WMRegisterViewForDraggedTypes(WMView *view, char *acceptedTypes[])
|
WMRegisterViewForDraggedTypes(WMView *view, char *acceptedTypes[])
|
||||||
{
|
{
|
||||||
@@ -100,6 +92,38 @@ WMUnregisterViewDraggedTypes(WMView *view)
|
|||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned defDraggingEntered(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return WDOperationNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned defDraggingUpdated(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return WDOperationNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defDraggingExited(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* defPrepareForDragOperation(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool defPerformDragOperation(WMView *self, WMDraggingInfo *info,
|
||||||
|
WMData *data)
|
||||||
|
{
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defConcludeDragOperation(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
||||||
{
|
{
|
||||||
@@ -110,6 +134,27 @@ WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
|||||||
*view->dragDestinationProcs = *procs;
|
*view->dragDestinationProcs = *procs;
|
||||||
|
|
||||||
/*XXX fill in non-implemented stuffs */
|
/*XXX fill in non-implemented stuffs */
|
||||||
|
if (procs->draggingEntered == NULL) {
|
||||||
|
view->dragDestinationProcs->draggingEntered = defDraggingEntered;
|
||||||
|
}
|
||||||
|
if (procs->draggingUpdated == NULL) {
|
||||||
|
view->dragDestinationProcs->draggingUpdated = defDraggingUpdated;
|
||||||
|
}
|
||||||
|
if (procs->draggingExited == NULL) {
|
||||||
|
view->dragDestinationProcs->draggingExited = defDraggingExited;
|
||||||
|
}
|
||||||
|
if (procs->prepareForDragOperation == NULL) {
|
||||||
|
view->dragDestinationProcs->prepareForDragOperation =
|
||||||
|
defPrepareForDragOperation;
|
||||||
|
}
|
||||||
|
if (procs->performDragOperation == NULL) {
|
||||||
|
view->dragDestinationProcs->performDragOperation =
|
||||||
|
defPerformDragOperation;
|
||||||
|
}
|
||||||
|
if (procs->concludeDragOperation == NULL) {
|
||||||
|
view->dragDestinationProcs->concludeDragOperation =
|
||||||
|
defConcludeDragOperation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define SPIT(a) puts(a)
|
#define SPIT(a)
|
||||||
|
|
||||||
|
|
||||||
#define IS_DROPPABLE(view) (view!=NULL && view->droppableTypes!=NULL && \
|
#define IS_DROPPABLE(view) (view!=NULL && view->droppableTypes!=NULL && \
|
||||||
view->dragDestinationProcs!=NULL)
|
view->dragDestinationProcs!=NULL)
|
||||||
|
|
||||||
|
|
||||||
|
static Atom operationToAction(WMScreen *scr, WMDragOperationType operation);
|
||||||
|
static WMDragOperationType actionToOperation(WMScreen *scr, Atom action);
|
||||||
|
|
||||||
static Bool _XErrorOccured = False;
|
static Bool _XErrorOccured = False;
|
||||||
|
|
||||||
|
|
||||||
@@ -317,13 +320,7 @@ sendClientMessage(Display *dpy, Window win, Atom message,
|
|||||||
static unsigned
|
static unsigned
|
||||||
notifyPosition(WMScreen *scr, WMDraggingInfo *info)
|
notifyPosition(WMScreen *scr, WMDraggingInfo *info)
|
||||||
{
|
{
|
||||||
unsigned operation;
|
Atom action = operationToAction(scr, info->sourceOperation);
|
||||||
|
|
||||||
switch (info->sourceOperation) {
|
|
||||||
default:
|
|
||||||
operation = None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendClientMessage(scr->display, info->destinationWindow,
|
sendClientMessage(scr->display, info->destinationWindow,
|
||||||
scr->xdndPositionAtom,
|
scr->xdndPositionAtom,
|
||||||
@@ -331,7 +328,7 @@ notifyPosition(WMScreen *scr, WMDraggingInfo *info)
|
|||||||
0, /* reserved */
|
0, /* reserved */
|
||||||
info->location.x<<16|info->location.y,
|
info->location.x<<16|info->location.y,
|
||||||
info->timestamp,
|
info->timestamp,
|
||||||
operation/* operation */);
|
action/* operation */);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -418,34 +415,6 @@ updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info,
|
|||||||
info->location.y,
|
info->location.y,
|
||||||
iconWindow);
|
iconWindow);
|
||||||
info->destinationWindow = toplevel;
|
info->destinationWindow = toplevel;
|
||||||
/*
|
|
||||||
if (toplevel == None) {
|
|
||||||
info->destinationWindow = None;
|
|
||||||
} else if (toplevel == scr->rootWin) {
|
|
||||||
info->destinationWindow = scr->rootWin;
|
|
||||||
} else {
|
|
||||||
Window child;
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
XTranslateCoordinates(scr->display, scr->rootWin, toplevel,
|
|
||||||
info->location.x, info->location.y,
|
|
||||||
&x, &y, &child);
|
|
||||||
|
|
||||||
child = findChildInWindow(scr->display, toplevel, x, y);
|
|
||||||
|
|
||||||
if (child != None) {
|
|
||||||
info->destination = W_GetViewForXWindow(scr->display, child);
|
|
||||||
if (info->destination->droppableTypes == NULL) {
|
|
||||||
info->destination = NULL;
|
|
||||||
} else if (info->destination->dragDestinationProcs == NULL) {
|
|
||||||
info->destination = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info->destination = NULL;
|
|
||||||
}
|
|
||||||
info->destinationWindow = toplevel;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -503,36 +472,57 @@ processMotion(WMScreen *scr, WMDraggingInfo *info, WMDraggingInfo *oldInfo,
|
|||||||
rect->size.width = 0;
|
rect->size.width = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* little trick to simulate XdndStatus for local dnd */
|
|
||||||
/*
|
|
||||||
if (bla && action != currentAction) {
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
ev.type = ClientMessage;
|
|
||||||
ev.xclient.display = scr->display;
|
|
||||||
ev.xclient.message_type = scr->xdndStatusAtom;
|
|
||||||
ev.xclient.format = 32;
|
|
||||||
ev.xclient.window = info->destinationWindow;
|
|
||||||
ev.xclient.data.l[0] = info->sourceWindow;
|
|
||||||
ev.xclient.data.l[1] = (action ? 1 : 0);
|
|
||||||
ev.xclient.data.l[2] = 0;
|
|
||||||
ev.xclient.data.l[3] = 0;
|
|
||||||
ev.xclient.data.l[4] = action;
|
|
||||||
|
|
||||||
XPutBackEvent(scr->display, &ev);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static WMData*
|
||||||
|
convertSelection(WMView *view, Atom selection, Atom target,
|
||||||
|
void *cdata, Atom *type)
|
||||||
|
{
|
||||||
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
||||||
|
WMData *data;
|
||||||
|
char *typeName = XGetAtomName(scr->display, target);
|
||||||
|
|
||||||
|
*type = target;
|
||||||
|
|
||||||
|
data = view->dragSourceProcs->fetchDragData(view, typeName);
|
||||||
|
|
||||||
|
if (typeName != NULL)
|
||||||
|
XFree(typeName);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
selectionLost(WMView *view, Atom selection, void *cdata)
|
||||||
|
{
|
||||||
|
if (W_VIEW_SCREEN(view)->dragSourceView == view) {
|
||||||
|
wwarning("DND selection lost during drag operation...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
selectionDone(WMView *view, Atom selection, Atom target, void *cdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
timeoutCallback(void *data)
|
timeoutCallback(void *data)
|
||||||
{
|
{
|
||||||
wwarning("drag & drop timed out while waiting for response from 0x%x\n",
|
wwarning("drag & drop timed out while waiting for response from 0x%x\n",
|
||||||
(unsigned)data);
|
(unsigned)data);
|
||||||
_XErrorOccured = 1;
|
_XErrorOccured = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -594,9 +584,15 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
WMDraggingInfo dragInfo;
|
WMDraggingInfo dragInfo;
|
||||||
WMDraggingInfo oldDragInfo;
|
WMDraggingInfo oldDragInfo;
|
||||||
WMHandlerID timer = NULL;
|
WMHandlerID timer = NULL;
|
||||||
WMData *draggedData = NULL;
|
static WMSelectionProcs handler = {
|
||||||
|
convertSelection,
|
||||||
|
selectionLost,
|
||||||
|
selectionDone
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
wassertr(scr->dragSourceView == NULL);
|
||||||
|
|
||||||
wassertr(view->dragSourceProcs != NULL);
|
wassertr(view->dragSourceProcs != NULL);
|
||||||
|
|
||||||
|
|
||||||
@@ -614,9 +610,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
|
|
||||||
|
|
||||||
/* init dragging info */
|
/* init dragging info */
|
||||||
|
|
||||||
|
scr->dragSourceView = view;
|
||||||
|
|
||||||
memset(&dragInfo, 0, sizeof(WMDraggingInfo));
|
memset(&dragInfo, 0, sizeof(WMDraggingInfo));
|
||||||
memset(&oldDragInfo, 0, sizeof(WMDraggingInfo));
|
memset(&oldDragInfo, 0, sizeof(WMDraggingInfo));
|
||||||
dragInfo.image = image;
|
dragInfo.image = image;
|
||||||
|
dragInfo.sourceView = view;
|
||||||
dragInfo.sourceWindow = W_VIEW_DRAWABLE(W_TopLevelOfView(view));
|
dragInfo.sourceWindow = W_VIEW_DRAWABLE(W_TopLevelOfView(view));
|
||||||
|
|
||||||
dragInfo.destinationWindow = dragInfo.sourceWindow;
|
dragInfo.destinationWindow = dragInfo.sourceWindow;
|
||||||
@@ -636,8 +636,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
|
|
||||||
_XErrorOccured = False;
|
_XErrorOccured = False;
|
||||||
|
|
||||||
/* XXX: take ownership of XdndSelection */
|
/* take ownership of XdndSelection */
|
||||||
|
if (!WMCreateSelectionHandler(view, scr->xdndSelectionAtom,
|
||||||
|
event->xmotion.time,
|
||||||
|
&handler, NULL)) {
|
||||||
|
wwarning("could not get ownership or DND selection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (view->dragSourceProcs->beganDragImage != NULL) {
|
if (view->dragSourceProcs->beganDragImage != NULL) {
|
||||||
view->dragSourceProcs->beganDragImage(view, image, atLocation);
|
view->dragSourceProcs->beganDragImage(view, image, atLocation);
|
||||||
@@ -665,9 +670,8 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
||||||
dragInfo.imageLocation.y);
|
dragInfo.imageLocation.y);
|
||||||
|
|
||||||
if (state != 2) {
|
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
|
||||||
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
|
|
||||||
}
|
|
||||||
protectBlock(False);
|
protectBlock(False);
|
||||||
|
|
||||||
/* XXXif entered a different destination, check the operation */
|
/* XXXif entered a different destination, check the operation */
|
||||||
@@ -675,6 +679,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case 1:
|
case 1:
|
||||||
if (oldDragInfo.destinationWindow != None
|
if (oldDragInfo.destinationWindow != None
|
||||||
|
&& oldDragInfo.destinationWindow != scr->rootWin
|
||||||
&& (dragInfo.destinationWindow == None
|
&& (dragInfo.destinationWindow == None
|
||||||
|| dragInfo.destinationWindow == scr->rootWin)) {
|
|| dragInfo.destinationWindow == scr->rootWin)) {
|
||||||
/* left the droppable window */
|
/* left the droppable window */
|
||||||
@@ -684,7 +689,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
if (dragInfo.destinationWindow != None) {
|
if (dragInfo.destinationWindow != None
|
||||||
|
&& dragInfo.destinationWindow != scr->rootWin) {
|
||||||
|
|
||||||
state = 1;
|
state = 1;
|
||||||
action = -1;
|
action = -1;
|
||||||
}
|
}
|
||||||
@@ -693,6 +700,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
if (oldDragInfo.destinationWindow != None
|
if (oldDragInfo.destinationWindow != None
|
||||||
|
&& oldDragInfo.destinationWindow != scr->rootWin
|
||||||
&& (dragInfo.destinationWindow == None
|
&& (dragInfo.destinationWindow == None
|
||||||
|| dragInfo.destinationWindow == scr->rootWin)) {
|
|| dragInfo.destinationWindow == scr->rootWin)) {
|
||||||
/* left the droppable window */
|
/* left the droppable window */
|
||||||
@@ -717,8 +725,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
||||||
dragInfo.imageLocation.y);
|
dragInfo.imageLocation.y);
|
||||||
|
|
||||||
processMotion(scr, &dragInfo, &oldDragInfo, &rect,
|
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
|
||||||
action);
|
|
||||||
|
dragInfo.timestamp = ev.xbutton.time;
|
||||||
|
|
||||||
protectBlock(False);
|
protectBlock(False);
|
||||||
|
|
||||||
@@ -741,20 +750,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case SelectionRequest:
|
|
||||||
|
|
||||||
draggedData = NULL;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
if ((state == 1 || state == 3 || state == 4 || state == 5)
|
if ((state == 1 || state == 3 || state == 4 || state == 5)
|
||||||
&& ev.xclient.message_type == scr->xdndStatusAtom
|
&& ev.xclient.message_type == scr->xdndStatusAtom
|
||||||
&& ev.xclient.window == dragInfo.destinationWindow) {
|
&& ev.xclient.data.l[0] == dragInfo.destinationWindow) {
|
||||||
|
|
||||||
if (ev.xclient.data.l[1] & 1) {
|
if (ev.xclient.data.l[1] & 1) {
|
||||||
puts("got accept msg");
|
SPIT("got accept msg");
|
||||||
/* will accept drop */
|
/* will accept drop */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -770,13 +772,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
state = 6;
|
state = 6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ev.xclient.data.l[4] == None) {
|
action = actionToOperation(scr, ev.xclient.data.l[4]);
|
||||||
action = 0;
|
|
||||||
} else {
|
|
||||||
action = ev.xclient.data.l[4];/*XXX*/
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
puts("got reject msg");
|
SPIT("got reject msg");
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
@@ -825,7 +823,6 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ostate != state) {
|
if (ostate != state) {
|
||||||
printf("state changed to %i\n", state);
|
|
||||||
if (state == 3) {
|
if (state == 3) {
|
||||||
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
|
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
|
||||||
} else if (ostate == 3) {
|
} else if (ostate == 3) {
|
||||||
@@ -838,6 +835,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
if (timer) {
|
if (timer) {
|
||||||
WMDeleteTimerHandler(timer);
|
WMDeleteTimerHandler(timer);
|
||||||
timer = NULL;
|
timer = NULL;
|
||||||
|
} else if (_XErrorOccured) {
|
||||||
|
/* got a timeout, send leave */
|
||||||
|
notifyDragLeave(scr, &dragInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
XUngrabPointer(dpy, CurrentTime);
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
@@ -859,22 +859,17 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
|||||||
|
|
||||||
|
|
||||||
SPIT("dropped");
|
SPIT("dropped");
|
||||||
/* wait for Finished message and SelectionRequest if not a local drop */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
XDestroyWindow(dpy, icon);
|
XDestroyWindow(dpy, icon);
|
||||||
if (view->dragSourceProcs->endedDragImage != NULL) {
|
|
||||||
view->dragSourceProcs->endedDragImage(view, image,
|
|
||||||
dragInfo.imageLocation,
|
|
||||||
True);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cancelled:
|
cancelled:
|
||||||
if (draggedData) {
|
scr->dragSourceView = NULL;
|
||||||
WMReleaseData(draggedData);
|
|
||||||
}
|
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
|
||||||
|
event->xmotion.time);
|
||||||
|
|
||||||
if (slideBack) {
|
if (slideBack) {
|
||||||
slideWindow(dpy, icon,
|
slideWindow(dpy, icon,
|
||||||
@@ -900,6 +895,65 @@ cancelled:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Atom
|
||||||
|
operationToAction(WMScreen *scr, WMDragOperationType operation)
|
||||||
|
{
|
||||||
|
switch (operation) {
|
||||||
|
case WDOperationNone:
|
||||||
|
return None;
|
||||||
|
|
||||||
|
case WDOperationCopy:
|
||||||
|
return scr->xdndActionCopy;
|
||||||
|
|
||||||
|
case WDOperationMove:
|
||||||
|
return scr->xdndActionMove;
|
||||||
|
|
||||||
|
case WDOperationLink:
|
||||||
|
return scr->xdndActionLink;
|
||||||
|
|
||||||
|
case WDOperationAsk:
|
||||||
|
return scr->xdndActionAsk;
|
||||||
|
|
||||||
|
case WDOperationPrivate:
|
||||||
|
return scr->xdndActionPrivate;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static WMDragOperationType
|
||||||
|
actionToOperation(WMScreen *scr, Atom action)
|
||||||
|
{
|
||||||
|
if (action == scr->xdndActionCopy) {
|
||||||
|
return WDOperationCopy;
|
||||||
|
|
||||||
|
} else if (action == scr->xdndActionMove) {
|
||||||
|
return WDOperationMove;
|
||||||
|
|
||||||
|
} else if (action == scr->xdndActionLink) {
|
||||||
|
return WDOperationLink;
|
||||||
|
|
||||||
|
} else if (action == scr->xdndActionAsk) {
|
||||||
|
return WDOperationAsk;
|
||||||
|
|
||||||
|
} else if (action == scr->xdndActionPrivate) {
|
||||||
|
return WDOperationPrivate;
|
||||||
|
|
||||||
|
} else if (action == None) {
|
||||||
|
|
||||||
|
return WDOperationCopy;
|
||||||
|
} else {
|
||||||
|
char *tmp = XGetAtomName(scr->display, action);
|
||||||
|
|
||||||
|
wwarning("unknown XDND action %s from 0x%x", tmp,
|
||||||
|
(unsigned)scr->dragInfo.sourceWindow);
|
||||||
|
XFree(tmp);
|
||||||
|
|
||||||
|
return WDOperationCopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -934,20 +988,86 @@ getTypeList(Window window, XClientMessageEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DISPATCH(view, func, info) (view)->dragDestinationProcs->func(view, info)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
receivedData(WMView *view, Atom selection, Atom target,
|
||||||
|
Time timestamp, void *cdata, WMData *data)
|
||||||
|
{
|
||||||
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
||||||
|
WMDraggingInfo *info = (WMDraggingInfo*)cdata;
|
||||||
|
Bool res;
|
||||||
|
|
||||||
|
res = view->dragDestinationProcs->performDragOperation(view, info, data);
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
DISPATCH(view, concludeDragOperation, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send finished message */
|
||||||
|
sendClientMessage(scr->display, info->sourceWindow,
|
||||||
|
scr->xdndFinishedAtom,
|
||||||
|
info->destinationWindow,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
|
||||||
|
memset(&scr->dragInfo, 0, sizeof(WMDraggingInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
WMScreen *scr = W_VIEW_SCREEN(toplevel);
|
WMScreen *scr = W_VIEW_SCREEN(toplevel);
|
||||||
WMView *oldView = NULL, *newView = NULL;
|
WMView *oldView = NULL;
|
||||||
|
WMView *newView = NULL;
|
||||||
unsigned operation = 0;
|
unsigned operation = 0;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
enum {
|
||||||
|
WNothing,
|
||||||
|
WEnter,
|
||||||
|
WLeave,
|
||||||
|
WCross, /* leave one and enter another */
|
||||||
|
WUpdate,
|
||||||
|
WDrop
|
||||||
|
};
|
||||||
|
Window source;
|
||||||
|
int what = WNothing;
|
||||||
|
Bool sendStatus = False;
|
||||||
|
|
||||||
|
|
||||||
|
source = scr->dragInfo.sourceWindow;
|
||||||
|
oldView = scr->dragInfo.destView;
|
||||||
|
|
||||||
|
|
||||||
|
if (event->message_type == scr->xdndFinishedAtom) {
|
||||||
|
WMView *view = scr->dragSourceView;
|
||||||
|
|
||||||
|
if (view->dragSourceProcs->endedDragImage != NULL) {
|
||||||
|
view->dragSourceProcs->endedDragImage(view,
|
||||||
|
scr->dragInfo.image,
|
||||||
|
scr->dragInfo.imageLocation,
|
||||||
|
True);
|
||||||
|
}
|
||||||
|
|
||||||
|
scr->dragSourceView = NULL;
|
||||||
|
|
||||||
|
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
|
||||||
|
scr->dragInfo.timestamp);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (event->message_type == scr->xdndEnterAtom) {
|
if (event->message_type == scr->xdndEnterAtom) {
|
||||||
Window foo, bar;
|
Window foo, bar;
|
||||||
int bla;
|
int bla;
|
||||||
unsigned ble;
|
unsigned ble;
|
||||||
puts("entered");
|
|
||||||
|
|
||||||
if (scr->dragInfo.sourceWindow != None) {
|
if (scr->dragInfo.sourceWindow != None) {
|
||||||
puts("received Enter event in bad order");
|
puts("received Enter event in bad order");
|
||||||
@@ -956,14 +1076,14 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
|||||||
memset(&scr->dragInfo, 0, sizeof(WMDraggingInfo));
|
memset(&scr->dragInfo, 0, sizeof(WMDraggingInfo));
|
||||||
|
|
||||||
|
|
||||||
if ((event->data.l[0] >> 24) > XDND_VERSION) {
|
if ((event->data.l[1] >> 24) > XDND_VERSION) {
|
||||||
wwarning("received drag & drop request with unsupported version %i",
|
wwarning("received drag & drop request with unsupported version %i",
|
||||||
(event->data.l[0] >> 24));
|
(event->data.l[1] >> 24));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scr->dragInfo.protocolVersion = event->data.l[1] >> 24;
|
scr->dragInfo.protocolVersion = event->data.l[1] >> 24;
|
||||||
scr->dragInfo.sourceWindow = event->data.l[0];
|
scr->dragInfo.sourceWindow = source = event->data.l[0];
|
||||||
scr->dragInfo.destinationWindow = event->window;
|
scr->dragInfo.destinationWindow = event->window;
|
||||||
|
|
||||||
/* XXX */
|
/* XXX */
|
||||||
@@ -982,29 +1102,6 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
|||||||
scr->dragInfo.destinationWindow,
|
scr->dragInfo.destinationWindow,
|
||||||
x, y);
|
x, y);
|
||||||
|
|
||||||
if (IS_DROPPABLE(view)) {
|
|
||||||
|
|
||||||
scr->dragInfo.destinationView = view;
|
|
||||||
|
|
||||||
operation =
|
|
||||||
view->dragDestinationProcs->draggingEntered(view,
|
|
||||||
&scr->dragInfo);
|
|
||||||
}
|
|
||||||
if (operation > 0) {
|
|
||||||
Atom action;
|
|
||||||
|
|
||||||
switch (operation) {
|
|
||||||
default:
|
|
||||||
action = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendClientMessage(scr->display, scr->dragInfo.sourceWindow,
|
|
||||||
scr->xdndStatusAtom,
|
|
||||||
scr->dragInfo.destinationWindow,
|
|
||||||
1, 0, 0, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (event->message_type == scr->xdndPositionAtom
|
} else if (event->message_type == scr->xdndPositionAtom
|
||||||
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
||||||
|
|
||||||
@@ -1013,71 +1110,138 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
|||||||
|
|
||||||
if (scr->dragInfo.protocolVersion >= 1) {
|
if (scr->dragInfo.protocolVersion >= 1) {
|
||||||
scr->dragInfo.timestamp = event->data.l[3];
|
scr->dragInfo.timestamp = event->data.l[3];
|
||||||
scr->dragInfo.sourceOperation = event->data.l[4];
|
scr->dragInfo.sourceOperation = actionToOperation(scr,
|
||||||
|
event->data.l[4]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
scr->dragInfo.timestamp = CurrentTime;
|
scr->dragInfo.timestamp = CurrentTime;
|
||||||
scr->dragInfo.sourceOperation = 0; /*XXX*/
|
scr->dragInfo.sourceOperation = WDOperationCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
translateCoordinates(scr, scr->dragInfo.destinationWindow,
|
translateCoordinates(scr, scr->dragInfo.destinationWindow,
|
||||||
scr->dragInfo.location.x,
|
scr->dragInfo.location.x,
|
||||||
scr->dragInfo.location.y, &x, &y);
|
scr->dragInfo.location.y, &x, &y);
|
||||||
|
|
||||||
view = findViewInToplevel(scr->display,
|
newView = findViewInToplevel(scr->display,
|
||||||
scr->dragInfo.destinationWindow,
|
scr->dragInfo.destinationWindow,
|
||||||
x, y);
|
x, y);
|
||||||
|
|
||||||
if (scr->dragInfo.destinationView != view) {
|
|
||||||
WMView *oldVIew = scr->dragInfo.destinationView;
|
|
||||||
|
|
||||||
oldView->dragDestinationProcs->draggingExited(oldView,
|
|
||||||
&scr->dragInfo);
|
|
||||||
|
|
||||||
scr->dragInfo.destinationView = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (IS_DROPPABLE(view)) {
|
|
||||||
|
|
||||||
|
|
||||||
operation =
|
|
||||||
view->dragDestinationProcs->draggingUpdated(view,
|
|
||||||
&scr->dragInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operation == 0) {
|
|
||||||
sendClientMessage(scr->display, scr->dragInfo.sourceWindow,
|
|
||||||
scr->xdndStatusAtom,
|
|
||||||
scr->dragInfo.destinationWindow,
|
|
||||||
0, 0, 0, None);
|
|
||||||
} else {
|
|
||||||
Atom action;
|
|
||||||
|
|
||||||
switch (operation) {
|
|
||||||
default:
|
|
||||||
action = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendClientMessage(scr->display, scr->dragInfo.sourceWindow,
|
|
||||||
scr->xdndStatusAtom,
|
|
||||||
scr->dragInfo.destinationWindow,
|
|
||||||
1, 0, 0, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (event->message_type == scr->xdndLeaveAtom
|
} else if (event->message_type == scr->xdndLeaveAtom
|
||||||
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
||||||
|
|
||||||
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
|
memset(&scr->dragInfo, 0, sizeof(WMDraggingInfo));
|
||||||
|
|
||||||
puts("leave");
|
|
||||||
} else if (event->message_type == scr->xdndDropAtom
|
} else if (event->message_type == scr->xdndDropAtom
|
||||||
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
||||||
|
|
||||||
|
/* drop */
|
||||||
|
what = WDrop;
|
||||||
|
|
||||||
|
} else {
|
||||||
puts("drop");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now map the XDND events to WINGs events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (what == WNothing) {
|
||||||
|
if (IS_DROPPABLE(newView)) {
|
||||||
|
if (oldView == NULL) { /* entered */
|
||||||
|
what = WEnter;
|
||||||
|
} else if (oldView == newView) { /* updated */
|
||||||
|
what = WUpdate;
|
||||||
|
} else {
|
||||||
|
what = WCross;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (oldView != NULL) {
|
||||||
|
what = WLeave;
|
||||||
|
} else {
|
||||||
|
/* just send rejection msg */
|
||||||
|
sendStatus = True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
switch (what) {
|
||||||
|
|
||||||
|
case WEnter:
|
||||||
|
scr->dragInfo.destView = newView;
|
||||||
|
operation = DISPATCH(newView, draggingEntered, &scr->dragInfo);
|
||||||
|
sendStatus = True;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WLeave:
|
||||||
|
scr->dragInfo.destView = NULL;
|
||||||
|
DISPATCH(oldView, draggingExited, &scr->dragInfo);
|
||||||
|
sendStatus = True;
|
||||||
|
operation = WDOperationNone;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WCross:
|
||||||
|
DISPATCH(oldView, draggingExited, &scr->dragInfo);
|
||||||
|
scr->dragInfo.destView = newView;
|
||||||
|
operation = DISPATCH(newView, draggingEntered, &scr->dragInfo);
|
||||||
|
sendStatus = True;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WUpdate:
|
||||||
|
operation = DISPATCH(oldView, draggingUpdated, &scr->dragInfo);
|
||||||
|
sendStatus = True;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WDrop:
|
||||||
|
{
|
||||||
|
char *type;
|
||||||
|
|
||||||
|
type = DISPATCH(oldView, prepareForDragOperation, &scr->dragInfo);
|
||||||
|
|
||||||
|
if (type != NULL) {
|
||||||
|
if (!WMRequestSelection(scr->dragInfo.destView,
|
||||||
|
scr->xdndSelectionAtom,
|
||||||
|
XInternAtom(scr->display, type, False),
|
||||||
|
scr->dragInfo.timestamp,
|
||||||
|
receivedData, &scr->dragInfo)) {
|
||||||
|
wwarning("could not request data for dropped data");
|
||||||
|
|
||||||
|
/* send finished message */
|
||||||
|
sendClientMessage(scr->display, source,
|
||||||
|
scr->xdndFinishedAtom,
|
||||||
|
scr->dragInfo.destinationWindow,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* send finished message */
|
||||||
|
sendClientMessage(scr->display, source,
|
||||||
|
scr->xdndFinishedAtom,
|
||||||
|
scr->dragInfo.destinationWindow,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (sendStatus) {
|
||||||
|
Atom action;
|
||||||
|
|
||||||
|
action = operationToAction(scr, operation);
|
||||||
|
|
||||||
|
sendClientMessage(scr->display, source,
|
||||||
|
scr->xdndStatusAtom,
|
||||||
|
scr->dragInfo.destinationWindow,
|
||||||
|
action != None ? 1 : 0, 0, 0, action);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,62 +10,63 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct SelectionHandler {
|
typedef struct SelectionHandler {
|
||||||
WMWidget *widget;
|
WMView *view;
|
||||||
Atom selection;
|
Atom selection;
|
||||||
Time timestamp;
|
Time timestamp;
|
||||||
WMConvertSelectionProc *convProc;
|
WMSelectionProcs procs;
|
||||||
WMLoseSelectionProc *loseProc;
|
void *data;
|
||||||
WMSelectionDoneProc *doneProc;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned delete_pending:1;
|
unsigned delete_pending:1;
|
||||||
unsigned done_pending:1;
|
unsigned done_pending:1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
struct SelectionHandler *next;
|
|
||||||
} SelectionHandler;
|
} SelectionHandler;
|
||||||
|
|
||||||
|
|
||||||
static SelectionHandler *selHandlers = NULL;
|
typedef struct SelectionCallback {
|
||||||
|
WMView *view;
|
||||||
|
Atom selection;
|
||||||
|
Atom target;
|
||||||
|
Time timestamp;
|
||||||
|
WMSelectionCallback *callback;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned delete_pending:1;
|
||||||
|
unsigned done_pending:1;
|
||||||
|
} flags;
|
||||||
|
} SelectionCallback;
|
||||||
|
|
||||||
|
|
||||||
|
WMBag *selCallbacks = NULL;
|
||||||
|
|
||||||
|
WMBag *selHandlers = NULL;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WMDeleteSelectionHandler(WMWidget *widget, Atom selection)
|
WMDeleteSelectionHandler(WMView *view, Atom selection, Time timestamp)
|
||||||
{
|
{
|
||||||
SelectionHandler *handler, *tmp;
|
SelectionHandler *handler;
|
||||||
Display *dpy = WMWidgetScreen(widget)->display;
|
Display *dpy = W_VIEW_SCREEN(view)->display;
|
||||||
Window win = WMWidgetXID(widget);
|
Window win = W_VIEW_DRAWABLE(view);
|
||||||
Time timestamp;
|
WMBagIterator iter;
|
||||||
|
|
||||||
if (!selHandlers)
|
if (!selHandlers)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tmp = selHandlers;
|
|
||||||
|
|
||||||
if (tmp->widget == widget) {
|
WM_ITERATE_BAG(selHandlers, handler, iter) {
|
||||||
|
if (handler->view == view
|
||||||
|
&& (handler->selection == selection || selection == None)
|
||||||
|
&& (handler->timestamp == timestamp || timestamp == CurrentTime)) {
|
||||||
|
|
||||||
if (tmp->flags.done_pending) {
|
if (handler->flags.done_pending) {
|
||||||
tmp->flags.delete_pending = 1;
|
handler->flags.delete_pending = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selHandlers = tmp->next;
|
WMRemoveFromBag(selHandlers, handler);
|
||||||
timestamp = tmp->timestamp;
|
wfree(handler);
|
||||||
wfree(tmp);
|
break;
|
||||||
} else {
|
|
||||||
while (tmp->next) {
|
|
||||||
if (tmp->next->widget == widget) {
|
|
||||||
|
|
||||||
if (tmp->next->flags.done_pending) {
|
|
||||||
tmp->next->flags.delete_pending = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handler = tmp->next;
|
|
||||||
tmp->next = handler->next;
|
|
||||||
timestamp = handler->timestamp;
|
|
||||||
wfree(handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +78,34 @@ WMDeleteSelectionHandler(WMWidget *widget, Atom selection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMDeleteSelectionCallback(WMView *view, Atom selection, Time timestamp)
|
||||||
|
{
|
||||||
|
SelectionCallback *handler;
|
||||||
|
WMBagIterator iter;
|
||||||
|
|
||||||
|
if (!selCallbacks)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WM_ITERATE_BAG(selCallbacks, handler, iter) {
|
||||||
|
if (handler->view == view
|
||||||
|
&& (handler->selection == selection || selection == 0)
|
||||||
|
&& (handler->timestamp == timestamp || timestamp == CurrentTime)) {
|
||||||
|
|
||||||
|
if (handler->flags.done_pending) {
|
||||||
|
handler->flags.delete_pending = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WMRemoveFromBag(selCallbacks, handler);
|
||||||
|
wfree(handler);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Bool gotError = 0;
|
static Bool gotError = 0;
|
||||||
/*
|
/*
|
||||||
static int
|
static int
|
||||||
@@ -88,8 +117,14 @@ errorHandler(XErrorEvent *error)
|
|||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
writeSelection(Display *dpy, Window requestor, Atom property, Atom type,
|
writeSelection(Display *dpy, Window requestor, Atom property, Atom type,
|
||||||
void *value, long length, int format)
|
WMData *data)
|
||||||
{
|
{
|
||||||
|
int format;
|
||||||
|
|
||||||
|
format = WMGetDataFormat(data);
|
||||||
|
if (format == 0)
|
||||||
|
format = 8;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
printf("write to %x: %s\n", requestor, XGetAtomName(dpy, property));
|
printf("write to %x: %s\n", requestor, XGetAtomName(dpy, property));
|
||||||
*/
|
*/
|
||||||
@@ -97,12 +132,13 @@ writeSelection(Display *dpy, Window requestor, Atom property, Atom type,
|
|||||||
|
|
||||||
#ifndef __sgi
|
#ifndef __sgi
|
||||||
if (!XChangeProperty(dpy, requestor, property, type, format,
|
if (!XChangeProperty(dpy, requestor, property, type, format,
|
||||||
PropModeReplace, value, length))
|
PropModeReplace, WMDataBytes(data),
|
||||||
|
WMGetDataLength(data)))
|
||||||
return False;
|
return False;
|
||||||
#else
|
#else
|
||||||
/* in sgi seems this seems to return void */
|
/* in sgi seems this seems to return void */
|
||||||
XChangeProperty(dpy, requestor, property, type, format,
|
XChangeProperty(dpy, requestor, property, type, format,
|
||||||
PropModeReplace, value, length);
|
PropModeReplace, WMDataBytes(data), WMGetDataLength(data));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XFlush(dpy);
|
XFlush(dpy);
|
||||||
@@ -134,92 +170,222 @@ notifySelection(XEvent *event, Atom prop)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
W_HandleSelectionEvent(XEvent *event)
|
static void
|
||||||
|
deleteHandlers(WMBagIterator iter)
|
||||||
{
|
{
|
||||||
SelectionHandler *handler;
|
SelectionHandler *handler;
|
||||||
|
|
||||||
handler = selHandlers;
|
if (iter == NULL)
|
||||||
|
handler = WMBagFirst(selHandlers, &iter);
|
||||||
|
else
|
||||||
|
handler = WMBagNext(selHandlers, &iter);
|
||||||
|
|
||||||
while (handler) {
|
if (handler == NULL)
|
||||||
if (WMWidgetXID(handler->widget)==event->xany.window
|
return;
|
||||||
/* && handler->selection == event->selection*/) {
|
|
||||||
|
|
||||||
switch (event->type) {
|
deleteHandlers(iter);
|
||||||
case SelectionClear:
|
|
||||||
if (handler->loseProc)
|
|
||||||
(*handler->loseProc)(handler->widget, handler->selection);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SelectionRequest:
|
if (handler->flags.delete_pending) {
|
||||||
if (handler->convProc) {
|
WMDeleteSelectionHandler(handler->view, handler->selection,
|
||||||
Atom atom;
|
handler->timestamp);
|
||||||
void *data;
|
}
|
||||||
unsigned length;
|
}
|
||||||
int format;
|
|
||||||
Atom prop;
|
|
||||||
|
|
||||||
/* they're requesting for something old */
|
|
||||||
if (event->xselectionrequest.time < handler->timestamp
|
|
||||||
&& event->xselectionrequest.time != CurrentTime) {
|
|
||||||
|
|
||||||
notifySelection(event, None);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
handler->flags.done_pending = 1;
|
|
||||||
|
|
||||||
if (!(*handler->convProc)(handler->widget,
|
|
||||||
handler->selection,
|
|
||||||
event->xselectionrequest.target,
|
|
||||||
&atom, &data, &length, &format)) {
|
|
||||||
|
|
||||||
notifySelection(event, None);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
prop = event->xselectionrequest.property;
|
|
||||||
/* obsolete clients that don't set the property field */
|
|
||||||
if (prop == None)
|
|
||||||
prop = event->xselectionrequest.target;
|
|
||||||
|
|
||||||
if (!writeSelection(event->xselectionrequest.display,
|
static void
|
||||||
event->xselectionrequest.requestor,
|
handleRequestEvent(XEvent *event)
|
||||||
prop, atom, data, length, format)) {
|
{
|
||||||
|
SelectionHandler *handler;
|
||||||
|
WMBagIterator iter;
|
||||||
|
Bool handledRequest = False;
|
||||||
|
|
||||||
wfree(data);
|
WM_ITERATE_BAG(selHandlers, handler, iter) {
|
||||||
notifySelection(event, None);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wfree(data);
|
|
||||||
|
|
||||||
notifySelection(event, prop);
|
|
||||||
|
|
||||||
if (handler->doneProc) {
|
|
||||||
(*handler->doneProc)(handler->widget,
|
|
||||||
handler->selection,
|
|
||||||
event->xselectionrequest.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
handler->flags.done_pending = 0;
|
|
||||||
|
|
||||||
/* in case the handler was deleted from some
|
|
||||||
* callback */
|
|
||||||
if (handler->flags.delete_pending) {
|
|
||||||
WMDeleteSelectionHandler(handler->widget,
|
|
||||||
handler->selection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SelectionNotify:
|
|
||||||
|
|
||||||
|
switch (event->type) {
|
||||||
|
case SelectionClear:
|
||||||
|
if (W_VIEW_DRAWABLE(handler->view)
|
||||||
|
!= event->xselectionclear.window) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handler->flags.done_pending = 1;
|
||||||
|
if (handler->procs.selectionLost)
|
||||||
|
handler->procs.selectionLost(handler->view,
|
||||||
|
handler->selection,
|
||||||
|
handler->data);
|
||||||
|
handler->flags.done_pending = 0;
|
||||||
|
handler->flags.delete_pending = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SelectionRequest:
|
||||||
|
if (W_VIEW_DRAWABLE(handler->view)
|
||||||
|
!= event->xselectionrequest.owner) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler->procs.convertSelection != NULL
|
||||||
|
&& handler->selection == event->xselectionrequest.selection) {
|
||||||
|
Atom atom;
|
||||||
|
WMData *data;
|
||||||
|
Atom prop;
|
||||||
|
|
||||||
|
/* they're requesting for something old.. maybe another handler
|
||||||
|
* can handle it */
|
||||||
|
if (event->xselectionrequest.time < handler->timestamp
|
||||||
|
&& event->xselectionrequest.time != CurrentTime) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->flags.done_pending = 1;
|
||||||
|
|
||||||
|
data = handler->procs.convertSelection(handler->view,
|
||||||
|
handler->selection,
|
||||||
|
event->xselectionrequest.target,
|
||||||
|
handler->data,
|
||||||
|
&atom);
|
||||||
|
if (data == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
handledRequest = True;
|
||||||
|
|
||||||
|
|
||||||
|
prop = event->xselectionrequest.property;
|
||||||
|
/* obsolete clients that don't set the property field */
|
||||||
|
if (prop == None)
|
||||||
|
prop = event->xselectionrequest.target;
|
||||||
|
|
||||||
|
if (!writeSelection(event->xselectionrequest.display,
|
||||||
|
event->xselectionrequest.requestor,
|
||||||
|
prop, atom, data)) {
|
||||||
|
WMReleaseData(data);
|
||||||
|
notifySelection(event, None);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WMReleaseData(data);
|
||||||
|
|
||||||
|
notifySelection(event, prop);
|
||||||
|
|
||||||
|
if (handler->procs.selectionDone != NULL) {
|
||||||
|
handler->procs.selectionDone(handler->view,
|
||||||
|
handler->selection,
|
||||||
|
event->xselectionrequest.target,
|
||||||
|
handler->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->flags.done_pending = 0;
|
||||||
|
|
||||||
|
if (!handledRequest) {
|
||||||
|
notifySelection(event, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteHandlers(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
deleteCallbacks(WMBagIterator iter)
|
||||||
|
{
|
||||||
|
SelectionCallback *handler;
|
||||||
|
|
||||||
|
if (iter == NULL)
|
||||||
|
handler = WMBagFirst(selCallbacks, &iter);
|
||||||
|
else
|
||||||
|
handler = WMBagNext(selCallbacks, &iter);
|
||||||
|
|
||||||
|
if (handler == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
deleteCallbacks(iter);
|
||||||
|
|
||||||
|
if (handler->flags.delete_pending) {
|
||||||
|
WMDeleteSelectionCallback(handler->view, handler->selection,
|
||||||
|
handler->timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static WMData*
|
||||||
|
getSelectionData(Display *dpy, Window win, Atom where)
|
||||||
|
{
|
||||||
|
WMData *wdata;
|
||||||
|
unsigned char *data;
|
||||||
|
Atom rtype;
|
||||||
|
unsigned bits;
|
||||||
|
unsigned long len, bytes;
|
||||||
|
|
||||||
|
|
||||||
|
if (XGetWindowProperty(dpy, win, where, 0, MAX_PROPERTY_SIZE,
|
||||||
|
False, AnyPropertyType, &rtype, &bits, &len,
|
||||||
|
&bytes, &data)!=Success) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdata = WMCreateDataWithBytesAndDestructor(data, len,
|
||||||
|
(WMFreeDataProc*)XFree);
|
||||||
|
if (wdata == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
WMSetDataFormat(wdata, bits);
|
||||||
|
|
||||||
|
return wdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handleNotifyEvent(XEvent *event)
|
||||||
|
{
|
||||||
|
SelectionCallback *handler;
|
||||||
|
WMBagIterator iter;
|
||||||
|
WMData *data;
|
||||||
|
|
||||||
|
WM_ITERATE_BAG(selCallbacks, handler, iter) {
|
||||||
|
|
||||||
|
if (W_VIEW_DRAWABLE(handler->view) != event->xselection.requestor
|
||||||
|
&& handler->selection == event->xselection.selection) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handler->flags.done_pending = 1;
|
||||||
|
|
||||||
|
if (event->xselection.property == None) {
|
||||||
|
data = NULL;
|
||||||
|
} else {
|
||||||
|
data = getSelectionData(event->xselection.display,
|
||||||
|
event->xselection.requestor,
|
||||||
|
event->xselection.property);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = handler->next;
|
(*handler->callback)(handler->view, handler->selection,
|
||||||
|
handler->target, handler->timestamp,
|
||||||
|
handler->data, data);
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
WMReleaseData(data);
|
||||||
|
}
|
||||||
|
handler->flags.done_pending = 0;
|
||||||
|
handler->flags.delete_pending = 1;
|
||||||
|
}
|
||||||
|
deleteCallbacks(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
W_HandleSelectionEvent(XEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type == SelectionNotify) {
|
||||||
|
handleNotifyEvent(event);
|
||||||
|
} else {
|
||||||
|
handleRequestEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,196 +393,69 @@ W_HandleSelectionEvent(XEvent *event)
|
|||||||
|
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
WMCreateSelectionHandler(WMWidget *w, Atom selection, Time timestamp,
|
WMCreateSelectionHandler(WMView *view, Atom selection, Time timestamp,
|
||||||
WMConvertSelectionProc *convProc,
|
WMSelectionProcs *procs, void *cdata)
|
||||||
WMLoseSelectionProc *loseProc,
|
|
||||||
WMSelectionDoneProc *doneProc)
|
|
||||||
{
|
{
|
||||||
SelectionHandler *handler, *tmp;
|
SelectionHandler *handler;
|
||||||
Display *dpy = WMWidgetScreen(w)->display;
|
Display *dpy = W_VIEW_SCREEN(view)->display;
|
||||||
|
|
||||||
XSetSelectionOwner(dpy, selection, WMWidgetXID(w), timestamp);
|
XSetSelectionOwner(dpy, selection, W_VIEW_DRAWABLE(view), timestamp);
|
||||||
if (XGetSelectionOwner(dpy, selection) != WMWidgetXID(w))
|
if (XGetSelectionOwner(dpy, selection) != W_VIEW_DRAWABLE(view))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
handler = malloc(sizeof(SelectionHandler));
|
handler = malloc(sizeof(SelectionHandler));
|
||||||
if (!handler)
|
if (handler == NULL)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
handler->widget = w;
|
handler->view = view;
|
||||||
handler->selection = selection;
|
handler->selection = selection;
|
||||||
handler->timestamp = timestamp;
|
handler->timestamp = timestamp;
|
||||||
handler->convProc = convProc;
|
handler->procs = *procs;
|
||||||
handler->loseProc = loseProc;
|
handler->data = cdata;
|
||||||
handler->doneProc = doneProc;
|
|
||||||
memset(&handler->flags, 0, sizeof(handler->flags));
|
memset(&handler->flags, 0, sizeof(handler->flags));
|
||||||
|
|
||||||
if (!selHandlers) {
|
if (selHandlers == NULL) {
|
||||||
/* first in the queue */
|
selHandlers = WMCreateTreeBag();
|
||||||
handler->next = selHandlers;
|
|
||||||
selHandlers = handler;
|
|
||||||
} else {
|
|
||||||
tmp = selHandlers;
|
|
||||||
while (tmp->next) {
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
handler->next = tmp->next;
|
|
||||||
tmp->next = handler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WMPutInBag(selHandlers, handler);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Bool
|
||||||
static void
|
WMRequestSelection(WMView *view, Atom selection, Atom target, Time timestamp,
|
||||||
timeoutHandler(void *data)
|
WMSelectionCallback *callback, void *cdata)
|
||||||
{
|
{
|
||||||
*(int*)data = 1;
|
SelectionCallback *handler;
|
||||||
}
|
|
||||||
|
|
||||||
|
if (XGetSelectionOwner(W_VIEW_SCREEN(view)->display, selection) == None)
|
||||||
static Bool
|
|
||||||
getInternalSelection(WMScreen *scr, Atom selection, Atom target,
|
|
||||||
void **data, unsigned *length)
|
|
||||||
{
|
|
||||||
Window owner;
|
|
||||||
SelectionHandler *handler;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the selection is owned by this application and if so,
|
|
||||||
* do the conversion directly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*data = NULL;
|
|
||||||
|
|
||||||
owner = XGetSelectionOwner(scr->display, selection);
|
|
||||||
if (!owner)
|
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
handler = selHandlers;
|
handler = wmalloc(sizeof(SelectionCallback));
|
||||||
|
|
||||||
while (handler) {
|
handler->view = view;
|
||||||
if (WMWidgetXID(handler->widget) == owner
|
handler->selection = selection;
|
||||||
/* && handler->selection == event->selection*/) {
|
handler->target = target;
|
||||||
break;
|
handler->timestamp = timestamp;
|
||||||
}
|
handler->callback = callback;
|
||||||
handler = handler->next;
|
handler->data = cdata;
|
||||||
|
memset(&handler->flags, 0, sizeof(handler->flags));
|
||||||
|
|
||||||
|
if (selCallbacks == NULL) {
|
||||||
|
selCallbacks = WMCreateTreeBag();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handler)
|
WMPutInBag(selCallbacks, handler);
|
||||||
|
|
||||||
|
if (!XConvertSelection(W_VIEW_SCREEN(view)->display, selection, target,
|
||||||
|
W_VIEW_SCREEN(view)->clipboardAtom,
|
||||||
|
W_VIEW_DRAWABLE(view), timestamp)) {
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
if (handler->convProc) {
|
|
||||||
Atom atom;
|
|
||||||
int format;
|
|
||||||
|
|
||||||
if (!(*handler->convProc)(handler->widget, handler->selection,
|
|
||||||
target, &atom, data, length, &format)) {
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler->doneProc) {
|
|
||||||
(*handler->doneProc)(handler->widget, handler->selection, target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char*
|
|
||||||
W_GetTextSelection(WMScreen *scr, Atom selection)
|
|
||||||
{
|
|
||||||
int buffer = -1;
|
|
||||||
|
|
||||||
switch (selection) {
|
|
||||||
case XA_CUT_BUFFER0:
|
|
||||||
buffer = 0;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER1:
|
|
||||||
buffer = 1;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER2:
|
|
||||||
buffer = 2;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER3:
|
|
||||||
buffer = 3;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER4:
|
|
||||||
buffer = 4;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER5:
|
|
||||||
buffer = 5;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER6:
|
|
||||||
buffer = 6;
|
|
||||||
break;
|
|
||||||
case XA_CUT_BUFFER7:
|
|
||||||
buffer = 7;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buffer >= 0) {
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
data = XFetchBuffer(scr->display, &size, buffer);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
} else {
|
|
||||||
char *data;
|
|
||||||
int bits;
|
|
||||||
Atom rtype;
|
|
||||||
unsigned long len, bytes;
|
|
||||||
WMHandlerID timer;
|
|
||||||
int timeout = 0;
|
|
||||||
XEvent ev;
|
|
||||||
unsigned length;
|
|
||||||
|
|
||||||
XDeleteProperty(scr->display, scr->groupLeader, scr->clipboardAtom);
|
|
||||||
|
|
||||||
if (getInternalSelection(scr, selection, XA_STRING, (void**)&data,
|
|
||||||
&length)) {
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
XConvertSelection(scr->display, selection, XA_STRING,
|
|
||||||
scr->clipboardAtom, scr->groupLeader,
|
|
||||||
scr->lastEventTime);
|
|
||||||
|
|
||||||
timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
|
|
||||||
|
|
||||||
while (!XCheckTypedWindowEvent(scr->display, scr->groupLeader,
|
|
||||||
SelectionNotify, &ev) && !timeout);
|
|
||||||
|
|
||||||
if (!timeout) {
|
|
||||||
WMDeleteTimerHandler(timer);
|
|
||||||
} else {
|
|
||||||
wwarning("selection retrieval timed out");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nobody owns the selection or the current owner has
|
|
||||||
* nothing to do with what we need */
|
|
||||||
if (ev.xselection.property == None) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XGetWindowProperty(scr->display, scr->groupLeader,
|
|
||||||
scr->clipboardAtom, 0, MAX_PROPERTY_SIZE,
|
|
||||||
False, XA_STRING, &rtype, &bits, &len,
|
|
||||||
&bytes, (unsigned char**)&data)!=Success) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (rtype!=XA_STRING || bits!=8) {
|
|
||||||
wwarning("invalid data in text selection");
|
|
||||||
if (data)
|
|
||||||
XFree(data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,18 +46,42 @@ static void willResizeColorWell();
|
|||||||
|
|
||||||
W_ViewDelegate _ColorWellViewDelegate = {
|
W_ViewDelegate _ColorWellViewDelegate = {
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
willResizeColorWell
|
willResizeColorWell
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
static unsigned draggingSourceOperation(WMView *self, Bool local);
|
||||||
static WMDragSourceProcs dragProcs = {
|
|
||||||
|
|
||||||
|
static WMData* fetchDragData(WMView *self, char *type);
|
||||||
|
|
||||||
|
static WMDragSourceProcs _DragSourceProcs = {
|
||||||
|
draggingSourceOperation,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
fetchDragData
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
|
static unsigned draggingEntered(WMView *self, WMDraggingInfo *info);
|
||||||
|
static unsigned draggingUpdated(WMView *self, WMDraggingInfo *info);
|
||||||
|
static void draggingExited(WMView *self, WMDraggingInfo *info);
|
||||||
|
static char *prepareForDragOperation(WMView *self, WMDraggingInfo *info);
|
||||||
|
static Bool performDragOperation(WMView *self, WMDraggingInfo *info,
|
||||||
|
WMData *data);
|
||||||
|
static void concludeDragOperation(WMView *self, WMDraggingInfo *info);
|
||||||
|
|
||||||
|
static WMDragDestinationProcs _DragDestinationProcs = {
|
||||||
|
draggingEntered,
|
||||||
|
draggingUpdated,
|
||||||
|
draggingExited,
|
||||||
|
prepareForDragOperation,
|
||||||
|
performDragOperation,
|
||||||
|
concludeDragOperation
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_WIDTH 60
|
#define DEFAULT_WIDTH 60
|
||||||
#define DEFAULT_HEIGHT 30
|
#define DEFAULT_HEIGHT 30
|
||||||
@@ -169,6 +193,15 @@ WMCreateColorWell(WMWidget *parent)
|
|||||||
WMAddNotificationObserver(colorChangedObserver, cPtr,
|
WMAddNotificationObserver(colorChangedObserver, cPtr,
|
||||||
WMColorPanelColorChangedNotification, NULL);
|
WMColorPanelColorChangedNotification, NULL);
|
||||||
|
|
||||||
|
WMSetViewDragSourceProcs(cPtr->view, &_DragSourceProcs);
|
||||||
|
WMSetViewDragDestinationProcs(cPtr->view, &_DragDestinationProcs);
|
||||||
|
|
||||||
|
{
|
||||||
|
char *types[2] = {"application/X-color", NULL};
|
||||||
|
|
||||||
|
WMRegisterViewForDraggedTypes(cPtr->view, types);
|
||||||
|
}
|
||||||
|
|
||||||
return cPtr;
|
return cPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +309,27 @@ handleEvents(XEvent *event, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
draggingSourceOperation(WMView *self, Bool local)
|
||||||
|
{
|
||||||
|
return WDOperationCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static WMData*
|
||||||
|
fetchDragData(WMView *self, char *type)
|
||||||
|
{
|
||||||
|
char *color = WMGetColorRGBDescription(((WMColorWell*)self->self)->color);
|
||||||
|
WMData *data;
|
||||||
|
|
||||||
|
data = WMCreateDataWithBytes(color, strlen(color)+1);
|
||||||
|
|
||||||
|
free(color);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static WMPixmap*
|
static WMPixmap*
|
||||||
makeDragPixmap(WMColorWell *cPtr)
|
makeDragPixmap(WMColorWell *cPtr)
|
||||||
{
|
{
|
||||||
@@ -292,221 +346,6 @@ makeDragPixmap(WMColorWell *cPtr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
slideView(WMView *view, int srcX, int srcY, int dstX, int dstY)
|
|
||||||
{
|
|
||||||
double x, y, dx, dy;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
srcX -= 8;
|
|
||||||
srcY -= 8;
|
|
||||||
dstX -= 8;
|
|
||||||
dstY -= 8;
|
|
||||||
|
|
||||||
x = srcX;
|
|
||||||
y = srcY;
|
|
||||||
|
|
||||||
dx = (double)(dstX-srcX)/20.0;
|
|
||||||
dy = (double)(dstY-srcY)/20.0;
|
|
||||||
|
|
||||||
for (i = 0; i < 20; i++) {
|
|
||||||
W_MoveView(view, x, y);
|
|
||||||
XFlush(view->screen->display);
|
|
||||||
|
|
||||||
x += dx;
|
|
||||||
y += dy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Window
|
|
||||||
findChildInWindow(Display *dpy, Window toplevel, int x, int y)
|
|
||||||
{
|
|
||||||
Window foo, bar;
|
|
||||||
Window *children;
|
|
||||||
unsigned nchildren;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!XQueryTree(dpy, toplevel, &foo, &bar,
|
|
||||||
&children, &nchildren) || children == NULL) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* first window that contains the point is the one */
|
|
||||||
for (i = nchildren-1; i >= 0; i--) {
|
|
||||||
XWindowAttributes attr;
|
|
||||||
|
|
||||||
if (XGetWindowAttributes(dpy, children[i], &attr)
|
|
||||||
&& attr.map_state == IsViewable
|
|
||||||
&& x >= attr.x && y >= attr.y
|
|
||||||
&& x < attr.x + attr.width && y < attr.y + attr.height) {
|
|
||||||
Window child;
|
|
||||||
|
|
||||||
child = findChildInWindow(dpy, children[i],
|
|
||||||
x - attr.x, y - attr.y);
|
|
||||||
|
|
||||||
XFree(children);
|
|
||||||
|
|
||||||
if (!child)
|
|
||||||
return toplevel;
|
|
||||||
else
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(children);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Window
|
|
||||||
findWindowUnderDragPointer(WMScreen *scr, int x, int y, Window iconWindow)
|
|
||||||
{
|
|
||||||
Window foo, bar;
|
|
||||||
Window *children;
|
|
||||||
unsigned nchildren;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!XQueryTree(scr->display, scr->rootWin, &foo, &bar,
|
|
||||||
&children, &nchildren) || children == NULL) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* try to find the window below the iconWindow by traversing
|
|
||||||
* the whole window list */
|
|
||||||
|
|
||||||
/* first find the position of the iconWindow */
|
|
||||||
for (i = nchildren-1; i >= 0; i--) {
|
|
||||||
if (children[i] == iconWindow) {
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i <= 0) {
|
|
||||||
XFree(children);
|
|
||||||
return scr->rootWin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* first window that contains the point is the one */
|
|
||||||
for (; i >= 0; i--) {
|
|
||||||
XWindowAttributes attr;
|
|
||||||
Window child;
|
|
||||||
|
|
||||||
if (XGetWindowAttributes(scr->display, children[i], &attr)
|
|
||||||
&& attr.map_state == IsViewable
|
|
||||||
&& x >= attr.x && y >= attr.y
|
|
||||||
&& x < attr.x + attr.width && y < attr.y + attr.height
|
|
||||||
&& (child = findChildInWindow(scr->display, children[i],
|
|
||||||
x - attr.x, y - attr.y))) {
|
|
||||||
XFree(children);
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(children);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
dragColor(ColorWell *cPtr, XEvent *event, WMPixmap *image)
|
|
||||||
{
|
|
||||||
WMView *dragView;
|
|
||||||
WMScreen *scr = cPtr->view->screen;
|
|
||||||
Display *dpy = scr->display;
|
|
||||||
XColor black = {0, 0,0,0, DoRed|DoGreen|DoBlue};
|
|
||||||
XColor green = {0x0045b045, 0x4500,0xb000,0x4500, DoRed|DoGreen|DoBlue};
|
|
||||||
XColor back = {0, 0xffff,0xffff,0xffff, DoRed|DoGreen|DoBlue};
|
|
||||||
Bool done = False;
|
|
||||||
WMColorWell *activeWell = NULL;
|
|
||||||
|
|
||||||
dragView = W_CreateTopView(scr);
|
|
||||||
|
|
||||||
W_ResizeView(dragView, 16, 16);
|
|
||||||
dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
|
|
||||||
dragView->attribs.event_mask = StructureNotifyMask;
|
|
||||||
dragView->attribs.override_redirect = True;
|
|
||||||
dragView->attribs.save_under = True;
|
|
||||||
|
|
||||||
W_MoveView(dragView, event->xmotion.x_root-8, event->xmotion.y_root-8);
|
|
||||||
|
|
||||||
W_RealizeView(dragView);
|
|
||||||
|
|
||||||
W_MapView(dragView);
|
|
||||||
|
|
||||||
XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(image));
|
|
||||||
XClearWindow(dpy, dragView->window);
|
|
||||||
|
|
||||||
|
|
||||||
XGrabPointer(dpy, scr->rootWin, True,
|
|
||||||
ButtonMotionMask|ButtonReleaseMask,
|
|
||||||
GrabModeSync, GrabModeAsync,
|
|
||||||
scr->rootWin, scr->defaultCursor, CurrentTime);
|
|
||||||
|
|
||||||
while (!done) {
|
|
||||||
XEvent ev;
|
|
||||||
WMView *view;
|
|
||||||
Window win;
|
|
||||||
|
|
||||||
XAllowEvents(dpy, SyncPointer, CurrentTime);
|
|
||||||
WMNextEvent(dpy, &ev);
|
|
||||||
|
|
||||||
switch (ev.type) {
|
|
||||||
case ButtonRelease:
|
|
||||||
if (activeWell != NULL) {
|
|
||||||
WMSetColorWellColor(activeWell, cPtr->color);
|
|
||||||
WMPostNotificationName(WMColorWellDidChangeNotification,
|
|
||||||
activeWell, NULL);
|
|
||||||
} else {
|
|
||||||
slideView(dragView, ev.xbutton.x_root, ev.xbutton.y_root,
|
|
||||||
event->xmotion.x_root, event->xmotion.y_root);
|
|
||||||
}
|
|
||||||
|
|
||||||
done = True;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionNotify:
|
|
||||||
while (XCheckTypedEvent(dpy, MotionNotify, &ev)) ;
|
|
||||||
|
|
||||||
W_MoveView(dragView, ev.xmotion.x_root-8, ev.xmotion.y_root-8);
|
|
||||||
|
|
||||||
win = findWindowUnderDragPointer(scr, ev.xmotion.x_root,
|
|
||||||
ev.xmotion.y_root,
|
|
||||||
dragView->window);
|
|
||||||
|
|
||||||
if (win != None && win != scr->rootWin) {
|
|
||||||
view = W_GetViewForXWindow(dpy, win);
|
|
||||||
} else {
|
|
||||||
view = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view && view->self && W_CLASS(view->self) == WC_ColorWell
|
|
||||||
&& view->self != activeWell && view->self != cPtr) {
|
|
||||||
|
|
||||||
activeWell = view->self;
|
|
||||||
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
|
|
||||||
|
|
||||||
} else if (!view || view->self != activeWell) {
|
|
||||||
|
|
||||||
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
|
|
||||||
activeWell = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
WMHandleEvent(&ev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XUngrabPointer(dpy, CurrentTime);
|
|
||||||
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
|
|
||||||
|
|
||||||
W_DestroyView(dragView);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleDragEvents(XEvent *event, void *data)
|
handleDragEvents(XEvent *event, void *data)
|
||||||
{
|
{
|
||||||
@@ -526,17 +365,17 @@ handleDragEvents(XEvent *event, void *data)
|
|||||||
|| abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
|
|| abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
|
||||||
WMSize offs;
|
WMSize offs;
|
||||||
WMPixmap *pixmap;
|
WMPixmap *pixmap;
|
||||||
|
char *types[2] = {"application/X-color", NULL};
|
||||||
|
|
||||||
offs.width = 2;
|
offs.width = 2;
|
||||||
offs.height = 2;
|
offs.height = 2;
|
||||||
pixmap = makeDragPixmap(cPtr);
|
pixmap = makeDragPixmap(cPtr);
|
||||||
|
|
||||||
/*
|
WMDragImageFromView(cPtr->view, pixmap, types,
|
||||||
WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
|
wmkpoint(event->xmotion.x_root,
|
||||||
offs, event, True);
|
event->xmotion.y_root),
|
||||||
* */
|
offs, event, True);
|
||||||
|
|
||||||
dragColor(cPtr, event, pixmap);
|
|
||||||
|
|
||||||
WMReleasePixmap(pixmap);
|
WMReleasePixmap(pixmap);
|
||||||
}
|
}
|
||||||
@@ -585,3 +424,53 @@ destroyColorWell(ColorWell *cPtr)
|
|||||||
wfree(cPtr);
|
wfree(cPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
draggingEntered(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return WDOperationCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
draggingUpdated(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return WDOperationCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
draggingExited(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char*
|
||||||
|
prepareForDragOperation(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
return "application/X-color";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
performDragOperation(WMView *self, WMDraggingInfo *info, WMData *data)
|
||||||
|
{
|
||||||
|
char *colorName = WMDataBytes(data);
|
||||||
|
WMColor *color;
|
||||||
|
|
||||||
|
color = WMCreateNamedColor(W_VIEW_SCREEN(self), colorName, True);
|
||||||
|
|
||||||
|
WMSetColorWellColor(self->self, color);
|
||||||
|
|
||||||
|
WMReleaseColor(color);
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
concludeDragOperation(WMView *self, WMDraggingInfo *info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -559,10 +559,16 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
|||||||
"XdndDrop",
|
"XdndDrop",
|
||||||
"XdndFinished",
|
"XdndFinished",
|
||||||
"XdndTypeList",
|
"XdndTypeList",
|
||||||
|
"XdndActionCopy",
|
||||||
|
"XdndActionMove",
|
||||||
|
"XdndActionLink",
|
||||||
|
"XdndActionAsk",
|
||||||
|
"XdndActionPrivate",
|
||||||
"XdndStatus",
|
"XdndStatus",
|
||||||
"WM_STATE"
|
"WM_STATE"
|
||||||
};
|
};
|
||||||
Atom atoms[sizeof(atomNames)/sizeof(char*)];
|
Atom atoms[sizeof(atomNames)/sizeof(char*)];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
|
|
||||||
@@ -767,25 +773,32 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scrPtr->attribsAtom = atoms[0];
|
i = 0;
|
||||||
|
scrPtr->attribsAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->deleteWindowAtom = atoms[1];
|
scrPtr->deleteWindowAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->protocolsAtom = atoms[2];
|
scrPtr->protocolsAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->clipboardAtom = atoms[3];
|
scrPtr->clipboardAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->xdndAwareAtom = atoms[4];
|
scrPtr->xdndAwareAtom = atoms[i++];
|
||||||
scrPtr->xdndSelectionAtom = atoms[5];
|
scrPtr->xdndSelectionAtom = atoms[i++];
|
||||||
scrPtr->xdndEnterAtom = atoms[6];
|
scrPtr->xdndEnterAtom = atoms[i++];
|
||||||
scrPtr->xdndLeaveAtom = atoms[7];
|
scrPtr->xdndLeaveAtom = atoms[i++];
|
||||||
scrPtr->xdndPositionAtom = atoms[8];
|
scrPtr->xdndPositionAtom = atoms[i++];
|
||||||
scrPtr->xdndDropAtom = atoms[9];
|
scrPtr->xdndDropAtom = atoms[i++];
|
||||||
scrPtr->xdndFinishedAtom = atoms[10];
|
scrPtr->xdndFinishedAtom = atoms[i++];
|
||||||
scrPtr->xdndTypeListAtom = atoms[11];
|
scrPtr->xdndTypeListAtom = atoms[i++];
|
||||||
scrPtr->xdndStatusAtom = atoms[12];
|
scrPtr->xdndStatusAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->wmStateAtom = atoms[13];
|
scrPtr->xdndActionCopy = atoms[i++];
|
||||||
|
scrPtr->xdndActionMove = atoms[i++];
|
||||||
|
scrPtr->xdndActionLink = atoms[i++];
|
||||||
|
scrPtr->xdndActionAsk = atoms[i++];
|
||||||
|
scrPtr->xdndActionPrivate = atoms[i++];
|
||||||
|
|
||||||
|
scrPtr->wmStateAtom = atoms[i++];
|
||||||
|
|
||||||
scrPtr->rootView = W_CreateRootView(scrPtr);
|
scrPtr->rootView = W_CreateRootView(scrPtr);
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ typedef struct W_TabView {
|
|||||||
struct {
|
struct {
|
||||||
WMReliefType relief:4;
|
WMReliefType relief:4;
|
||||||
WMTitlePosition titlePosition:4;
|
WMTitlePosition titlePosition:4;
|
||||||
WMTabViewTypes type:2;
|
WMTabViewType type:2;
|
||||||
|
|
||||||
unsigned tabbed:1;
|
unsigned tabbed:1;
|
||||||
unsigned dontFitAll:1;
|
unsigned dontFitAll:1;
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ typedef struct W_TextField {
|
|||||||
|
|
||||||
unsigned int pointerGrabbed:1;
|
unsigned int pointerGrabbed:1;
|
||||||
|
|
||||||
|
unsigned int ownsSelection:1;
|
||||||
|
|
||||||
|
unsigned int waitingSelection:1; /* requested selection, but
|
||||||
|
* didnt get yet */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
unsigned int notIllegalMovement:1;
|
unsigned int notIllegalMovement:1;
|
||||||
} flags;
|
} flags;
|
||||||
@@ -116,6 +121,20 @@ struct W_ViewDelegate _TextFieldViewDelegate = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void lostHandler(WMView *view, Atom selection, void *cdata);
|
||||||
|
|
||||||
|
static WMData *requestHandler(WMView *view, Atom selection, Atom target,
|
||||||
|
void *cdata, Atom *type);
|
||||||
|
|
||||||
|
|
||||||
|
static WMSelectionProcs selectionHandler = {
|
||||||
|
requestHandler,
|
||||||
|
lostHandler,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->font, \
|
#define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->font, \
|
||||||
&((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
|
&((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
|
||||||
|
|
||||||
@@ -210,73 +229,73 @@ decrToFit(TextField *tPtr)
|
|||||||
#undef TEXT_WIDTH
|
#undef TEXT_WIDTH
|
||||||
#undef TEXT_WIDTH2
|
#undef TEXT_WIDTH2
|
||||||
|
|
||||||
static Bool
|
|
||||||
requestHandler(WMWidget *w, Atom selection, Atom target, Atom *type,
|
|
||||||
void **value, unsigned *length, int *format)
|
static WMData*
|
||||||
|
requestHandler(WMView *view, Atom selection, Atom target, void *cdata,
|
||||||
|
Atom *type)
|
||||||
{
|
{
|
||||||
TextField *tPtr = w;
|
TextField *tPtr = view->self;
|
||||||
int count;
|
int count;
|
||||||
Display *dpy = tPtr->view->screen->display;
|
Display *dpy = tPtr->view->screen->display;
|
||||||
Atom _TARGETS;
|
Atom _TARGETS;
|
||||||
char *text;
|
Atom TEXT = XInternAtom(dpy, "TEXT", False);
|
||||||
text = XGetAtomName(tPtr->view->screen->display,target);
|
Atom COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
||||||
XFree(text);
|
WMData *data;
|
||||||
text = XGetAtomName(tPtr->view->screen->display,selection);
|
|
||||||
XFree(text);
|
|
||||||
|
|
||||||
*format = 32;
|
|
||||||
*length = 0;
|
|
||||||
*value = NULL;
|
|
||||||
count = tPtr->selection.count < 0
|
count = tPtr->selection.count < 0
|
||||||
? tPtr->selection.position + tPtr->selection.count
|
? tPtr->selection.position + tPtr->selection.count
|
||||||
: tPtr->selection.position;
|
: tPtr->selection.position;
|
||||||
|
|
||||||
if (target == XA_STRING ||
|
if (target == XA_STRING || target == TEXT || target == COMPOUND_TEXT) {
|
||||||
target == XInternAtom(dpy, "TEXT", False) ||
|
|
||||||
target == XInternAtom(dpy, "COMPOUND_TEXT", False)) {
|
data = WMCreateDataWithBytes(&(tPtr->text[count]),
|
||||||
*value = wstrdup(&(tPtr->text[count]));
|
abs(tPtr->selection.count));
|
||||||
*length = abs(tPtr->selection.count);
|
WMSetDataFormat(data, 8);
|
||||||
*format = 8;
|
|
||||||
*type = target;
|
*type = target;
|
||||||
return True;
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||||
if (target == _TARGETS) {
|
if (target == _TARGETS) {
|
||||||
int *ptr;
|
Atom *ptr;
|
||||||
|
|
||||||
*length = 4;
|
ptr = wmalloc(4 * sizeof(Atom));
|
||||||
ptr = *value = (char *) wmalloc(4 * sizeof(Atom));
|
|
||||||
ptr[0] = _TARGETS;
|
ptr[0] = _TARGETS;
|
||||||
ptr[1] = XA_STRING;
|
ptr[1] = XA_STRING;
|
||||||
ptr[2] = XInternAtom(dpy, "TEXT", False);
|
ptr[2] = TEXT;
|
||||||
ptr[3] = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
ptr[3] = COMPOUND_TEXT;
|
||||||
|
|
||||||
|
data = WMCreateDataWithBytes(ptr, 4*4);
|
||||||
|
WMSetDataFormat(data, 32);
|
||||||
|
|
||||||
*type = target;
|
*type = target;
|
||||||
return True;
|
return data;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
*target = XA_PRIMARY;
|
return NULL;
|
||||||
*/
|
|
||||||
return False;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lostHandler(WMWidget *w, Atom selection)
|
lostHandler(WMView *view, Atom selection, void *cdata)
|
||||||
{
|
{
|
||||||
TextField *tPtr = (WMTextField*)w;
|
TextField *tPtr = (WMTextField*)view->self;
|
||||||
|
|
||||||
|
tPtr->flags.ownsSelection = 0;
|
||||||
tPtr->selection.count = 0;
|
tPtr->selection.count = 0;
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_notification(void *observerData, WMNotification *notification)
|
_notification(void *observerData, WMNotification *notification)
|
||||||
{
|
{
|
||||||
WMTextField *to = (WMTextField*)observerData;
|
WMTextField *to = (WMTextField*)observerData;
|
||||||
WMTextField *tw = (WMTextField*)WMGetNotificationClientData(notification);
|
WMTextField *tw = (WMTextField*)WMGetNotificationClientData(notification);
|
||||||
if (to != tw) lostHandler(to, 0);
|
if (to != tw) lostHandler(to->view, XA_PRIMARY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
WMTextField*
|
WMTextField*
|
||||||
@@ -327,8 +346,6 @@ WMCreateTextField(WMWidget *parent)
|
|||||||
|ButtonReleaseMask|ButtonPressMask|KeyPressMask|Button1MotionMask,
|
|ButtonReleaseMask|ButtonPressMask|KeyPressMask|Button1MotionMask,
|
||||||
handleTextFieldActionEvents, tPtr);
|
handleTextFieldActionEvents, tPtr);
|
||||||
|
|
||||||
WMCreateSelectionHandler(tPtr, XA_PRIMARY, CurrentTime, requestHandler,
|
|
||||||
lostHandler, NULL);
|
|
||||||
WMAddNotificationObserver(_notification, tPtr, "_lostOwnership", tPtr);
|
WMAddNotificationObserver(_notification, tPtr, "_lostOwnership", tPtr);
|
||||||
|
|
||||||
|
|
||||||
@@ -1185,20 +1202,17 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
|
|||||||
|
|
||||||
if (!cancelSelection) {
|
if (!cancelSelection) {
|
||||||
if (tPtr->selection.count != tPtr->cursorPosition - tPtr->selection.position) {
|
if (tPtr->selection.count != tPtr->cursorPosition - tPtr->selection.position) {
|
||||||
WMNotification *notif;
|
|
||||||
|
|
||||||
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
||||||
|
|
||||||
XSetSelectionOwner(tPtr->view->screen->display,
|
WMPostNotificationName("_lostOwnership", NULL, tPtr);
|
||||||
XA_PRIMARY, tPtr->view->window,
|
|
||||||
event->xbutton.time);
|
|
||||||
notif = WMCreateNotification("_lostOwnership", NULL, tPtr);
|
|
||||||
WMPostNotification(notif);
|
|
||||||
WMReleaseNotification(notif);
|
|
||||||
|
|
||||||
refresh = 1;
|
refresh = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
lostHandler(tPtr->view, XA_PRIMARY, NULL);
|
||||||
|
|
||||||
if (tPtr->selection.count) {
|
if (tPtr->selection.count) {
|
||||||
tPtr->selection.count = 0;
|
tPtr->selection.count = 0;
|
||||||
refresh = 1;
|
refresh = 1;
|
||||||
@@ -1264,21 +1278,56 @@ pointToCursorPosition(TextField *tPtr, int x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pasteText(WMView *view, Atom selection, Atom target, Time timestamp,
|
||||||
|
void *cdata, WMData *data)
|
||||||
|
{
|
||||||
|
TextField *tPtr = (TextField*)view->self;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
tPtr->flags.waitingSelection = 0;
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
str = (char*)WMDataBytes(data);
|
||||||
|
|
||||||
|
WMInsertTextFieldText(tPtr, str, tPtr->cursorPosition);
|
||||||
|
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
||||||
|
(void*)WMInsertTextEvent);
|
||||||
|
} else {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
str = XFetchBuffer(tPtr->view->screen->display, &n, 0);
|
||||||
|
|
||||||
|
if (str != NULL) {
|
||||||
|
str[n] = 0;
|
||||||
|
WMInsertTextFieldText(tPtr, str, tPtr->cursorPosition);
|
||||||
|
XFree(str);
|
||||||
|
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
||||||
|
(void*)WMInsertTextEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleTextFieldActionEvents(XEvent *event, void *data)
|
handleTextFieldActionEvents(XEvent *event, void *data)
|
||||||
{
|
{
|
||||||
TextField *tPtr = (TextField*)data;
|
TextField *tPtr = (TextField*)data;
|
||||||
static int move = 0;
|
static int move = 0;
|
||||||
static Time lastButtonReleasedEvent = 0;
|
static Time lastButtonReleasedEvent = 0;
|
||||||
|
Display *dpy = event->xany.display;
|
||||||
|
|
||||||
CHECK_CLASS(data, WC_TextField);
|
CHECK_CLASS(data, WC_TextField);
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
|
if (tPtr->flags.waitingSelection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (tPtr->flags.enabled && tPtr->flags.focused) {
|
if (tPtr->flags.enabled && tPtr->flags.focused) {
|
||||||
handleTextFieldKeyPress(tPtr, event);
|
handleTextFieldKeyPress(tPtr, event);
|
||||||
XGrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen),
|
XGrabPointer(dpy, W_VIEW(tPtr)->window, False,
|
||||||
W_VIEW(tPtr)->window, False,
|
|
||||||
PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
|
PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
|
||||||
GrabModeAsync, GrabModeAsync, None,
|
GrabModeAsync, GrabModeAsync, None,
|
||||||
W_VIEW(tPtr)->screen->invisibleCursor,
|
W_VIEW(tPtr)->screen->invisibleCursor,
|
||||||
@@ -1291,7 +1340,10 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
|||||||
|
|
||||||
if (tPtr->flags.pointerGrabbed) {
|
if (tPtr->flags.pointerGrabbed) {
|
||||||
tPtr->flags.pointerGrabbed = 0;
|
tPtr->flags.pointerGrabbed = 0;
|
||||||
XUngrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen), CurrentTime);
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
}
|
||||||
|
if (tPtr->flags.waitingSelection) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tPtr->flags.enabled && (event->xmotion.state & Button1Mask)) {
|
if (tPtr->flags.enabled && (event->xmotion.state & Button1Mask)) {
|
||||||
@@ -1309,40 +1361,35 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
|||||||
tPtr->viewPosition--;
|
tPtr->viewPosition--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (!tPtr->selection.count) {
|
|
||||||
tPtr->selection.position = tPtr->cursorPosition;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
tPtr->cursorPosition =
|
tPtr->cursorPosition =
|
||||||
pointToCursorPosition(tPtr, event->xmotion.x);
|
pointToCursorPosition(tPtr, event->xmotion.x);
|
||||||
|
|
||||||
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
||||||
/*printf("(%d,%d)\n", tPtr->selection.position, tPtr->selection.count);*/
|
|
||||||
|
|
||||||
/*
|
if (tPtr->selection.count != 0) {
|
||||||
printf("notify %d %d\n",event->xmotion.x,tPtr->usableWidth);
|
if (!tPtr->flags.ownsSelection) {
|
||||||
*/
|
WMCreateSelectionHandler(tPtr->view,
|
||||||
|
XA_PRIMARY,
|
||||||
|
event->xbutton.time,
|
||||||
|
&selectionHandler, NULL);
|
||||||
|
tPtr->flags.ownsSelection = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
paintCursor(tPtr);
|
paintCursor(tPtr);
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (move) {
|
|
||||||
XSetSelectionOwner(tPtr->view->screen->display,
|
|
||||||
XA_PRIMARY, tPtr->view->window, event->xmotion.time);
|
|
||||||
{
|
|
||||||
WMNotification *notif = WMCreateNotification("_lostOwnership",
|
|
||||||
NULL,tPtr);
|
|
||||||
WMPostNotification(notif);
|
|
||||||
WMReleaseNotification(notif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
if (tPtr->flags.pointerGrabbed) {
|
if (tPtr->flags.pointerGrabbed) {
|
||||||
tPtr->flags.pointerGrabbed = 0;
|
tPtr->flags.pointerGrabbed = 0;
|
||||||
XUngrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen), CurrentTime);
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tPtr->flags.waitingSelection) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1353,26 +1400,18 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
|||||||
textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
||||||
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
||||||
WMSetFocusToWidget(tPtr);
|
WMSetFocusToWidget(tPtr);
|
||||||
|
|
||||||
} else if (tPtr->flags.focused) {
|
} else if (tPtr->flags.focused) {
|
||||||
tPtr->selection.position = tPtr->cursorPosition;
|
tPtr->selection.position = tPtr->cursorPosition;
|
||||||
tPtr->selection.count = 0;
|
tPtr->selection.count = 0;
|
||||||
}
|
}
|
||||||
if(textWidth < tPtr->usableWidth){
|
if(textWidth < tPtr->usableWidth) {
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
event->xbutton.x - tPtr->usableWidth
|
event->xbutton.x - tPtr->usableWidth
|
||||||
+ textWidth);
|
+ textWidth);
|
||||||
}
|
} else tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
else tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
|
||||||
event->xbutton.x);
|
event->xbutton.x);
|
||||||
/*
|
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
|
||||||
event->xbutton.x);
|
|
||||||
tPtr->cursorPosition += tPtr->usableWidth - textWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
|
||||||
event->xbutton.x);
|
|
||||||
*/
|
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1382,7 +1421,8 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
|||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
event->xbutton.x);
|
event->xbutton.x);
|
||||||
paintTextField(tPtr);
|
paintTextField(tPtr);
|
||||||
} else if (tPtr->flags.focused) {
|
} else if (tPtr->flags.focused
|
||||||
|
&& event->xbutton.button == Button1) {
|
||||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||||
event->xbutton.x);
|
event->xbutton.x);
|
||||||
tPtr->selection.position = tPtr->cursorPosition;
|
tPtr->selection.position = tPtr->cursorPosition;
|
||||||
@@ -1391,51 +1431,71 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
|||||||
}
|
}
|
||||||
if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
|
if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
|
||||||
char *text;
|
char *text;
|
||||||
|
int n;
|
||||||
|
|
||||||
text = W_GetTextSelection(tPtr->view->screen, XA_PRIMARY);
|
if (!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING,
|
||||||
|
event->xbutton.time,
|
||||||
|
pasteText, NULL)) {
|
||||||
|
text = XFetchBuffer(tPtr->view->screen->display, &n, 0);
|
||||||
|
|
||||||
if (!text) {
|
if (text) {
|
||||||
text = W_GetTextSelection(tPtr->view->screen,
|
text[n] = 0;
|
||||||
tPtr->view->screen->clipboardAtom);
|
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
||||||
}
|
XFree(text);
|
||||||
if (!text) {
|
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
||||||
text = W_GetTextSelection(tPtr->view->screen,
|
(void*)WMInsertTextEvent);
|
||||||
XA_CUT_BUFFER0);
|
}
|
||||||
}
|
} else {
|
||||||
if (text) {
|
tPtr->flags.waitingSelection = 1;
|
||||||
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
}
|
||||||
XFree(text);
|
|
||||||
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
|
||||||
(void*)WMInsertTextEvent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (tPtr->flags.pointerGrabbed) {
|
if (tPtr->flags.pointerGrabbed) {
|
||||||
tPtr->flags.pointerGrabbed = 0;
|
tPtr->flags.pointerGrabbed = 0;
|
||||||
XUngrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen), CurrentTime);
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
}
|
||||||
|
if (tPtr->flags.waitingSelection) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tPtr->selection.count != 0) {
|
||||||
|
int start, count;
|
||||||
|
XRotateBuffers(dpy, 1);
|
||||||
|
|
||||||
|
count = abs(tPtr->selection.count);
|
||||||
|
if (tPtr->selection.count < 0)
|
||||||
|
start = tPtr->selection.position - count;
|
||||||
|
else
|
||||||
|
start = tPtr->selection.position;
|
||||||
|
|
||||||
|
XStoreBuffer(dpy, &tPtr->text[start], count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
move = 0;
|
||||||
|
|
||||||
|
if (event->xbutton.time - lastButtonReleasedEvent
|
||||||
|
<= WINGsConfiguration.doubleClickDelay) {
|
||||||
|
tPtr->selection.position = 0;
|
||||||
|
tPtr->selection.count = tPtr->textLen;
|
||||||
|
paintTextField(tPtr);
|
||||||
|
|
||||||
|
if (!tPtr->flags.ownsSelection) {
|
||||||
|
WMCreateSelectionHandler(tPtr->view,
|
||||||
|
XA_PRIMARY,
|
||||||
|
event->xbutton.time,
|
||||||
|
&selectionHandler, NULL);
|
||||||
|
tPtr->flags.ownsSelection = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
move = 0;
|
WMPostNotificationName("_lostOwnership", NULL, tPtr);
|
||||||
|
}
|
||||||
if (event->xbutton.time - lastButtonReleasedEvent
|
lastButtonReleasedEvent = event->xbutton.time;
|
||||||
<= WINGsConfiguration.doubleClickDelay) {
|
|
||||||
tPtr->selection.position = 0;
|
|
||||||
tPtr->selection.count = tPtr->textLen;
|
|
||||||
paintTextField(tPtr);
|
|
||||||
XSetSelectionOwner(tPtr->view->screen->display,
|
|
||||||
XA_PRIMARY, tPtr->view->window, event->xbutton.time);
|
|
||||||
{
|
|
||||||
WMNotification *notif = WMCreateNotification("_lostOwnership",
|
|
||||||
NULL,tPtr);
|
|
||||||
WMPostNotification(notif);
|
|
||||||
WMReleaseNotification(notif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastButtonReleasedEvent = event->xbutton.time;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1451,7 +1511,7 @@ destroyTextField(TextField *tPtr)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
WMReleaseFont(tPtr->font);
|
WMReleaseFont(tPtr->font);
|
||||||
WMDeleteSelectionHandler(tPtr, XA_PRIMARY);
|
WMDeleteSelectionHandler(tPtr->view, XA_PRIMARY, CurrentTime);
|
||||||
WMRemoveNotificationObserver(tPtr);
|
WMRemoveNotificationObserver(tPtr);
|
||||||
|
|
||||||
if (tPtr->text)
|
if (tPtr->text)
|
||||||
|
|||||||
@@ -411,6 +411,10 @@ destroyView(W_View *view)
|
|||||||
|
|
||||||
if (view->dragDestinationProcs)
|
if (view->dragDestinationProcs)
|
||||||
wfree(view->dragDestinationProcs);
|
wfree(view->dragDestinationProcs);
|
||||||
|
|
||||||
|
if (scr->dragInfo.destView == view) {
|
||||||
|
scr->dragInfo.destView = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
wfree(view);
|
wfree(view);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user