|
|
1.1 root 1: /*-
2: * sunKbd.c --
3: * Functions for retrieving data from a keyboard.
4: *
5: * Copyright (c) 1987 by the Regents of the University of California
6: *
7: * Permission to use, copy, modify, and distribute this
8: * software and its documentation for any purpose and without
9: * fee is hereby granted, provided that the above copyright
10: * notice appear in all copies. The University of California
11: * makes no representations about the suitability of this
12: * software for any purpose. It is provided "as is" without
13: * express or implied warranty.
14: *
15: */
16:
17: /************************************************************
18: Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
19:
20: All Rights Reserved
21:
22: Permission to use, copy, modify, and distribute this
23: software and its documentation for any purpose and without
24: fee is hereby granted, provided that the above copyright no-
25: tice appear in all copies and that both that copyright no-
26: tice and this permission notice appear in supporting docu-
27: mentation, and that the names of Sun or MIT not be used in
28: advertising or publicity pertaining to distribution of the
29: software without specific prior written permission. Sun and
30: M.I.T. make no representations about the suitability of this
31: software for any purpose. It is provided "as is" without any
32: express or implied warranty.
33:
34: SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
35: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
36: NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
37: ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
39: PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
40: OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
41: THE USE OR PERFORMANCE OF THIS SOFTWARE.
42:
43: ********************************************************/
44:
45: #ifndef lint
46: static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
47: #endif
48:
49: #define NEED_EVENTS
50: #include "sun.h"
51: #include <stdio.h>
52: #include "Xproto.h"
53: #include "keysym.h"
54:
55: typedef struct {
56: int trans; /* Original translation form */
57: } SunKbPrivRec, *SunKbPrivPtr;
58:
59: extern CARD8 *sunModMap[];
60: extern KeySymsRec sunKeySyms[];
61:
62: static void sunBell();
63: static void sunKbdCtrl();
64: static Firm_event *sunKbdGetEvents();
65: static void sunKbdProcessEvent();
66: static void sunKbdDoneEvents();
67: int autoRepeatKeyDown = 0;
68: int autoRepeatDebug = 0;
69: int autoRepeatReady;
70: static int autoRepeatFirst;
71: static struct timeval autoRepeatLastKeyDownTv;
72: static struct timeval autoRepeatDeltaTv;
73: #define tvminus(tv, tv1, tv2) /* tv = tv1 - tv2 */ \
74: if ((tv1).tv_usec < (tv2).tv_usec) { \
75: (tv1).tv_usec += 1000000; \
76: (tv1).tv_sec -= 1; \
77: } \
78: (tv).tv_usec = (tv1).tv_usec - (tv2).tv_usec; \
79: (tv).tv_sec = (tv1).tv_sec - (tv2).tv_sec;
80: #define tvplus(tv, tv1, tv2) /* tv = tv1 + tv2 */ \
81: (tv).tv_sec = (tv1).tv_sec + (tv2).tv_sec; \
82: (tv).tv_usec = (tv1).tv_usec + (tv2).tv_usec; \
83: if ((tv).tv_usec > 1000000) { \
84: (tv).tv_usec -= 1000000; \
85: (tv).tv_sec += 1; \
86: }
87:
88:
89: static SunKbPrivRec sunKbPriv;
90: static KbPrivRec sysKbPriv = {
91: -1, /* Type of keyboard */
92: -1, /* Descriptor open to device */
93: sunKbdGetEvents, /* Function to read events */
94: sunKbdProcessEvent, /* Function to process an event */
95: sunKbdDoneEvents, /* Function called when all events */
96: /* have been handled. */
97: (pointer)&sunKbPriv, /* Private to keyboard device */
98: (Bool)0, /* Mapped queue */
99: 0, /* offset for device keycodes */
100: };
101:
102: /*-
103: *-----------------------------------------------------------------------
104: * sunKbdProc --
105: * Handle the initialization, etc. of a keyboard.
106: *
107: * Results:
108: * None.
109: *
110: * Side Effects:
111: *
112: * Note:
113: * When using sunwindows, all input comes off a single fd, stored in the
114: * global windowFd. Therefore, only one device should be enabled and
115: * disabled, even though the application still sees both mouse and
116: * keyboard. We have arbitrarily chosen to enable and disable windowFd
117: * in the keyboard routine sunKbdProc rather than in sunMouseProc.
118: *
119: *-----------------------------------------------------------------------
120: */
121: int
122: sunKbdProc (pKeyboard, what)
123: DevicePtr pKeyboard; /* Keyboard to manipulate */
124: int what; /* What to do to it */
125: {
126: KbPrivPtr pPriv;
127: register int kbdFd;
128:
129: switch (what) {
130: case DEVICE_INIT:
131: if (pKeyboard != LookupKeyboardDevice()) {
132: ErrorF ("Cannot open non-system keyboard");
133: return (!Success);
134: }
135:
136: /*
137: * First open and find the current state of the keyboard.
138: */
139: if (sysKbPriv.fd >= 0) {
140: kbdFd = sysKbPriv.fd;
141: } else {
142: kbdFd = open ("/dev/kbd", O_RDWR, 0);
143: if (kbdFd < 0) {
144: Error ("Opening /dev/kbd");
145: return (!Success);
146: }
147: sysKbPriv.fd = kbdFd;
148: (void) ioctl (kbdFd, KIOCTYPE, &sysKbPriv.type);
149: (void) ioctl (kbdFd, KIOCGTRANS, &sunKbPriv.trans);
150: if (sysKbPriv.type < 0 || sysKbPriv.type > KB_SUN3
151: || sunKeySyms[sysKbPriv.type].map == NULL)
152: FatalError("Unsupported keyboard type %d\n",
153: sysKbPriv.type);
154: if (sunUseSunWindows()) {
155: (void) close( kbdFd );
156: sysKbPriv.fd = -1;
157: } else {
158: if (fcntl (kbdFd, F_SETFL, (FNDELAY|FASYNC)) < 0
159: || fcntl(kbdFd, F_SETOWN, getpid()) < 0) {
160: perror("sunKbdProc");
161: FatalError("Can't set up kbd on fd %d\n", kbdFd);
162: }
163: }
164: }
165:
166: /*
167: * Perform final initialization of the system private keyboard
168: * structure and fill in various slots in the device record
169: * itself which couldn't be filled in before.
170: */
171: pKeyboard->devicePrivate = (pointer)&sysKbPriv;
172:
173: pKeyboard->on = FALSE;
174: /*
175: * ensure that the keycodes on the wire are >= MIN_KEYCODE
176: */
177: if (sunKeySyms[sysKbPriv.type].minKeyCode < MIN_KEYCODE) {
178: int offset = MIN_KEYCODE -sunKeySyms[sysKbPriv.type].minKeyCode;
179:
180: sunKeySyms[sysKbPriv.type].minKeyCode += offset;
181: sunKeySyms[sysKbPriv.type].maxKeyCode += offset;
182: sysKbPriv.offset = offset;
183: }
184: InitKeyboardDeviceStruct(
185: pKeyboard,
186: &(sunKeySyms[sysKbPriv.type]),
187: (sunModMap[sysKbPriv.type]),
188: sunBell,
189: sunKbdCtrl);
190: break;
191:
192: case DEVICE_ON:
193: if (sunUseSunWindows()) {
194: #ifdef SUN_WINDOWS
195: if (! sunSetUpKbdSunWin(windowFd, TRUE, pKeyboard)) {
196: FatalError("Can't set up keyboard\n");
197: }
198: AddEnabledDevice(windowFd);
199: #endif SUN_WINDOWS
200: }
201: else {
202: pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
203: kbdFd = pPriv->fd;
204:
205: /*
206: * Set the keyboard into "direct" mode and turn on
207: * event translation.
208: */
209: if (sunChangeKbdTranslation(pKeyboard,TRUE) < 0) {
210: FatalError("Can't set keyboard translation\n");
211: }
212:
213: AddEnabledDevice(kbdFd);
214: }
215: pKeyboard->on = TRUE;
216: break;
217:
218: case DEVICE_CLOSE:
219: case DEVICE_OFF:
220: if (sunUseSunWindows()) {
221: #ifdef SUN_WINDOWS
222: if (! sunSetUpKbdSunWin(windowFd, FALSE, pKeyboard)) {
223: FatalError("Can't close keyboard\n");
224: }
225: RemoveEnabledDevice(windowFd);
226: #endif SUN_WINDOWS
227: }
228: else {
229: pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
230: kbdFd = pPriv->fd;
231:
232: /*
233: * Restore original keyboard directness and translation.
234: */
235: if (sunChangeKbdTranslation(pKeyboard,FALSE) < 0) {
236: FatalError("Can't reset keyboard translation\n");
237: }
238:
239: RemoveEnabledDevice(kbdFd);
240: }
241: pKeyboard->on = FALSE;
242: break;
243: }
244: return (Success);
245: }
246:
247: /*-
248: *-----------------------------------------------------------------------
249: * sunBell --
250: * Ring the terminal/keyboard bell
251: *
252: * Results:
253: * None.
254: *
255: * Side Effects:
256: * None, really...
257: *
258: *-----------------------------------------------------------------------
259: */
260: static void
261: sunBell (loudness, pKeyboard)
262: int loudness; /* Percentage of full volume */
263: DevicePtr pKeyboard; /* Keyboard to ring */
264: {
265: /* no can do, for now */
266: }
267:
268: /*-
269: *-----------------------------------------------------------------------
270: * sunKbdCtrl --
271: * Alter some of the keyboard control parameters
272: *
273: * Results:
274: * None.
275: *
276: * Side Effects:
277: * Some...
278: *
279: *-----------------------------------------------------------------------
280: */
281: static void
282: sunKbdCtrl (pKeyboard)
283: DevicePtr pKeyboard; /* Keyboard to alter */
284: {
285: /* can only change key click on sun 3 keyboards, so what's the use? */
286: }
287:
288: /*-
289: *-----------------------------------------------------------------------
290: * sunKbdGetEvents --
291: * Return the events waiting in the wings for the given keyboard.
292: *
293: * Results:
294: * A pointer to an array of Firm_events or (Firm_event *)0 if no events
295: * The number of events contained in the array.
296: * If there are no keyboard events ready and autoRepeatKeyDown > 0,
297: * then *pNumEvents is set to 1 and Firm_event id is set to
298: * AUTOREPEAT_EVENTID. In sunKbdProcessEvent, if autoRepeatKeyDown > 0
299: * and Firm_event id == AUTOREPEAT_EVENTID, then the event buffer is
300: * ignored and the event is generated from the last KeyPress event.
301: *
302: * Side Effects:
303: * None.
304: *-----------------------------------------------------------------------
305: */
306: static Firm_event *
307: sunKbdGetEvents (pKeyboard, pNumEvents)
308: DevicePtr pKeyboard; /* Keyboard to read */
309: int *pNumEvents; /* Place to return number of events */
310: {
311: int nBytes; /* number of bytes of events available. */
312: KbPrivPtr pPriv;
313: static Firm_event evBuf[MAXEVENTS]; /* Buffer for Firm_events */
314:
315: pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
316: nBytes = read (pPriv->fd, evBuf, sizeof(evBuf));
317:
318: if (nBytes < 0) {
319: if (errno == EWOULDBLOCK) {
320: *pNumEvents = 0;
321: } else {
322: Error ("Reading keyboard");
323: FatalError ("Could not read the keyboard");
324: }
325: } else {
326: *pNumEvents = nBytes / sizeof (Firm_event);
327: }
328:
329: if (autoRepeatKeyDown && autoRepeatReady && *pNumEvents == 0) {
330: *pNumEvents = 1; /* Fake the event */
331: evBuf[0].id = AUTOREPEAT_EVENTID; /* Flags autoRepeat event */
332: if (autoRepeatDebug)
333: ErrorF("sunKbdGetEvents: autoRepeatKeyDown = %d event\n",
334: autoRepeatKeyDown);
335: }
336:
337: return (evBuf);
338: }
339:
340: /*-
341: *-----------------------------------------------------------------------
342: * sunKbdProcessEvent --
343: *
344: * Results:
345: *
346: * Side Effects:
347: *
348: * Caveat:
349: * To reduce duplication of code and logic (and therefore bugs), the
350: * sunwindows version of kbd processing (sunKbdProcessEventSunWin())
351: * counterfeits a firm event and calls this routine. This
352: * couunterfeiting relies on the fact this this routine only looks at the
353: * id, time, and value fields of the firm event which it is passed. If
354: * this ever changes, the sunKbdProcessEventSunWin will also have to
355: * change.
356: *
357: *-----------------------------------------------------------------------
358: */
359: static void
360: sunKbdProcessEvent (pKeyboard, fe)
361: DevicePtr pKeyboard;
362: Firm_event *fe;
363: {
364: xEvent xE;
365: PtrPrivPtr ptrPriv;
366: int delta;
367: static xEvent autoRepeatEvent;
368:
369: ptrPriv = (PtrPrivPtr) LookupPointerDevice()->devicePrivate;
370:
371: if (autoRepeatKeyDown && fe->id == AUTOREPEAT_EVENTID) {
372: /*
373: * Generate auto repeat event. XXX one for now.
374: * Update time & pointer location of saved KeyPress event.
375: */
376: if (autoRepeatDebug)
377: ErrorF("sunKbdProcessEvent: autoRepeatKeyDown = %d\n",
378: autoRepeatKeyDown);
379:
380: delta = TVTOMILLI(autoRepeatDeltaTv) / 2;
381: if (autoRepeatFirst == TRUE)
382: autoRepeatFirst = FALSE;
383:
384: /*
385: * Fake a key up event and a key down event
386: * for the last key pressed.
387: */
388: autoRepeatEvent.u.keyButtonPointer.time += delta;
389: autoRepeatEvent.u.keyButtonPointer.rootX = ptrPriv->x;
390: autoRepeatEvent.u.keyButtonPointer.rootY = ptrPriv->y;
391: autoRepeatEvent.u.u.type = KeyRelease;
392: (* pKeyboard->processInputProc) (&autoRepeatEvent, pKeyboard);
393:
394: autoRepeatEvent.u.keyButtonPointer.time += delta;
395: autoRepeatEvent.u.u.type = KeyPress;
396: (* pKeyboard->processInputProc) (&autoRepeatEvent, pKeyboard);
397:
398: /* Update time of last key down */
399: tvplus(autoRepeatLastKeyDownTv, autoRepeatLastKeyDownTv,
400: autoRepeatDeltaTv);
401:
402: return;
403: }
404:
405: /*
406: * Kill AutoRepeater on any real Kbd event.
407: */
408: autoRepeatKeyDown = 0;
409: if (autoRepeatDebug)
410: ErrorF("sunKbdProcessEvent: autoRepeat off\n");
411:
412: xE.u.keyButtonPointer.time = TVTOMILLI(fe->time);
413: xE.u.keyButtonPointer.rootX = ptrPriv->x;
414: xE.u.keyButtonPointer.rootY = ptrPriv->y;
415: xE.u.u.type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
416: xE.u.u.detail = (fe->id & 0x7F) + sysKbPriv.offset;
417:
418: if (fe->value == VKEY_DOWN) { /* turn on AutoRepeater */
419: if (autoRepeatDebug)
420: ErrorF("sunKbdProcessEvent: VKEY_DOWN\n");
421: autoRepeatEvent = xE;
422: autoRepeatFirst = TRUE;
423: autoRepeatKeyDown++;
424: autoRepeatLastKeyDownTv = fe->time;
425: }
426:
427: (* pKeyboard->processInputProc) (&xE, pKeyboard);
428: }
429:
430: /*-
431: *-----------------------------------------------------------------------
432: * sunDoneEvents --
433: * Nothing to do, here...
434: *
435: * Results:
436: *
437: * Side Effects:
438: *
439: *-----------------------------------------------------------------------
440: */
441: static void
442: sunKbdDoneEvents (pKeyboard)
443: DevicePtr pKeyboard;
444: {
445: }
446:
447: /*-
448: *-----------------------------------------------------------------------
449: * sunChangeKbdTranslation
450: * Makes operating system calls to set keyboard translation
451: * and direction on or off.
452: *
453: * Results:
454: * -1 if failure, else 0.
455: *
456: * Side Effects:
457: * Changes kernel management of keyboard.
458: *
459: *-----------------------------------------------------------------------
460: */
461: int
462: sunChangeKbdTranslation(pKeyboard,makeTranslated)
463: DevicePtr pKeyboard;
464: Bool makeTranslated;
465: {
466: KbPrivPtr pPriv;
467: int kbdFd;
468: int tmp;
469: int KbdOpenedHere;
470:
471: pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
472: kbdFd = pPriv->fd;
473:
474: KbdOpenedHere = ( kbdFd < 0 );
475: if ( KbdOpenedHere ) {
476: kbdFd = open("/dev/kbd", O_RDONLY, 0);
477: if ( kbdFd < 0 ) {
478: Error( "sunChangeKbdTranslation: Can't open keyboard" );
479: goto bad;
480: }
481: }
482:
483: if (makeTranslated) {
484: /*
485: * Next set the keyboard into "direct" mode and turn on
486: * event translation. If either of these fails, we can't go
487: * on.
488: */
489: if ( ! sunUseSunWindows() ) {
490: tmp = 1;
491: if (ioctl (kbdFd, KIOCSDIRECT, &tmp) < 0) {
492: Error ("Setting keyboard direct mode");
493: goto bad;
494: }
495: }
496: tmp = TR_UNTRANS_EVENT;
497: if (ioctl (kbdFd, KIOCTRANS, &tmp) < 0) {
498: Error ("Setting keyboard translation");
499: goto bad;
500: }
501: }
502: else {
503: /*
504: * Next set the keyboard into "indirect" mode and turn off
505: * event translation.
506: */
507: if ( ! sunUseSunWindows() ) {
508: tmp = 0;
509: (void)ioctl (kbdFd, KIOCSDIRECT, &tmp);
510: }
511: tmp = ((SunKbPrivPtr)pPriv->devPrivate)->trans;
512: (void)ioctl (kbdFd, KIOCTRANS, &tmp);
513: }
514:
515: if ( KbdOpenedHere )
516: (void) close( kbdFd );
517: return(0);
518:
519: bad:
520: if ( KbdOpenedHere )
521: (void) close( kbdFd );
522: return( -1 );
523: }
524:
525:
526: #ifdef SUN_WINDOWS
527:
528: /*-
529: *-----------------------------------------------------------------------
530: * sunSetUpKbdSunWin
531: * Change which events the kernel will pass through as keyboard
532: * events.
533: *
534: * Results:
535: *
536: * Side Effects:
537: *
538: *-----------------------------------------------------------------------
539: */
540:
541: Bool
542: sunSetUpKbdSunWin(windowFd, onoff, pKeyboard)
543: int windowFd;
544: Bool onoff;
545: DeviceRec *pKeyboard;
546: {
547: struct inputmask inputMask;
548: static struct inputmask oldInputMask;
549:
550: if (onoff) {
551: register int i;
552:
553: win_get_kbd_mask(windowFd, &oldInputMask);
554: input_imnull(&inputMask);
555: inputMask.im_flags |=
556: IM_ASCII | IM_NEGASCII |
557: IM_META | IM_NEGMETA |
558: IM_NEGEVENT | IM_INTRANSIT;
559: win_setinputcodebit(&inputMask, KBD_USE);
560: win_setinputcodebit(&inputMask, KBD_DONE);
561: win_setinputcodebit(&inputMask, SHIFT_CAPSLOCK);
562: win_setinputcodebit(&inputMask, SHIFT_LOCK);
563: win_setinputcodebit(&inputMask, SHIFT_LEFT);
564: win_setinputcodebit(&inputMask, SHIFT_RIGHT);
565: win_setinputcodebit(&inputMask, SHIFT_LEFTCTRL);
566: win_setinputcodebit(&inputMask, SHIFT_RIGHTCTRL);
567: win_setinputcodebit(&inputMask, SHIFT_META);
568: win_setinputcodebit(&inputMask, WIN_STOP);
569:
570: for (i=KEY_LEFTFIRST; i<=KEY_LEFTLAST; i++) {
571: win_setinputcodebit(&inputMask, i);
572: }
573: for (i=KEY_TOPFIRST; i<=KEY_TOPLAST; i++) {
574: win_setinputcodebit(&inputMask, i);
575: }
576: for (i=KEY_RIGHTFIRST; i<=KEY_RIGHTLAST; i++) {
577: win_setinputcodebit(&inputMask, i);
578: }
579:
580: win_set_kbd_mask(windowFd, &inputMask);
581:
582: /*
583: * Set the keyboard into "direct" mode and turn on
584: * event translation.
585: */
586: #ifdef notdef
587: if (sunChangeKbdTranslation(pKeyboard,TRUE) < 0) {
588: FatalError("Can't set keyboard translation\n");
589: }
590: #endif notdef
591: }
592: else {
593: win_set_kbd_mask(windowFd, &oldInputMask);
594:
595: /*
596: * Restore original keyboard directness and translation.
597: */
598: if (sunChangeKbdTranslation(pKeyboard,FALSE) < 0) {
599: FatalError("Can't reset keyboard translation\n");
600: }
601:
602: }
603: return (TRUE);
604: }
605:
606: #endif SUN_WINDOWS
607:
608:
609: #ifdef SUN_WINDOWS
610:
611: /*-
612: *-----------------------------------------------------------------------
613: * sunKbdProcessEventSunWin
614: * Process sunwindows event destined for the keyboard.
615: * Rather than replicate the logic (and therefore replicate
616: * bug fixes, etc), this code counterfeits a vuid
617: * Firm_event and then uses the non-sunwindows code.
618: *
619: * Results:
620: *
621: * Side Effects:
622: *
623: *-----------------------------------------------------------------------
624: */
625:
626: void
627: sunKbdProcessEventSunWin(pKeyboard,se)
628: DeviceRec *pKeyboard;
629: register struct inputevent *se;
630: {
631: Firm_event fe;
632:
633: fe.time = event_time(se);
634: fe.id = event_id(se);
635: fe.value = (event_is_up(se) ? VKEY_UP : VKEY_DOWN);
636:
637: sunKbdProcessEvent (pKeyboard, &fe);
638: }
639: #endif SUN_WINDOWS
640:
641:
642: Bool
643: LegalModifier(key)
644: {
645: return (TRUE);
646: }
647:
648: /*ARGSUSED*/
649: void
650: sunBlockHandler(nscreen, pbdata, pptv, pReadmask)
651: int nscreen;
652: pointer pbdata;
653: struct timeval **pptv;
654: pointer pReadmask;
655: {
656: static struct timeval artv; /* autorepeat timeval */
657: static sec1 = 0; /* tmp for patching */
658: static sec2 = AUTOREPEAT_INITIATE;
659: static sec3 = AUTOREPEAT_DELAY;
660:
661: if (!autoRepeatKeyDown)
662: return;
663:
664: artv.tv_sec = sec1;
665: if (autoRepeatFirst == TRUE)
666: artv.tv_usec = 1000 * sec2;
667: else
668: artv.tv_usec = 1000 * sec3;
669: *pptv = &artv;
670: if (autoRepeatDebug)
671: ErrorF("sunBlockHandler(%d,%d): \n", artv.tv_sec, artv.tv_usec);
672: }
673:
674: /*ARGSUSED*/
675: void
676: sunWakeupHandler(nscreen, pbdata, err, pReadmask)
677: int nscreen;
678: pointer pbdata;
679: unsigned long err;
680: pointer pReadmask;
681: {
682: struct timeval tv;
683:
684: if (autoRepeatDebug)
685: ErrorF("sunWakeupHandler(ar=%d, err=%d):\n", autoRepeatKeyDown, err);
686:
687: if (autoRepeatKeyDown) {
688: gettimeofday(&tv, (struct timezone *) NULL);
689: tvminus(autoRepeatDeltaTv, tv, autoRepeatLastKeyDownTv);
690: if (autoRepeatDeltaTv.tv_sec > 0 ||
691: (!autoRepeatFirst && autoRepeatDeltaTv.tv_usec >
692: 1000 * AUTOREPEAT_DELAY) ||
693: (autoRepeatDeltaTv.tv_usec >
694: 1000 * AUTOREPEAT_INITIATE))
695: autoRepeatReady++;
696: }
697:
698: if (autoRepeatReady)
699: ProcessInputEvents();
700: autoRepeatReady = 0;
701: }
702:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.