PageRenderTime 63ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/nx-3.5.0/nx-X11/lib/Xt/NextEvent.c

#
C | 1642 lines | 1287 code | 155 blank | 200 comment | 354 complexity | 8d9108b8f7225afa9260232abc3f57c5 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
  1. /* $Xorg: NextEvent.c,v 1.8 2001/02/09 02:03:55 xorgcvs Exp $ */
  2. /***********************************************************
  3. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  4. Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
  5. All Rights Reserved
  6. Permission to use, copy, modify, and distribute this software and its
  7. documentation for any purpose and without fee is hereby granted,
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in
  10. supporting documentation, and that the names of Digital or Sun not be
  11. used in advertising or publicity pertaining to distribution of the
  12. software without specific, written prior permission.
  13. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  14. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  15. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  16. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  17. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  18. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  19. SOFTWARE.
  20. SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  21. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
  22. NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
  23. ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  24. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  25. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  26. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
  27. THE USE OR PERFORMANCE OF THIS SOFTWARE.
  28. ******************************************************************/
  29. /*
  30. Copyright 1987, 1988, 1994, 1998, 2001 The Open Group
  31. Permission to use, copy, modify, distribute, and sell this software and its
  32. documentation for any purpose is hereby granted without fee, provided that
  33. the above copyright notice appear in all copies and that both that
  34. copyright notice and this permission notice appear in supporting
  35. documentation.
  36. The above copyright notice and this permission notice shall be included in
  37. all copies or substantial portions of the Software.
  38. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  39. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  40. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  41. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  42. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  43. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  44. Except as contained in this notice, the name of The Open Group shall not be
  45. used in advertising or otherwise to promote the sale, use or other dealings
  46. in this Software without prior written authorization from The Open Group.
  47. */
  48. /**************************************************************************/
  49. /* */
  50. /* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
  51. /* */
  52. /* NX-X11, NX protocol compression and NX extensions to this software */
  53. /* are copyright of NoMachine. Redistribution and use of the present */
  54. /* software is allowed according to terms specified in the file LICENSE */
  55. /* which comes in the source distribution. */
  56. /* */
  57. /* Check http://www.nomachine.com/licensing.html for applicability. */
  58. /* */
  59. /* NX and NoMachine are trademarks of Medialogic S.p.A. */
  60. /* */
  61. /* All rights reserved. */
  62. /* */
  63. /**************************************************************************/
  64. /* $XFree86: xc/lib/Xt/NextEvent.c,v 3.26 2002/06/04 21:55:42 dawes Exp $ */
  65. #ifdef HAVE_CONFIG_H
  66. #include <config.h>
  67. #endif
  68. #include "IntrinsicI.h"
  69. #include <stdio.h>
  70. #include <errno.h>
  71. #ifdef __UNIXOS2__
  72. #include <sys/time.h>
  73. #endif
  74. static TimerEventRec* freeTimerRecs;
  75. static WorkProcRec* freeWorkRecs;
  76. static SignalEventRec* freeSignalRecs;
  77. /* Some systems running NTP daemons are known to return strange usec
  78. * values from gettimeofday.
  79. */
  80. #ifndef NEEDS_NTPD_FIXUP
  81. # if defined(sun) || defined(MOTOROLA) || (defined(__osf__) && defined(__alpha))
  82. # define NEEDS_NTPD_FIXUP 1
  83. # else
  84. # define NEEDS_NTPD_FIXUP 0
  85. # endif
  86. #endif
  87. #if NEEDS_NTPD_FIXUP
  88. #define FIXUP_TIMEVAL(t) { \
  89. while ((t).tv_usec >= 1000000) { \
  90. (t).tv_usec -= 1000000; \
  91. (t).tv_sec++; \
  92. } \
  93. while ((t).tv_usec < 0) { \
  94. if ((t).tv_sec > 0) { \
  95. (t).tv_usec += 1000000; \
  96. (t).tv_sec--; \
  97. } else { \
  98. (t).tv_usec = 0; \
  99. break; \
  100. } \
  101. }}
  102. #else
  103. #define FIXUP_TIMEVAL(t)
  104. #endif /*NEEDS_NTPD_FIXUP*/
  105. /*
  106. * Private routines
  107. */
  108. #define ADD_TIME(dest, src1, src2) { \
  109. if(((dest).tv_usec = (src1).tv_usec + (src2).tv_usec) >= 1000000) {\
  110. (dest).tv_usec -= 1000000;\
  111. (dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1 ; \
  112. } else { (dest).tv_sec = (src1).tv_sec + (src2).tv_sec ; \
  113. if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
  114. (dest).tv_sec --;(dest).tv_usec += 1000000; } } }
  115. #define TIMEDELTA(dest, src1, src2) { \
  116. if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\
  117. (dest).tv_usec += 1000000;\
  118. (dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\
  119. } else (dest).tv_sec = (src1).tv_sec - (src2).tv_sec; }
  120. #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  121. || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))
  122. #define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  123. || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec)))
  124. #ifdef USE_POLL
  125. #ifndef XT_DEFAULT_FDLIST_SIZE
  126. #define XT_DEFAULT_FDLIST_SIZE 32
  127. #endif
  128. #endif
  129. static void AdjustHowLong (
  130. unsigned long *howlong,
  131. struct timeval *start_time)
  132. {
  133. struct timeval new_time, time_spent, lstart_time;
  134. lstart_time = *start_time;
  135. X_GETTIMEOFDAY (&new_time);
  136. FIXUP_TIMEVAL(new_time);
  137. TIMEDELTA(time_spent, new_time, lstart_time);
  138. if(*howlong <= (unsigned long)(time_spent.tv_sec*1000+time_spent.tv_usec/1000))
  139. *howlong = (unsigned long)0; /* Timed out */
  140. else
  141. *howlong -= (time_spent.tv_sec*1000+time_spent.tv_usec/1000);
  142. }
  143. typedef struct {
  144. struct timeval cur_time;
  145. struct timeval start_time;
  146. struct timeval wait_time;
  147. struct timeval new_time;
  148. struct timeval time_spent;
  149. struct timeval max_wait_time;
  150. #ifndef USE_POLL
  151. struct timeval *wait_time_ptr;
  152. #else
  153. int poll_wait;
  154. #endif
  155. } wait_times_t, *wait_times_ptr_t;
  156. static struct timeval zero_time = { 0 , 0};
  157. #ifndef USE_POLL
  158. static fd_set zero_fd;
  159. #else
  160. #define X_BLOCK -1
  161. #define X_DONT_BLOCK 0
  162. #endif
  163. static void InitTimes (
  164. Boolean block,
  165. unsigned long* howlong,
  166. wait_times_ptr_t wt)
  167. {
  168. if (block) {
  169. X_GETTIMEOFDAY (&wt->cur_time);
  170. FIXUP_TIMEVAL(wt->cur_time);
  171. wt->start_time = wt->cur_time;
  172. if(howlong == NULL) { /* special case for ever */
  173. #ifndef USE_POLL
  174. wt->wait_time_ptr = NULL;
  175. #else
  176. wt->poll_wait = X_BLOCK;
  177. #endif
  178. } else { /* block until at most */
  179. wt->max_wait_time.tv_sec = *howlong/1000;
  180. wt->max_wait_time.tv_usec = (*howlong %1000)*1000;
  181. #ifndef USE_POLL
  182. wt->wait_time_ptr = &wt->max_wait_time;
  183. #else
  184. wt->poll_wait = *howlong;
  185. #endif
  186. }
  187. } else { /* don't block */
  188. wt->max_wait_time = zero_time;
  189. #ifndef USE_POLL
  190. wt->wait_time_ptr = &wt->max_wait_time;
  191. #else
  192. wt->poll_wait = X_DONT_BLOCK;
  193. #endif
  194. }
  195. }
  196. typedef struct {
  197. #ifndef USE_POLL
  198. fd_set rmask, wmask, emask;
  199. int nfds;
  200. #else
  201. struct pollfd* fdlist;
  202. struct pollfd* stack;
  203. int fdlistlen, num_dpys;
  204. #endif
  205. } wait_fds_t, *wait_fds_ptr_t;
  206. static void InitFds (
  207. XtAppContext app,
  208. Boolean ignoreEvents,
  209. Boolean ignoreInputs,
  210. wait_fds_ptr_t wf)
  211. {
  212. int ii;
  213. app->rebuild_fdlist = FALSE;
  214. #ifndef USE_POLL
  215. wf->nfds = app->fds.nfds;
  216. if( !ignoreInputs ) {
  217. wf->rmask = app->fds.rmask;
  218. wf->wmask = app->fds.wmask;
  219. wf->emask = app->fds.emask;
  220. } else
  221. wf->rmask = wf->wmask = wf->emask = zero_fd;
  222. if (!ignoreEvents)
  223. for (ii = 0; ii < app->count; ii++) {
  224. FD_SET (ConnectionNumber(app->list[ii]), &wf->rmask);
  225. }
  226. #else
  227. #ifndef POLLRDNORM
  228. #define POLLRDNORM 0
  229. #endif
  230. #ifndef POLLRDBAND
  231. #define POLLRDBAND 0
  232. #endif
  233. #ifndef POLLWRNORM
  234. #define POLLWRNORM 0
  235. #endif
  236. #ifndef POLLWRBAND
  237. #define POLLWRBAND 0
  238. #endif
  239. #define XPOLL_READ (POLLIN|POLLRDNORM|POLLPRI|POLLRDBAND)
  240. #define XPOLL_WRITE (POLLOUT|POLLWRNORM|POLLWRBAND)
  241. #define XPOLL_EXCEPT 0
  242. if (!ignoreEvents)
  243. wf->fdlistlen = wf->num_dpys = app->count;
  244. else
  245. wf->fdlistlen = wf->num_dpys = 0;
  246. if (!ignoreInputs && app->input_list != NULL) {
  247. int ii;
  248. for (ii = 0; ii < (int) app->input_max; ii++)
  249. if (app->input_list[ii] != NULL)
  250. wf->fdlistlen++;
  251. }
  252. if (!wf->fdlist || wf->fdlist == wf->stack) {
  253. wf->fdlist = (struct pollfd*)
  254. XtStackAlloc (sizeof (struct pollfd) * wf->fdlistlen, wf->stack);
  255. } else {
  256. wf->fdlist = (struct pollfd*)
  257. XtRealloc ((char*) wf->fdlist,
  258. sizeof (struct pollfd) * wf->fdlistlen);
  259. }
  260. if (wf->fdlistlen) {
  261. struct pollfd* fdlp = wf->fdlist;
  262. InputEvent* iep;
  263. if (!ignoreEvents)
  264. for (ii = 0 ; ii < wf->num_dpys; ii++, fdlp++) {
  265. fdlp->fd = ConnectionNumber (app->list[ii]);
  266. fdlp->events = POLLIN;
  267. }
  268. if (!ignoreInputs && app->input_list != NULL)
  269. for (ii = 0; ii < app->input_max; ii++)
  270. if (app->input_list[ii] != NULL) {
  271. iep = app->input_list[ii];
  272. fdlp->fd = ii;
  273. fdlp->events = 0;
  274. for ( ; iep; iep = iep->ie_next) {
  275. if (iep->ie_condition & XtInputReadMask)
  276. fdlp->events |= XPOLL_READ;
  277. if (iep->ie_condition & XtInputWriteMask)
  278. fdlp->events |= XPOLL_WRITE;
  279. if (iep->ie_condition & XtInputExceptMask)
  280. fdlp->events |= XPOLL_EXCEPT;
  281. }
  282. fdlp++;
  283. }
  284. }
  285. #endif
  286. }
  287. static void AdjustTimes (
  288. XtAppContext app,
  289. Boolean block,
  290. unsigned long* howlong,
  291. Boolean ignoreTimers,
  292. wait_times_ptr_t wt)
  293. {
  294. if (app->timerQueue != NULL && !ignoreTimers && block) {
  295. if (IS_AFTER (wt->cur_time, app->timerQueue->te_timer_value)) {
  296. TIMEDELTA (wt->wait_time, app->timerQueue->te_timer_value, wt->cur_time);
  297. if (howlong == NULL || IS_AFTER (wt->wait_time, wt->max_wait_time))
  298. #ifndef USE_POLL
  299. wt->wait_time_ptr = &wt->wait_time;
  300. else
  301. wt->wait_time_ptr = &wt->max_wait_time;
  302. } else
  303. wt->wait_time_ptr = &zero_time;
  304. }
  305. #else
  306. wt->poll_wait = wt->wait_time.tv_sec * 1000 + wt->wait_time.tv_usec / 1000;
  307. else
  308. wt->poll_wait = wt->max_wait_time.tv_sec * 1000 + wt->max_wait_time.tv_usec / 1000;
  309. } else
  310. wt->poll_wait = X_DONT_BLOCK;
  311. }
  312. #endif
  313. }
  314. static int IoWait (
  315. wait_times_ptr_t wt,
  316. wait_fds_ptr_t wf)
  317. {
  318. #ifndef USE_POLL
  319. #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
  320. fprintf(stderr, "Xt::IoWait: Select called with [%d][%p][%p][%p][%p].\n",
  321. wf->nfds, (void *) &wf->rmask, (void *) &wf->wmask, (void *) &wf->emask,
  322. (void *) wt->wait_time_ptr);
  323. #endif
  324. return Select (wf->nfds, &wf->rmask, &wf->wmask, &wf->emask,
  325. wt->wait_time_ptr);
  326. #else
  327. return poll (wf->fdlist, wf->fdlistlen, wt->poll_wait);
  328. #endif
  329. }
  330. static void FindInputs (
  331. XtAppContext app,
  332. wait_fds_ptr_t wf,
  333. int nfds,
  334. Boolean ignoreEvents,
  335. Boolean ignoreInputs,
  336. int* dpy_no,
  337. int* found_input)
  338. {
  339. XtInputMask condition;
  340. InputEvent *ep;
  341. int ii;
  342. #ifndef USE_POLL /* { check ready file descriptors block */
  343. #ifdef XTHREADS
  344. fd_set rmask;
  345. #endif
  346. int dd;
  347. *dpy_no = -1;
  348. *found_input = False;
  349. #ifdef XTHREADS
  350. rmask = app->fds.rmask;
  351. for (dd = app->count; dd-- > 0; )
  352. FD_SET (ConnectionNumber (app->list[dd]), &rmask);
  353. #endif
  354. for (ii = 0; ii < wf->nfds && nfds > 0; ii++) {
  355. condition = 0;
  356. if (FD_ISSET (ii, &wf->rmask)
  357. #ifdef XTHREADS
  358. && FD_ISSET (ii, &rmask)
  359. #endif
  360. ) {
  361. nfds--;
  362. if (!ignoreEvents) {
  363. for (dd = 0; dd < app->count; dd++) {
  364. if (ii == ConnectionNumber (app->list[dd])) {
  365. if (*dpy_no == -1) {
  366. if (XEventsQueued (app->list[dd], QueuedAfterReading ))
  367. *dpy_no = dd;
  368. /*
  369. * An error event could have arrived
  370. * without any real events, or events
  371. * could have been swallowed by Xlib,
  372. * or the connection may be broken.
  373. * We can't tell the difference, so
  374. * assume Xlib will eventually discover
  375. * a broken connection.
  376. */
  377. }
  378. goto ENDILOOP;
  379. }
  380. }
  381. }
  382. condition = XtInputReadMask;
  383. }
  384. if (FD_ISSET (ii, &wf->wmask)
  385. #ifdef XTHREADS
  386. && FD_ISSET (ii, &app->fds.wmask)
  387. #endif
  388. ) {
  389. condition |= XtInputWriteMask;
  390. nfds--;
  391. }
  392. if (FD_ISSET (ii, &wf->emask)
  393. #ifdef XTHREADS
  394. && FD_ISSET (ii, &app->fds.emask)
  395. #endif
  396. ) {
  397. condition |= XtInputExceptMask;
  398. nfds--;
  399. }
  400. if (condition) {
  401. for (ep = app->input_list[ii]; ep; ep = ep->ie_next)
  402. if (condition & ep->ie_condition) {
  403. /* make sure this input isn't already marked outstanding */
  404. InputEvent *oq;
  405. for (oq = app->outstandingQueue; oq; oq = oq->ie_oq)
  406. if (oq == ep)
  407. break;
  408. if (!oq)
  409. {
  410. ep->ie_oq = app->outstandingQueue;
  411. app->outstandingQueue = ep;
  412. }
  413. }
  414. *found_input = True;
  415. }
  416. ENDILOOP: ;
  417. } /* endfor */
  418. #else /* }{ */
  419. struct pollfd* fdlp;
  420. *dpy_no = -1;
  421. *found_input = False;
  422. if (!ignoreEvents) {
  423. fdlp = wf->fdlist;
  424. for (ii = 0; ii < wf->num_dpys; ii++, fdlp++) {
  425. if (*dpy_no == -1 && fdlp->revents & (POLLIN|POLLHUP|POLLERR) &&
  426. #ifdef XTHREADS
  427. !(fdlp->revents & POLLNVAL) &&
  428. #endif
  429. XEventsQueued (app->list[ii], QueuedAfterReading)) {
  430. *dpy_no = ii;
  431. break;
  432. }
  433. }
  434. }
  435. if (!ignoreInputs) {
  436. fdlp = &wf->fdlist[wf->num_dpys];
  437. for (ii = wf->num_dpys; ii < wf->fdlistlen; ii++, fdlp++) {
  438. condition = 0;
  439. if (fdlp->revents) {
  440. if (fdlp->revents & (XPOLL_READ|POLLHUP|POLLERR)
  441. #ifdef XTHREADS
  442. && !(fdlp->revents & POLLNVAL)
  443. #endif
  444. )
  445. condition = XtInputReadMask;
  446. if (fdlp->revents & XPOLL_WRITE)
  447. condition |= XtInputWriteMask;
  448. if (fdlp->revents & XPOLL_EXCEPT)
  449. condition |= XtInputExceptMask;
  450. }
  451. if (condition) {
  452. *found_input = True;
  453. for (ep = app->input_list[fdlp->fd]; ep; ep = ep->ie_next)
  454. if (condition & ep->ie_condition) {
  455. InputEvent *oq;
  456. /* make sure this input isn't already marked outstanding */
  457. for (oq = app->outstandingQueue; oq; oq = oq->ie_oq)
  458. if (oq == ep)
  459. break;
  460. if (!oq)
  461. {
  462. ep->ie_oq = app->outstandingQueue;
  463. app->outstandingQueue = ep;
  464. }
  465. }
  466. }
  467. }
  468. }
  469. #endif /* } */
  470. }
  471. /*
  472. * Routine to block in the toolkit. This should be the only call to select.
  473. *
  474. * This routine returns when there is something to be done.
  475. *
  476. * Before calling this with ignoreInputs==False, app->outstandingQueue should
  477. * be checked; this routine will not verify that an alternate input source
  478. * has not already been enqueued.
  479. *
  480. *
  481. * _XtWaitForSomething( appContext,
  482. * ignoreEvent, ignoreTimers, ignoreInputs, ignoreSignals,
  483. * block, drop_lock, howlong)
  484. * XtAppContext app; (Displays to check wait on)
  485. *
  486. * Boolean ignoreEvents; (Don't return if XEvents are available
  487. * Also implies forget XEvents exist)
  488. *
  489. * Boolean ignoreTimers; (Ditto for timers)
  490. *
  491. * Boolean ignoreInputs; (Ditto for input callbacks )
  492. *
  493. * Boolean ignoreSignals; (Ditto for signals)
  494. *
  495. * Boolean block; (Okay to block)
  496. *
  497. * Boolean drop_lock (drop lock before going into select/poll)
  498. *
  499. * TimeVal howlong; (howlong to wait for if blocking and not
  500. * doing Timers... Null means forever.
  501. * Maybe should mean shortest of both)
  502. * Returns display for which input is available, if any
  503. * and if ignoreEvents==False, else returns -1
  504. *
  505. * if ignoring everything && block=True && howlong=NULL, you'll have
  506. * lots of time for coffee; better not try it! In fact, it probably
  507. * makes little sense to do this regardless of the value of howlong
  508. * (bottom line is, we don't bother checking here).
  509. *
  510. * If drop_lock is FALSE, the app->lock->mutex is not unlocked before
  511. * entering select/poll. It is illegal for drop_lock to be FALSE if
  512. * ignoreTimers, ignoreInputs, or ignoreSignals is FALSE.
  513. */
  514. int _XtWaitForSomething(
  515. XtAppContext app,
  516. _XtBoolean ignoreEvents,
  517. _XtBoolean ignoreTimers,
  518. _XtBoolean ignoreInputs,
  519. _XtBoolean ignoreSignals,
  520. _XtBoolean block,
  521. #ifdef XTHREADS
  522. _XtBoolean drop_lock,
  523. #endif
  524. unsigned long *howlong)
  525. {
  526. wait_times_t wt;
  527. wait_fds_t wf;
  528. int nfds, dpy_no, found_input, dd;
  529. #ifdef XTHREADS
  530. Boolean push_thread = TRUE;
  531. Boolean pushed_thread = FALSE;
  532. int level = 0;
  533. #endif
  534. #ifdef USE_POLL
  535. struct pollfd fdlist[XT_DEFAULT_FDLIST_SIZE];
  536. #endif
  537. #ifdef XTHREADS
  538. /* assert ((ignoreTimers && ignoreInputs && ignoreSignals) || drop_lock); */
  539. /* If not multi-threaded, never drop lock */
  540. if (app->lock == (ThreadAppProc) NULL)
  541. drop_lock = FALSE;
  542. #endif
  543. InitTimes (block, howlong, &wt);
  544. #ifdef USE_POLL
  545. wf.fdlist = NULL;
  546. wf.stack = fdlist;
  547. #endif
  548. app->rebuild_fdlist = TRUE;
  549. while (1) {
  550. WaitLoop:
  551. AdjustTimes (app, block, howlong, ignoreTimers, &wt);
  552. if (block && app->block_hook_list) {
  553. BlockHook hook;
  554. for (hook = app->block_hook_list;
  555. hook != NULL;
  556. hook = hook->next)
  557. (*hook->proc) (hook->closure);
  558. if (!ignoreEvents)
  559. /* see if the hook(s) generated any protocol */
  560. for (dd = 0; dd < app->count; dd++)
  561. if (XEventsQueued(app->list[dd], QueuedAlready)) {
  562. #ifdef USE_POLL
  563. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  564. #endif
  565. return dd;
  566. }
  567. }
  568. if (app->rebuild_fdlist)
  569. InitFds (app, ignoreEvents, ignoreInputs, &wf);
  570. #ifdef XTHREADS /* { */
  571. if (drop_lock) {
  572. YIELD_APP_LOCK(app, &push_thread, &pushed_thread, &level);
  573. nfds = IoWait (&wt, &wf);
  574. RESTORE_APP_LOCK(app, level, &pushed_thread);
  575. } else
  576. #endif /* } */
  577. nfds = IoWait (&wt, &wf);
  578. if (nfds == -1) {
  579. /*
  580. * interrupt occured recalculate time value and wait again.
  581. */
  582. if (errno == EINTR || errno == EAGAIN) {
  583. if (errno == EAGAIN) {
  584. errno = 0; /* errno is not self reseting */
  585. continue;
  586. }
  587. errno = 0; /* errno is not self reseting */
  588. /* was it interrupted by a signal that we care about? */
  589. if (!ignoreSignals && app->signalQueue != NULL) {
  590. SignalEventRec *se_ptr = app->signalQueue;
  591. while (se_ptr != NULL) {
  592. if (se_ptr->se_notice) {
  593. if (block && howlong != NULL)
  594. AdjustHowLong (howlong, &wt.start_time);
  595. #ifdef USE_POLL
  596. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  597. #endif
  598. return -1;
  599. }
  600. se_ptr = se_ptr->se_next;
  601. }
  602. }
  603. if (!ignoreEvents)
  604. /* get Xlib to detect a bad connection */
  605. for (dd = 0; dd < app->count; dd++)
  606. if (XEventsQueued(app->list[dd], QueuedAfterReading)) {
  607. #ifdef USE_POLL
  608. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  609. #endif
  610. return dd;
  611. }
  612. if (block) {
  613. #ifndef USE_POLL
  614. if (wt.wait_time_ptr == NULL)
  615. #else
  616. if (wt.poll_wait == X_BLOCK)
  617. #endif
  618. continue;
  619. X_GETTIMEOFDAY (&wt.new_time);
  620. FIXUP_TIMEVAL (wt.new_time);
  621. TIMEDELTA (wt.time_spent, wt.new_time, wt.cur_time);
  622. wt.cur_time = wt.new_time;
  623. #ifndef USE_POLL
  624. if (IS_AFTER (wt.time_spent, *wt.wait_time_ptr)) {
  625. TIMEDELTA (wt.wait_time, *wt.wait_time_ptr, wt.time_spent);
  626. wt.wait_time_ptr = &wt.wait_time;
  627. continue;
  628. } else
  629. #else
  630. if ((wt.time_spent.tv_sec * 1000 + wt.time_spent.tv_usec / 1000) < wt.poll_wait) {
  631. wt.poll_wait -= (wt.time_spent.tv_sec * 1000 + wt.time_spent.tv_usec / 1000);
  632. continue;
  633. } else
  634. #endif
  635. nfds = 0;
  636. }
  637. } else {
  638. char Errno[12];
  639. String param = Errno;
  640. Cardinal param_count = 1;
  641. sprintf( Errno, "%d", errno);
  642. XtAppWarningMsg(app, "communicationError","select",
  643. XtCXtToolkitError,"Select failed; error code %s",
  644. &param, &param_count);
  645. continue;
  646. }
  647. } /* timed out or input available */
  648. break;
  649. }
  650. if (nfds == 0) {
  651. /* Timed out */
  652. if (howlong)
  653. *howlong = (unsigned long)0;
  654. #ifdef USE_POLL
  655. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  656. #endif
  657. return -1;
  658. }
  659. if (block && howlong != NULL)
  660. AdjustHowLong (howlong, &wt.start_time);
  661. if (ignoreInputs && ignoreEvents) {
  662. #ifdef USE_POLL
  663. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  664. #endif
  665. return -1;
  666. } else
  667. FindInputs (app, &wf, nfds,
  668. ignoreEvents, ignoreInputs,
  669. &dpy_no, &found_input);
  670. if (dpy_no >= 0 || found_input) {
  671. #ifdef USE_POLL
  672. XtStackFree ((XtPointer) wf.fdlist, fdlist);
  673. #endif
  674. return dpy_no;
  675. }
  676. goto WaitLoop;
  677. }
  678. #define IeCallProc(ptr) \
  679. (*ptr->ie_proc) (ptr->ie_closure, &ptr->ie_source, (XtInputId*)&ptr);
  680. #define TeCallProc(ptr) \
  681. (*ptr->te_proc) (ptr->te_closure, (XtIntervalId*)&ptr);
  682. #define SeCallProc(ptr) \
  683. (*ptr->se_proc) (ptr->se_closure, (XtSignalId*)&ptr);
  684. /*
  685. * Public Routines
  686. */
  687. XtIntervalId XtAddTimeOut(
  688. unsigned long interval,
  689. XtTimerCallbackProc proc,
  690. XtPointer closure)
  691. {
  692. return XtAppAddTimeOut(_XtDefaultAppContext(),
  693. interval, proc, closure);
  694. }
  695. static void QueueTimerEvent(
  696. XtAppContext app,
  697. TimerEventRec *ptr)
  698. {
  699. TimerEventRec *t,**tt;
  700. tt = &app->timerQueue;
  701. t = *tt;
  702. while (t != NULL &&
  703. IS_AFTER(t->te_timer_value, ptr->te_timer_value)) {
  704. tt = &t->te_next;
  705. t = *tt;
  706. }
  707. ptr->te_next = t;
  708. *tt = ptr;
  709. }
  710. XtIntervalId XtAppAddTimeOut(
  711. XtAppContext app,
  712. unsigned long interval,
  713. XtTimerCallbackProc proc,
  714. XtPointer closure)
  715. {
  716. TimerEventRec *tptr;
  717. struct timeval current_time;
  718. LOCK_APP(app);
  719. LOCK_PROCESS;
  720. if (freeTimerRecs) {
  721. tptr = freeTimerRecs;
  722. freeTimerRecs = tptr->te_next;
  723. }
  724. else tptr = XtNew(TimerEventRec);
  725. UNLOCK_PROCESS;
  726. tptr->te_next = NULL;
  727. tptr->te_closure = closure;
  728. tptr->te_proc = proc;
  729. tptr->app = app;
  730. tptr->te_timer_value.tv_sec = interval/1000;
  731. tptr->te_timer_value.tv_usec = (interval%1000)*1000;
  732. X_GETTIMEOFDAY (&current_time);
  733. FIXUP_TIMEVAL(current_time);
  734. ADD_TIME(tptr->te_timer_value,tptr->te_timer_value,current_time);
  735. QueueTimerEvent(app, tptr);
  736. UNLOCK_APP(app);
  737. return( (XtIntervalId) tptr);
  738. }
  739. void XtRemoveTimeOut(
  740. XtIntervalId id)
  741. {
  742. TimerEventRec *t, *last, *tid = (TimerEventRec *) id;
  743. XtAppContext app = tid->app;
  744. /* find it */
  745. LOCK_APP(app);
  746. for(t = app->timerQueue, last = NULL;
  747. t != NULL && t != tid;
  748. t = t->te_next) last = t;
  749. if (t == NULL) {
  750. UNLOCK_APP(app);
  751. return; /* couldn't find it */
  752. }
  753. if(last == NULL) { /* first one on the list */
  754. app->timerQueue = t->te_next;
  755. } else last->te_next = t->te_next;
  756. LOCK_PROCESS;
  757. t->te_next = freeTimerRecs;
  758. freeTimerRecs = t;
  759. UNLOCK_PROCESS;
  760. UNLOCK_APP(app);
  761. }
  762. XtWorkProcId XtAddWorkProc(
  763. XtWorkProc proc,
  764. XtPointer closure)
  765. {
  766. return XtAppAddWorkProc(_XtDefaultAppContext(), proc, closure);
  767. }
  768. XtWorkProcId XtAppAddWorkProc(
  769. XtAppContext app,
  770. XtWorkProc proc,
  771. XtPointer closure)
  772. {
  773. WorkProcRec *wptr;
  774. LOCK_APP(app);
  775. LOCK_PROCESS;
  776. if (freeWorkRecs) {
  777. wptr = freeWorkRecs;
  778. freeWorkRecs = wptr->next;
  779. } else wptr = XtNew(WorkProcRec);
  780. UNLOCK_PROCESS;
  781. wptr->next = app->workQueue;
  782. wptr->closure = closure;
  783. wptr->proc = proc;
  784. wptr->app = app;
  785. app->workQueue = wptr;
  786. UNLOCK_APP(app);
  787. return (XtWorkProcId) wptr;
  788. }
  789. void XtRemoveWorkProc(
  790. XtWorkProcId id)
  791. {
  792. WorkProcRec *wid= (WorkProcRec *) id, *w, *last;
  793. XtAppContext app = wid->app;
  794. LOCK_APP(app);
  795. /* find it */
  796. for(w = app->workQueue, last = NULL;
  797. w != NULL && w != wid; w = w->next) last = w;
  798. if (w == NULL) {
  799. UNLOCK_APP(app);
  800. return; /* couldn't find it */
  801. }
  802. if(last == NULL) app->workQueue = w->next;
  803. else last->next = w->next;
  804. LOCK_PROCESS;
  805. w->next = freeWorkRecs;
  806. freeWorkRecs = w;
  807. UNLOCK_PROCESS;
  808. UNLOCK_APP(app);
  809. }
  810. XtSignalId XtAddSignal(
  811. XtSignalCallbackProc proc,
  812. XtPointer closure)
  813. {
  814. return XtAppAddSignal(_XtDefaultAppContext(), proc, closure);
  815. }
  816. XtSignalId XtAppAddSignal(
  817. XtAppContext app,
  818. XtSignalCallbackProc proc,
  819. XtPointer closure)
  820. {
  821. SignalEventRec *sptr;
  822. LOCK_APP(app);
  823. LOCK_PROCESS;
  824. if (freeSignalRecs) {
  825. sptr = freeSignalRecs;
  826. freeSignalRecs = sptr->se_next;
  827. } else
  828. sptr = XtNew(SignalEventRec);
  829. UNLOCK_PROCESS;
  830. sptr->se_next = app->signalQueue;
  831. sptr->se_closure = closure;
  832. sptr->se_proc = proc;
  833. sptr->app = app;
  834. sptr->se_notice = FALSE;
  835. app->signalQueue = sptr;
  836. UNLOCK_APP(app);
  837. return (XtSignalId) sptr;
  838. }
  839. void XtRemoveSignal(
  840. XtSignalId id)
  841. {
  842. SignalEventRec *sid = (SignalEventRec*) id, *s, *last = NULL;
  843. XtAppContext app = sid->app;
  844. LOCK_APP(app);
  845. for (s = app->signalQueue; s != NULL && s != sid; s = s->se_next)
  846. last = s;
  847. if (s == NULL) {
  848. UNLOCK_APP(app);
  849. return;
  850. }
  851. if (last == NULL)
  852. app->signalQueue = s->se_next;
  853. else
  854. last->se_next = s->se_next;
  855. LOCK_PROCESS;
  856. s->se_next = freeSignalRecs;
  857. freeSignalRecs = s;
  858. UNLOCK_PROCESS;
  859. UNLOCK_APP(app);
  860. }
  861. void XtNoticeSignal(
  862. XtSignalId id)
  863. {
  864. /*
  865. * It would be overkill to lock the app to set this flag.
  866. * In the worst case, 2..n threads would be modifying this
  867. * flag. The last one wins. Since signals occur asynchronously
  868. * anyway, this can occur with or without threads.
  869. *
  870. * The other issue is that thread t1 sets the flag in a
  871. * signalrec that has been deleted in thread t2. We rely
  872. * on a detail of the implementation, i.e. free'd signalrecs
  873. * aren't really free'd, they're just moved to a list of
  874. * free recs, so deref'ing one won't hurt anything.
  875. *
  876. * Lastly, and perhaps most importantly, since POSIX threads
  877. * says that the handling of asynchronous signals in a synchronous
  878. * threads environment is undefined. Therefor it would be an
  879. * error for both signals and threads to be in use in the same
  880. * program.
  881. */
  882. SignalEventRec *sid = (SignalEventRec*) id;
  883. sid->se_notice = TRUE;
  884. }
  885. XtInputId XtAddInput(
  886. int source,
  887. XtPointer Condition,
  888. XtInputCallbackProc proc,
  889. XtPointer closure)
  890. {
  891. return XtAppAddInput(_XtDefaultAppContext(),
  892. source, Condition, proc, closure);
  893. }
  894. XtInputId XtAppAddInput(
  895. XtAppContext app,
  896. int source,
  897. XtPointer Condition,
  898. XtInputCallbackProc proc,
  899. XtPointer closure)
  900. {
  901. InputEvent* sptr;
  902. XtInputMask condition = (XtInputMask) Condition;
  903. LOCK_APP(app);
  904. if (!condition ||
  905. condition & ~(XtInputReadMask|XtInputWriteMask|XtInputExceptMask))
  906. XtAppErrorMsg(app,"invalidParameter","xtAddInput",XtCXtToolkitError,
  907. "invalid condition passed to XtAppAddInput",
  908. (String *)NULL, (Cardinal *)NULL);
  909. if (app->input_max <= source) {
  910. Cardinal n = source + 1;
  911. int ii;
  912. app->input_list = (InputEvent**)XtRealloc((char*) app->input_list,
  913. n * sizeof(InputEvent*));
  914. for (ii = app->input_max; ii < (int) n; ii++)
  915. app->input_list[ii] = (InputEvent*) NULL;
  916. app->input_max = n;
  917. }
  918. sptr = XtNew(InputEvent);
  919. sptr->ie_proc = proc;
  920. sptr->ie_closure = closure;
  921. sptr->app = app;
  922. sptr->ie_oq = NULL;
  923. sptr->ie_source = source;
  924. sptr->ie_condition = condition;
  925. sptr->ie_next = app->input_list[source];
  926. app->input_list[source] = sptr;
  927. #ifndef USE_POLL
  928. if (condition & XtInputReadMask) FD_SET(source, &app->fds.rmask);
  929. if (condition & XtInputWriteMask) FD_SET(source, &app->fds.wmask);
  930. if (condition & XtInputExceptMask) FD_SET(source, &app->fds.emask);
  931. if (app->fds.nfds < (source+1)) app->fds.nfds = source+1;
  932. #else
  933. if (sptr->ie_next == NULL)
  934. app->fds.nfds++;
  935. #endif
  936. app->input_count++;
  937. app->rebuild_fdlist = TRUE;
  938. UNLOCK_APP(app);
  939. return((XtInputId)sptr);
  940. }
  941. void XtRemoveInput(
  942. register XtInputId id)
  943. {
  944. register InputEvent *sptr, *lptr;
  945. XtAppContext app = ((InputEvent *)id)->app;
  946. register int source = ((InputEvent *)id)->ie_source;
  947. Boolean found = False;
  948. LOCK_APP(app);
  949. sptr = app->outstandingQueue;
  950. lptr = NULL;
  951. for (; sptr != NULL; sptr = sptr->ie_oq) {
  952. if (sptr == (InputEvent *)id) {
  953. if (lptr == NULL) app->outstandingQueue = sptr->ie_oq;
  954. else lptr->ie_oq = sptr->ie_oq;
  955. }
  956. lptr = sptr;
  957. }
  958. if(app->input_list && (sptr = app->input_list[source]) != NULL) {
  959. for( lptr = NULL ; sptr; sptr = sptr->ie_next ){
  960. if(sptr == (InputEvent *) id) {
  961. #ifndef USE_POLL
  962. XtInputMask condition = 0;
  963. #endif
  964. if(lptr == NULL) {
  965. app->input_list[source] = sptr->ie_next;
  966. } else {
  967. lptr->ie_next = sptr->ie_next;
  968. }
  969. #ifndef USE_POLL
  970. for (lptr = app->input_list[source];
  971. lptr; lptr = lptr->ie_next)
  972. condition |= lptr->ie_condition;
  973. if ((sptr->ie_condition & XtInputReadMask) &&
  974. !(condition & XtInputReadMask))
  975. FD_CLR(source, &app->fds.rmask);
  976. if ((sptr->ie_condition & XtInputWriteMask) &&
  977. !(condition & XtInputWriteMask))
  978. FD_CLR(source, &app->fds.wmask);
  979. if ((sptr->ie_condition & XtInputExceptMask) &&
  980. !(condition & XtInputExceptMask))
  981. FD_CLR(source, &app->fds.emask);
  982. #endif
  983. XtFree((char *) sptr);
  984. found = True;
  985. break;
  986. }
  987. lptr = sptr;
  988. }
  989. }
  990. if (found) {
  991. app->input_count--;
  992. #ifdef USE_POLL
  993. if (app->input_list[source] == NULL)
  994. app->fds.nfds--;
  995. #endif
  996. app->rebuild_fdlist = TRUE;
  997. } else
  998. XtAppWarningMsg(app, "invalidProcedure","inputHandler",
  999. XtCXtToolkitError,
  1000. "XtRemoveInput: Input handler not found",
  1001. (String *)NULL, (Cardinal *)NULL);
  1002. UNLOCK_APP(app);
  1003. }
  1004. void _XtRemoveAllInputs(
  1005. XtAppContext app)
  1006. {
  1007. int i;
  1008. for (i = 0; i < app->input_max; i++) {
  1009. InputEvent* ep = app->input_list[i];
  1010. while (ep) {
  1011. InputEvent *next = ep->ie_next;
  1012. XtFree( (char*)ep );
  1013. ep = next;
  1014. }
  1015. }
  1016. XtFree((char *) app->input_list);
  1017. }
  1018. /* Do alternate input and timer callbacks if there are any */
  1019. static void DoOtherSources(
  1020. XtAppContext app)
  1021. {
  1022. TimerEventRec *te_ptr;
  1023. InputEvent *ie_ptr;
  1024. struct timeval cur_time;
  1025. #define DrainQueue() \
  1026. for (ie_ptr = app->outstandingQueue; ie_ptr != NULL;) { \
  1027. app->outstandingQueue = ie_ptr->ie_oq; \
  1028. ie_ptr ->ie_oq = NULL; \
  1029. IeCallProc(ie_ptr); \
  1030. ie_ptr = app->outstandingQueue; \
  1031. }
  1032. /*enddef*/
  1033. DrainQueue();
  1034. if (app->input_count > 0) {
  1035. /* Call _XtWaitForSomething to get input queued up */
  1036. (void) _XtWaitForSomething (app,
  1037. TRUE, TRUE, FALSE, TRUE,
  1038. FALSE,
  1039. #ifdef XTHREADS
  1040. TRUE,
  1041. #endif
  1042. (unsigned long *)NULL);
  1043. DrainQueue();
  1044. }
  1045. if (app->timerQueue != NULL) { /* check timeout queue */
  1046. X_GETTIMEOFDAY (&cur_time);
  1047. FIXUP_TIMEVAL(cur_time);
  1048. while(IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time)) {
  1049. te_ptr = app->timerQueue;
  1050. app->timerQueue = te_ptr->te_next;
  1051. te_ptr->te_next = NULL;
  1052. if (te_ptr->te_proc != NULL)
  1053. TeCallProc(te_ptr);
  1054. LOCK_PROCESS;
  1055. te_ptr->te_next = freeTimerRecs;
  1056. freeTimerRecs = te_ptr;
  1057. UNLOCK_PROCESS;
  1058. if (app->timerQueue == NULL) break;
  1059. }
  1060. }
  1061. if (app->signalQueue != NULL) {
  1062. SignalEventRec *se_ptr = app->signalQueue;
  1063. while (se_ptr != NULL) {
  1064. if (se_ptr->se_notice) {
  1065. se_ptr->se_notice = FALSE;
  1066. if (se_ptr->se_proc != NULL)
  1067. SeCallProc(se_ptr);
  1068. }
  1069. se_ptr = se_ptr->se_next;
  1070. }
  1071. }
  1072. #undef DrainQueue
  1073. }
  1074. /* If there are any work procs, call them. Return whether we did so */
  1075. static Boolean CallWorkProc(
  1076. XtAppContext app)
  1077. {
  1078. register WorkProcRec *w = app->workQueue;
  1079. Boolean delete;
  1080. if (w == NULL) return FALSE;
  1081. app->workQueue = w->next;
  1082. delete = (*(w->proc)) (w->closure);
  1083. if (delete) {
  1084. LOCK_PROCESS;
  1085. w->next = freeWorkRecs;
  1086. freeWorkRecs = w;
  1087. UNLOCK_PROCESS;
  1088. }
  1089. else {
  1090. w->next = app->workQueue;
  1091. app->workQueue = w;
  1092. }
  1093. return TRUE;
  1094. }
  1095. /*
  1096. * XtNextEvent()
  1097. * return next event;
  1098. */
  1099. void XtNextEvent(
  1100. XEvent *event)
  1101. {
  1102. XtAppNextEvent(_XtDefaultAppContext(), event);
  1103. }
  1104. void _XtRefreshMapping(
  1105. XEvent* event,
  1106. _XtBoolean dispatch)
  1107. {
  1108. XtPerDisplay pd;
  1109. LOCK_PROCESS;
  1110. pd = _XtGetPerDisplay(event->xmapping.display);
  1111. if (event->xmapping.request != MappingPointer &&
  1112. pd && pd->keysyms && (event->xmapping.serial >= pd->keysyms_serial))
  1113. _XtBuildKeysymTables( event->xmapping.display, pd );
  1114. XRefreshKeyboardMapping(&event->xmapping);
  1115. if (dispatch && pd && pd->mapping_callbacks)
  1116. XtCallCallbackList((Widget) NULL,
  1117. (XtCallbackList)pd->mapping_callbacks,
  1118. (XtPointer)event );
  1119. UNLOCK_PROCESS;
  1120. }
  1121. void XtAppNextEvent(
  1122. XtAppContext app,
  1123. XEvent *event)
  1124. {
  1125. int i, d;
  1126. LOCK_APP(app);
  1127. for (;;) {
  1128. if (app->count == 0)
  1129. DoOtherSources(app);
  1130. else {
  1131. for (i = 1; i <= app->count; i++) {
  1132. d = (i + app->last) % app->count;
  1133. if (d == 0) DoOtherSources(app);
  1134. if (XEventsQueued(app->list[d], QueuedAfterReading))
  1135. goto GotEvent;
  1136. }
  1137. for (i = 1; i <= app->count; i++) {
  1138. d = (i + app->last) % app->count;
  1139. if (XEventsQueued(app->list[d], QueuedAfterFlush))
  1140. goto GotEvent;
  1141. }
  1142. }
  1143. /* We're ready to wait...if there is a work proc, call it */
  1144. if (CallWorkProc(app)) continue;
  1145. d = _XtWaitForSomething (app,
  1146. FALSE, FALSE, FALSE, FALSE,
  1147. TRUE,
  1148. #ifdef XTHREADS
  1149. TRUE,
  1150. #endif
  1151. (unsigned long *) NULL);
  1152. if (d != -1) {
  1153. GotEvent:
  1154. XNextEvent (app->list[d], event);
  1155. #ifdef XTHREADS
  1156. /* assert(app->list[d] == event->xany.display); */
  1157. #endif
  1158. app->last = d;
  1159. if (event->xany.type == MappingNotify)
  1160. _XtRefreshMapping(event, False);
  1161. UNLOCK_APP(app);
  1162. return;
  1163. }
  1164. } /* for */
  1165. }
  1166. void XtProcessEvent(
  1167. XtInputMask mask)
  1168. {
  1169. XtAppProcessEvent(_XtDefaultAppContext(), mask);
  1170. }
  1171. void XtAppProcessEvent(
  1172. XtAppContext app,
  1173. XtInputMask mask)
  1174. {
  1175. int i, d;
  1176. XEvent event;
  1177. struct timeval cur_time;
  1178. LOCK_APP(app);
  1179. if (mask == 0) {
  1180. UNLOCK_APP(app);
  1181. return;
  1182. }
  1183. for (;;) {
  1184. if (mask & XtIMSignal && app->signalQueue != NULL) {
  1185. SignalEventRec *se_ptr = app->signalQueue;
  1186. while (se_ptr != NULL) {
  1187. if (se_ptr->se_notice) {
  1188. se_ptr->se_notice = FALSE;
  1189. SeCallProc(se_ptr);
  1190. UNLOCK_APP(app);
  1191. return;
  1192. }
  1193. se_ptr = se_ptr->se_next;
  1194. }
  1195. }
  1196. if (mask & XtIMTimer && app->timerQueue != NULL) {
  1197. X_GETTIMEOFDAY (&cur_time);
  1198. FIXUP_TIMEVAL(cur_time);
  1199. if (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)){
  1200. TimerEventRec *te_ptr = app->timerQueue;
  1201. app->timerQueue = app->timerQueue->te_next;
  1202. te_ptr->te_next = NULL;
  1203. if (te_ptr->te_proc != NULL)
  1204. TeCallProc(te_ptr);
  1205. LOCK_PROCESS;
  1206. te_ptr->te_next = freeTimerRecs;
  1207. freeTimerRecs = te_ptr;
  1208. UNLOCK_PROCESS;
  1209. UNLOCK_APP(app);
  1210. return;
  1211. }
  1212. }
  1213. if (mask & XtIMAlternateInput) {
  1214. if (app->input_count > 0 && app->outstandingQueue == NULL) {
  1215. /* Call _XtWaitForSomething to get input queued up */
  1216. (void) _XtWaitForSomething (app,
  1217. TRUE, TRUE, FALSE, TRUE,
  1218. FALSE,
  1219. #ifdef XTHREADS
  1220. TRUE,
  1221. #endif
  1222. (unsigned long *)NULL);
  1223. }
  1224. if (app->outstandingQueue != NULL) {
  1225. InputEvent *ie_ptr = app->outstandingQueue;
  1226. app->outstandingQueue = ie_ptr->ie_oq;
  1227. ie_ptr->ie_oq = NULL;
  1228. IeCallProc(ie_ptr);
  1229. UNLOCK_APP(app);
  1230. return;
  1231. }
  1232. }
  1233. if (mask & XtIMXEvent) {
  1234. for (i = 1; i <= app->count; i++) {
  1235. d = (i + app->last) % app->count;
  1236. if (XEventsQueued(app->list[d], QueuedAfterReading))
  1237. goto GotEvent;
  1238. }
  1239. for (i = 1; i <= app->count; i++) {
  1240. d = (i + app->last) % app->count;
  1241. if (XEventsQueued(app->list[d], QueuedAfterFlush))
  1242. goto GotEvent;
  1243. }
  1244. }
  1245. /* Nothing to do...wait for something */
  1246. if (CallWorkProc(app)) continue;
  1247. d = _XtWaitForSomething (app,
  1248. (mask & XtIMXEvent ? FALSE : TRUE),
  1249. (mask & XtIMTimer ? FALSE : TRUE),
  1250. (mask & XtIMAlternateInput ? FALSE : TRUE),
  1251. (mask & XtIMSignal ? FALSE : TRUE),
  1252. TRUE,
  1253. #ifdef XTHREADS
  1254. TRUE,
  1255. #endif
  1256. (unsigned long *) NULL);
  1257. if (mask & XtIMXEvent && d != -1) {
  1258. GotEvent:
  1259. XNextEvent(app->list[d], &event);
  1260. #ifdef XTHREADS
  1261. /* assert(app->list[d] == event.xany.display); */
  1262. #endif
  1263. app->last = d;
  1264. if (event.xany.type == MappingNotify) {
  1265. _XtRefreshMapping(&event, False);
  1266. }
  1267. XtDispatchEvent(&event);
  1268. UNLOCK_APP(app);
  1269. return;
  1270. }
  1271. }
  1272. }
  1273. Boolean XtPending(void)
  1274. {
  1275. return (XtAppPending(_XtDefaultAppContext()) != 0);
  1276. }
  1277. XtInputMask XtAppPending(
  1278. XtAppContext app)
  1279. {
  1280. struct timeval cur_time;
  1281. int d;
  1282. XtInputMask ret = 0;
  1283. /*
  1284. * Check for pending X events
  1285. */
  1286. LOCK_APP(app);
  1287. for (d = 0; d < app->count; d++) {
  1288. if (XEventsQueued(app->list[d], QueuedAfterReading)) {
  1289. ret = XtIMXEvent;
  1290. break;
  1291. }
  1292. }
  1293. if (ret == 0) {
  1294. for (d = 0; d < app->count; d++) {
  1295. if (XEventsQueued(app->list[d], QueuedAfterFlush)) {
  1296. ret = XtIMXEvent;
  1297. break;
  1298. }
  1299. }
  1300. }
  1301. if (app->signalQueue != NULL) {
  1302. SignalEventRec *se_ptr = app->signalQueue;
  1303. while (se_ptr != NULL) {
  1304. if (se_ptr->se_notice) {
  1305. ret |= XtIMSignal;
  1306. break;
  1307. }
  1308. se_ptr = se_ptr->se_next;
  1309. }
  1310. }
  1311. /*
  1312. * Check for pending alternate input
  1313. */
  1314. if (app->timerQueue != NULL) { /* check timeout queue */
  1315. X_GETTIMEOFDAY (&cur_time);
  1316. FIXUP_TIMEVAL(cur_time);
  1317. if ((IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) &&
  1318. (app->timerQueue->te_proc != 0)) {
  1319. ret |= XtIMTimer;
  1320. }
  1321. }
  1322. if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
  1323. else {
  1324. /* This won't cause a wait, but will enqueue any input */
  1325. if(_XtWaitForSomething (app,
  1326. FALSE, TRUE, FALSE, TRUE,
  1327. FALSE,
  1328. #ifdef XTHREADS
  1329. TRUE,
  1330. #endif
  1331. (unsigned long *) NULL) != -1)
  1332. ret |= XtIMXEvent;
  1333. if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
  1334. }
  1335. UNLOCK_APP(app);
  1336. return ret;
  1337. }
  1338. /* Peek at alternate input and timer callbacks if there are any */
  1339. static Boolean PeekOtherSources(
  1340. XtAppContext app)
  1341. {
  1342. struct timeval cur_time;
  1343. if (app->outstandingQueue != NULL) return TRUE;
  1344. if (app->signalQueue != NULL) {
  1345. SignalEventRec *se_ptr = app->signalQueue;
  1346. while (se_ptr != NULL) {
  1347. if (se_ptr->se_notice)
  1348. return TRUE;
  1349. se_ptr = se_ptr->se_next;
  1350. }
  1351. }
  1352. if (app->input_count > 0) {
  1353. /* Call _XtWaitForSomething to get input queued up */
  1354. (void) _XtWaitForSomething (app,
  1355. TRUE, TRUE, FALSE, TRUE,
  1356. FALSE,
  1357. #ifdef XTHREADS
  1358. TRUE,
  1359. #endif
  1360. (unsigned long *)NULL);
  1361. if (app->outstandingQueue != NULL) return TRUE;
  1362. }
  1363. if (app->timerQueue != NULL) { /* check timeout queue */
  1364. X_GETTIMEOFDAY (&cur_time);
  1365. FIXUP_TIMEVAL(cur_time);
  1366. if (IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time))
  1367. return TRUE;
  1368. }
  1369. return FALSE;
  1370. }
  1371. Boolean XtPeekEvent(
  1372. XEvent *event)
  1373. {
  1374. return XtAppPeekEvent(_XtDefaultAppContext(), event);
  1375. }
  1376. Boolean XtAppPeekEvent_SkipTimer;
  1377. Boolean XtAppPeekEvent(
  1378. XtAppContext app,
  1379. XEvent *event)
  1380. {
  1381. int i, d;
  1382. Boolean foundCall = FALSE;
  1383. LOCK_APP(app);
  1384. for (i = 1; i <= app->count; i++) {
  1385. d = (i + app->last) % app->count;
  1386. if (d == 0) foundCall = PeekOtherSources(app);
  1387. if (XEventsQueued(app->list[d], QueuedAfterReading))
  1388. goto GotEvent;
  1389. }
  1390. for (i = 1; i <= app->count; i++) {
  1391. d = (i + app->last) % app->count;
  1392. if (XEventsQueued(app->list[d], QueuedAfterFlush))
  1393. goto GotEvent;
  1394. }
  1395. if (foundCall) {
  1396. event->xany.type = 0;
  1397. event->xany.display = NULL;
  1398. event->xany.window = 0;
  1399. UNLOCK_APP(app);
  1400. return FALSE;
  1401. }
  1402. while (1) {
  1403. d = _XtWaitForSomething (app,
  1404. FALSE, FALSE, FALSE, FALSE,
  1405. TRUE,
  1406. #ifdef XTHREADS
  1407. TRUE,
  1408. #endif
  1409. (unsigned long *) NULL);
  1410. if (d != -1) { /* event */
  1411. GotEvent:
  1412. XPeekEvent(app->list[d], event);
  1413. app->last = (d == 0 ? app->count : d) - 1;
  1414. UNLOCK_APP(app);
  1415. return TRUE;
  1416. }
  1417. else { /* input or timer or signal */
  1418. /*
  1419. * Check to see why a -1 was returned, if a timer expired,
  1420. * call it and block some more
  1421. */
  1422. if ((app->timerQueue != NULL) && ! XtAppPeekEvent_SkipTimer) { /* timer */
  1423. struct timeval cur_time;
  1424. Bool did_timer = False;
  1425. X_GETTIMEOFDAY (&cur_time);
  1426. FIXUP_TIMEVAL(cur_time);
  1427. while (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) {
  1428. TimerEventRec *te_ptr = app->timerQueue;
  1429. app->timerQueue = app->timerQueue->te_next;
  1430. te_ptr->te_next = NULL;
  1431. if (te_ptr->te_proc != NULL) {
  1432. TeCallProc(te_ptr);
  1433. did_timer = True;
  1434. }
  1435. LOCK_PROCESS;
  1436. te_ptr->te_next = freeTimerRecs;
  1437. freeTimerRecs = te_ptr;
  1438. UNLOCK_PROCESS;
  1439. if (app->timerQueue == NULL) break;
  1440. }
  1441. if (did_timer)
  1442. {
  1443. for (d = 0; d < app->count; d++)
  1444. /* the timer's procedure may have caused an event */
  1445. if (XEventsQueued(app->list[d], QueuedAfterFlush)) {
  1446. goto GotEvent;
  1447. }
  1448. continue; /* keep blocking */
  1449. }
  1450. }
  1451. /*
  1452. * spec is vague here; we'll assume signals also return FALSE,
  1453. * of course to determine whether a signal is pending requires
  1454. * walking the signalQueue looking for se_notice flags which
  1455. * this code doesn't do.
  1456. */
  1457. #if 0
  1458. if (app->signalQueue != NULL) { /* signal */
  1459. event->xany.type = 0;
  1460. event->xany.display = NULL;
  1461. event->xany.window = 0;
  1462. UNLOCK_APP(app);
  1463. return FALSE;
  1464. }
  1465. else
  1466. #endif
  1467. { /* input */
  1468. event->xany.type = 0;
  1469. event->xany.display = NULL;
  1470. event->xany.window = 0;
  1471. UNLOCK_APP(app);
  1472. return FALSE;
  1473. }
  1474. }
  1475. } /* end while */
  1476. }