/* * Name : void vGetNextEvent(XEvent *tEvent) * * Parameters: None. * * Returns : void * * Purpose : Creates the main viewing window. */ void vGetNextEvent(XEvent *tEvent) { /* Get the next event, however, event compression is used */ /* for MotionNotify events. MotionNotify events are disregarded */ /* until the queue is empty. */ do { XNextEvent(display, tEvent); if (tEvent->type == ConfigureNotify) { vInitGL(tEvent->xconfigure.width, tEvent->xconfigure.height); nWinHeight = tEvent->xconfigure.height; nWinWidth = tEvent->xconfigure.width; continue; } if (QLength(display) == 0) { break; } } while (tEvent->type == MotionNotify); }
static Bool LookAhead(Widget w, XEvent *event) { XEvent newEvent; struct EventData eventData; if (QLength(XtDisplay(w)) == 0) return (False); eventData.count = 0; eventData.oldEvent = event; XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData); if (CompareEvents(event, &newEvent)) return (True); return (False); }
void run(void) { XEvent xe; while(1){ while(QLength(disp)) { XNextEvent(disp, &xe); } int bat = get_battery_percent(bat_id); height = bat*3; resize(width, height); XMoveResizeWindow(disp, win, x-width, y-height, width, height); colorR = color_in_range("#ff0000", "#00ff00", bat); draw_rectangle(0,0,width,height,1,colorW); draw_rectangle(border,border, width-(2*border),height-(2*border),1,colorR); remap(win, width, height); usleep(60000000); } }
int TkUnixDoOneXEvent( Tcl_Time *timePtr) /* Specifies the absolute time when the call * should time out. */ { TkDisplay *dispPtr; static fd_mask readMask[MASK_SIZE]; struct timeval blockTime, *timeoutPtr; Tcl_Time now; int fd, index, numFound, numFdBits = 0; fd_mask bit, *readMaskPtr = readMask; /* * Look for queued events first. */ if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) { return 1; } /* * Compute the next block time and check to see if we have timed out. Note * that HP-UX defines tv_sec to be unsigned so we have to be careful in * our arithmetic. */ if (timePtr) { Tcl_GetTime(&now); blockTime.tv_sec = timePtr->sec; blockTime.tv_usec = timePtr->usec - now.usec; if (blockTime.tv_usec < 0) { now.sec += 1; blockTime.tv_usec += 1000000; } if (blockTime.tv_sec < now.sec) { blockTime.tv_sec = 0; blockTime.tv_usec = 0; } else { blockTime.tv_sec -= now.sec; } timeoutPtr = &blockTime; } else { timeoutPtr = NULL; } /* * Set up the select mask for all of the displays. If a display has data * pending, then we want to poll instead of blocking. */ memset(readMask, 0, MASK_SIZE*sizeof(fd_mask)); for (dispPtr = TkGetDisplayList(); dispPtr != NULL; dispPtr = dispPtr->nextPtr) { XFlush(dispPtr->display); if (QLength(dispPtr->display) > 0) { blockTime.tv_sec = 0; blockTime.tv_usec = 0; } fd = ConnectionNumber(dispPtr->display); index = fd/(NBBY*sizeof(fd_mask)); bit = ((fd_mask)1) << (fd%(NBBY*sizeof(fd_mask))); readMask[index] |= bit; if (numFdBits <= fd) { numFdBits = fd+1; } } numFound = select(numFdBits, (SELECT_MASK *) readMaskPtr, NULL, NULL, timeoutPtr); if (numFound <= 0) { /* * Some systems don't clear the masks after an error, so we have to do * it here. */ memset(readMask, 0, MASK_SIZE*sizeof(fd_mask)); } /* * Process any new events on the display connections. */ for (dispPtr = TkGetDisplayList(); dispPtr != NULL; dispPtr = dispPtr->nextPtr) { fd = ConnectionNumber(dispPtr->display); index = fd/(NBBY*sizeof(fd_mask)); bit = ((fd_mask)1) << (fd%(NBBY*sizeof(fd_mask))); if ((readMask[index] & bit) || (QLength(dispPtr->display) > 0)) { DisplayFileProc((ClientData)dispPtr, TCL_READABLE); } } if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) { return 1; } /* * Check to see if we timed out. */ if (timePtr) { Tcl_GetTime(&now); if ((now.sec > timePtr->sec) || ((now.sec == timePtr->sec) && (now.usec > timePtr->usec))) { return 0; } } /* * We had an event but we did not generate a Tcl event from it. Behave as * though we dealt with it. (JYL&SS) */ return 1; }
static void TransferXEventsToTcl( Display *display) { union { int type; XEvent x; TkKeyEvent k; } event; Window w; TkDisplay *dispPtr = NULL; /* * Transfer events from the X event queue to the Tk event queue after XIM * event filtering. KeyPress and KeyRelease events need special treatment * so that they get directed according to Tk's focus rules during XIM * handling. Theoretically they can go to the wrong place still (if * there's a focus change in the queue) but if we push the handling off * until Tk_HandleEvent then many input methods actually cease to work * correctly. Most of the time, Tk processes its event queue fast enough * for this to not be an issue anyway. [Bug 1924761] */ while (QLength(display) > 0) { XNextEvent(display, &event.x); w = None; if (event.type == KeyPress || event.type == KeyRelease) { for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { break; } else if (dispPtr->display == event.x.xany.display) { if (dispPtr->focusPtr != NULL) { w = dispPtr->focusPtr->window; } break; } } } if (XFilterEvent(&event.x, w)) { continue; } if (event.type == KeyPress || event.type == KeyRelease) { event.k.charValuePtr = NULL; event.k.charValueLen = 0; event.k.keysym = NoSymbol; /* * Force the calling of the input method engine now. The results * from it will be cached in the event so that they don't get lost * (to a race condition with other XIM-handled key events) between * entering the event queue and getting serviced. [Bug 1924761] */ #ifdef TK_USE_INPUT_METHODS if (event.type == KeyPress && dispPtr && (dispPtr->flags & TK_DISPLAY_USE_IM)) { if (dispPtr->focusPtr && dispPtr->focusPtr->inputContext) { Tcl_DString ds; Tcl_DStringInit(&ds); (void) TkpGetString(dispPtr->focusPtr, &event.x, &ds); Tcl_DStringFree(&ds); } } #endif } Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); } }
int XMenuActivate( register Display *display, /* Display to put menu on. */ register XMenu *menu, /* Menu to activate. */ int *p_num, /* Pane number selected. */ int *s_num, /* Selection number selected. */ int x_pos, /* X coordinate of menu position. */ int y_pos, /* Y coordinate of menu position. */ unsigned int event_mask, /* Mouse button event mask. */ char **data, /* Pointer to return data value. */ void (*help_callback) (char const *, int, int)) /* Help callback. */ { int status; /* X routine call status. */ int orig_x; /* Upper left menu origin X coord. */ int orig_y; /* Upper left menu origin Y coord. */ int ret_val; /* Return value. */ register XMPane *p_ptr; /* Current XMPane. */ register XMPane *event_xmp; /* Event XMPane pointer. */ register XMPane *cur_p; /* Current pane. */ register XMSelect *cur_s; /* Current selection. */ XMWindow *event_xmw; /* Event XMWindow pointer. */ XEvent event; /* X input event. */ XEvent peek_event; /* X input peek ahead event. */ Bool selection = False; /* Selection has been made. */ Bool forward = True; /* Moving forward in the pane list. */ Window root, child; int root_x, root_y, win_x, win_y; unsigned int mask; KeySym keysym; /* * Define and allocate a foreign event queue to hold events * that don't belong to XMenu. These events are later restored * to the X event queue. */ typedef struct _xmeventque { XEvent event; struct _xmeventque *next; } XMEventQue; XMEventQue *feq = NULL; /* Foreign event queue. */ XMEventQue *feq_tmp; /* Foreign event queue temporary. */ /* * If there are no panes in the menu then return failure * because the menu is not initialized. */ if (menu->p_count == 0) { _XMErrorCode = XME_NOT_INIT; return(XM_FAILURE); } /* * Find the desired current pane. */ cur_p = _XMGetPanePtr(menu, *p_num); if (cur_p == NULL) { return(XM_FAILURE); } cur_p->activated = cur_p->active; /* * Find the desired current selection. * If the current selection index is out of range a null current selection * will be assumed and the cursor will be placed in the current pane * header. */ cur_s = _XMGetSelectionPtr(cur_p, *s_num); /* * Compute origin of menu so that cursor is in * Correct pane and selection. */ _XMTransToOrigin(display, menu, cur_p, cur_s, x_pos, y_pos, &orig_x, &orig_y); menu->x_pos = orig_x; /* Store X and Y coords of menu. */ menu->y_pos = orig_y; if (XMenuRecompute(display, menu) == XM_FAILURE) { return(XM_FAILURE); } /* * Flush the window creation queue. * This batches all window creates since lazy evaluation * is more efficient than individual evaluation. * This routine also does an XFlush(). */ if (_XMWinQueFlush(display, menu, cur_p, cur_s) == _FAILURE) { return(XM_FAILURE); } /* * Make sure windows are in correct order (in case we were passed * an already created menu in incorrect order.) */ for(p_ptr = menu->p_list->next; p_ptr != cur_p; p_ptr = p_ptr->next) XRaiseWindow(display, p_ptr->window); for(p_ptr = menu->p_list->prev; p_ptr != cur_p->prev; p_ptr = p_ptr->prev) XRaiseWindow(display, p_ptr->window); /* * Make sure all selection windows are mapped. */ for ( p_ptr = menu->p_list->next; p_ptr != menu->p_list; p_ptr = p_ptr->next ){ XMapSubwindows(display, p_ptr->window); } /* * Synchronize the X buffers and the event queue. * From here on, all events in the queue that don't belong to * XMenu are sent back to the application via an application * provided event handler or discarded if the application has * not provided an event handler. */ XSync(display, 0); /* * Grab the mouse for menu input. */ status = XGrabPointer( display, menu->parent, True, event_mask, GrabModeAsync, GrabModeAsync, None, menu->mouse_cursor, CurrentTime ); if (status == Success && x_menu_grab_keyboard) { status = XGrabKeyboard (display, menu->parent, False, GrabModeAsync, GrabModeAsync, CurrentTime); if (status != Success) XUngrabPointer(display, CurrentTime); } if (status == _X_FAILURE) { _XMErrorCode = XME_GRAB_MOUSE; return(XM_FAILURE); } /* * Map the menu panes. */ XMapWindow(display, cur_p->window); for (p_ptr = menu->p_list->next; p_ptr != cur_p; p_ptr = p_ptr->next) XMapWindow(display, p_ptr->window); for (p_ptr = cur_p->next; p_ptr != menu->p_list; p_ptr = p_ptr->next) XMapWindow(display, p_ptr->window); XRaiseWindow(display, cur_p->window); /* Make sure current */ /* pane is on top. */ cur_s = NULL; /* Clear current selection. */ /* * Begin event processing loop. */ while (1) { if (wait_func) (*wait_func) (wait_data); XNextEvent(display, &event); /* Get next event. */ switch (event.type) { /* Dispatch on the event type. */ case Expose: event_xmp = (XMPane *)XLookUpAssoc(display, menu->assoc_tab, event.xexpose.window); if (event_xmp == NULL) { /* * If AEQ mode is enabled then queue the event. */ if (menu->aeq) { feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue)); if (feq_tmp == NULL) { _XMErrorCode = XME_CALLOC; return(XM_FAILURE); } feq_tmp->event = event; feq_tmp->next = feq; feq = feq_tmp; } else if (_XMEventHandler) (*_XMEventHandler)(&event); break; } if (event_xmp->activated) { XSetWindowBackground(display, event_xmp->window, menu->bkgnd_color); } else { XSetWindowBackgroundPixmap(display, event_xmp->window, menu->inact_pixmap); } _XMRefreshPane(display, menu, event_xmp); break; case EnterNotify: /* * First wait a small period of time, and see * if another EnterNotify event follows hard on the * heels of this one. i.e., the user is simply * "passing through". If so, ignore this one. */ event_xmw = (XMWindow *)XLookUpAssoc(display, menu->assoc_tab, event.xcrossing.window); if (event_xmw == NULL) break; if (event_xmw->type == SELECTION) { /* * We have entered a selection. */ /* if (XPending(display) == 0) usleep(150000); */ if (XPending(display) != 0) { XPeekEvent(display, &peek_event); if(peek_event.type == LeaveNotify) { break; } } cur_s = (XMSelect *)event_xmw; help_callback (cur_s->help_string, cur_p->serial, cur_s->serial); /* * If the pane we are in is active and the * selection entered is active then activate * the selection. */ if (cur_p->active && cur_s->active > 0) { cur_s->activated = 1; _XMRefreshSelection(display, menu, cur_s); } } else { /* * We have entered a pane. */ /* if (XPending(display) == 0) usleep(150000); */ if (XPending(display) != 0) { XPeekEvent(display, &peek_event); if (peek_event.type == EnterNotify) break; } XQueryPointer(display, menu->parent, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask); event_xmp = (XMPane *)XLookUpAssoc(display, menu->assoc_tab, child); if (event_xmp == NULL) break; if (event_xmp == cur_p) break; if (event_xmp->serial > cur_p->serial) forward = True; else forward = False; p_ptr = cur_p; while (p_ptr != event_xmp) { if (forward) p_ptr = p_ptr->next; else p_ptr = p_ptr->prev; XRaiseWindow(display, p_ptr->window); } if (cur_p->activated) { cur_p->activated = False; XSetWindowBackgroundPixmap(display, cur_p->window, menu->inact_pixmap); _XMRefreshPane(display, menu, cur_p); } if (event_xmp->active) event_xmp->activated = True; #if 1 /* * i suspect the we don't get an EXPOSE event when backing * store is enabled; the menu windows content is probably * not drawn in when it should be in that case. * in that case, this is probably an ugly fix! * i hope someone more familiar with this code would * take it from here. -- [email protected]. */ XSetWindowBackground(display, event_xmp->window, menu->bkgnd_color); _XMRefreshPane(display, menu, event_xmp); #endif cur_p = event_xmp; } break; case LeaveNotify: event_xmw = (XMWindow *)XLookUpAssoc( display, menu->assoc_tab, event.xcrossing.window ); if (event_xmw == NULL) break; if(cur_s == NULL) break; /* * If the current selection was activated then * deactivate it. */ if (cur_s->activated) { cur_s->activated = False; _XMRefreshSelection(display, menu, cur_s); } cur_s = NULL; break; case ButtonPress: case ButtonRelease: *p_num = cur_p->serial; /* * Check to see if there is a current selection. */ if (cur_s != NULL) { /* * Set the selection number to the current selection. */ *s_num = cur_s->serial; /* * If the current selection was activated then * we have a valid selection otherwise we have * an inactive selection. */ if (cur_s->activated) { *data = cur_s->data; ret_val = XM_SUCCESS; } else { ret_val = XM_IA_SELECT; } } else { /* * No selection was current. */ ret_val = XM_NO_SELECT; } selection = True; break; case KeyPress: case KeyRelease: keysym = XLookupKeysym (&event.xkey, 0); /* Pop down on C-g and Escape. */ if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0) || keysym == XK_Escape) /* Any escape, ignore modifiers. */ { ret_val = XM_NO_SELECT; selection = True; } break; default: /* * If AEQ mode is enabled then queue the event. */ if (menu->aeq) { feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue)); if (feq_tmp == NULL) { _XMErrorCode = XME_CALLOC; return(XM_FAILURE); } feq_tmp->event = event; feq_tmp->next = feq; feq = feq_tmp; } else if (_XMEventHandler) (*_XMEventHandler)(&event); } /* * If a selection has been made, break out of the event loop. */ if (selection == True) break; } /* * Unmap the menu. */ for ( p_ptr = menu->p_list->next; p_ptr != menu->p_list; p_ptr = p_ptr->next) { XUnmapWindow(display, p_ptr->window); } /* * Ungrab the mouse. */ XUngrabPointer(display, CurrentTime); XUngrabKeyboard(display, CurrentTime); /* * Restore bits under where the menu was if we managed * to save them and free the pixmap. */ /* * If there is a current selection deactivate it. */ if (cur_s != NULL) cur_s->activated = 0; /* * Deactivate the current pane. */ cur_p->activated = 0; XSetWindowBackgroundPixmap(display, cur_p->window, menu->inact_pixmap); /* * Synchronize the X buffers and the X event queue. */ XSync(display, 0); /* * Dispatch any events remaining on the queue. */ while (QLength(display)) { /* * Fetch the next event. */ XNextEvent(display, &event); /* * Discard any events left on the queue that belong to XMenu. * All others are held and then returned to the event queue. */ switch (event.type) { case Expose: case EnterNotify: case LeaveNotify: case ButtonPress: case ButtonRelease: /* * Does this event belong to one of XMenu's windows? * If so, discard it and process the next event. * If not fall through and treat it as a foreign event. */ event_xmp = (XMPane *)XLookUpAssoc( display, menu->assoc_tab, event.xbutton.window ); if (event_xmp != NULL) continue; default: /* * This is a foreign event. * Queue it for later return to the X event queue. */ feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue)); if (feq_tmp == NULL) { _XMErrorCode = XME_CALLOC; return(XM_FAILURE); } feq_tmp->event = event; feq_tmp->next = feq; feq = feq_tmp; } } /* * Return any foreign events that were queued to the X event queue. */ while (feq != NULL) { feq_tmp = feq; XPutBackEvent(display, &feq_tmp->event); feq = feq_tmp->next; free((char *)feq_tmp); } wait_func = 0; /* * Return successfully. */ _XMErrorCode = XME_NO_ERROR; return(ret_val); }
static void draw_scope(double *values) { static int32 call_cnt; int offset, expose; XEvent e; char pixels[SCOPE_HEIGHT*32]; double work[SCOPE_HEIGHT]; int nze; char *mname; KeySym k; make_logspectrogram(values, work); set_draw_pixel(work, pixels); expose = 0; nze = 0; while(QLength(disp) || XPending(disp)) { XNextEvent(disp, &e); switch(e.type) { case Expose: expose++; break; case KeyPress: k = xlookup_key(&e.xkey); switch(k) { #ifdef XK_Down case XK_Up: #endif /* XK_Up */ #ifdef XK_KP_Up case XK_KP_Up: #endif /* XK_KP_Up */ nze++; break; #ifdef XK_Down case XK_Down: #endif /* XK_Down */ #ifdef XK_KP_Down case XK_KP_Down: #endif /* XK_KP_Down */ nze--; break; #ifdef XK_Left case XK_Left: #endif /* XK_Left */ #ifdef XK_KP_Left case XK_KP_Left: #endif /* XK_KP_Left */ soundspec_update_interval = (int32)(soundspec_update_interval*1.1); break; #ifdef XK_Right case XK_Right: #endif /* XK_Right */ #ifdef XK_KP_Right case XK_KP_Right: #endif /* XK_KP_Right */ soundspec_update_interval = (int32)(soundspec_update_interval/1.1); if(soundspec_update_interval < 0.01 * play_mode->rate) soundspec_update_interval = (int32)(0.01 * play_mode->rate); break; } break; case ClientMessage: if(wm_delete_window == e.xclient.data.l[0]) { mname = XGetAtomName(disp, e.xclient.message_type); if(mname != NULL && strcmp(mname, "WM_PROTOCOLS") == 0) { /* Delete message from WM */ ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "Sound Spectrogram Window is closed"); close_soundspec(); XCloseDisplay(disp); disp = NULL; return; } } break; } } offset = call_cnt % SCROLL_THRESHOLD; if(offset == 0) { XCopyArea(disp, offscr, offscr, gc, SCROLL_THRESHOLD, 0, SCOPE_WIDTH - SCROLL_THRESHOLD, SCOPE_HEIGHT, 0, 0); XSetForeground(disp, gc, BlackPixel(disp, DefaultScreen(disp))); XFillRectangle(disp, offscr, gc, SCOPE_WIDTH - SCROLL_THRESHOLD, 0, SCROLL_THRESHOLD, SCOPE_HEIGHT); XCopyArea(disp, offscr, win, gc, 0, 0, SCOPE_WIDTH, SCOPE_HEIGHT, 0, 0); } img->data = (char *)pixels; XPutImage(disp, offscr, gc, img, 0, 0, SCOPE_WIDTH - SCROLL_THRESHOLD + offset, 0, 1, SCOPE_HEIGHT); if(!expose) XCopyArea(disp, offscr, win, gc, SCOPE_WIDTH - SCROLL_THRESHOLD + offset, 0, 1, SCOPE_HEIGHT, SCOPE_WIDTH - SCROLL_THRESHOLD + offset, 0); else { XCopyArea(disp, offscr, win, gc, 0, 0, SCOPE_WIDTH, SCOPE_HEIGHT, 0, 0); } XSync(disp, False); if(nze) initialize_exp_hz_table(soundspec_zoom - 4 * nze); call_cnt++; }
bool Workspace::x11Event( XEvent *event ) { //bool dumpWindows = false; //bool reportNextUpdate = false; static int debugs = 0; qDebug() << ++debugs << __PRETTY_FUNCTION__ << "got event" << eventName(event->type); switch ( event->type ) { case CreateNotify: createNotifyEvent( &event->xcreatewindow ); //std::cout << "window " << std::hex << event->xcreatewindow.window << " created\n"; //dumpWindows = true; break; case DestroyNotify: remove( event->xdestroywindow.window ); //std::cout << "window " << std::hex << event->xdestroywindow.window << " destroyed\n"; //dumpWindows = true; break; case ConfigureNotify: configureNotifyEvent( &event->xconfigure ); //std::cout << "window " << std::hex << event->xconfigure.window << " configured\n"; break; case MapNotify: if ( Client *client = find( event->xmap.window ) ) client->show(); //dumpWindows = true; //std::cout << "window " << std::hex << event->xmap.window << " mapped\n"; break; case UnmapNotify: if ( Client *client = find( event->xunmap.window ) ) client->hide(); //dumpWindows = true; //std::cout << "window " << std::hex << event->xunmap.window << " unmapped\n"; break; case ReparentNotify: reparentNotifyEvent( &event->xreparent ); //dumpWindows = true; break; case CirculateNotify: circulateNotifyEvent( &event->xcirculate ); //std::cout << "circulate event\n"; break; case Expose: exposeEvent( &event->xexpose ); break; case PropertyNotify: propertyNotifyEvent( &event->xproperty ); break; default: if ( event->type == Extensions::damageEvent(XDamageNotify) ) damageNotifyEvent( reinterpret_cast< XDamageNotifyEvent * >( event ) ); else if ( event->type == Extensions::shapeEvent(ShapeNotify )) shapeNotifyEvent( reinterpret_cast< XShapeEvent * >( event ) ); } /* if ( dumpWindows ) { std::cout << "===Clients===\n"; ClientList::ConstIterator end = mList.constEnd(); for (ClientList::ConstIterator it = mList.constBegin(); it != end; ++it) { Client *client = *it; //if (!client->isVisible() || client->width() <= 10 || client->height() <= 10) // continue; Window target = XmuClientWindow( dpy, client->winId() ); XTextProperty tp; XGetWMName( dpy, target, &tp ); std::cout << std::hex << client->winId() << " " << (client->isVisible() ? "(mapped)" : "(not mapped)") << " " << std::dec << client->width() << "x" << client->height() << ": "; for (uint i = 0; i < tp.nitems; i++) std::cout << (char)tp.value[i]; std::cout << std::endl; } //std::cout << "=============\n"; std::cout << std::endl; } */ // Update the root window if there's damage and there are no more events pending if ( mDamage && QLength( dpy ) == 0 ) { if ( mWaitForClients && !allVisibleClientsPainted() ) { //std::cout << "delaying update.\n."; } else { mWaitForClients = false; repaint(); } // Helps to accumulate more events XSync( dpy, false ); } return false; }
/* * Given an XEvent, process it if it pertains to a ColorBar, else do * nothing with it. * Input: event - the X event * Output: whichcb - which colorbar this event pertained to. * Return: 1 - if color table was changed. * 2 - if reset key was pressed * 3 - if <shift>+reset key was pressed * 0 - if no change */ static int colorbar_process( LUI_COLORBAR *cb, XEvent *event ) { static int p1 = 0, p2 = 0, p3 = 0, p4 = 0; /* red, green, blue, alpha */ static int pentry; int i, modify, entry, result; static int move_marker; result = modify = 0; if (event->type==KeyPress) { char keybuf[50]; KeySym key; XComposeStatus compose; int count; count = XLookupString( &event->xkey, keybuf, 50, &key, &compose ); if (count==1) { if (keybuf[0]=='r') { /* Reset RGB */ cb->params[DRAWFLAG] = 0.0; result = LUI_RGB_RESET; } else if (keybuf[0]=='R') { /* Reset alpha */ result = LUI_ALPHA_RESET; cb->params[DRAWFLAG] = 0.0; } else if (keybuf[0]=='c' || keybuf[0]=='C') { /* Copy current colors to clipboard */ copy_colors( cb ); } else if (keybuf[0]=='p' || keybuf[0]=='P') { /* Paste clipboard colors to current color widget */ paste_colors( cb ); LUI_ColorBarRedraw( cb ); result = LUI_RGB_CHANGE | LUI_ALPHA_CHANGE; cb->params[DRAWFLAG] = 0.0; result = LUI_RGB_CHANGE | LUI_ALPHA_CHANGE; } /* WLH 7-18-96 */ else if (keybuf[0]=='s' || keybuf[0]=='S') { /* save colors to a file */ save_colors( cb ); } else if (keybuf[0]=='l' || keybuf[0]=='L') { /* load colors from a file */ load_colors( cb ); LUI_ColorBarRedraw( cb ); return 1; } else { /* if unused key, toggle help display */ cb->helpflag = !cb->helpflag; LUI_ColorBarRedraw( cb ); } } else if (key == XK_Left) { /* rotate left */ cb->params[BIAS] -= 0.03/cb->params[CURVE]; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } else if (key == XK_Right) { /* rotate right */ cb->params[BIAS] += 0.03/cb->params[CURVE]; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } else if (key == XK_Up) { /* expand color map */ if (event->xkey.state & ANY_MODIFIER) { cb->params[ALPHAPOW] -= 0.1; if (cb->params[ALPHAPOW]<0.0) cb->params[ALPHAPOW] = 0.0; result = LUI_ALPHA_SHAPE; cb->params[DRAWFLAG] = 0.0; } else { cb->params[CURVE] -= 0.1; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } } else if (key == XK_Down) { /* compress color map */ if (event->xkey.state & ANY_MODIFIER) { cb->params[ALPHAPOW] += 0.1; result = LUI_ALPHA_SHAPE; cb->params[DRAWFLAG] = 0.0; } else { cb->params[CURVE] += 0.1; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } } } else if (event->type==Expose && event->xexpose.count==0) { LUI_ColorBarRedraw( cb ); result = 0; } else if (event->type==ConfigureNotify) { /* MJK 4.15.99 */ LUI_ColorBarSetSize( cb, event->xconfigure.width, event->xconfigure.height ); result = 0; } else if (event->type==ButtonPress ) { if (event->xbutton.y<cb->wedge_y) { /* change color function */ move_marker = 0; } else { /* change marker position */ move_marker = 1; } /* determine which curve to modify */ if (event->xbutton.state&ANY_MODIFIER) { p4 = 1; } else { if (event->xbutton.button==Button1) p1 = 1; if (event->xbutton.button==Button2) p2 = 1; if (event->xbutton.button==Button3) p3 = 1; } pentry = x_to_index( cb, event->xbutton.x ); modify = 1; } else if (event->type==ButtonRelease) { if (p1 || p2 || p3) { result = LUI_RGB_CHANGE; } else { result = LUI_ALPHA_CHANGE; } if (event->xbutton.button==Button1) p1 = 0; if (event->xbutton.button==Button2) p2 = 0; if (event->xbutton.button==Button3) p3 = 0; p4 = 0; } else if (event->type==MotionNotify) { /* Flush extra MotionNotify events */ while (QLength(LUI_Display)>0) { XEvent next; XPeekEvent(LUI_Display, &next); if (next.type!=MotionNotify) break; XNextEvent(LUI_Display, event); } modify = 1; } /* Modify one or more of the color curves */ if (modify && (p1 || p2 || p3 || p4)) { /* calculate which entry in color table to change */ entry = x_to_index( cb, event->xbutton.x ); /* update */ if (move_marker) { /* changing marker position */ cb->markerpos = entry; redraw_marker( cb ); } else { /* changing color graph */ int a, b, value; value = y_to_intensity( cb, event->xbutton.y ); if (pentry<=entry) { a = pentry; b = entry; } else { a = entry; b = pentry; } /* update entries from 'pentry' to 'entry' */ for (i=a; i<=b; i++) { int red, green, blue, alpha; red = UNPACK_RED(cb->table[i]); green = UNPACK_GREEN(cb->table[i]); blue = UNPACK_BLUE(cb->table[i]); alpha = UNPACK_ALPHA(cb->table[i]); if (p1) { /* modify red */ red = value; } if (p2) { /* modify green */ green = value; } if (p3) { /* modify blue */ blue = value; } if (p4) { /* modify alpha */ alpha = value; } /* change the color table entry */ cb->table[i] = PACK_COLOR(red,green,blue,alpha); } /* for */ /* redraw the color curves */ if (pentry<entry) redraw_range( cb, pentry-1, entry+1 ); else redraw_range( cb, entry-1, pentry+1 ); pentry = entry; if (p4) { /* update min,max alpha values */ cb->minalpha = 256; cb->maxalpha = 0; for (i=0;i<cb->table_size;i++) { int a = UNPACK_ALPHA( cb->table[i] ); if (a<cb->minalpha) cb->minalpha = a; if (a>cb->maxalpha) cb->maxalpha = a; } } if (p4) { result = LUI_ALPHA_MODIFY; /* result = LUI_ALPHA_CHANGE; */ } else { result = LUI_RGB_MODIFY; /* result = LUI_RGB_CHANGE; */ } cb->params[DRAWFLAG] = 1.0; } } /*modify*/ if (result!=0 && cb->callback) { (*cb->callback)(cb, result); } return result; }
int XQLength(Display *dpy) { return (QLength(dpy)); }
void x11_event_thread(void *args) { int x; int high_fd; fd_set fdset; XEvent ev; static struct timeval tv; SetThreadName("X11 Events"); if(video_init()) { sem_post(&init_complete); return; } x11_initialized=1; sem_post(&init_complete); if(local_pipe[0] > xfd) high_fd=local_pipe[0]; else high_fd=xfd; for (;;) { tv.tv_sec=0; tv.tv_usec=54925; /* was 54925 (was also 10) */ /* * Handle any events just sitting around... */ while (QLength(dpy) > 0) { x11.XNextEvent(dpy, &ev); x11_event(&ev); } FD_ZERO(&fdset); FD_SET(xfd, &fdset); FD_SET(local_pipe[0], &fdset); x = select(high_fd+1, &fdset, 0, 0, &tv); switch (x) { case -1: /* * Errno might be wrong, so we just select again. * This could cause a problem is something really * was wrong with select.... */ /* perror("select"); */ break; case 0: /* Timeout */ break; default: if (FD_ISSET(xfd, &fdset)) { x11.XNextEvent(dpy, &ev); x11_event(&ev); } while(FD_ISSET(local_pipe[0], &fdset)) { struct x11_local_event lev; read(local_pipe[0], &lev, sizeof(lev)); switch(lev.type) { case X11_LOCAL_SETMODE: init_mode(lev.data.mode); break; case X11_LOCAL_SETNAME: x11.XSetIconName(dpy, win, lev.data.name); x11.XFlush(dpy); break; case X11_LOCAL_SETTITLE: x11.XStoreName(dpy, win, lev.data.title); x11.XFlush(dpy); break; case X11_LOCAL_COPY: x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime); break; case X11_LOCAL_PASTE: { Window sowner=None; sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD); if(sowner==win) { /* Get your own primary selection */ if(copybuf==NULL) pastebuf=NULL; else pastebuf=strdup(copybuf); /* Set paste buffer */ sem_post(&pastebuf_set); sem_wait(&pastebuf_used); FREE_AND_NULL(pastebuf); } else if(sowner!=None) { x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, XA_STRING, win, CurrentTime); } else { /* Set paste buffer */ pastebuf=NULL; sem_post(&pastebuf_set); sem_wait(&pastebuf_used); } } break; case X11_LOCAL_DRAWRECT: local_draw_rect(&lev.data.rect); break; case X11_LOCAL_FLUSH: x11.XFlush(dpy); break; case X11_LOCAL_BEEP: x11.XBell(dpy, 100); break; } tv.tv_sec=0; tv.tv_usec=0; FD_ZERO(&fdset); FD_SET(local_pipe[0], &fdset); if(select(local_pipe[0]+1, &fdset, 0, 0, &tv)!=1) FD_ZERO(&fdset); } } } }
void XWindowsEventQueueBuffer::waitForEvent(double dtimeout) { Thread::testCancel(); // clear out the pipe in preparation for waiting. char buf[16]; ssize_t read_response = read(m_pipefd[0], buf, 15); // with linux automake, warnings are treated as errors by default if (read_response < 0) { // todo: handle read response } { Lock lock(&m_mutex); // we're now waiting for events m_waiting = true; // push out pending events flush(); } // calling flush may have queued up a new event. if (!XWindowsEventQueueBuffer::isEmpty()) { Thread::testCancel(); return; } // use poll() to wait for a message from the X server or for timeout. // this is a good deal more efficient than polling and sleeping. #if HAVE_POLL struct pollfd pfds[2]; pfds[0].fd = ConnectionNumber(m_display); pfds[0].events = POLLIN; pfds[1].fd = m_pipefd[0]; pfds[1].events = POLLIN; int timeout = (dtimeout < 0.0) ? -1 : static_cast<int>(1000.0 * dtimeout); int remaining = timeout; int retval = 0; #else struct timeval timeout; struct timeval* timeoutPtr; if (dtimeout < 0.0) { timeoutPtr = NULL; } else { timeout.tv_sec = static_cast<int>(dtimeout); timeout.tv_usec = static_cast<int>(1.0e+6 * (dtimeout - timeout.tv_sec)); timeoutPtr = &timeout; } // initialize file descriptor sets fd_set rfds; FD_ZERO(&rfds); FD_SET(ConnectionNumber(m_display), &rfds); FD_SET(m_pipefd[0], &rfds); int nfds; if (ConnectionNumber(m_display) > m_pipefd[0]) { nfds = ConnectionNumber(m_display) + 1; } else { nfds = m_pipefd[0] + 1; } #endif // It's possible that the X server has queued events locally // in xlib's event buffer and not pushed on to the fd. Hence we // can't simply monitor the fd as we may never be woken up. // ie addEvent calls flush, XFlush may not send via the fd hence // there is an event waiting to be sent but we must exit the poll // before it can. // Instead we poll for a brief period of time (so if events // queued locally in the xlib buffer can be processed) // and continue doing this until timeout is reached. // The human eye can notice 60hz (ansi) which is 16ms, however // we want to give the cpu a chance s owe up this to 25ms #define TIMEOUT_DELAY 25 while (((dtimeout < 0.0) || (remaining > 0)) && QLength(m_display)==0 && retval==0){ #if HAVE_POLL retval = poll(pfds, 2, TIMEOUT_DELAY); //16ms = 60hz, but we make it > to play nicely with the cpu if (pfds[1].revents & POLLIN) { ssize_t read_response = read(m_pipefd[0], buf, 15); // with linux automake, warnings are treated as errors by default if (read_response < 0) { // todo: handle read response } } #else retval = select(nfds, SELECT_TYPE_ARG234 &rfds, SELECT_TYPE_ARG234 NULL, SELECT_TYPE_ARG234 NULL, SELECT_TYPE_ARG5 TIMEOUT_DELAY); if (FD_SET(m_pipefd[0], &rfds)) { read(m_pipefd[0], buf, 15); } #endif remaining-=TIMEOUT_DELAY; } { // we're no longer waiting for events Lock lock(&m_mutex); m_waiting = false; } Thread::testCancel(); }