1 /************************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ********************************************************/
50 #include <X11/extensions/XI2proto.h>
55 #include "dixstruct.h"
56 #include "cursorstr.h"
60 extern _X_EXPORT
void AssignTypeAndName(DeviceIntPtr dev
,
64 #define BitIsOn(ptr, bit) (!!(((const BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))))
65 #define SetBit(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))
66 #define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7)))
67 extern _X_EXPORT
int CountBits(const uint8_t * mask
, int len
);
69 #define SameClient(obj,client) \
70 (CLIENT_BITS((obj)->resource) == (client)->clientAsMask)
72 #define EMASKSIZE (MAXDEVICES + 2)
74 /* This is the last XI2 event supported by the server. If you add
75 * events to the protocol, the server will not support these events until
76 * this number here is bumped.
78 #define XI2LASTEVENT XI_GestureSwipeEnd
79 #define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */
82 * Scroll types for ::SetScrollValuator and the scroll type in the
86 SCROLL_TYPE_NONE
= 0, /**< Not a scrolling valuator */
87 SCROLL_TYPE_VERTICAL
= 8,
88 SCROLL_TYPE_HORIZONTAL
= 9,
92 * This struct stores the core event mask for each client except the client
93 * that created the window.
95 * Each window that has events selected from other clients has at least one of
96 * these masks. If multiple clients selected for events on the same window,
97 * these masks are in a linked list.
99 * The event mask for the client that created the window is stored in
100 * win->eventMask instead.
102 * The resource id is simply a fake client ID to associate this mask with a
105 * Kludge: OtherClients and InputClients must be compatible, see code.
107 typedef struct _OtherClients
{
108 OtherClientsPtr next
; /**< Pointer to the next mask */
109 XID resource
; /**< id for putting into resource manager */
110 Mask mask
; /**< Core event mask */
114 * This struct stores the XI event mask for each client.
116 * Each window that has events selected has at least one of these masks. If
117 * multiple client selected for events on the same window, these masks are in
120 typedef struct _InputClients
{
121 InputClientsPtr next
; /**< Pointer to the next mask */
122 XID resource
; /**< id for putting into resource manager */
123 Mask mask
[EMASKSIZE
]; /**< Actual XI event mask, deviceid is index */
124 /** XI2 event masks. One per device, each bit is a mask of (1 << type) */
125 struct _XI2Mask
*xi2mask
;
129 * Combined XI event masks from all devices.
131 * This is the XI equivalent of the deliverableEvents, eventMask and
132 * dontPropagate mask of the WindowRec (or WindowOptRec).
134 * A window that has an XI client selecting for events has exactly one
135 * OtherInputMasks struct and exactly one InputClients struct hanging off
136 * inputClients. Each further client appends to the inputClients list.
137 * Each Mask field is per-device, with the device id as the index.
138 * Exception: for non-device events (Presence events), the MAXDEVICES
141 typedef struct _OtherInputMasks
{
143 * Bitwise OR of all masks by all clients and the window's parent's masks.
145 Mask deliverableEvents
[EMASKSIZE
];
147 * Bitwise OR of all masks by all clients on this window.
149 Mask inputEvents
[EMASKSIZE
];
150 /** The do-not-propagate masks for each device. */
151 Mask dontPropagateMask
[EMASKSIZE
];
152 /** The clients that selected for events */
153 InputClientsPtr inputClients
;
154 /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
155 struct _XI2Mask
*xi2mask
;
159 * The following structure gets used for both active and passive grabs. For
160 * active grabs some of the fields (e.g. modifiers) are not used. However,
161 * that is not much waste since there aren't many active grabs (one per
162 * keyboard/pointer device) going at once in the server.
165 #define MasksPerDetailMask 8 /* 256 keycodes and 256 possible
166 modifier combinations, but only
169 typedef struct _DetailRec
{ /* Grab details may be bit masks */
177 struct _XI2Mask
*xi2mask
;
181 * Central struct for device grabs.
182 * The same struct is used for both core grabs and device grabs, with
183 * different fields being set.
184 * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
185 * is a combination of standard event masks (i.e. PointerMotionMask |
187 * If the grab is a device grab (GrabDevice), then the eventMask is a
188 * combination of event masks for a given XI event type (see SetEventInfo).
190 * If the grab is a result of a ButtonPress, then eventMask is the core mask
191 * and deviceMask is set to the XI event mask for the grab.
193 typedef struct _GrabRec
{
194 GrabPtr next
; /* for chain of passive grabs */
198 unsigned ownerEvents
:1;
199 unsigned keyboardMode
:1;
200 unsigned pointerMode
:1;
201 enum InputLevel grabtype
;
202 CARD8 type
; /* event type for passive grabs, 0 for active grabs */
203 DetailRec modifiersDetail
;
204 DeviceIntPtr modifierDevice
;
205 DetailRec detail
; /* key or button */
206 WindowPtr confineTo
; /* always NULL for keyboards */
207 CursorPtr cursor
; /* always NULL for keyboards */
210 /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
211 struct _XI2Mask
*xi2mask
;
215 * Sprite information for a device.
217 typedef struct _SpriteRec
{
219 BoxRec hotLimits
; /* logical constraints of hot spot */
220 Bool confined
; /* confined to screen */
221 RegionPtr hotShape
; /* additional logical shape constraint */
222 BoxRec physLimits
; /* physical constraints of hot spot */
223 WindowPtr win
; /* window of logical position */
224 HotSpot hot
; /* logical pointer position */
225 HotSpot hotPhys
; /* physical pointer position */
227 ScreenPtr screen
; /* all others are in Screen 0 coordinates */
228 RegionRec Reg1
; /* Region 1 for confining motion */
229 RegionRec Reg2
; /* Region 2 for confining virtual motion */
230 WindowPtr windows
[MAXSCREENS
];
231 WindowPtr confineWin
; /* confine window */
233 /* The window trace information is used at dix/events.c to avoid having
234 * to compute all the windows between the root and the current pointer
235 * window each time a button or key goes down. The grabs on each of those
236 * windows must be checked.
237 * spriteTraces should only be used at dix/events.c! */
238 WindowPtr
*spriteTrace
;
242 /* Due to delays between event generation and event processing, it is
243 * possible that the pointer has crossed screen boundaries between the
244 * time in which it begins generating events and the time when
245 * those events are processed.
247 * pEnqueueScreen: screen the pointer was on when the event was generated
248 * pDequeueScreen: screen the pointer was on when the event is processed
250 ScreenPtr pEnqueueScreen
;
251 ScreenPtr pDequeueScreen
;
255 typedef struct _KeyClassRec
{
257 CARD8 down
[DOWN_LENGTH
];
258 CARD8 postdown
[DOWN_LENGTH
];
259 int modifierKeyCount
[8];
260 struct _XkbSrvInfo
*xkbInfo
;
261 } KeyClassRec
, *KeyClassPtr
;
263 typedef struct _ScrollInfo
{
264 enum ScrollType type
;
267 } ScrollInfo
, *ScrollInfoPtr
;
269 typedef struct _AxisInfo
{
278 } AxisInfo
, *AxisInfoPtr
;
280 typedef struct _ValuatorAccelerationRec
{
282 PointerAccelSchemeProc AccelSchemeProc
;
283 void *accelData
; /* at disposal of AccelScheme */
284 PointerAccelSchemeInitProc AccelInitProc
;
285 DeviceCallbackProc AccelCleanupProc
;
286 } ValuatorAccelerationRec
, *ValuatorAccelerationPtr
;
288 typedef struct _ValuatorClassRec
{
293 void *motion
; /* motion history buffer. Different layout
295 WindowPtr motionHintWindow
;
298 unsigned short numAxes
;
299 double *axisVal
; /* always absolute, but device-coord system */
300 ValuatorAccelerationRec accelScheme
;
301 int h_scroll_axis
; /* horiz smooth-scrolling axis */
302 int v_scroll_axis
; /* vert smooth-scrolling axis */
305 typedef struct _TouchListener
{
306 XID listener
; /* grabs/event selection IDs receiving
307 * events for this touch */
308 int resource_type
; /* listener's resource type */
309 enum TouchListenerType type
;
310 enum TouchListenerState state
;
311 enum InputLevel level
; /* matters only for emulating touches */
316 typedef struct _TouchPointInfo
{
317 uint32_t client_id
; /* touch ID as seen in client events */
318 int sourceid
; /* Source device's ID for this touchpoint */
319 Bool active
; /* whether or not the touch is active */
320 Bool pending_finish
; /* true if the touch is physically inactive
321 * but still owned by a grab */
322 SpriteRec sprite
; /* window trace for delivery */
323 ValuatorMask
*valuators
; /* last recorded axis values */
324 TouchListener
*listeners
; /* set of listeners */
326 int num_grabs
; /* number of open grabs on this touch
327 * which have not accepted or rejected */
328 Bool emulate_pointer
;
329 DeviceEvent
*history
; /* History of events on this touchpoint */
330 size_t history_elements
; /* Number of current elements in history */
331 size_t history_size
; /* Size of history in elements */
334 typedef struct _DDXTouchPointInfo
{
335 uint32_t client_id
; /* touch ID as seen in client events */
336 Bool active
; /* whether or not the touch is active */
337 uint32_t ddx_id
; /* touch ID given by the DDX */
338 Bool emulate_pointer
;
340 ValuatorMask
*valuators
; /* last axis values as posted, pre-transform */
341 } DDXTouchPointInfoRec
;
343 typedef struct _TouchClassRec
{
345 TouchPointInfoPtr touches
;
346 unsigned short num_touches
; /* number of allocated touches */
347 unsigned short max_touches
; /* maximum number of touches, may be 0 */
348 CARD8 mode
; /* ::XIDirectTouch, XIDependentTouch */
349 /* for pointer-emulation */
350 CARD8 buttonsDown
; /* number of buttons down */
351 unsigned short state
; /* logical button state */
355 typedef struct _GestureListener
{
356 XID listener
; /* grabs/event selection IDs receiving
357 * events for this gesture */
358 int resource_type
; /* listener's resource type */
359 enum GestureListenerType type
;
364 typedef struct _GestureInfo
{
365 int sourceid
; /* Source device's ID for this gesture */
366 Bool active
; /* whether or not the gesture is active */
367 uint8_t type
; /* Gesture type: either ET_GesturePinchBegin or
368 ET_GestureSwipeBegin. Valid if active == TRUE */
369 int num_touches
; /* The number of touches in the gesture */
370 SpriteRec sprite
; /* window trace for delivery */
371 GestureListener listener
; /* the listener that will receive events */
372 Bool has_listener
; /* true if listener has been setup already */
375 typedef struct _GestureClassRec
{
377 GestureInfoRec gesture
;
378 unsigned short max_touches
; /* maximum number of touches, may be 0 */
381 typedef struct _ButtonClassRec
{
384 CARD8 buttonsDown
; /* number of buttons currently down
385 This counts logical buttons, not
386 physical ones, i.e if some buttons
387 are mapped to 0, they're not counted
389 unsigned short state
;
391 CARD8 down
[DOWN_LENGTH
];
392 CARD8 postdown
[DOWN_LENGTH
];
393 CARD8 map
[MAP_LENGTH
];
394 union _XkbAction
*xkb_acts
;
395 Atom labels
[MAX_BUTTONS
];
396 } ButtonClassRec
, *ButtonClassPtr
;
398 typedef struct _FocusClassRec
{
400 WindowPtr win
; /* May be set to a int constant (e.g. PointerRootWin)! */
406 } FocusClassRec
, *FocusClassPtr
;
408 typedef struct _ProximityClassRec
{
411 } ProximityClassRec
, *ProximityClassPtr
;
413 typedef struct _KbdFeedbackClassRec
*KbdFeedbackPtr
;
414 typedef struct _PtrFeedbackClassRec
*PtrFeedbackPtr
;
415 typedef struct _IntegerFeedbackClassRec
*IntegerFeedbackPtr
;
416 typedef struct _StringFeedbackClassRec
*StringFeedbackPtr
;
417 typedef struct _BellFeedbackClassRec
*BellFeedbackPtr
;
418 typedef struct _LedFeedbackClassRec
*LedFeedbackPtr
;
420 typedef struct _KbdFeedbackClassRec
{
421 BellProcPtr BellProc
;
422 KbdCtrlProcPtr CtrlProc
;
425 struct _XkbSrvLedInfo
*xkb_sli
;
426 } KbdFeedbackClassRec
;
428 typedef struct _PtrFeedbackClassRec
{
429 PtrCtrlProcPtr CtrlProc
;
432 } PtrFeedbackClassRec
;
434 typedef struct _IntegerFeedbackClassRec
{
435 IntegerCtrlProcPtr CtrlProc
;
437 IntegerFeedbackPtr next
;
438 } IntegerFeedbackClassRec
;
440 typedef struct _StringFeedbackClassRec
{
441 StringCtrlProcPtr CtrlProc
;
443 StringFeedbackPtr next
;
444 } StringFeedbackClassRec
;
446 typedef struct _BellFeedbackClassRec
{
447 BellProcPtr BellProc
;
448 BellCtrlProcPtr CtrlProc
;
450 BellFeedbackPtr next
;
451 } BellFeedbackClassRec
;
453 typedef struct _LedFeedbackClassRec
{
454 LedCtrlProcPtr CtrlProc
;
457 struct _XkbSrvLedInfo
*xkb_sli
;
458 } LedFeedbackClassRec
;
460 typedef struct _ClassesRec
{
462 ValuatorClassPtr valuator
;
464 GestureClassPtr gesture
;
465 ButtonClassPtr button
;
467 ProximityClassPtr proximity
;
468 KbdFeedbackPtr kbdfeed
;
469 PtrFeedbackPtr ptrfeed
;
470 IntegerFeedbackPtr intfeed
;
471 StringFeedbackPtr stringfeed
;
472 BellFeedbackPtr bell
;
476 /* Device properties */
477 typedef struct _XIPropertyValue
{
478 Atom type
; /* ignored by server */
479 short format
; /* format of data for swapping - 8,16,32 */
480 long size
; /* size of data in (format/8) bytes */
481 void *data
; /* private to client */
482 } XIPropertyValueRec
;
484 typedef struct _XIProperty
{
485 struct _XIProperty
*next
;
487 BOOL deletable
; /* clients can delete this prop? */
488 XIPropertyValueRec value
;
491 typedef XIPropertyRec
*XIPropertyPtr
;
492 typedef XIPropertyValueRec
*XIPropertyValuePtr
;
494 typedef struct _XIPropertyHandler
{
495 struct _XIPropertyHandler
*next
;
497 int (*SetProperty
) (DeviceIntPtr dev
,
498 Atom property
, XIPropertyValuePtr prop
, BOOL checkonly
);
499 int (*GetProperty
) (DeviceIntPtr dev
, Atom property
);
500 int (*DeleteProperty
) (DeviceIntPtr dev
, Atom property
);
501 } XIPropertyHandler
, *XIPropertyHandlerPtr
;
503 /* states for devices */
505 #define NOT_GRABBED 0
507 #define THAWED_BOTH 2 /* not a real state */
508 #define FREEZE_NEXT_EVENT 3
509 #define FREEZE_BOTH_NEXT_EVENT 4
510 #define FROZEN 5 /* any state >= has device frozen */
511 #define FROZEN_NO_EVENT 5
512 #define FROZEN_WITH_EVENT 6
513 #define THAW_OTHERS 7
515 typedef struct _GrabInfoRec
{
517 Bool fromPassiveGrab
; /* true if from passive grab */
518 Bool implicitGrab
; /* implicit from ButtonPress */
519 GrabPtr unused
; /* Kept for ABI stability, remove soon */
522 void (*ActivateGrab
) (DeviceIntPtr
/*device */ ,
524 TimeStamp
/*time */ ,
525 Bool
/*autoGrab */ );
526 void (*DeactivateGrab
) (DeviceIntPtr
/*device */ );
530 GrabPtr other
; /* if other grab has this frozen */
531 InternalEvent
*event
; /* saved to be replayed */
533 } GrabInfoRec
, *GrabInfoPtr
;
535 typedef struct _SpriteInfoRec
{
536 /* sprite must always point to a valid sprite. For devices sharing the
537 * sprite, let sprite point to a paired spriteOwner's sprite. */
538 SpritePtr sprite
; /* sprite information */
539 Bool spriteOwner
; /* True if device owns the sprite */
540 DeviceIntPtr paired
; /* The paired device. Keyboard if
541 spriteOwner is TRUE, otherwise the
542 pointer that owns the sprite. */
544 /* keep states for animated cursor */
550 } SpriteInfoRec
, *SpriteInfoPtr
;
553 #define MASTER_POINTER 1
554 #define MASTER_KEYBOARD 2
556 /* special types for GetMaster */
557 #define MASTER_ATTACHED 4 /* Master for this device */
558 #define KEYBOARD_OR_FLOAT 5 /* Keyboard master for this device or this device if floating */
559 #define POINTER_OR_FLOAT 6 /* Pointer master for this device or this device if floating */
561 typedef struct _DeviceIntRec
{
564 Bool startup
; /* true if needs to be turned on at
565 server initialization time */
566 DeviceProc deviceProc
; /* proc(DevicePtr, DEVICE_xx). It is
567 used to initialize, turn on, or
568 turn off the device */
569 Bool inited
; /* TRUE if INIT returns Success */
570 Bool enabled
; /* TRUE if ON returns Success */
571 Bool coreEvents
; /* TRUE if device also sends core */
572 GrabInfoRec deviceGrab
; /* grab on the device */
573 int type
; /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */
578 ValuatorClassPtr valuator
;
580 GestureClassPtr gesture
;
581 ButtonClassPtr button
;
583 ProximityClassPtr proximity
;
584 KbdFeedbackPtr kbdfeed
;
585 PtrFeedbackPtr ptrfeed
;
586 IntegerFeedbackPtr intfeed
;
587 StringFeedbackPtr stringfeed
;
588 BellFeedbackPtr bell
;
590 struct _XkbInterest
*xkb_interest
;
591 char *config_info
; /* used by the hotplug layer */
592 ClassesPtr unused_classes
; /* for master devices */
593 int saved_master_id
; /* for slaves while grabbed */
594 PrivateRec
*devPrivates
;
595 DeviceUnwrapProc unwrapProc
;
596 SpriteInfoPtr spriteInfo
;
597 DeviceIntPtr master
; /* master device */
598 DeviceIntPtr lastSlave
; /* last slave device used */
600 /* last valuator values recorded, not posted to client;
601 * for slave devices, valuators is in device coordinates, mapped to the
603 * for master devices, valuators is in desktop coordinates.
604 * see dix/getevents.c
605 * remainder supports acceleration
608 double valuators
[MAX_VALUATORS
];
611 ValuatorMask
*scroll
;
612 int num_touches
; /* size of the touches array */
613 DDXTouchPointInfoPtr touches
;
616 /* Input device property handling. */
618 XIPropertyPtr properties
;
619 XIPropertyHandlerPtr handlers
; /* NULL-terminated */
622 /* coordinate transformation matrix for relative movement. Matrix with
623 * the translation component dropped */
624 struct pixman_f_transform relative_transform
;
625 /* scale matrix for absolute devices, this is the combined matrix of
626 [1/scale] . [transform] . [scale]. See DeviceSetTransform */
627 struct pixman_f_transform scale_and_transform
;
629 /* XTest related master device id */
631 DeviceSendEventsProc sendEventsProc
;
633 struct _SyncCounter
*idle_counter
;
635 Bool ignoreXkbActionsBehaviors
; /* TRUE if keys don't trigger behaviors and actions */
639 int numDevices
; /* total number of devices */
640 DeviceIntPtr devices
; /* all devices turned on */
641 DeviceIntPtr off_devices
; /* all devices turned off */
642 DeviceIntPtr keyboard
; /* the main one for the server */
643 DeviceIntPtr pointer
;
644 DeviceIntPtr all_devices
;
645 DeviceIntPtr all_master_devices
;
648 extern _X_EXPORT InputInfo inputInfo
;
650 /* for keeping the events for devices grabbed synchronously */
651 typedef struct _QdEvent
*QdEventPtr
;
652 typedef struct _QdEvent
{
653 struct xorg_list next
;
655 ScreenPtr pScreen
; /* what screen the pointer was on */
656 unsigned long months
; /* milliseconds is in the event */
657 InternalEvent
*event
;
661 * syncEvents is the global structure for queued events.
663 * Devices can be frozen through GrabModeSync pointer grabs. If this is the
664 * case, events from these devices are added to "pending" instead of being
665 * processed normally. When the device is unfrozen, events in "pending" are
666 * replayed and processed as if they would come from the device directly.
668 typedef struct _EventSyncInfo
{
669 struct xorg_list pending
;
671 /** The device to replay events for. Only set in AllowEvents(), in which
672 * case it is set to the device specified in the request. */
673 DeviceIntPtr replayDev
; /* kludgy rock to put flag for */
676 * The window the events are supposed to be replayed on.
677 * This window may be set to the grab's window (but only when
678 * Replay{Pointer|Keyboard} is given in the XAllowEvents()
680 WindowPtr replayWin
; /* ComputeFreezes */
682 * Flag to indicate whether we're in the process of
683 * replaying events. Only set in ComputeFreezes(). */
686 } EventSyncInfoRec
, *EventSyncInfoPtr
;
688 extern EventSyncInfoRec syncEvents
;
691 * Given a sprite, returns the window at the bottom of the trace (i.e. the
692 * furthest window from the root).
694 static inline WindowPtr
695 DeepestSpriteWin(SpritePtr sprite
)
697 assert(sprite
->spriteTraceGood
> 0);
698 return sprite
->spriteTrace
[sprite
->spriteTraceGood
- 1];
702 unsigned char **masks
; /* event mask in masks[deviceid][event type byte] */
703 size_t nmasks
; /* number of masks */
704 size_t mask_size
; /* size of each mask in bytes */
707 #endif /* INPUTSTRUCT_H */