SDL_pen_c.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../SDL_internal.h"
  19. #ifndef SDL_pen_c_h_
  20. #define SDL_pen_c_h_
  21. #include "../../include/SDL3/SDL_pen.h"
  22. #include "SDL_mouse_c.h"
  23. /* For testing alternate code paths: */
  24. #define SDL_PEN_DEBUG_NOID 0 /* Pretend that pen device does not supply ID / ID is some default value \
  25. affects: SDL_x11pen.c \
  26. SDL_waylandevents.c */
  27. #define SDL_PEN_DEBUG_NONWACOM 0 /* Pretend that no attached device is a Wacom device \
  28. affects: SDL_x11pen.c \
  29. SDL_waylandevents.c */
  30. #define SDL_PEN_DEBUG_UNKNOWN_WACOM 0 /* Pretend that any attached Wacom device is of an unknown make \
  31. affects: SDL_PenModifyFromWacomID() */
  32. #define SDL_PEN_DEBUG_NOSERIAL_WACOM 0 /* Pretend that any attached Wacom device has serial number 0 \
  33. affects: SDL_x11pen.c \
  34. SDL_waylandevents.c */
  35. #define SDL_PEN_TYPE_NONE 0 /**< Pen type for non-pens (use to cancel pen registration) */
  36. #define SDL_PEN_MAX_NAME 64
  37. #define SDL_PEN_FLAG_ERROR (1ul << 28) /* Printed an internal API usage error about this pen (used to prevent spamming) */
  38. #define SDL_PEN_FLAG_NEW (1ul << 29) /* Pen was registered in most recent call to SDL_PenRegisterBegin() */
  39. #define SDL_PEN_FLAG_DETACHED (1ul << 30) /* Detached (not re-registered before last SDL_PenGCSweep()) */
  40. #define SDL_PEN_FLAG_STALE (1ul << 31) /* Not re-registered since last SDL_PenGCMark() */
  41. typedef struct SDL_PenStatusInfo
  42. {
  43. float x, y;
  44. float axes[SDL_PEN_NUM_AXES];
  45. Uint16 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */
  46. } SDL_PenStatusInfo;
  47. /**
  48. * Internal (backend driver-independent) pen representation
  49. *
  50. * Implementation-specific backend drivers may read and write most of this structure, and
  51. * are expected to initialise parts of it when registering a new pen. They must not write
  52. * to the "header" section.
  53. */
  54. typedef struct SDL_Pen
  55. {
  56. /* Backend driver MUST NOT not write to: */
  57. struct SDL_Pen_header
  58. {
  59. SDL_PenID id; /* id determines sort order unless SDL_PEN_FLAG_DETACHED is set */
  60. Uint32 flags; /* SDL_PEN_FLAG_* | SDK_PEN_DOWN_MASK | SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_* */
  61. SDL_Window *window; /* Current SDL window for this pen, or NULL */
  62. } header;
  63. SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */
  64. /* Backend: MUST initialise this block when pen is first registered: */
  65. SDL_GUID guid; /* GUID, MUST be set by backend.
  66. MUST be unique (no other pen ID with same GUID).
  67. SHOULD be persistent across sessions. */
  68. /* Backend: SHOULD initialise this block when pen is first registered if it can
  69. Otherwise: Set to sane default values during SDL_PenModifyEnd() */
  70. SDL_PenCapabilityInfo info; /* Detail information about the pen (buttons, tilt) */
  71. SDL_PenSubtype type;
  72. Uint8 last_mouse_button; /* For mouse button emulation: last emulated button */
  73. char *name; /* Preallocated; set via SDL_strlcpy(pen->name, src, SDL_PEN_MAX_NAME) */
  74. /* We hand this exact pointer to client code, so it must not be modified after
  75. creation. */
  76. void *deviceinfo; /* implementation-specific information */
  77. } SDL_Pen;
  78. /* ---- API for backend driver only ---- */
  79. /**
  80. * (Only for backend driver) Look up a pen by pen ID
  81. *
  82. * \param instance_id A Uint32 pen identifier (driver-dependent meaning). Must not be 0 = SDL_PEN_INVALID.
  83. * The same ID is exposed to clients as SDL_PenID.
  84. *
  85. * The pen pointer is only valid until the next call to SDL_PenModifyEnd() or SDL_PenGCSweep()
  86. *
  87. * \return pen, if it exists, or NULL
  88. */
  89. extern SDL_Pen *SDL_GetPenPtr(Uint32 instance_id);
  90. /**
  91. * (Only for backend driver) Start registering a new pen or updating an existing pen.
  92. *
  93. * Acquires the pen mutex, which is held until the next call to SDL_PenModifyEnd() .
  94. *
  95. * If the PenID already exists, returns the existing entry. Otherwise initialise fresh SDL_Pen.
  96. * For new pens, sets SDL_PEN_FLAG_NEW.
  97. *
  98. * Usage:
  99. * - SDL_PenModifyStart()
  100. * - update pen object, in any order:
  101. * - SDL_PenModifyAddCapabilities()
  102. * - pen->guid (MUST be set for new pens, e.g. via ::SDL_PenUpdateGUIDForGeneric and related operations)
  103. * - pen->info.num_buttons
  104. * - pen->info.max_tilt
  105. * - pen->type
  106. * - pen->name
  107. * - pen->deviceinfo (backend-specific)
  108. * - SDL_PenModifyEnd()
  109. *
  110. * For new pens, sets defaults for:
  111. * - num_buttons (SDL_PEN_INFO_UNKNOWN)
  112. * - max_tilt (SDL_PEN_INFO_UNKNOWN)
  113. * - pen_type (SDL_PEN_TYPE_PEN)
  114. * - Zeroes all other (non-header) fields
  115. *
  116. * \param instance_id Pen ID to allocate (must not be 0 = SDL_PEN_ID_INVALID)
  117. * \returns SDL_Pen pointer; only valid until the call to SDL_PenModifyEnd()
  118. */
  119. extern SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id);
  120. /**
  121. * (Only for backend driver) Add capabilities to a pen (cf. SDL_PenModifyBegin()).
  122. *
  123. * Adds capabilities to a pen obtained via SDL_PenModifyBegin(). Can be called more than once.
  124. *
  125. * \param pen The pen to update
  126. * \param capabilities Capabilities flags, out of: SDL_PEN_AXIS_*, SDL_PEN_ERASER_MASK, SDL_PEN_INK_MASK
  127. * Setting SDL_PEN_ERASER_MASK will clear SDL_PEN_INK_MASK, and vice versa.
  128. */
  129. extern void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities);
  130. /**
  131. * Set up a pen structure for a Wacom device.
  132. *
  133. * Some backends (e.g., XInput2, Wayland) can only partially identify the capabilities of a given
  134. * pen but can identify Wacom pens and obtain their Wacom-specific device type identifiers.
  135. * This function partly automates device setup in those cases.
  136. *
  137. * This function does NOT set up the pen's GUID. Use ::SD_PenModifyGUIDForWacom instead.
  138. *
  139. * This function does NOT call SDL_PenModifyAddCapabilities() ifself, since some backends may
  140. * not have access to all pen axes (e.g., Xinput2).
  141. *
  142. * \param pen The pen to initialise
  143. * \param wacom_devicetype_id The Wacom-specific device type identifier
  144. * \param[out] axis_flags The set of physically supported axes for this pen, suitable for passing to
  145. * SDL_PenModifyAddCapabilities()
  146. *
  147. * \returns SDL_TRUE if the device ID could be identified, otherwise SDL_FALSE
  148. */
  149. extern int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags);
  150. /**
  151. * Updates a GUID for a generic pen device.
  152. *
  153. * Assumes that the GUID has been pre-initialised (typically to 0).
  154. * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForType
  155. *
  156. * \param[out] guid The GUID to update
  157. * \param upper Upper half of the device ID (assume lower entropy than "lower"; pass 0 if not available)
  158. * \param lower Lower half of the device ID (assume higher entropy than "upper")
  159. */
  160. extern void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower);
  161. /**
  162. * Updates a GUID based on a pen type
  163. *
  164. * Assumes that the GUID has been pre-initialised (typically to 0).
  165. * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForGeneric
  166. *
  167. * \param[out] guid The GUID to update
  168. * \param pentype The pen type to insert
  169. */
  170. extern void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype);
  171. /**
  172. * Updates a GUID for a Wacom pen device.
  173. *
  174. * Assumes that the GUID has been pre-initialised (typically to 0).
  175. * Idempotent, and commutative with ::SDL_PenUpdateGUIDForType and ::SDL_PenUpdateGUIDForGeneric
  176. *
  177. * This update is identical to the one written by ::SDL_PenModifyFromWacomID .
  178. *
  179. * \param[out] guid The GUID to update
  180. * \param wacom_devicetype_id The Wacom-specific device type identifier
  181. * \param wacom_serial_id The Wacom-specific serial number
  182. */
  183. extern void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id);
  184. /**
  185. * (Only for backend driver) Finish updating a pen.
  186. *
  187. * Releases the pen mutex acquired by SDL_PenModifyBegin() .
  188. *
  189. * If pen->type == SDL_PEN_TYPE_NONE, removes the pen entirely (only
  190. * for new pens). This allows backends to start registering a
  191. * potential pen device and to abort if the device turns out to not be
  192. * a pen.
  193. *
  194. * For new pens, this call will also set the following:
  195. * - name (default name, if not yet set)
  196. *
  197. * \param pen The pen to register. That pointer is no longer valid after this call.
  198. * \param attach Whether the pen should be attached (SDL_TRUE) or detached (SDL_FALSE).
  199. *
  200. * If the pen is detached or removed, it is the caller's responsibility to free
  201. * and null "deviceinfo".
  202. */
  203. extern void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach);
  204. /**
  205. * (Only for backend driver) Mark all current pens for garbage collection.
  206. *
  207. * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
  208. *
  209. * SDL_PenGCMark() / SDL_PenGCSweep() provide a simple mechanism for
  210. * detaching all known pens that are not discoverable. This allows
  211. * backends to use the same code for pen discovery and for
  212. * hotplugging:
  213. *
  214. * - SDL_PenGCMark() and start backend-specific discovery
  215. * - for each discovered pen: SDL_PenModifyBegin() + SDL_PenModifyEnd() (this will retain existing state)
  216. * - SDL_PenGCSweep() (will now detach all pens that were not re-registered).
  217. */
  218. extern void SDL_PenGCMark(void);
  219. /**
  220. * (Only for backend driver) Detach pens that haven't been reported attached since the last call to SDL_PenGCMark().
  221. *
  222. * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
  223. *
  224. * See SDL_PenGCMark() for details.
  225. *
  226. * \param context Extra parameter to pass through to "free_deviceinfo"
  227. * \param free_deviceinfo Operation to call on any non-NULL "backend.deviceinfo".
  228. *
  229. * \sa SDL_PenGCMark()
  230. */
  231. extern void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32 instance_id, void *deviceinfo, void *context));
  232. /**
  233. * (Only for backend driver) Send a pen motion event.
  234. *
  235. * Suppresses pen motion events that do not change the current pen state.
  236. * May also send a mouse motion event, if mouse emulation is enabled and the pen position has
  237. * changed sufficiently for the motion to be visible to mouse event listeners.
  238. *
  239. * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
  240. * While 0 is safe to report, your backends may be able to report more precise
  241. * timing information.
  242. * Keep in mind that you should never report timestamps that are greater than
  243. * SDL_GetTicksNS() . In particular, SDL_GetTicksNS() reports nanoseconds since the start
  244. * of the SDL session, and your backend may use a different starting point as "timestamp zero".
  245. * \param instance_id Pen
  246. * \param window_relative Coordinates are already window-relative
  247. * \param status Coordinates and axes (buttons are ignored)
  248. *
  249. * \returns SDL_TRUE if at least one event was sent
  250. */
  251. extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_bool window_relative, const SDL_PenStatusInfo *status);
  252. /**
  253. * (Only for backend driver) Send a pen button event
  254. *
  255. * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
  256. * See SDL_SendPenMotion() for a discussion about how to handle timestamps.
  257. * \param instance_id Pen
  258. * \param state SDL_PRESSED or SDL_RELEASED
  259. * \param button Button number: 1 (first physical button) etc.
  260. *
  261. * \returns SDL_TRUE if at least one event was sent
  262. */
  263. extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button);
  264. /**
  265. * (Only for backend driver) Send a pen tip event (touching or no longer touching the surface)
  266. *
  267. * Note: the backend should perform hit testing on window decoration elements to allow the pen
  268. * to e.g. resize/move the window, just as for mouse events, unless ::SDL_SendPenTipEvent is false.
  269. *
  270. * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
  271. * See SDL_SendPenMotion() for a discussion about how to handle timestamps.
  272. * \param instance_id Pen
  273. * \param state SDL_PRESSED (for PEN_DOWN) or SDL_RELEASED (for PEN_UP)
  274. *
  275. * \returns SDL_TRUE if at least one event was sent
  276. */
  277. extern int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state);
  278. /**
  279. * (Only for backend driver) Check if a PEN_DOWN event should perform hit box testing.
  280. *
  281. * \returns SDL_TRUE if and only if the backend should perform hit testing
  282. */
  283. extern SDL_bool SDL_PenPerformHitTest(void);
  284. /**
  285. * (Only for backend driver) Send a pen window event.
  286. *
  287. * Tracks when a pen has entered/left a window.
  288. * Don't call this when reporting new pens or removing known pens; those cases are handled automatically.
  289. *
  290. * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
  291. * See SDL_SendPenMotion() for a discussion about how to handle timestamps.
  292. * \param instance_id Pen
  293. * \param window Window to enter, or NULL to exit
  294. */
  295. extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window);
  296. /**
  297. * Initialises the pen subsystem.
  298. */
  299. extern void SDL_PenInit(void);
  300. /**
  301. * De-initialises the pen subsystem.
  302. */
  303. extern void SDL_PenQuit(void);
  304. #endif /* SDL_pen_c_h_ */
  305. /* vi: set ts=4 sw=4 expandtab: */