📄 client.c
字号:
/** * GrGetSysColor: * @index: an index into the server's colour look up table * @Returns: the colour found at the specified index * * Returns the colour at the specified index into the server's colour look * up table. The colours in the table are those with names like * "GR_COLOR_DESKTOP", "GR_COLOR_ACTIVECAPTION", "GR_COLOR_APPWINDOW", etc. * as listed in nano-X.h */GR_COLORGrGetSysColor(int index){ nxGetSysColorReq *req; GR_COLOR color; req = AllocReq(GetSysColor); req->index = index; if(GrTypedReadBlock(&color, sizeof(color),GrNumGetSysColor) == -1) return 0; return color;}/** * GrGetFontInfo: * @fontno: the font ID number * @fip: pointer to a GR_FONT_INFO structure * * Fills in the specified GR_FONT_INFO structure with information regarding * the specified font. */void GrGetFontInfo(GR_FONT_ID fontno, GR_FONT_INFO *fip){ nxGetFontInfoReq *req; req = AllocReq(GetFontInfo); req->fontid = fontno; GrTypedReadBlock(fip, sizeof(GR_FONT_INFO),GrNumGetFontInfo);}/** * GrGetGCInfo: * @gc: a graphics context * @gcip: pointer to a GR_GC_INFO structure * * Fills in the specified GR_GC_INFO structure with information regarding the * specified graphics context. */void GrGetGCInfo(GR_GC_ID gc, GR_GC_INFO *gcip){ nxGetGCInfoReq *req; req = AllocReq(GetGCInfo); req->gcid = gc; GrTypedReadBlock(gcip, sizeof(GR_GC_INFO),GrNumGetGCInfo);}/** * GrGetGCTextSize: * @gc: the graphics context * @str: pointer to a text string * @count: the length of the string * @flags: text rendering flags (GR_TF*) * @retwidth: pointer to the variable the width will be returned in * @retheight: pointer to the variable the height will be returned in * @retbase: pointer to the variable the baseline height will be returned in * * Calculates the dimensions of the specified text string using the current font * and flags in the specified graphics context. The count argument can be -1 * if the string is null terminated. */void GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags, GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase){ nxGetGCTextSizeReq *req; int size; if(count == -1 && (flags&MWTF_PACKMASK) == MWTF_ASCII) count = strlen((char *)str); size = nxCalcStringBytes(str, count, flags); req = AllocReqExtra(GetGCTextSize, size); req->gcid = gc; req->flags = flags; memcpy(GetReqData(req), str, size); GrTypedReadBlock(retwidth, sizeof(*retwidth),GrNumGetGCTextSize); GrReadBlock(retheight, sizeof(*retheight)); GrReadBlock(retbase, sizeof(*retbase));}/** * GrRegisterInput: * @fd: the file descriptor to monitor * * Register an extra file descriptor to monitor in the main select() call. * An event will be returned when the fd has data waiting to be read if that * event has been selected for. */void GrRegisterInput(int fd){ ACCESS_PER_THREAD_DATA() if (fd < 0) return; FD_SET(fd, ®fdset); if (fd > regfdmax) regfdmax = fd + 1;}/** * GrUnregisterInput: * @fd: the file descriptor to stop monitoring * * Stop monitoring a file descriptor (previously registered with * GrRegisterInput()) in the main select() call. */voidGrUnregisterInput(int fd){ int i, max; ACCESS_PER_THREAD_DATA() /* unregister all inputs if fd is -1 */ if (fd == -1) { FD_ZERO(®fdset); regfdmax = -1; return; } FD_CLR(fd, ®fdset); /* recalculate the max file descriptor */ for (i = 0, max = regfdmax, regfdmax = -1; i < max; i++) if (FD_ISSET(i, ®fdset)) regfdmax = i + 1;}/** * GrPrepareSelect: * @maxfd: pointer to a variable which the highest in use fd will be written to * @rfdset: pointer to the file descriptor set structure to use * * Prepare for a GrServiceSelect function by asking the server to send the next * event but not waiting around for it to arrive and initialising the * specified fd_set structure with the client/server socket descriptor and any * previously registered external file descriptors. Also compares the current * contents of maxfd, the client/server socket descriptor, and the previously * registered external file descriptors, and returns the highest of them in * maxfd. */voidGrPrepareSelect(int *maxfd,void *rfdset){ fd_set *rfds = rfdset; int fd; ACCESS_PER_THREAD_DATA() AllocReq(GetNextEvent); GrFlush(); FD_SET(nxSocket, rfds); if(nxSocket > *maxfd) *maxfd = nxSocket; /* handle registered input file descriptors*/ for (fd = 0; fd < regfdmax; fd++) { if (FD_ISSET(fd, ®fdset)) { FD_SET(fd, rfds); if (fd > *maxfd) *maxfd = fd; } }}/** * GrServiceSelect: * @rfdset: pointer to the file descriptor set to monitor * @fncb: pointer to the function to call when an event needs handling * * Used by GrMainLoop() to call the specified callback function when an * event arrives or there is data waiting on an external fd specified by * GrRegisterInput(). */voidGrServiceSelect(void *rfdset, GR_FNCALLBACKEVENT fncb){ fd_set * rfds = rfdset; int fd; GR_EVENT ev; ACCESS_PER_THREAD_DATA() /* Clean out any event that might have arrived while waiting * for other data, for instance by doing Nano-X requests * between GrPrepareSelect() and GrServiceSelect(), or when * an event is generated in Nano-X at the same time as the * client wakes up for some reason and calls Nano-X functions. */ if (evlist) { /*DPRINTF("nxclient: Handling queued event\n");*/ GetNextQueuedEvent(&ev); CheckErrorEvent(&ev); fncb(&ev); } else { if(FD_ISSET(nxSocket, rfds)) { GrTypedReadBlock(&ev, sizeof(ev),GrNumGetNextEvent); GrCheckForClientData(&ev); CheckErrorEvent(&ev); fncb(&ev); } } /* check for input on registered file descriptors */ for (fd = 0; fd < regfdmax; fd++) { if (FD_ISSET(fd, ®fdset) && FD_ISSET(fd, rfds)) { ev.type = GR_EVENT_TYPE_FDINPUT; ev.fdinput.fd = fd; fncb(&ev); } }}/** * GrMainLoop: * @fncb: * * A convenience function which calls the specified callback function whenever * an event arrives or there is data to be read on a file descriptor previously * specified by GrRegisterInput(). Currently never returns. */voidGrMainLoop(GR_FNCALLBACKEVENT fncb){ fd_set rfds; int setsize = 0; for(;;) { FD_ZERO(&rfds); GrPrepareSelect(&setsize, &rfds); if(select(setsize+1, &rfds, NULL, NULL, NULL) > 0) GrServiceSelect(&rfds, fncb); }}/** * GrGetNextEvent: * @ep: pointer to the GR_EVENT structure to return the event in * * Gets the next event from the event queue and places it in the specified * GR_EVENT structure. If the queue is currently empty, we sleep until the * next event arrives from the server or input is read on a file descriptor * previously specified by GrRegisterInput(). */void GrGetNextEvent(GR_EVENT *ep){ GrGetNextEventTimeout(ep, 0L);}/** * GrGetNextEventTimeout: * @ep: pointer to the GR_EVENT structure to return the event in * @timeout: the number of milliseconds to wait before timing out * * Gets the next event from the event queue and places it in the specified * GR_EVENT structure. If the queue is currently empty, we sleep until the * next event arrives from the server, input is read on a file descriptor * previously specified by GrRegisterInput(), or a timeout occurs. Note * that a value of 0 for the timeout parameter doesn't mean "timeout after 0 * milliseconds" but is in fact a magic number meaning "never time out". */voidGrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout){ fd_set rfds; int setsize = 0; int e; struct timeval to; ACCESS_PER_THREAD_DATA() if (evlist) { /*DPRINTF("nxclient %d: Returning queued event\n",getpid());*/ GetNextQueuedEvent(ep); CheckErrorEvent(ep); return; } FD_ZERO(&rfds); /* * This will cause a GrGetNextEvent to be sent down the wire. * If we timeout before the server responds, and then * call this procedure again, and the server has more than * one event waiting for this process, then more than one * event will be written on the socket by the server. At * that point, a single stored event won't work, and the * client needs an event queue. */ GrPrepareSelect(&setsize, &rfds); if (timeout) { to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; } if((e = select(setsize+1, &rfds, NULL, NULL, timeout ? &to : NULL))>0) { int fd; if(FD_ISSET(nxSocket, &rfds)) { /* * This will never be GR_EVENT_NONE with the current * implementation. */ GrTypedReadBlock(ep, sizeof(*ep),GrNumGetNextEvent); GrCheckForClientData(ep); CheckErrorEvent(ep); return; } /* check for input on registered file descriptors */ for (fd = 0; fd < regfdmax; fd++) { if (FD_ISSET(fd, ®fdset) && FD_ISSET(fd, &rfds)) { ep->type = GR_EVENT_TYPE_FDINPUT; ep->fdinput.fd = fd; break; } } } else if (e == 0) { /* * Timeout has occured. We currently return a timeout event * regardless of whether the client has selected for it. */ ep->type = GR_EVENT_TYPE_TIMEOUT; } else { if(errno == EINTR) { ep->type = GR_EVENT_TYPE_NONE; } else { EPRINTF("nxclient: select failed\n"); GrClose(); exit(1); } }}/** * GrCheckNextEvent: * @ep: pointer to the GR_EVENT structure to return the event in * * Gets the next event from the event queue if there is one, or returns * immediately with an event type of GR_EVENT_TYPE_NONE if it is empty. */void GrCheckNextEvent(GR_EVENT *ep){ ACCESS_PER_THREAD_DATA() if (evlist) { /*DPRINTF("nxclient %d: Returning queued event\n",getpid());*/ GetNextQueuedEvent(ep); CheckErrorEvent(ep); return; } AllocReq(CheckNextEvent); GrTypedReadBlock(ep, sizeof(*ep),GrNumGetNextEvent); GrCheckForClientData(ep); CheckErrorEvent(ep);}/** * GrPeekEvent: * @ep: pointer to the GR_EVENT structure to return the event in * @Returns: 1 if an event was returned, or 0 if the queue was empty * * Fills in the specified event structure with a copy of the next event on the * queue, without actually removing it from the queue. An event type of * GR_EVENT_TYPE_NONE is given if the queue is empty. */int GrPeekEvent(GR_EVENT *ep){ int ret; ACCESS_PER_THREAD_DATA() if (evlist) { *ep = evlist->event; CheckErrorEvent(ep); return 1; } AllocReq(PeekEvent); GrTypedReadBlock(ep, sizeof(*ep),GrNumPeekEvent); GrCheckForClientData(ep); ret = GrReadByte(); CheckErrorEvent(ep); return ret;}/** * GrPeekWaitEvent: * @ep: pointer to the GR_EVENT structure to return the event in * * Wait until an event is available for a client, and then peek at it. */voidGrPeekWaitEvent(GR_EVENT *ep){ EVENT_LIST * elp; ACCESS_PER_THREAD_DATA() if (evlist) { *ep = evlist->event; CheckErrorEvent(ep); return; } /* no events, wait for next event*/ GrGetNextEvent(ep); /* add event back on head of list*/ elp = malloc(sizeof(EVENT_LIST)); if (elp) { elp->event = *ep; elp->next = evlist; } /* peek at it*/ GrPeekEvent(ep);}/** * GrSelectEvents: * @wid: the ID of the window to set the event mask of * @eventmask: a bit field specifying the desired event mask * * Select the event types which should be returned for the specified window. */void GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask){ nxSelectEventsReq *req; req = AllocReq(SelectEvents); req->windowid = wid; req->eventmask = eventmask;}/** * GrNewWindow: * @parent: the ID of the parent window * @x: the X coordinate of the new window relative to the parent window * @y: the Y coordinate of the new window relative to the parent window * @width: the width of the new window * @height: the height of the new window * @bordersize: the width of the window border * @background: the colour of the window background * @bordercolor: the colour of the window border * @Returns: the ID of the newly created window * * Create a new window with the specified parent and window attributes. */GR_WINDOW_IDGrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height, GR_SIZE bordersize, GR_COLOR background, GR_COLOR bordercolor){ nxNewWindowReq *req; GR_WINDOW_ID wid; req = AllocReq(NewWindow); req->parentid = parent; req->x = x; req->y = y; req->width = width; req->height = height; req->backgroundcolor = background; req->bordercolor = bordercolor; req->bordersize = bordersize; if(GrTypedReadBlock(&wid, sizeof(wid),GrNumNewWindow) == -1) return 0; return wid;} /** * GrNewPixmap: * @width: the width of the pixmap * @height: the height of the pixmap * @addr: currently unused in client/server mode * @Returns: the ID of the newly created pixmap * * Create a new server side pixmap (an offscreen drawing area which can be * copied into a window using a GrCopyArea call) of the specified width and * height. *//* FIXME: Add support for shared memory... */GR_WINDOW_IDGrNewPixmap(GR_SIZE width, GR_SIZE height, void *addr){ nxNewPixmapReq *req; GR_WINDOW_ID wid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -