From bb886be82ea8dc346a515978df12e723e40307d8 Mon Sep 17 00:00:00 2001 From: kojima Date: Thu, 18 Jan 2001 02:00:56 +0000 Subject: [PATCH] added responder chain alike stuff for relaying kbd events from widget to widget --- WINGs/Extras/wtableview.c | 6 + WINGs/Extras/wtableview.h | 2 + WINGs/WINGs.h | 6 +- WINGs/WINGsP.h | 6 +- WINGs/wevent.c | 34 +++++- WINGs/wpopupbutton.c | 4 - WINGs/wtext.c | 2 + WINGs/wtextfield.c | 298 +++++++++++++++++++++++++++------------------- WINGs/wview.c | 1 - 9 files changed, 227 insertions(+), 132 deletions(-) diff --git a/WINGs/Extras/wtableview.c b/WINGs/Extras/wtableview.c index 44dda4bf..9401b053 100644 --- a/WINGs/Extras/wtableview.c +++ b/WINGs/Extras/wtableview.c @@ -433,6 +433,12 @@ int WMGetTableViewClickedRow(WMTableView *table) } +WMArray *WMGetTableViewSelectedRows(WMTableView *table) +{ + return table->selectedRows; +} + + WMView *WMGetTableViewDocumentView(WMTableView *table) { return table->tableView; diff --git a/WINGs/Extras/wtableview.h b/WINGs/Extras/wtableview.h index 8d5daa03..49d46d29 100644 --- a/WINGs/Extras/wtableview.h +++ b/WINGs/Extras/wtableview.h @@ -77,6 +77,8 @@ void *WMGetTableViewClickedColumn(WMTableView *table); int WMGetTableViewClickedRow(WMTableView *table); +WMArray *WMGetTableViewSelectedRows(WMTableView *table); + WMView *WMGetTableViewDocumentView(WMTableView *table); void WMEditTableViewRow(WMTableView *table, int row); diff --git a/WINGs/WINGs.h b/WINGs/WINGs.h index 6d53256c..aa348116 100644 --- a/WINGs/WINGs.h +++ b/WINGs/WINGs.h @@ -7,7 +7,7 @@ #include #include -#define WINGS_H_VERSION 20000521 +#define WINGS_H_VERSION 20010117 #ifdef __cplusplus @@ -849,6 +849,10 @@ WMPoint WMGetViewScreenPosition(WMView *view); WMWidget *WMWidgetOfView(WMView *view); +void WMSetViewNextResponder(WMView *view, WMView *responder); + +void WMRelayToNextResponder(WMView *view, XEvent *event); + /* notifications */ extern char *WMViewSizeDidChangeNotification; diff --git a/WINGs/WINGsP.h b/WINGs/WINGsP.h index ce361063..f8c0da34 100644 --- a/WINGs/WINGsP.h +++ b/WINGs/WINGsP.h @@ -8,7 +8,7 @@ #include -#if WINGS_H_VERSION < 20000521 +#if WINGS_H_VERSION < 20010117 #error There_is_an_old_WINGs.h_file_somewhere_in_your_system._Please_remove_it. #endif @@ -321,6 +321,8 @@ typedef struct W_View { struct W_View *nextFocusChain; /* next/prev in focus chain */ struct W_View *prevFocusChain; + + struct W_View *nextResponder; /* next to receive keyboard events */ struct W_View *parent; /* parent WMView */ @@ -500,7 +502,7 @@ void W_SetFocusOfToplevel(W_View *toplevel, W_View *view); W_View *W_FocusedViewOfToplevel(W_View *view); void W_SetFocusOfTopLevel(W_View *toplevel, W_View *view); - + void W_ReleaseView(WMView *view); WMView *W_RetainView(WMView *view); diff --git a/WINGs/wevent.c b/WINGs/wevent.c index d596cb02..201f3e02 100644 --- a/WINGs/wevent.c +++ b/WINGs/wevent.c @@ -523,6 +523,36 @@ W_CallDestroyHandlers(W_View *view) } + +void +WMSetViewNextResponder(WMView *view, WMView *responder) +{ + /* set the widget to receive keyboard events that aren't handled + * by this widget */ + + view->nextResponder = responder; +} + + +void +WMRelayToNextResponder(WMView *view, XEvent *event) +{ + unsigned long mask = eventMasks[event->xany.type]; + + if (view->nextResponder) { + WMView *next = view->nextResponder; + W_EventHandler *hPtr; + WMBagIterator iter; + + WM_ITERATE_BAG(next->eventHandlers, hPtr, iter) { + if ((hPtr->eventMask & mask)) { + (*hPtr->proc)(event, hPtr->clientData); + } + } + } +} + + int WMHandleEvent(XEvent *event) { @@ -627,7 +657,7 @@ WMHandleEvent(XEvent *event) (*hPtr->proc)(event, hPtr->clientData); } } - +#if 0 /* pass the event to the top level window of the widget */ /* TODO: change this to a responder chain */ if (view->parent != NULL) { @@ -641,7 +671,7 @@ WMHandleEvent(XEvent *event) } } } - +#endif /* save button click info to track double-clicks */ if (view->screen->ignoreNextDoubleClick) { view->screen->ignoreNextDoubleClick = 0; diff --git a/WINGs/wpopupbutton.c b/WINGs/wpopupbutton.c index bafbb110..f380f8fa 100644 --- a/WINGs/wpopupbutton.c +++ b/WINGs/wpopupbutton.c @@ -571,10 +571,6 @@ static void popDownMenu(PopUpButton *bPtr) { W_UnmapView(bPtr->menuView); - - /* free the background pixmap used to draw the menu contents */ - XSetWindowBackgroundPixmap(bPtr->view->screen->display, - bPtr->menuView->window, None); } diff --git a/WINGs/wtext.c b/WINGs/wtext.c index 60f6af8f..535fdfcc 100644 --- a/WINGs/wtext.c +++ b/WINGs/wtext.c @@ -2312,6 +2312,8 @@ R_imaGFX: if(tb->next) { } else if (control_pressed && buffer[0] == '') XBell(tPtr->view->screen->display, 0); + else + WMRelayToNextResponder(tPtr->view, event); } if (!control_pressed && tPtr->flags.ownsSelection) diff --git a/WINGs/wtextfield.c b/WINGs/wtextfield.c index 824d2deb..8b6f2e98 100644 --- a/WINGs/wtextfield.c +++ b/WINGs/wtextfield.c @@ -998,45 +998,67 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) int count, refresh = 0; int control_pressed = 0; int cancelSelection = 1; + Bool shifted, controled, modified; + Bool relay = True; /*printf("(%d,%d) -> ", tPtr->selection.position, tPtr->selection.count);*/ if (((XKeyEvent *) event)->state & WM_EMACSKEYMASK) control_pressed = 1; + + shifted = event->xkey.state & ShiftMask; + controled = event->xkey.state & ControlMask; + if ((event->xkey.state & ~(ShiftMask|ControlMask)) != 0) { + modified = True; + } else { + modified = False; + } count = XLookupString(&event->xkey, buffer, 63, &ksym, NULL); buffer[count] = '\0'; - + switch (ksym) { case XK_Tab: #ifdef XK_ISO_Left_Tab case XK_ISO_Left_Tab: #endif - if (event->xkey.state & ShiftMask) { - if (tPtr->view->prevFocusChain) { - W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view), - tPtr->view->prevFocusChain); - tPtr->flags.notIllegalMovement = 1; - } - data = (void*)WMBacktabTextMovement; - } else { - if (tPtr->view->nextFocusChain) { - W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view), - tPtr->view->nextFocusChain); - tPtr->flags.notIllegalMovement = 1; - } - data = (void*)WMTabTextMovement; + if (!controled && !modified) { + if (shifted) { + if (tPtr->view->prevFocusChain) { + W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view), + tPtr->view->prevFocusChain); + tPtr->flags.notIllegalMovement = 1; + } + data = (void*)WMBacktabTextMovement; + } else { + if (tPtr->view->nextFocusChain) { + W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view), + tPtr->view->nextFocusChain); + tPtr->flags.notIllegalMovement = 1; + } + data = (void*)WMTabTextMovement; + } + textEvent = WMTextDidEndEditingNotification; + + relay = False; } - textEvent = WMTextDidEndEditingNotification; break; case XK_Escape: - data = (void*)WMEscapeTextMovement; - textEvent = WMTextDidEndEditingNotification; + if (!shifted && !controled && !modified) { + data = (void*)WMEscapeTextMovement; + textEvent = WMTextDidEndEditingNotification; + + relay = False; + } break; case XK_Return: - data = (void*)WMReturnTextMovement; - textEvent = WMTextDidEndEditingNotification; + if (!shifted && !controled && !modified) { + data = (void*)WMReturnTextMovement; + textEvent = WMTextDidEndEditingNotification; + + relay = False; + } break; case WM_EMACSKEY_LEFT: @@ -1047,26 +1069,30 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) case XK_KP_Left: #endif case XK_Left: - if (tPtr->cursorPosition > 0) { - paintCursor(tPtr); - if (event->xkey.state & ControlMask) { - int i = tPtr->cursorPosition - 1; - - while (i > 0 && tPtr->text[i] != ' ') i--; - while (i > 0 && tPtr->text[i] == ' ') i--; - - tPtr->cursorPosition = (i > 0) ? i + 1 : 0; - } else - tPtr->cursorPosition--; - - if (tPtr->cursorPosition < tPtr->viewPosition) { - tPtr->viewPosition = tPtr->cursorPosition; - refresh = 1; - } else + if (!modified) { + if (tPtr->cursorPosition > 0) { paintCursor(tPtr); + if (event->xkey.state & ControlMask) { + int i = tPtr->cursorPosition - 1; + + while (i > 0 && tPtr->text[i] != ' ') i--; + while (i > 0 && tPtr->text[i] == ' ') i--; + + tPtr->cursorPosition = (i > 0) ? i + 1 : 0; + } else + tPtr->cursorPosition--; + + if (tPtr->cursorPosition < tPtr->viewPosition) { + tPtr->viewPosition = tPtr->cursorPosition; + refresh = 1; + } else + paintCursor(tPtr); + } + if (event->xkey.state & ShiftMask) + cancelSelection = 0; + + relay = False; } - if (event->xkey.state & ShiftMask) - cancelSelection = 0; break; case WM_EMACSKEY_RIGHT: @@ -1077,30 +1103,34 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) case XK_KP_Right: #endif case XK_Right: - if (tPtr->cursorPosition < tPtr->textLen) { - paintCursor(tPtr); - if (event->xkey.state & ControlMask) { - int i = tPtr->cursorPosition; - - while (tPtr->text[i] && tPtr->text[i] != ' ') i++; - while (tPtr->text[i] == ' ') i++; - - tPtr->cursorPosition = i; - } else { - tPtr->cursorPosition++; - } - while (WMWidthOfString(tPtr->font, - &(tPtr->text[tPtr->viewPosition]), - tPtr->cursorPosition-tPtr->viewPosition) - > tPtr->usableWidth) { - tPtr->viewPosition++; - refresh = 1; - } - if (!refresh) + if (!modified) { + if (tPtr->cursorPosition < tPtr->textLen) { paintCursor(tPtr); + if (event->xkey.state & ControlMask) { + int i = tPtr->cursorPosition; + + while (tPtr->text[i] && tPtr->text[i] != ' ') i++; + while (tPtr->text[i] == ' ') i++; + + tPtr->cursorPosition = i; + } else { + tPtr->cursorPosition++; + } + while (WMWidthOfString(tPtr->font, + &(tPtr->text[tPtr->viewPosition]), + tPtr->cursorPosition-tPtr->viewPosition) + > tPtr->usableWidth) { + tPtr->viewPosition++; + refresh = 1; + } + if (!refresh) + paintCursor(tPtr); + } + if (event->xkey.state & ShiftMask) + cancelSelection = 0; + + relay = False; } - if (event->xkey.state & ShiftMask) - cancelSelection = 0; break; case WM_EMACSKEY_HOME: @@ -1111,17 +1141,21 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) case XK_KP_Home: #endif case XK_Home: - if (tPtr->cursorPosition > 0) { - paintCursor(tPtr); - tPtr->cursorPosition = 0; - if (tPtr->viewPosition > 0) { - tPtr->viewPosition = 0; - refresh = 1; - } else + if (!modified && !controled) { + if (tPtr->cursorPosition > 0) { paintCursor(tPtr); + tPtr->cursorPosition = 0; + if (tPtr->viewPosition > 0) { + tPtr->viewPosition = 0; + refresh = 1; + } else + paintCursor(tPtr); + } + if (event->xkey.state & ShiftMask) + cancelSelection = 0; + + relay = False; } - if (event->xkey.state & ShiftMask) - cancelSelection = 0; break; case WM_EMACSKEY_END: @@ -1132,22 +1166,26 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) case XK_KP_End: #endif case XK_End: - if (tPtr->cursorPosition < tPtr->textLen) { - paintCursor(tPtr); - tPtr->cursorPosition = tPtr->textLen; - tPtr->viewPosition = 0; - while (WMWidthOfString(tPtr->font, - &(tPtr->text[tPtr->viewPosition]), - tPtr->textLen-tPtr->viewPosition) - > tPtr->usableWidth) { - tPtr->viewPosition++; - refresh = 1; - } - if (!refresh) + if (!modified && !controled) { + if (tPtr->cursorPosition < tPtr->textLen) { paintCursor(tPtr); + tPtr->cursorPosition = tPtr->textLen; + tPtr->viewPosition = 0; + while (WMWidthOfString(tPtr->font, + &(tPtr->text[tPtr->viewPosition]), + tPtr->textLen-tPtr->viewPosition) + > tPtr->usableWidth) { + tPtr->viewPosition++; + refresh = 1; + } + if (!refresh) + paintCursor(tPtr); + } + if (event->xkey.state & ShiftMask) + cancelSelection = 0; + + relay = False; } - if (event->xkey.state & ShiftMask) - cancelSelection = 0; break; case WM_EMACSKEY_BS: @@ -1155,17 +1193,21 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) goto normal_key; } case XK_BackSpace: - if (tPtr->selection.count) { - WMDeleteTextFieldRange(tPtr, tPtr->selection); - data = (void*)WMDeleteTextEvent; - textEvent = WMTextDidChangeNotification; - } else if (tPtr->cursorPosition > 0) { - WMRange range; - range.position = tPtr->cursorPosition - 1; - range.count = 1; - WMDeleteTextFieldRange(tPtr, range); - data = (void*)WMDeleteTextEvent; - textEvent = WMTextDidChangeNotification; + if (!modified && !shifted && !controled) { + if (tPtr->selection.count) { + WMDeleteTextFieldRange(tPtr, tPtr->selection); + data = (void*)WMDeleteTextEvent; + textEvent = WMTextDidChangeNotification; + } else if (tPtr->cursorPosition > 0) { + WMRange range; + range.position = tPtr->cursorPosition - 1; + range.count = 1; + WMDeleteTextFieldRange(tPtr, range); + data = (void*)WMDeleteTextEvent; + textEvent = WMTextDidChangeNotification; + } + + relay = False; } break; @@ -1177,34 +1219,46 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event) case XK_KP_Delete: #endif case XK_Delete: - if (tPtr->selection.count) { - WMDeleteTextFieldRange(tPtr, tPtr->selection); - data = (void*)WMDeleteTextEvent; - textEvent = WMTextDidChangeNotification; - } else if (tPtr->cursorPosition < tPtr->textLen) { - WMRange range; - range.position = tPtr->cursorPosition; - range.count = 1; - WMDeleteTextFieldRange(tPtr, range); - data = (void*)WMDeleteTextEvent; - textEvent = WMTextDidChangeNotification; + if (!modified && !controled && !shifted) { + if (tPtr->selection.count) { + WMDeleteTextFieldRange(tPtr, tPtr->selection); + data = (void*)WMDeleteTextEvent; + textEvent = WMTextDidChangeNotification; + } else if (tPtr->cursorPosition < tPtr->textLen) { + WMRange range; + range.position = tPtr->cursorPosition; + range.count = 1; + WMDeleteTextFieldRange(tPtr, range); + data = (void*)WMDeleteTextEvent; + textEvent = WMTextDidChangeNotification; + } + + relay = False; } break; normal_key: default: - if (count > 0 && isprint(buffer[0])) { - if (tPtr->selection.count) - WMDeleteTextFieldRange(tPtr, tPtr->selection); - WMInsertTextFieldText(tPtr, buffer, tPtr->cursorPosition); - data = (void*)WMInsertTextEvent; - textEvent = WMTextDidChangeNotification; - } else { - /* should we rather break and goto cancel selection below? -Dan */ - return; + if (!controled && !modified) { + if (count > 0 && isprint(buffer[0])) { + if (tPtr->selection.count) + WMDeleteTextFieldRange(tPtr, tPtr->selection); + WMInsertTextFieldText(tPtr, buffer, tPtr->cursorPosition); + data = (void*)WMInsertTextEvent; + textEvent = WMTextDidChangeNotification; + + relay = False; + } } break; } + + + if (relay) { + WMRelayToNextResponder(W_VIEW(tPtr), event); + return; + } + if (!cancelSelection) { if (tPtr->selection.count != tPtr->cursorPosition - tPtr->selection.position) { @@ -1335,11 +1389,8 @@ handleTextFieldActionEvents(XEvent *event, void *data) } if (tPtr->flags.enabled && tPtr->flags.focused) { handleTextFieldKeyPress(tPtr, event); - XGrabPointer(dpy, W_VIEW(tPtr)->window, False, - PointerMotionMask|ButtonPressMask|ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, - W_VIEW(tPtr)->screen->invisibleCursor, - CurrentTime); + XDefineCursor(dpy, W_VIEW(tPtr)->window, + W_VIEW(tPtr)->screen->invisibleCursor); tPtr->flags.pointerGrabbed = 1; } break; @@ -1348,7 +1399,8 @@ handleTextFieldActionEvents(XEvent *event, void *data) if (tPtr->flags.pointerGrabbed) { tPtr->flags.pointerGrabbed = 0; - XUngrabPointer(dpy, CurrentTime); + XDefineCursor(dpy, W_VIEW(tPtr)->window, + W_VIEW(tPtr)->screen->textCursor); } if (tPtr->flags.waitingSelection) { return; @@ -1393,7 +1445,8 @@ handleTextFieldActionEvents(XEvent *event, void *data) case ButtonPress: if (tPtr->flags.pointerGrabbed) { tPtr->flags.pointerGrabbed = 0; - XUngrabPointer(dpy, CurrentTime); + XDefineCursor(dpy, W_VIEW(tPtr)->window, + W_VIEW(tPtr)->screen->textCursor); break; } @@ -1466,7 +1519,8 @@ handleTextFieldActionEvents(XEvent *event, void *data) case ButtonRelease: if (tPtr->flags.pointerGrabbed) { tPtr->flags.pointerGrabbed = 0; - XUngrabPointer(dpy, CurrentTime); + XDefineCursor(dpy, W_VIEW(tPtr)->window, + W_VIEW(tPtr)->screen->textCursor); } if (tPtr->flags.waitingSelection) { break; diff --git a/WINGs/wview.c b/WINGs/wview.c index 726620bf..6d42a894 100644 --- a/WINGs/wview.c +++ b/WINGs/wview.c @@ -673,7 +673,6 @@ W_RetainView(WMView *view) } - void W_ReleaseView(WMView *view) { -- 2.11.4.GIT