/* * 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; } }
/* * 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 "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; gp = (GR_EVENT_SELECTION_CHANGED *) GsAllocEvent(ecp->client); if (gp == NULL) continue; gp->type = GR_EVENT_TYPE_SELECTION_CHANGED; gp->new_owner = new_owner; } }
/* * Prepare the specified window for drawing into it. * This sets up the clipping regions to just allow drawing into it. * Returns NULL if the drawing is illegal (with an error generated), * or if the window is not mapped. */ GR_WINDOW *GsPrepareWindow(GR_WINDOW_ID wid) { GR_WINDOW *wp; /* found window */ wp = GsFindWindow(wid); if (wp == NULL) return NULL; if (!wp->output) { GsError(GR_ERROR_INPUT_ONLY_WINDOW, wid); return NULL; } if (wp->unmapcount) return NULL; if (wp != clipwp) { /* FIXME: no user region clipping here*/ GsSetClipWindow(wp, NULL, 0); } return wp; }
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; } } }
/* * Prepare to do drawing in a window or pixmap using the specified * graphics context. Returns the drawable pointer if successful, * and the type of drawing id that was supplied. Returns the special value * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless. */ GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp) { GR_WINDOW *wp; /* found window */ GR_PIXMAP *pp; /* found pixmap */ GR_GC *gcp; /* found graphics context */ GR_FONT *fontp; GR_REGION *regionp; /* user clipping region */ MWCLIPREGION *reg; PMWFONT pf; *retdp = NULL; gcp = GsFindGC(gcid); if (gcp == NULL) return GR_DRAW_TYPE_NONE; /* * If the graphics context is not the current one, then * make it the current one and remember to update it. */ if (gcp != curgcp) { curgcp = gcp; gcp->changed = GR_TRUE; } /* * Look for window or pixmap id */ pp = NULL; wp = GsFindWindow(id); if (wp == NULL) { pp = GsFindPixmap(id); if (pp == NULL) return GR_DRAW_TYPE_NONE; #if DYNAMICREGIONS reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres); /* intersect with user region if any*/ if (gcp->regionid) { regionp = GsFindRegion(gcp->regionid); if (regionp) GdIntersectRegion(reg, reg, regionp->rgn); } GdSetClipRegion(pp->psd, reg); #else { MWCLIPRECT cliprect; /* FIXME: setup pixmap clipping, different from windows*/ cliprect.x = 0; cliprect.y = 0; cliprect.width = pp->psd->xvirtres; cliprect.height = pp->psd->yvirtres; GdSetClipRects(pp->psd, 1, &cliprect); } #endif /* reset clip cache for next window draw*/ clipwp = NULL; } else { if (!wp->output) { GsError(GR_ERROR_INPUT_ONLY_WINDOW, id); return GR_DRAW_TYPE_NONE; } if (wp->unmapcount) return GR_DRAW_TYPE_NONE; /* * If the window is not the currently clipped one, * then make it the current one and define its clip rectangles. */ if (wp != clipwp || gcp->changed) { /* find user region for intersect*/ if (gcp->regionid) regionp = GsFindRegion(gcp->regionid); else regionp = NULL; /* * Special handling if user region is not at offset 0,0 */ if (regionp && (gcp->xoff || gcp->yoff)) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GsSetClipWindow(wp, local, gcp->mode & ~GR_MODE_DRAWMASK); GdDestroyRegion(local); } else { GsSetClipWindow(wp, regionp? regionp->rgn: NULL, gcp->mode & ~GR_MODE_DRAWMASK); } } } /* * If the graphics context has been changed, then tell the * device driver about it. */ if (gcp->changed) { GdSetForeground(GdFindColor(gcp->foreground)); GdSetBackground(GdFindColor(gcp->background)); GdSetMode(gcp->mode & GR_MODE_DRAWMASK); GdSetUseBackground(gcp->usebackground); fontp = GsFindFont(gcp->fontid); pf = fontp? fontp->pfont: stdfont; GdSetFont(pf); gcp->changed = GR_FALSE; } *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp; return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP; }
/* * Prepare to do drawing in a window or pixmap using the specified * graphics context. Returns the drawable pointer if successful, * and the type of drawing id that was supplied. Returns the special value * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless. */ GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp) { GR_WINDOW *wp; /* found window */ GR_PIXMAP *pp; /* found pixmap */ GR_GC *gcp; /* found graphics context */ GR_REGION *regionp; /* user clipping region */ MWCLIPREGION*reg; *retdp = NULL; gcp = GsFindGC(gcid); if (gcp == NULL) return GR_DRAW_TYPE_NONE; /* * If the graphics context is not the current one, then * make it the current one and remember to update it. */ if (gcp != curgcp) { curgcp = gcp; gcp->changed = GR_TRUE; } /* * Look for window or pixmap id */ pp = NULL; wp = GsFindWindow(id); if (wp == NULL) { pp = GsFindPixmap(id); if (pp == NULL) return GR_DRAW_TYPE_NONE; havepixmap: #if DYNAMICREGIONS reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres); /* intersect with user region if any*/ if (gcp->regionid) { regionp = GsFindRegion(gcp->regionid); if (regionp) { /* handle pixmap offsets*/ if (gcp->xoff || gcp->yoff) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GdIntersectRegion(reg, reg, local); GdDestroyRegion(local); } else GdIntersectRegion(reg, reg, regionp->rgn); } } GdSetClipRegion(pp->psd, reg); #else { MWCLIPRECT cliprect; /* FIXME: setup pixmap clipping, different from windows*/ cliprect.x = 0; cliprect.y = 0; cliprect.width = pp->psd->xvirtres; cliprect.height = pp->psd->yvirtres; GdSetClipRects(pp->psd, 1, &cliprect); } #endif /* reset clip cache for next window draw*/ clipwp = NULL; } else { if (!wp->output) { GsError(GR_ERROR_INPUT_ONLY_WINDOW, id); return GR_DRAW_TYPE_NONE; } /* check if buffered window*/ if (wp->props & GR_WM_PROPS_BUFFERED) { pp = wp->buffer; wp = NULL; goto havepixmap; /* draw into pixmap buffer*/ } if (!wp->realized) return GR_DRAW_TYPE_NONE; /* * If the window is not the currently clipped one, * then make it the current one and define its clip rectangles. */ if (wp != clipwp || gcp->changed) { #if DYNAMICREGIONS /* find user region for intersect*/ regionp = gcp->regionid? GsFindRegion(gcp->regionid): NULL; /* Special handling if user region is not at offset 0,0*/ if (regionp && (gcp->xoff || gcp->yoff)) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GsSetClipWindow(wp, local, gcp->mode & ~GR_MODE_DRAWMASK); GdDestroyRegion(local); } else GsSetClipWindow(wp, regionp? regionp->rgn: NULL, gcp->mode & ~GR_MODE_DRAWMASK); #else GsSetClipWindow(wp, NULL, gcp->mode & ~GR_MODE_DRAWMASK); #endif /* DYNAMICREGIONS*/ } } /* * If the graphics context has been changed, then tell the * device driver about it. */ if (gcp->changed) { PSD psd = (wp ? wp->psd : pp->psd); uint32_t mask; int count; if (gcp->linestyle == GR_LINE_SOLID) { mask = 0; count = 0; } else { mask = gcp->dashmask; count = gcp->dashcount; } if (gcp->fgispixelval) GdSetForegroundPixelVal(psd, gcp->foreground); else GdSetForegroundColor(psd, gcp->foreground); if (gcp->bgispixelval) GdSetBackgroundPixelVal(psd, gcp->background); else GdSetBackgroundColor(psd, gcp->background); GdSetMode(gcp->mode & GR_MODE_DRAWMASK); GdSetUseBackground(gcp->usebackground); #if MW_FEATURE_SHAPES GdSetDash(&mask, &count); GdSetFillMode(gcp->fillmode); GdSetTSOffset(gcp->ts_offset.x, gcp->ts_offset.y); switch(gcp->fillmode) { case GR_FILL_STIPPLE: case GR_FILL_OPAQUE_STIPPLE: GdSetStippleBitmap(gcp->stipple.bitmap, gcp->stipple.width, gcp->stipple.height); break; case GR_FILL_TILE: GdSetTilePixmap(gcp->tile.psd, gcp->tile.width, gcp->tile.height); break; } #endif gcp->changed = GR_FALSE; } *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp; return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP; }
/* * Deliver a keyboard event to one of the clients which have selected for it. * Only the first client found gets the event (no duplicates are sent). The * window the event is delivered to is either the smallest one containing * the mouse coordinates, or else one of its direct ancestors (if such a * 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; GR_GRABBED_KEY *keygrab; eventmask = GR_EVENTMASK(type); if (eventmask == 0) return; GsResetScreenSaver(); /* Check for grabbed keystroke. * - GR_GRAB_HOTKEY events are sent (possibly multiple times) here, * and the loop terminates normally with keygrab==NULL so the * event is also delivered normally. * - GR_GRAB_HOTKEY_EXCLUSIVE sends the hotkey events then returns. * - Other exclusive events (GR_GRAB_EXCLUSIVE_MOUSE and GR_GRAB_EXCLUSIVE) * cause the loop to terminate with keygrab != NULL. The checking * for these events happens after the loop. * * Note: This algorithm requires any GR_GRAB_HOTKEY grabs to be * listed _after_ any exclusive grabs for the same key. The * GrGrabKey() and GrUngrabKey() methods ensure this property holds. */ for (keygrab = list_grabbed_keys; keygrab != NULL; keygrab = keygrab->next) { if (keygrab->key == keyvalue) { if ((keygrab->type == GR_GRAB_HOTKEY) || (keygrab->type == GR_GRAB_HOTKEY_EXCLUSIVE)) { ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(keygrab->owner); if (ep == NULL) continue; ep->type = type; ep->wid = keygrab->wid; ep->subwid = keygrab->wid; ep->rootx = cursorx; ep->rooty = cursory; ep->x = cursorx; ep->y = cursory; ep->buttons = curbuttons; ep->modifiers = modifiers; ep->ch = keyvalue; ep->scancode = scancode; ep->hotkey = GR_TRUE; if (keygrab->type == GR_GRAB_HOTKEY_EXCLUSIVE) return; /* only one client gets it */ } else { /* GR_GRAB_EXCLUSIVE or GR_GRAB_EXCLUSIVE_MOUSE */ break; /* found it, exit the loop. */ } } } /* Handle a grabbed key: * The associated window must be an ancestor of the focused window, * or (for GR_GRAB_EXCLUSIVE_MOUSE only) a descendent that contains the * pointer. */ if (keygrab != NULL) { /* The key grab must be of type GR_GRAB_EXCLUSIVE or * GR_GRAB_EXCLUSIVE_MOUSE */ /* Find the window that has the grab */ wp = GsFindWindow(keygrab->wid); if (wp == NULL) return; /* Key is reserved by window that doesn't exist. */ /* See if the grabbing window is an ancestor of the focussed window. */ kwp = focuswp; while (kwp != wp && kwp != rootwp) kwp = kwp->parent; /* Want to send event if: * GR_GRAB_EXCLUSIVE: grabbing window is an ancestor of focussed window * GR_GRAB_EXCLUSIVE_MOUSE: same as GR_GRAB_EXCLUSIVE OR * the mouse is in the grabbing window. */ if (kwp != wp && (keygrab->type != GR_GRAB_EXCLUSIVE_MOUSE || wp != mousewp)) return; subwid = wp->id; } else { /* 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; ep->hotkey = GR_FALSE; return; /* only one client gets it */ } if ((wp == rootwp) || (wp == kwp) || (wp->nopropmask & eventmask)) return; wp = wp->parent; } }