📄 srvevent.c
字号:
* window is a descendant of the focus window), or else just the focus window. * The lowest window in that tree which has enabled for the event gets it. * If a window with the correct noprop mask is reached, or if no window selects * for the event, then the event is discarded. */void GsDeliverKeyboardEvent(GR_WINDOW_ID wid, GR_EVENT_TYPE type, GR_KEY keyvalue, GR_KEYMOD modifiers, GR_SCANCODE scancode){ GR_EVENT_KEYSTROKE *ep; /* keystroke event */ GR_WINDOW *wp; /* current window */ GR_WINDOW *tempwp; /* temporary window pointer */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW_ID subwid; /* subwindow id event is for */ GR_EVENT_MASK eventmask; /* event mask */ GR_WINDOW *kwp; eventmask = GR_EVENTMASK(type); if (eventmask == 0) return; GsResetScreenSaver(); /* if window id passed, use it, otherwise focus window*/ if (wid) { kwp = GsFindWindow(wid); if (!kwp) return; } else kwp = focuswp; wp = mousewp; subwid = wp->id; /* * See if the actual window the pointer is in is a descendant of * the focus window. If not, then ignore it, and force the input * into the focus window itself. */ tempwp = wp; while ((tempwp != kwp) && (tempwp != rootwp)) tempwp = tempwp->parent; if (tempwp != kwp) { wp = kwp; subwid = wp->id; } /* * Now walk upwards looking for the first window which will accept * the keyboard event. However, do not go beyond the focus window, * and only give the event to one client. */ for (;;) { for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & eventmask) == 0) continue; ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(ecp->client); if (ep == NULL) return; ep->type = type; ep->wid = wp->id; ep->subwid = subwid; ep->rootx = cursorx; ep->rooty = cursory; ep->x = cursorx - wp->x; ep->y = cursory - wp->y; ep->buttons = curbuttons; ep->modifiers = modifiers; ep->ch = keyvalue; ep->scancode = scancode; return; /* only one client gets it */ } if ((wp == rootwp) || (wp == kwp) || (wp->nopropmask & eventmask)) return; wp = wp->parent; }}/* * Try to deliver a exposure event to the clients which have selected for it. * This does not send exposure events for unmapped or input-only windows. * Exposure events do not propagate upwards. */voidGsDeliverExposureEvent(GR_WINDOW *wp, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height){ GR_EVENT_EXPOSURE *ep; /* exposure event */ GR_EVENT_CLIENT *ecp; /* current event client */ if (wp->unmapcount || !wp->output) return; for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_EXPOSURE) == 0) continue; GsFreeExposureEvent(ecp->client, wp->id, x, y, width, height); ep = (GR_EVENT_EXPOSURE *) GsAllocEvent(ecp->client); if (ep == NULL) continue; ep->type = GR_EVENT_TYPE_EXPOSURE; ep->wid = wp->id; ep->x = x; ep->y = y; ep->width = width; ep->height = height; }}/* * Search for an enclosed expose event in the specified client's * event queue, and remove it. This is used to prevent multiple expose * events from being delivered, thus providing a more pleasing visual * redraw effect than if the events were all sent. */voidGsFreeExposureEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height){ GR_EVENT_LIST *elp; /* current element list */ GR_EVENT_LIST *prevelp; /* previous element list */ prevelp = NULL; for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) { if (elp->event.type != GR_EVENT_TYPE_EXPOSURE || elp->event.exposure.wid != wid) continue; if (elp->event.exposure.x < x || elp->event.exposure.y < y || elp->event.exposure.x+elp->event.exposure.width > x+width || elp->event.exposure.y+elp->event.exposure.height > y+height) continue; /* * Found one, remove it and put it back on the free list. */ if (prevelp) prevelp->next = elp->next; else client->eventhead = elp->next; if (client->eventtail == elp) client->eventtail = prevelp; elp->next = eventfree; eventfree = elp; return; }}/* * Try to deliver an update event to the clients which have selected for it. */void GsDeliverUpdateEvent(GR_WINDOW *wp, GR_UPDATE_TYPE utype, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height){ GR_EVENT_MASK cmask = GR_EVENT_MASK_UPDATE; GR_EVENT_UPDATE *ep; /* update event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW_ID id = wp->id; int lcount = 0; /* adjust reported x,y to be parent-relative*/ if (wp->parent) { x -= wp->parent->x; y -= wp->parent->y; }update_again: for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & cmask) == 0) continue; ep = (GR_EVENT_UPDATE *) GsAllocEvent(ecp->client); if (ep == NULL) continue; ep->type = lcount? GR_EVENT_TYPE_CHLD_UPDATE: GR_EVENT_TYPE_UPDATE; ep->utype = utype; ep->wid = wp->id; /* GrSelectEvents window id*/ ep->subwid = id; /* update window id*/ ep->x = x; ep->y = y; ep->width = width; ep->height = height; } /* If we are currently checking the window updated, go back and * check its parent too */ if (!lcount++) { wp = wp->parent; /* check for NULL on root window id*/ if (wp == NULL) return; cmask = GR_EVENT_MASK_CHLD_UPDATE; goto update_again; }}/* * Try to deliver a general event such as focus in, focus out, mouse enter, * or mouse exit to the clients which have selected for it. These events * only have the window id as data, and do not propagate upwards. */void GsDeliverGeneralEvent(GR_WINDOW *wp, GR_EVENT_TYPE type, GR_WINDOW *other){ GR_EVENT_GENERAL *gp; /* general event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_EVENT_MASK eventmask; /* event mask */ eventmask = GR_EVENTMASK(type); if (eventmask == 0) return; for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & eventmask) == 0) continue; gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = type; gp->wid = wp->id; if (other) gp->otherid = other->id; else gp->otherid = 0; }}/* * Deliver a portrait mode changed event to all windows which * have selected for it. */void GsDeliverPortraitChangedEvent(void){ GR_WINDOW *wp; GR_EVENT_GENERAL *gp; GR_EVENT_CLIENT *ecp; for (wp=listwp; wp; wp=wp->next) { for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_PORTRAIT_CHANGED) == 0) continue; gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_PORTRAIT_CHANGED; gp->wid = wp->id; gp->otherid = 0; } }}/* * Deliver a Screen Saver event. There is only one parameter- activate the * screen saver or deactivate it. We only deliver it to the root window, * but we do send it to every client which has selected for it (because the * program which starts the screen saver on an activate event might not also * be the screen saver program which wants to catch the deactivate event). */void GsDeliverScreenSaverEvent(GR_BOOL activate){ GR_EVENT_SCREENSAVER *gp; /* screensaver event */ GR_EVENT_CLIENT *ecp; /* current event client */ for (ecp = rootwp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_SCREENSAVER) == 0) continue; gp = (GR_EVENT_SCREENSAVER *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_SCREENSAVER; gp->activate = activate; }}/* * Deliver a client data request event. Delivered to the clients who have * selected for this event on the specified window only. */voidGsDeliverClientDataReqEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial, GR_MIMETYPE mimetype){ GR_EVENT_CLIENT_DATA_REQ *gp; /* client data request event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW *wp; if(!(wp = GsFindWindow(wid))) return; for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA_REQ) == 0) continue; gp = (GR_EVENT_CLIENT_DATA_REQ *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_CLIENT_DATA_REQ; gp->wid = wid; gp->rid = rid; gp->serial = serial; gp->mimetype = mimetype; continue; }}/* * Deliver a client data event. Delivered to the clients who have selected for * this event on the specified window only. */voidGsDeliverClientDataEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial, GR_LENGTH len, GR_LENGTH thislen, void *data){ GR_EVENT_CLIENT_DATA *gp; /* client data request event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW *wp; if(!(wp = GsFindWindow(wid))) return; for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA) == 0) continue; gp = (GR_EVENT_CLIENT_DATA *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_CLIENT_DATA; gp->wid = wid; gp->rid = rid; gp->serial = serial; gp->len = len; gp->datalen = thislen; if(!(gp->data = malloc(thislen))) { GsError(GR_ERROR_MALLOC_FAILED, wid); return; } memcpy(gp->data, data, thislen); continue; }}/* * Search for a matching mouse position event in the specified client's * event queue, and remove it. This is used to prevent multiple position * events from being delivered, thus providing a more efficient rubber- * banding effect than if the mouse motion events were all sent. */voidGsFreePositionEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_WINDOW_ID subwid){ GR_EVENT_LIST *elp; /* current element list */ GR_EVENT_LIST *prevelp; /* previous element list */ prevelp = NULL; for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) { if (elp->event.type != GR_EVENT_TYPE_MOUSE_POSITION) continue; if (elp->event.mouse.wid != wid) continue; if (elp->event.mouse.subwid != subwid) continue; /* * Found one, remove it and put it back on the free list. */ if (prevelp) prevelp->next = elp->next; else client->eventhead = elp->next; if (client->eventtail == elp) client->eventtail = prevelp; elp->next = eventfree; eventfree = elp; return; }}/* * Deliver a "selection owner changed" event to all windows which have * selected for it. We deliver this event to all clients which have selected * to receive GR_EVENT_TYPE_SELECTION_CHANGED events for the window of the * _previous_ selection owner. */void GsDeliverSelectionChangedEvent(GR_WINDOW_ID old_owner, GR_WINDOW_ID new_owner){ GR_EVENT_SELECTION_CHANGED *gp; /* selection changed event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW *wp; if(!(wp = GsFindWindow(old_owner))) return; for (ecp = wp->eventclients; ecp; ecp = ecp->next) { if ((ecp->eventmask & GR_EVENT_MASK_SELECTION_CHANGED) == 0) continue; fprintf(stderr, "Delivering a selection changed event\n"); gp = (GR_EVENT_SELECTION_CHANGED *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_SELECTION_CHANGED; gp->new_owner = new_owner; }}void GsDeliverTimerEvent (GR_CLIENT *client, GR_WINDOW_ID wid, GR_TIMER_ID tid){ GR_EVENT_TIMER *event; /* general event */ GR_EVENT_CLIENT *ecp; /* current event client */ GR_WINDOW *wp; /* current window */ if ((wp = GsFindWindow (wid)) == NULL) { return; } for (ecp = wp->eventclients; ecp != NULL; ecp = ecp->next) { if ((ecp->client == client) && ((ecp->eventmask & GR_EVENT_MASK_TIMER) != 0)) { event = (GR_EVENT_TIMER*) GsAllocEvent (client); if (event == NULL) { break; } event->type = GR_EVENT_TYPE_TIMER; event->wid = wid; event->tid = tid; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -