1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-23 22:52:34 +01:00

drag and drop!

selection code rewrite!
textfield with new selection code!
etc etc
This commit is contained in:
kojima
2000-04-03 03:10:20 +00:00
parent a5f7e65111
commit 60a247f271
12 changed files with 1184 additions and 888 deletions

View File

@@ -64,6 +64,11 @@ typedef struct W_TextField {
unsigned int secure:1; /* password entry style */
unsigned int pointerGrabbed:1;
unsigned int ownsSelection:1;
unsigned int waitingSelection:1; /* requested selection, but
* didnt get yet */
/**/
unsigned int notIllegalMovement:1;
@@ -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,26 +1400,18 @@ 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;
}
if(textWidth < tPtr->usableWidth){
if(textWidth < tPtr->usableWidth) {
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,51 +1431,71 @@ 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 (!text) {
text = W_GetTextSelection(tPtr->view->screen,
tPtr->view->screen->clipboardAtom);
}
if (!text) {
text = W_GetTextSelection(tPtr->view->screen,
XA_CUT_BUFFER0);
}
if (text) {
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
XFree(text);
NOTIFY(tPtr, didChange, WMTextDidChangeNotification,
(void*)WMInsertTextEvent);
}
if (!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING,
event->xbutton.time,
pasteText, NULL)) {
text = XFetchBuffer(tPtr->view->screen->display, &n, 0);
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;
case ButtonRelease:
if (tPtr->flags.pointerGrabbed) {
tPtr->flags.pointerGrabbed = 0;
XUngrabPointer(WMScreenDisplay(W_VIEW(tPtr)->screen), CurrentTime);
}
case ButtonRelease:
if (tPtr->flags.pointerGrabbed) {
tPtr->flags.pointerGrabbed = 0;
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;
move = 0;
if (event->xbutton.time - lastButtonReleasedEvent
<= 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);
}
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;
}
lastButtonReleasedEvent = event->xbutton.time;
WMPostNotificationName("_lostOwnership", NULL, tPtr);
}
lastButtonReleasedEvent = event->xbutton.time;
break;
}
@@ -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)