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 <X11/Xlib.h>
|
||||
|
||||
#define WINGS_H_VERSION 991003
|
||||
#define WINGS_H_VERSION 20000402
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -170,7 +170,7 @@ typedef enum {
|
||||
WTNoTabsBevelBorder,
|
||||
WTNoTabsLineBorder,
|
||||
WTNoTabsNoBorder
|
||||
} WMTabViewTypes;
|
||||
} WMTabViewType;
|
||||
|
||||
|
||||
/* text movement types */
|
||||
@@ -192,6 +192,18 @@ enum {
|
||||
WMDeleteTextEvent
|
||||
};
|
||||
|
||||
|
||||
/* drag operations */
|
||||
typedef enum {
|
||||
WDOperationNone,
|
||||
WDOperationCopy,
|
||||
WDOperationMove,
|
||||
WDOperationLink,
|
||||
WDOperationAsk,
|
||||
WDOperationPrivate
|
||||
} WMDragOperationType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
WMGrayModeColorPanel = 1,
|
||||
WMRGBModeColorPanel = 2,
|
||||
@@ -392,8 +404,6 @@ typedef void WMCallback(void *data);
|
||||
|
||||
|
||||
/* delegate method like stuff */
|
||||
typedef void WMFreeDataProc(void *data);
|
||||
|
||||
typedef void WMListDrawProc(WMList *lPtr, int index, Drawable d, char *text,
|
||||
int state, WMRect *rect);
|
||||
|
||||
@@ -409,15 +419,6 @@ typedef void WMSplitViewConstrainProc(WMSplitView *sPtr, int dividerIndex,
|
||||
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 {
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -482,7 +499,7 @@ typedef struct W_DragSourceProcs {
|
||||
void (*beganDragImage)(WMView *self, WMPixmap *image, WMPoint point);
|
||||
void (*endedDragImage)(WMView *self, WMPixmap *image, WMPoint point,
|
||||
Bool deposited);
|
||||
WMData* (*fetchDragData)(WMView *self, char *type, Bool local);
|
||||
WMData* (*fetchDragData)(WMView *self, char *type);
|
||||
/* Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/
|
||||
} WMDragSourceProcs;
|
||||
|
||||
@@ -492,8 +509,9 @@ typedef struct W_DragDestinationProcs {
|
||||
unsigned (*draggingEntered)(WMView *self, WMDraggingInfo *info);
|
||||
unsigned (*draggingUpdated)(WMView *self, WMDraggingInfo *info);
|
||||
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
|
||||
Bool (*prepareForDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
Bool (*performDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
char *(*prepareForDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
Bool (*performDragOperation)(WMView *self, WMDraggingInfo *info,
|
||||
WMData *data);
|
||||
void (*concludeDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
} WMDragDestinationProcs;
|
||||
|
||||
@@ -581,12 +599,16 @@ WMHandlerID WMAddInputHandler(int fd, int condition, WMInputProc *proc,
|
||||
|
||||
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"
|
||||
|
||||
#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.
|
||||
#endif
|
||||
|
||||
@@ -105,9 +105,10 @@ struct W_DraggingInfo {
|
||||
|
||||
int protocolVersion;
|
||||
|
||||
/* should be treated as internal data */
|
||||
WMView *sourceView;
|
||||
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;
|
||||
|
||||
struct W_View *dragSourceView;
|
||||
struct W_DraggingInfo dragInfo;
|
||||
|
||||
/* colors */
|
||||
@@ -263,6 +265,12 @@ typedef struct W_Screen {
|
||||
Atom xdndTypeListAtom;
|
||||
Atom xdndStatusAtom;
|
||||
|
||||
Atom xdndActionCopy;
|
||||
Atom xdndActionMove;
|
||||
Atom xdndActionLink;
|
||||
Atom xdndActionAsk;
|
||||
Atom xdndActionPrivate;
|
||||
|
||||
Atom wmStateAtom; /* WM_STATE */
|
||||
|
||||
/* stuff for detecting double-clicks */
|
||||
@@ -485,8 +493,6 @@ void W_RedisplayView(WMView *view);
|
||||
|
||||
Bool W_ApplicationInitialized(void);
|
||||
|
||||
char *W_GetTextSelection(WMScreen *scr, Atom selection);
|
||||
|
||||
void W_HandleSelectionEvent(XEvent *event);
|
||||
|
||||
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
|
||||
|
||||
@@ -118,6 +118,10 @@ typedef struct W_Connection WMConnection;
|
||||
|
||||
|
||||
|
||||
typedef void WMFreeDataProc(void *data);
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int position;
|
||||
int count;
|
||||
@@ -438,6 +442,10 @@ WMData* WMCreateDataWithBytes(void *bytes, unsigned length);
|
||||
|
||||
WMData* WMCreateDataWithBytesNoCopy(void *bytes, unsigned length);
|
||||
|
||||
|
||||
WMData* WMCreateDataWithBytesAndDestructor(void *bytes, unsigned length,
|
||||
WMFreeDataProc *destructor);
|
||||
|
||||
WMData* WMCreateDataWithData(WMData *aData);
|
||||
|
||||
WMData* WMRetainData(WMData *aData);
|
||||
@@ -470,8 +478,6 @@ Bool WMIsDataEqualToData(WMData *aData, WMData *anotherData);
|
||||
|
||||
unsigned WMGetDataLength(WMData *aData);
|
||||
|
||||
unsigned WMGetDataHash(WMData *aData);
|
||||
|
||||
/* Adding data */
|
||||
|
||||
void WMAppendDataBytes(WMData *aData, void *bytes, unsigned length);
|
||||
|
||||
74
WINGs/data.c
74
WINGs/data.c
@@ -30,6 +30,8 @@ typedef struct W_Data {
|
||||
unsigned growth; /* How much to grow */
|
||||
void *bytes; /* Actual data */
|
||||
unsigned retainCount;
|
||||
WMFreeDataProc *destructor;
|
||||
int format; /* 0, 8, 16 or 32 */
|
||||
unsigned freeData:1; /* whether the data should be released */
|
||||
} W_Data;
|
||||
|
||||
@@ -54,6 +56,8 @@ WMCreateDataWithCapacity(unsigned capacity) /*FOLD00*/
|
||||
aData->length = 0;
|
||||
aData->retainCount = 1;
|
||||
aData->freeData = 1;
|
||||
aData->format = 0;
|
||||
aData->destructor = NULL;
|
||||
|
||||
return aData;
|
||||
}
|
||||
@@ -99,6 +103,28 @@ WMCreateDataWithBytesNoCopy(void *bytes, unsigned length) /*FOLD00*/
|
||||
aData->bytes = bytes;
|
||||
aData->retainCount = 1;
|
||||
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;
|
||||
}
|
||||
@@ -107,10 +133,16 @@ WMCreateDataWithBytesNoCopy(void *bytes, unsigned length) /*FOLD00*/
|
||||
WMData*
|
||||
WMCreateDataWithData(WMData *aData) /*FOLD00*/
|
||||
{
|
||||
if (aData->length > 0)
|
||||
return WMCreateDataWithBytes(aData->bytes, aData->length);
|
||||
else
|
||||
return WMCreateDataWithCapacity(0);
|
||||
WMData *newData;
|
||||
if (aData->length > 0) {
|
||||
newData = WMCreateDataWithBytes(aData->bytes, aData->length);
|
||||
} else {
|
||||
newData = WMCreateDataWithCapacity(0);
|
||||
}
|
||||
newData->destructor = aData->destructor;
|
||||
newData->format = aData->format;
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,8 +160,12 @@ WMReleaseData(WMData *aData) /*FOLD00*/
|
||||
aData->retainCount--;
|
||||
if (aData->retainCount > 0)
|
||||
return;
|
||||
if (aData->bytes && aData->freeData)
|
||||
if (aData->bytes && aData->freeData) {
|
||||
if (aData->destructor != NULL)
|
||||
aData->destructor(aData->bytes);
|
||||
else
|
||||
wfree(aData->bytes);
|
||||
}
|
||||
wfree(aData);
|
||||
}
|
||||
|
||||
@@ -166,6 +202,13 @@ WMSetDataLength(WMData *aData, unsigned length) /*FOLD00*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetDataFormat(WMData *aData, unsigned format)
|
||||
{
|
||||
aData->format = format;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMIncreaseDataLengthBy(WMData *aData, unsigned extraLength) /*FOLD00*/
|
||||
{
|
||||
@@ -191,6 +234,13 @@ WMGetDataBytes(WMData *aData, void *buffer) /*FOLD00*/
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
WMGetDataFormat(WMData *aData)
|
||||
{
|
||||
return aData->format;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMGetDataBytesWithLength(WMData *aData, void *buffer, unsigned length) /*FOLD00*/
|
||||
{
|
||||
@@ -217,13 +267,18 @@ WMData*
|
||||
WMGetSubdataWithRange(WMData *aData, WMRange aRange) /*FOLD00*/
|
||||
{
|
||||
void *buffer;
|
||||
WMData *newData;
|
||||
|
||||
/* return an empty subdata instead if aRange.count is 0 ? */
|
||||
wassertrv(aRange.count > 0, NULL);
|
||||
|
||||
buffer = wmalloc(aRange.count);
|
||||
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 */
|
||||
void
|
||||
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
|
||||
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
|
||||
WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
||||
{
|
||||
@@ -110,6 +134,27 @@ WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
||||
*view->dragDestinationProcs = *procs;
|
||||
|
||||
/*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 && \
|
||||
view->dragDestinationProcs!=NULL)
|
||||
|
||||
|
||||
static Atom operationToAction(WMScreen *scr, WMDragOperationType operation);
|
||||
static WMDragOperationType actionToOperation(WMScreen *scr, Atom action);
|
||||
|
||||
static Bool _XErrorOccured = False;
|
||||
|
||||
|
||||
@@ -317,13 +320,7 @@ sendClientMessage(Display *dpy, Window win, Atom message,
|
||||
static unsigned
|
||||
notifyPosition(WMScreen *scr, WMDraggingInfo *info)
|
||||
{
|
||||
unsigned operation;
|
||||
|
||||
switch (info->sourceOperation) {
|
||||
default:
|
||||
operation = None;
|
||||
break;
|
||||
}
|
||||
Atom action = operationToAction(scr, info->sourceOperation);
|
||||
|
||||
sendClientMessage(scr->display, info->destinationWindow,
|
||||
scr->xdndPositionAtom,
|
||||
@@ -331,7 +328,7 @@ notifyPosition(WMScreen *scr, WMDraggingInfo *info)
|
||||
0, /* reserved */
|
||||
info->location.x<<16|info->location.y,
|
||||
info->timestamp,
|
||||
operation/* operation */);
|
||||
action/* operation */);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -418,34 +415,6 @@ updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info,
|
||||
info->location.y,
|
||||
iconWindow);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
timeoutCallback(void *data)
|
||||
{
|
||||
wwarning("drag & drop timed out while waiting for response from 0x%x\n",
|
||||
(unsigned)data);
|
||||
_XErrorOccured = 1;
|
||||
_XErrorOccured = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -594,9 +584,15 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
WMDraggingInfo dragInfo;
|
||||
WMDraggingInfo oldDragInfo;
|
||||
WMHandlerID timer = NULL;
|
||||
WMData *draggedData = NULL;
|
||||
static WMSelectionProcs handler = {
|
||||
convertSelection,
|
||||
selectionLost,
|
||||
selectionDone
|
||||
};
|
||||
|
||||
|
||||
wassertr(scr->dragSourceView == NULL);
|
||||
|
||||
wassertr(view->dragSourceProcs != NULL);
|
||||
|
||||
|
||||
@@ -614,9 +610,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
|
||||
|
||||
/* init dragging info */
|
||||
|
||||
scr->dragSourceView = view;
|
||||
|
||||
memset(&dragInfo, 0, sizeof(WMDraggingInfo));
|
||||
memset(&oldDragInfo, 0, sizeof(WMDraggingInfo));
|
||||
dragInfo.image = image;
|
||||
dragInfo.sourceView = view;
|
||||
dragInfo.sourceWindow = W_VIEW_DRAWABLE(W_TopLevelOfView(view));
|
||||
|
||||
dragInfo.destinationWindow = dragInfo.sourceWindow;
|
||||
@@ -636,8 +636,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
|
||||
_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) {
|
||||
view->dragSourceProcs->beganDragImage(view, image, atLocation);
|
||||
@@ -665,9 +670,8 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
||||
dragInfo.imageLocation.y);
|
||||
|
||||
if (state != 2) {
|
||||
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
|
||||
}
|
||||
|
||||
protectBlock(False);
|
||||
|
||||
/* XXXif entered a different destination, check the operation */
|
||||
@@ -675,6 +679,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
switch (state) {
|
||||
case 1:
|
||||
if (oldDragInfo.destinationWindow != None
|
||||
&& oldDragInfo.destinationWindow != scr->rootWin
|
||||
&& (dragInfo.destinationWindow == None
|
||||
|| dragInfo.destinationWindow == scr->rootWin)) {
|
||||
/* left the droppable window */
|
||||
@@ -684,7 +689,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (dragInfo.destinationWindow != None) {
|
||||
if (dragInfo.destinationWindow != None
|
||||
&& dragInfo.destinationWindow != scr->rootWin) {
|
||||
|
||||
state = 1;
|
||||
action = -1;
|
||||
}
|
||||
@@ -693,6 +700,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
case 3:
|
||||
case 4:
|
||||
if (oldDragInfo.destinationWindow != None
|
||||
&& oldDragInfo.destinationWindow != scr->rootWin
|
||||
&& (dragInfo.destinationWindow == None
|
||||
|| dragInfo.destinationWindow == scr->rootWin)) {
|
||||
/* left the droppable window */
|
||||
@@ -717,8 +725,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
|
||||
dragInfo.imageLocation.y);
|
||||
|
||||
processMotion(scr, &dragInfo, &oldDragInfo, &rect,
|
||||
action);
|
||||
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
|
||||
|
||||
dragInfo.timestamp = ev.xbutton.time;
|
||||
|
||||
protectBlock(False);
|
||||
|
||||
@@ -741,20 +750,13 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SelectionRequest:
|
||||
|
||||
draggedData = NULL;
|
||||
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
if ((state == 1 || state == 3 || state == 4 || state == 5)
|
||||
&& 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) {
|
||||
puts("got accept msg");
|
||||
SPIT("got accept msg");
|
||||
/* will accept drop */
|
||||
switch (state) {
|
||||
case 1:
|
||||
@@ -770,13 +772,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
state = 6;
|
||||
break;
|
||||
}
|
||||
if (ev.xclient.data.l[4] == None) {
|
||||
action = 0;
|
||||
action = actionToOperation(scr, ev.xclient.data.l[4]);
|
||||
} else {
|
||||
action = ev.xclient.data.l[4];/*XXX*/
|
||||
}
|
||||
} else {
|
||||
puts("got reject msg");
|
||||
SPIT("got reject msg");
|
||||
switch (state) {
|
||||
case 1:
|
||||
case 3:
|
||||
@@ -825,7 +823,6 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
}
|
||||
|
||||
if (ostate != state) {
|
||||
printf("state changed to %i\n", state);
|
||||
if (state == 3) {
|
||||
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
|
||||
} else if (ostate == 3) {
|
||||
@@ -838,6 +835,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
if (timer) {
|
||||
WMDeleteTimerHandler(timer);
|
||||
timer = NULL;
|
||||
} else if (_XErrorOccured) {
|
||||
/* got a timeout, send leave */
|
||||
notifyDragLeave(scr, &dragInfo);
|
||||
}
|
||||
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
@@ -859,22 +859,17 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
|
||||
|
||||
|
||||
SPIT("dropped");
|
||||
/* wait for Finished message and SelectionRequest if not a local drop */
|
||||
|
||||
|
||||
|
||||
XDestroyWindow(dpy, icon);
|
||||
if (view->dragSourceProcs->endedDragImage != NULL) {
|
||||
view->dragSourceProcs->endedDragImage(view, image,
|
||||
dragInfo.imageLocation,
|
||||
True);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cancelled:
|
||||
if (draggedData) {
|
||||
WMReleaseData(draggedData);
|
||||
}
|
||||
scr->dragSourceView = NULL;
|
||||
|
||||
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
|
||||
event->xmotion.time);
|
||||
|
||||
if (slideBack) {
|
||||
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
|
||||
W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
||||
{
|
||||
#if 0
|
||||
WMScreen *scr = W_VIEW_SCREEN(toplevel);
|
||||
WMView *oldView = NULL, *newView = NULL;
|
||||
WMView *oldView = NULL;
|
||||
WMView *newView = NULL;
|
||||
unsigned operation = 0;
|
||||
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) {
|
||||
Window foo, bar;
|
||||
int bla;
|
||||
unsigned ble;
|
||||
puts("entered");
|
||||
|
||||
if (scr->dragInfo.sourceWindow != None) {
|
||||
puts("received Enter event in bad order");
|
||||
@@ -956,14 +1076,14 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
||||
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",
|
||||
(event->data.l[0] >> 24));
|
||||
(event->data.l[1] >> 24));
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* XXX */
|
||||
@@ -982,29 +1102,6 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
||||
scr->dragInfo.destinationWindow,
|
||||
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
|
||||
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
||||
|
||||
@@ -1013,71 +1110,138 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
|
||||
|
||||
if (scr->dragInfo.protocolVersion >= 1) {
|
||||
scr->dragInfo.timestamp = event->data.l[3];
|
||||
scr->dragInfo.sourceOperation = event->data.l[4];
|
||||
scr->dragInfo.sourceOperation = actionToOperation(scr,
|
||||
event->data.l[4]);
|
||||
|
||||
} else {
|
||||
scr->dragInfo.timestamp = CurrentTime;
|
||||
scr->dragInfo.sourceOperation = 0; /*XXX*/
|
||||
scr->dragInfo.sourceOperation = WDOperationCopy;
|
||||
}
|
||||
|
||||
translateCoordinates(scr, scr->dragInfo.destinationWindow,
|
||||
scr->dragInfo.location.x,
|
||||
scr->dragInfo.location.y, &x, &y);
|
||||
|
||||
view = findViewInToplevel(scr->display,
|
||||
newView = findViewInToplevel(scr->display,
|
||||
scr->dragInfo.destinationWindow,
|
||||
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
|
||||
&& 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
|
||||
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
|
||||
|
||||
/* drop */
|
||||
what = WDrop;
|
||||
|
||||
|
||||
puts("drop");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,63 +10,64 @@
|
||||
|
||||
|
||||
typedef struct SelectionHandler {
|
||||
WMWidget *widget;
|
||||
WMView *view;
|
||||
Atom selection;
|
||||
Time timestamp;
|
||||
WMConvertSelectionProc *convProc;
|
||||
WMLoseSelectionProc *loseProc;
|
||||
WMSelectionDoneProc *doneProc;
|
||||
WMSelectionProcs procs;
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
unsigned delete_pending:1;
|
||||
unsigned done_pending:1;
|
||||
} flags;
|
||||
|
||||
struct SelectionHandler *next;
|
||||
} 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
|
||||
WMDeleteSelectionHandler(WMWidget *widget, Atom selection)
|
||||
WMDeleteSelectionHandler(WMView *view, Atom selection, Time timestamp)
|
||||
{
|
||||
SelectionHandler *handler, *tmp;
|
||||
Display *dpy = WMWidgetScreen(widget)->display;
|
||||
Window win = WMWidgetXID(widget);
|
||||
Time timestamp;
|
||||
SelectionHandler *handler;
|
||||
Display *dpy = W_VIEW_SCREEN(view)->display;
|
||||
Window win = W_VIEW_DRAWABLE(view);
|
||||
WMBagIterator iter;
|
||||
|
||||
if (!selHandlers)
|
||||
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) {
|
||||
tmp->flags.delete_pending = 1;
|
||||
if (handler->flags.done_pending) {
|
||||
handler->flags.delete_pending = 1;
|
||||
return;
|
||||
}
|
||||
selHandlers = tmp->next;
|
||||
timestamp = tmp->timestamp;
|
||||
wfree(tmp);
|
||||
} 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;
|
||||
WMRemoveFromBag(selHandlers, handler);
|
||||
wfree(handler);
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
XGrabServer(dpy);
|
||||
@@ -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 int
|
||||
@@ -88,8 +117,14 @@ errorHandler(XErrorEvent *error)
|
||||
|
||||
static Bool
|
||||
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));
|
||||
*/
|
||||
@@ -97,12 +132,13 @@ writeSelection(Display *dpy, Window requestor, Atom property, Atom type,
|
||||
|
||||
#ifndef __sgi
|
||||
if (!XChangeProperty(dpy, requestor, property, type, format,
|
||||
PropModeReplace, value, length))
|
||||
PropModeReplace, WMDataBytes(data),
|
||||
WMGetDataLength(data)))
|
||||
return False;
|
||||
#else
|
||||
/* in sgi seems this seems to return void */
|
||||
XChangeProperty(dpy, requestor, property, type, format,
|
||||
PropModeReplace, value, length);
|
||||
PropModeReplace, WMDataBytes(data), WMGetDataLength(data));
|
||||
#endif
|
||||
|
||||
XFlush(dpy);
|
||||
@@ -134,50 +170,87 @@ notifySelection(XEvent *event, Atom prop)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_HandleSelectionEvent(XEvent *event)
|
||||
|
||||
static void
|
||||
deleteHandlers(WMBagIterator iter)
|
||||
{
|
||||
SelectionHandler *handler;
|
||||
|
||||
handler = selHandlers;
|
||||
if (iter == NULL)
|
||||
handler = WMBagFirst(selHandlers, &iter);
|
||||
else
|
||||
handler = WMBagNext(selHandlers, &iter);
|
||||
|
||||
while (handler) {
|
||||
if (WMWidgetXID(handler->widget)==event->xany.window
|
||||
/* && handler->selection == event->selection*/) {
|
||||
if (handler == NULL)
|
||||
return;
|
||||
|
||||
deleteHandlers(iter);
|
||||
|
||||
if (handler->flags.delete_pending) {
|
||||
WMDeleteSelectionHandler(handler->view, handler->selection,
|
||||
handler->timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleRequestEvent(XEvent *event)
|
||||
{
|
||||
SelectionHandler *handler;
|
||||
WMBagIterator iter;
|
||||
Bool handledRequest = False;
|
||||
|
||||
WM_ITERATE_BAG(selHandlers, handler, iter) {
|
||||
|
||||
switch (event->type) {
|
||||
case SelectionClear:
|
||||
if (handler->loseProc)
|
||||
(*handler->loseProc)(handler->widget, handler->selection);
|
||||
if (W_VIEW_DRAWABLE(handler->view)
|
||||
!= event->xselectionclear.window) {
|
||||
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 (handler->convProc) {
|
||||
if (W_VIEW_DRAWABLE(handler->view)
|
||||
!= event->xselectionrequest.owner) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler->procs.convertSelection != NULL
|
||||
&& handler->selection == event->xselectionrequest.selection) {
|
||||
Atom atom;
|
||||
void *data;
|
||||
unsigned length;
|
||||
int format;
|
||||
WMData *data;
|
||||
Atom prop;
|
||||
|
||||
/* they're requesting for something old */
|
||||
/* they're requesting for something old.. maybe another handler
|
||||
* can handle it */
|
||||
if (event->xselectionrequest.time < handler->timestamp
|
||||
&& event->xselectionrequest.time != CurrentTime) {
|
||||
|
||||
notifySelection(event, None);
|
||||
break;
|
||||
}
|
||||
|
||||
handler->flags.done_pending = 1;
|
||||
|
||||
if (!(*handler->convProc)(handler->widget,
|
||||
data = handler->procs.convertSelection(handler->view,
|
||||
handler->selection,
|
||||
event->xselectionrequest.target,
|
||||
&atom, &data, &length, &format)) {
|
||||
|
||||
notifySelection(event, None);
|
||||
handler->data,
|
||||
&atom);
|
||||
if (data == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
handledRequest = True;
|
||||
|
||||
|
||||
prop = event->xselectionrequest.property;
|
||||
/* obsolete clients that don't set the property field */
|
||||
@@ -186,40 +259,133 @@ W_HandleSelectionEvent(XEvent *event)
|
||||
|
||||
if (!writeSelection(event->xselectionrequest.display,
|
||||
event->xselectionrequest.requestor,
|
||||
prop, atom, data, length, format)) {
|
||||
|
||||
wfree(data);
|
||||
prop, atom, data)) {
|
||||
WMReleaseData(data);
|
||||
notifySelection(event, None);
|
||||
break;
|
||||
}
|
||||
wfree(data);
|
||||
WMReleaseData(data);
|
||||
|
||||
notifySelection(event, prop);
|
||||
|
||||
if (handler->doneProc) {
|
||||
(*handler->doneProc)(handler->widget,
|
||||
if (handler->procs.selectionDone != NULL) {
|
||||
handler->procs.selectionDone(handler->view,
|
||||
handler->selection,
|
||||
event->xselectionrequest.target);
|
||||
event->xselectionrequest.target,
|
||||
handler->data);
|
||||
}
|
||||
|
||||
handler->flags.done_pending = 0;
|
||||
|
||||
/* in case the handler was deleted from some
|
||||
* callback */
|
||||
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) {
|
||||
WMDeleteSelectionHandler(handler->widget,
|
||||
handler->selection);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectionNotify:
|
||||
|
||||
break;
|
||||
WMDeleteSelectionCallback(handler->view, handler->selection,
|
||||
handler->timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
handler = handler->next;
|
||||
|
||||
|
||||
|
||||
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->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
|
||||
WMCreateSelectionHandler(WMWidget *w, Atom selection, Time timestamp,
|
||||
WMConvertSelectionProc *convProc,
|
||||
WMLoseSelectionProc *loseProc,
|
||||
WMSelectionDoneProc *doneProc)
|
||||
WMCreateSelectionHandler(WMView *view, Atom selection, Time timestamp,
|
||||
WMSelectionProcs *procs, void *cdata)
|
||||
{
|
||||
SelectionHandler *handler, *tmp;
|
||||
Display *dpy = WMWidgetScreen(w)->display;
|
||||
SelectionHandler *handler;
|
||||
Display *dpy = W_VIEW_SCREEN(view)->display;
|
||||
|
||||
XSetSelectionOwner(dpy, selection, WMWidgetXID(w), timestamp);
|
||||
if (XGetSelectionOwner(dpy, selection) != WMWidgetXID(w))
|
||||
XSetSelectionOwner(dpy, selection, W_VIEW_DRAWABLE(view), timestamp);
|
||||
if (XGetSelectionOwner(dpy, selection) != W_VIEW_DRAWABLE(view))
|
||||
return False;
|
||||
|
||||
handler = malloc(sizeof(SelectionHandler));
|
||||
if (!handler)
|
||||
if (handler == NULL)
|
||||
return False;
|
||||
|
||||
handler->widget = w;
|
||||
handler->view = view;
|
||||
handler->selection = selection;
|
||||
handler->timestamp = timestamp;
|
||||
handler->convProc = convProc;
|
||||
handler->loseProc = loseProc;
|
||||
handler->doneProc = doneProc;
|
||||
handler->procs = *procs;
|
||||
handler->data = cdata;
|
||||
memset(&handler->flags, 0, sizeof(handler->flags));
|
||||
|
||||
if (!selHandlers) {
|
||||
/* first in the queue */
|
||||
handler->next = selHandlers;
|
||||
selHandlers = handler;
|
||||
} else {
|
||||
tmp = selHandlers;
|
||||
while (tmp->next) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
handler->next = tmp->next;
|
||||
tmp->next = handler;
|
||||
if (selHandlers == NULL) {
|
||||
selHandlers = WMCreateTreeBag();
|
||||
}
|
||||
|
||||
WMPutInBag(selHandlers, handler);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
timeoutHandler(void *data)
|
||||
Bool
|
||||
WMRequestSelection(WMView *view, Atom selection, Atom target, Time timestamp,
|
||||
WMSelectionCallback *callback, void *cdata)
|
||||
{
|
||||
*(int*)data = 1;
|
||||
}
|
||||
SelectionCallback *handler;
|
||||
|
||||
|
||||
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)
|
||||
if (XGetSelectionOwner(W_VIEW_SCREEN(view)->display, selection) == None)
|
||||
return False;
|
||||
|
||||
handler = selHandlers;
|
||||
handler = wmalloc(sizeof(SelectionCallback));
|
||||
|
||||
while (handler) {
|
||||
if (WMWidgetXID(handler->widget) == owner
|
||||
/* && handler->selection == event->selection*/) {
|
||||
break;
|
||||
}
|
||||
handler = handler->next;
|
||||
handler->view = view;
|
||||
handler->selection = selection;
|
||||
handler->target = target;
|
||||
handler->timestamp = timestamp;
|
||||
handler->callback = callback;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,11 +53,35 @@ W_ViewDelegate _ColorWellViewDelegate = {
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
static WMDragSourceProcs dragProcs = {
|
||||
static unsigned draggingSourceOperation(WMView *self, Bool local);
|
||||
|
||||
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_HEIGHT 30
|
||||
@@ -169,6 +193,15 @@ WMCreateColorWell(WMWidget *parent)
|
||||
WMAddNotificationObserver(colorChangedObserver, cPtr,
|
||||
WMColorPanelColorChangedNotification, NULL);
|
||||
|
||||
WMSetViewDragSourceProcs(cPtr->view, &_DragSourceProcs);
|
||||
WMSetViewDragDestinationProcs(cPtr->view, &_DragDestinationProcs);
|
||||
|
||||
{
|
||||
char *types[2] = {"application/X-color", NULL};
|
||||
|
||||
WMRegisterViewForDraggedTypes(cPtr->view, types);
|
||||
}
|
||||
|
||||
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*
|
||||
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
|
||||
handleDragEvents(XEvent *event, void *data)
|
||||
{
|
||||
@@ -526,17 +365,17 @@ handleDragEvents(XEvent *event, void *data)
|
||||
|| abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
|
||||
WMSize offs;
|
||||
WMPixmap *pixmap;
|
||||
char *types[2] = {"application/X-color", NULL};
|
||||
|
||||
offs.width = 2;
|
||||
offs.height = 2;
|
||||
pixmap = makeDragPixmap(cPtr);
|
||||
|
||||
/*
|
||||
WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
|
||||
WMDragImageFromView(cPtr->view, pixmap, types,
|
||||
wmkpoint(event->xmotion.x_root,
|
||||
event->xmotion.y_root),
|
||||
offs, event, True);
|
||||
* */
|
||||
|
||||
dragColor(cPtr, event, pixmap);
|
||||
|
||||
WMReleasePixmap(pixmap);
|
||||
}
|
||||
@@ -585,3 +424,53 @@ destroyColorWell(ColorWell *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",
|
||||
"XdndFinished",
|
||||
"XdndTypeList",
|
||||
"XdndActionCopy",
|
||||
"XdndActionMove",
|
||||
"XdndActionLink",
|
||||
"XdndActionAsk",
|
||||
"XdndActionPrivate",
|
||||
"XdndStatus",
|
||||
"WM_STATE"
|
||||
};
|
||||
Atom atoms[sizeof(atomNames)/sizeof(char*)];
|
||||
int i = 0;
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
@@ -767,25 +773,32 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
||||
}
|
||||
#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->xdndSelectionAtom = atoms[5];
|
||||
scrPtr->xdndEnterAtom = atoms[6];
|
||||
scrPtr->xdndLeaveAtom = atoms[7];
|
||||
scrPtr->xdndPositionAtom = atoms[8];
|
||||
scrPtr->xdndDropAtom = atoms[9];
|
||||
scrPtr->xdndFinishedAtom = atoms[10];
|
||||
scrPtr->xdndTypeListAtom = atoms[11];
|
||||
scrPtr->xdndStatusAtom = atoms[12];
|
||||
scrPtr->xdndAwareAtom = atoms[i++];
|
||||
scrPtr->xdndSelectionAtom = atoms[i++];
|
||||
scrPtr->xdndEnterAtom = atoms[i++];
|
||||
scrPtr->xdndLeaveAtom = atoms[i++];
|
||||
scrPtr->xdndPositionAtom = atoms[i++];
|
||||
scrPtr->xdndDropAtom = atoms[i++];
|
||||
scrPtr->xdndFinishedAtom = atoms[i++];
|
||||
scrPtr->xdndTypeListAtom = atoms[i++];
|
||||
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);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct W_TabView {
|
||||
struct {
|
||||
WMReliefType relief:4;
|
||||
WMTitlePosition titlePosition:4;
|
||||
WMTabViewTypes type:2;
|
||||
WMTabViewType type:2;
|
||||
|
||||
unsigned tabbed:1;
|
||||
unsigned dontFitAll:1;
|
||||
|
||||
@@ -65,6 +65,11 @@ typedef struct W_TextField {
|
||||
|
||||
unsigned int pointerGrabbed:1;
|
||||
|
||||
unsigned int ownsSelection:1;
|
||||
|
||||
unsigned int waitingSelection:1; /* requested selection, but
|
||||
* didnt get yet */
|
||||
|
||||
/**/
|
||||
unsigned int notIllegalMovement:1;
|
||||
} 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, \
|
||||
&((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
|
||||
|
||||
@@ -210,73 +229,73 @@ decrToFit(TextField *tPtr)
|
||||
#undef TEXT_WIDTH
|
||||
#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;
|
||||
Display *dpy = tPtr->view->screen->display;
|
||||
Atom _TARGETS;
|
||||
char *text;
|
||||
text = XGetAtomName(tPtr->view->screen->display,target);
|
||||
XFree(text);
|
||||
text = XGetAtomName(tPtr->view->screen->display,selection);
|
||||
XFree(text);
|
||||
Atom TEXT = XInternAtom(dpy, "TEXT", False);
|
||||
Atom COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
||||
WMData *data;
|
||||
|
||||
*format = 32;
|
||||
*length = 0;
|
||||
*value = NULL;
|
||||
count = tPtr->selection.count < 0
|
||||
? tPtr->selection.position + tPtr->selection.count
|
||||
: tPtr->selection.position;
|
||||
|
||||
if (target == XA_STRING ||
|
||||
target == XInternAtom(dpy, "TEXT", False) ||
|
||||
target == XInternAtom(dpy, "COMPOUND_TEXT", False)) {
|
||||
*value = wstrdup(&(tPtr->text[count]));
|
||||
*length = abs(tPtr->selection.count);
|
||||
*format = 8;
|
||||
if (target == XA_STRING || target == TEXT || target == COMPOUND_TEXT) {
|
||||
|
||||
data = WMCreateDataWithBytes(&(tPtr->text[count]),
|
||||
abs(tPtr->selection.count));
|
||||
WMSetDataFormat(data, 8);
|
||||
*type = target;
|
||||
return True;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
_TARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||
if (target == _TARGETS) {
|
||||
int *ptr;
|
||||
Atom *ptr;
|
||||
|
||||
*length = 4;
|
||||
ptr = *value = (char *) wmalloc(4 * sizeof(Atom));
|
||||
ptr = wmalloc(4 * sizeof(Atom));
|
||||
ptr[0] = _TARGETS;
|
||||
ptr[1] = XA_STRING;
|
||||
ptr[2] = XInternAtom(dpy, "TEXT", False);
|
||||
ptr[3] = XInternAtom(dpy, "COMPOUND_TEXT", False);
|
||||
ptr[2] = TEXT;
|
||||
ptr[3] = COMPOUND_TEXT;
|
||||
|
||||
data = WMCreateDataWithBytes(ptr, 4*4);
|
||||
WMSetDataFormat(data, 32);
|
||||
|
||||
*type = target;
|
||||
return True;
|
||||
return data;
|
||||
}
|
||||
/*
|
||||
*target = XA_PRIMARY;
|
||||
*/
|
||||
return False;
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_notification(void *observerData, WMNotification *notification)
|
||||
{
|
||||
WMTextField *to = (WMTextField*)observerData;
|
||||
WMTextField *tw = (WMTextField*)WMGetNotificationClientData(notification);
|
||||
if (to != tw) lostHandler(to, 0);
|
||||
if (to != tw) lostHandler(to->view, XA_PRIMARY, NULL);
|
||||
}
|
||||
|
||||
WMTextField*
|
||||
@@ -327,8 +346,6 @@ WMCreateTextField(WMWidget *parent)
|
||||
|ButtonReleaseMask|ButtonPressMask|KeyPressMask|Button1MotionMask,
|
||||
handleTextFieldActionEvents, tPtr);
|
||||
|
||||
WMCreateSelectionHandler(tPtr, XA_PRIMARY, CurrentTime, requestHandler,
|
||||
lostHandler, NULL);
|
||||
WMAddNotificationObserver(_notification, tPtr, "_lostOwnership", tPtr);
|
||||
|
||||
|
||||
@@ -1185,20 +1202,17 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
|
||||
|
||||
if (!cancelSelection) {
|
||||
if (tPtr->selection.count != tPtr->cursorPosition - tPtr->selection.position) {
|
||||
WMNotification *notif;
|
||||
|
||||
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
||||
|
||||
XSetSelectionOwner(tPtr->view->screen->display,
|
||||
XA_PRIMARY, tPtr->view->window,
|
||||
event->xbutton.time);
|
||||
notif = WMCreateNotification("_lostOwnership", NULL, tPtr);
|
||||
WMPostNotification(notif);
|
||||
WMReleaseNotification(notif);
|
||||
WMPostNotificationName("_lostOwnership", NULL, tPtr);
|
||||
|
||||
refresh = 1;
|
||||
}
|
||||
} else {
|
||||
|
||||
lostHandler(tPtr->view, XA_PRIMARY, NULL);
|
||||
|
||||
if (tPtr->selection.count) {
|
||||
tPtr->selection.count = 0;
|
||||
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
|
||||
handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
TextField *tPtr = (TextField*)data;
|
||||
static int move = 0;
|
||||
static Time lastButtonReleasedEvent = 0;
|
||||
Display *dpy = event->xany.display;
|
||||
|
||||
CHECK_CLASS(data, WC_TextField);
|
||||
|
||||
switch (event->type) {
|
||||
case KeyPress:
|
||||
if (tPtr->flags.waitingSelection) {
|
||||
return;
|
||||
}
|
||||
if (tPtr->flags.enabled && tPtr->flags.focused) {
|
||||
handleTextFieldKeyPress(tPtr, event);
|
||||
XGrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen),
|
||||
W_VIEW(tPtr)->window, False,
|
||||
XGrabPointer(dpy, W_VIEW(tPtr)->window, False,
|
||||
PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
|
||||
GrabModeAsync, GrabModeAsync, None,
|
||||
W_VIEW(tPtr)->screen->invisibleCursor,
|
||||
@@ -1291,7 +1340,10 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
|
||||
if (tPtr->flags.pointerGrabbed) {
|
||||
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)) {
|
||||
@@ -1309,40 +1361,35 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
tPtr->viewPosition--;
|
||||
}
|
||||
|
||||
/*if (!tPtr->selection.count) {
|
||||
tPtr->selection.position = tPtr->cursorPosition;
|
||||
}*/
|
||||
|
||||
tPtr->cursorPosition =
|
||||
pointToCursorPosition(tPtr, event->xmotion.x);
|
||||
|
||||
tPtr->selection.count = tPtr->cursorPosition - tPtr->selection.position;
|
||||
/*printf("(%d,%d)\n", tPtr->selection.position, tPtr->selection.count);*/
|
||||
|
||||
/*
|
||||
printf("notify %d %d\n",event->xmotion.x,tPtr->usableWidth);
|
||||
*/
|
||||
if (tPtr->selection.count != 0) {
|
||||
if (!tPtr->flags.ownsSelection) {
|
||||
WMCreateSelectionHandler(tPtr->view,
|
||||
XA_PRIMARY,
|
||||
event->xbutton.time,
|
||||
&selectionHandler, NULL);
|
||||
tPtr->flags.ownsSelection = 1;
|
||||
}
|
||||
}
|
||||
|
||||
paintCursor(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;
|
||||
|
||||
case ButtonPress:
|
||||
if (tPtr->flags.pointerGrabbed) {
|
||||
tPtr->flags.pointerGrabbed = 0;
|
||||
XUngrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen), CurrentTime);
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tPtr->flags.waitingSelection) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1353,6 +1400,7 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
textWidth = WMWidthOfString(tPtr->font, tPtr->text, tPtr->textLen);
|
||||
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
||||
WMSetFocusToWidget(tPtr);
|
||||
|
||||
} else if (tPtr->flags.focused) {
|
||||
tPtr->selection.position = tPtr->cursorPosition;
|
||||
tPtr->selection.count = 0;
|
||||
@@ -1361,18 +1409,9 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x - tPtr->usableWidth
|
||||
+ textWidth);
|
||||
}
|
||||
else tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
} else tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
/*
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
tPtr->cursorPosition += tPtr->usableWidth - textWidth;
|
||||
}
|
||||
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
*/
|
||||
paintTextField(tPtr);
|
||||
break;
|
||||
|
||||
@@ -1382,7 +1421,8 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
paintTextField(tPtr);
|
||||
} else if (tPtr->flags.focused) {
|
||||
} else if (tPtr->flags.focused
|
||||
&& event->xbutton.button == Button1) {
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
tPtr->selection.position = tPtr->cursorPosition;
|
||||
@@ -1391,24 +1431,26 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
}
|
||||
if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
|
||||
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) {
|
||||
text = W_GetTextSelection(tPtr->view->screen,
|
||||
tPtr->view->screen->clipboardAtom);
|
||||
}
|
||||
if (!text) {
|
||||
text = W_GetTextSelection(tPtr->view->screen,
|
||||
XA_CUT_BUFFER0);
|
||||
}
|
||||
if (text) {
|
||||
text[n] = 0;
|
||||
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
||||
XFree(text);
|
||||
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
|
||||
(void*)WMInsertTextEvent);
|
||||
}
|
||||
} else {
|
||||
tPtr->flags.waitingSelection = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1416,7 +1458,23 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
case ButtonRelease:
|
||||
if (tPtr->flags.pointerGrabbed) {
|
||||
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;
|
||||
@@ -1426,14 +1484,16 @@ handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
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);
|
||||
|
||||
if (!tPtr->flags.ownsSelection) {
|
||||
WMCreateSelectionHandler(tPtr->view,
|
||||
XA_PRIMARY,
|
||||
event->xbutton.time,
|
||||
&selectionHandler, NULL);
|
||||
tPtr->flags.ownsSelection = 1;
|
||||
}
|
||||
|
||||
WMPostNotificationName("_lostOwnership", NULL, tPtr);
|
||||
}
|
||||
lastButtonReleasedEvent = event->xbutton.time;
|
||||
|
||||
@@ -1451,7 +1511,7 @@ destroyTextField(TextField *tPtr)
|
||||
#endif
|
||||
|
||||
WMReleaseFont(tPtr->font);
|
||||
WMDeleteSelectionHandler(tPtr, XA_PRIMARY);
|
||||
WMDeleteSelectionHandler(tPtr->view, XA_PRIMARY, CurrentTime);
|
||||
WMRemoveNotificationObserver(tPtr);
|
||||
|
||||
if (tPtr->text)
|
||||
|
||||
@@ -411,6 +411,10 @@ destroyView(W_View *view)
|
||||
|
||||
if (view->dragDestinationProcs)
|
||||
wfree(view->dragDestinationProcs);
|
||||
|
||||
if (scr->dragInfo.destView == view) {
|
||||
scr->dragInfo.destView = NULL;
|
||||
}
|
||||
#endif
|
||||
wfree(view);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user