📄 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.
*/
void
GsDeliverExposureEvent(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.
*/
void
GsFreeExposureEvent(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.
*/
void
GsDeliverClientDataReqEvent(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.
*/
void
GsDeliverClientDataEvent(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.
*/
void
GsFreePositionEvent(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 + -