µGFX library fork

gdisp_lld_Win32.c 48KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  1. /*
  2. * This file is subject to the terms of the GFX License. If a copy of
  3. * the license was not distributed with this file, you can obtain one at:
  4. *
  5. * http://ugfx.org/license.html
  6. */
  7. // We need to include stdio.h below. Turn off GFILE_NEED_STDIO just for this file to prevent conflicts
  8. #define GFILE_NEED_STDIO_MUST_BE_OFF
  9. #include "gfx.h"
  10. #if GFX_USE_GDISP
  11. #define GDISP_DRIVER_VMT GDISPVMT_Win32
  12. #include "gdisp_lld_config.h"
  13. #include "../../../src/gdisp/gdisp_driver.h"
  14. // Configuration parameters for this driver
  15. #ifndef GDISP_SCREEN_WIDTH
  16. #define GDISP_SCREEN_WIDTH 640
  17. #endif
  18. #ifndef GDISP_SCREEN_HEIGHT
  19. #define GDISP_SCREEN_HEIGHT 480
  20. #endif
  21. #ifndef GDISP_WIN32_USE_INDIRECT_UPDATE
  22. /**
  23. * Setting this to TRUE delays updating the screen
  24. * to the windows paint routine. Due to the
  25. * drawing lock this does not add as much speed
  26. * as might be expected but it is still faster in
  27. * all tested circumstances and for all operations
  28. * even draw_pixel().
  29. * This is probably due to drawing operations being
  30. * combined as the update regions are merged.
  31. * The only time you might want to turn this off is
  32. * if you are debugging drawing and want to see each
  33. * pixel as it is set.
  34. */
  35. #define GDISP_WIN32_USE_INDIRECT_UPDATE TRUE
  36. #endif
  37. #ifndef GKEYBOARD_WIN32_NO_LAYOUT
  38. /**
  39. * Setting this to TRUE turns off the layout engine.
  40. * In this situation "cooked" characters are returned but
  41. * shift states etc are lost.
  42. * As only a limited number of keyboard layouts are currently
  43. * defined for Win32 in uGFX (currently only US English), setting this
  44. * to TRUE enables the windows keyboard mapping to be pass non-English
  45. * characters to uGFX or to handle non-standard keyboard layouts at
  46. * the expense of losing special function keys etc.
  47. */
  48. #define GKEYBOARD_WIN32_NO_LAYOUT FALSE
  49. #endif
  50. #ifndef GKEYBOARD_WIN32_DEFAULT_LAYOUT
  51. #define GKEYBOARD_WIN32_DEFAULT_LAYOUT KeyboardLayout_Win32_US
  52. #endif
  53. // How far extra windows (multiple displays) should be offset from the first.
  54. #define DISPLAY_X_OFFSET 50
  55. #define DISPLAY_Y_OFFSET 50
  56. // Oops - name clashes with Win32 symbols
  57. #undef Red
  58. #undef Green
  59. #undef Blue
  60. #define WIN32_LEAN_AND_MEAN
  61. #include <stdio.h>
  62. #include <string.h>
  63. #include <stdlib.h>
  64. #include <windows.h>
  65. #include <wingdi.h>
  66. #include <assert.h>
  67. #define GDISP_FLG_READY (GDISP_FLG_DRIVER<<0)
  68. #define GDISP_FLG_HASTOGGLE (GDISP_FLG_DRIVER<<1)
  69. #if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
  70. #define GDISP_FLG_WSTREAM (GDISP_FLG_DRIVER<<3)
  71. #define GDISP_FLG_WRAPPED (GDISP_FLG_DRIVER<<4)
  72. #endif
  73. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  74. /* Include toggle support code */
  75. #include "../../../src/ginput/ginput_driver_toggle.h"
  76. // Hack until toggle use gdriver.
  77. static GDisplay *toggleWindow;
  78. #endif
  79. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  80. // Include mouse support code
  81. #define GMOUSE_DRIVER_VMT GMOUSEVMT_Win32
  82. #include "../../../src/ginput/ginput_driver_mouse.h"
  83. // Forward definitions
  84. static bool_t Win32MouseInit(GMouse *m, unsigned driverinstance);
  85. static bool_t Win32MouseRead(GMouse *m, GMouseReading *prd);
  86. const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
  87. {
  88. GDRIVER_TYPE_MOUSE,
  89. GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
  90. // Extra flags for testing only
  91. //GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
  92. //GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
  93. //GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
  94. sizeof(GMouse),
  95. _gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
  96. },
  97. 1, // z_max
  98. 0, // z_min
  99. 1, // z_touchon
  100. 0, // z_touchoff
  101. { // pen_jitter
  102. 0, // calibrate
  103. 0, // click
  104. 0 // move
  105. },
  106. { // finger_jitter
  107. 0, // calibrate
  108. 2, // click
  109. 2 // move
  110. },
  111. Win32MouseInit, // init
  112. 0, // deinit
  113. Win32MouseRead, // get
  114. 0, // calsave
  115. 0 // calload
  116. }};
  117. #endif
  118. #if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
  119. #define GKEYBOARD_DRIVER_VMT GKEYBOARDVMT_Win32
  120. #include "../../../src/ginput/ginput_driver_keyboard.h"
  121. #if !GKEYBOARD_WIN32_NO_LAYOUT
  122. #if GKEYBOARD_LAYOUT_OFF
  123. #error "The Win32 keyboard driver is using the layout engine. Please set GKEYBOARD_LAYOUT_OFF=FALSE or GKEYBOARD_WIN32_NO_LAYOUT=TRUE."
  124. #endif
  125. #include "../../../src/ginput/ginput_keyboard_microcode.h"
  126. // Forward definitions
  127. extern uint8_t GKEYBOARD_WIN32_DEFAULT_LAYOUT[];
  128. // This is the layout code for the English US keyboard.
  129. // We make it public so that a user can switch to a different layout if required.
  130. uint8_t KeyboardLayout_Win32_US[] = {
  131. KMC_HEADERSTART, KMC_HEADER_ID1, KMC_HEADER_ID2, KMC_HEADER_VER_1,
  132. // Transient Shifters: SHIFT, CTRL, ALT, WINKEY
  133. /* 1 */KMC_RECORDSTART, 9, // SHIFT (left & Right)
  134. KMC_TEST_CODETABLE, 2, VK_SHIFT, VK_LSHIFT,
  135. KMC_TEST_LASTCODE, 0x00,
  136. KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_L_BIT|KMC_BIT_CLEAR,
  137. KMC_ACT_DONE,
  138. /* 2 */KMC_RECORDSTART, 9,
  139. KMC_TEST_CODETABLE, 2, VK_SHIFT, VK_LSHIFT,
  140. KMC_TEST_STATEBIT, GKEYSTATE_SHIFT_L_BIT|KMC_BIT_CLEAR,
  141. KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_L_BIT,
  142. KMC_ACT_DONE,
  143. /* 3 */KMC_RECORDSTART, 7,
  144. KMC_TEST_CODE, VK_RSHIFT,
  145. KMC_TEST_LASTCODE, 0x00,
  146. KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_R_BIT|KMC_BIT_CLEAR,
  147. KMC_ACT_DONE,
  148. /* 4 */KMC_RECORDSTART, 7,
  149. KMC_TEST_CODE, VK_RSHIFT,
  150. KMC_TEST_STATEBIT, GKEYSTATE_SHIFT_R_BIT|KMC_BIT_CLEAR,
  151. KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_R_BIT,
  152. KMC_ACT_DONE,
  153. /* 5 */KMC_RECORDSTART, 9, // CONTROL (left & Right)
  154. KMC_TEST_CODETABLE, 2, VK_CONTROL, VK_LCONTROL,
  155. KMC_TEST_LASTCODE, 0x00,
  156. KMC_ACT_STATEBIT, GKEYSTATE_CTRL_L_BIT|KMC_BIT_CLEAR,
  157. KMC_ACT_DONE,
  158. /* 6 */KMC_RECORDSTART, 9,
  159. KMC_TEST_CODETABLE, 2, VK_CONTROL, VK_LCONTROL,
  160. KMC_TEST_STATEBIT, GKEYSTATE_CTRL_L_BIT|KMC_BIT_CLEAR,
  161. KMC_ACT_STATEBIT, GKEYSTATE_CTRL_L_BIT,
  162. KMC_ACT_DONE,
  163. /* 7 */KMC_RECORDSTART, 7,
  164. KMC_TEST_CODE, VK_RCONTROL,
  165. KMC_TEST_LASTCODE, 0x00,
  166. KMC_ACT_STATEBIT, GKEYSTATE_CTRL_R_BIT|KMC_BIT_CLEAR,
  167. KMC_ACT_DONE,
  168. /* 8 */KMC_RECORDSTART, 7,
  169. KMC_TEST_CODE, VK_RCONTROL,
  170. KMC_TEST_STATEBIT, GKEYSTATE_CTRL_R_BIT|KMC_BIT_CLEAR,
  171. KMC_ACT_STATEBIT, GKEYSTATE_CTRL_R_BIT,
  172. KMC_ACT_DONE,
  173. /* 9 */KMC_RECORDSTART, 9, // ALT (left & Right)
  174. KMC_TEST_CODETABLE, 2, VK_MENU, VK_LMENU,
  175. KMC_TEST_LASTCODE, 0x00,
  176. KMC_ACT_STATEBIT, GKEYSTATE_ALT_L_BIT|KMC_BIT_CLEAR,
  177. KMC_ACT_DONE,
  178. /* 10 */KMC_RECORDSTART, 9,
  179. KMC_TEST_CODETABLE, 2, VK_MENU, VK_LMENU,
  180. KMC_TEST_STATEBIT, GKEYSTATE_ALT_L_BIT|KMC_BIT_CLEAR,
  181. KMC_ACT_STATEBIT, GKEYSTATE_ALT_L_BIT,
  182. KMC_ACT_DONE,
  183. /* 11 */KMC_RECORDSTART, 7,
  184. KMC_TEST_CODE, VK_RMENU,
  185. KMC_TEST_LASTCODE, 0x00,
  186. KMC_ACT_STATEBIT, GKEYSTATE_ALT_R_BIT|KMC_BIT_CLEAR,
  187. KMC_ACT_DONE,
  188. /* 12 */KMC_RECORDSTART, 7,
  189. KMC_TEST_CODE, VK_RMENU,
  190. KMC_TEST_STATEBIT, GKEYSTATE_ALT_R_BIT|KMC_BIT_CLEAR,
  191. KMC_ACT_STATEBIT, GKEYSTATE_ALT_R_BIT,
  192. KMC_ACT_DONE,
  193. /* 13 */KMC_RECORDSTART, 9, // WinKey (left or right)
  194. KMC_TEST_CODETABLE, 2, VK_LWIN, VK_RWIN,
  195. KMC_TEST_LASTCODE, 0x00,
  196. KMC_ACT_STATEBIT, GKEYSTATE_WINKEY_BIT|KMC_BIT_CLEAR,
  197. KMC_ACT_DONE,
  198. /* 14 */KMC_RECORDSTART, 9,
  199. KMC_TEST_CODETABLE, 2, VK_LWIN, VK_RWIN,
  200. KMC_TEST_STATEBIT, GKEYSTATE_WINKEY_BIT|KMC_BIT_CLEAR,
  201. KMC_ACT_STATEBIT, GKEYSTATE_WINKEY_BIT,
  202. KMC_ACT_DONE,
  203. // Locking Shifters: CAPSLOCK, NUMLOCK and SCROLLLOCK
  204. /* 15 */KMC_RECORDSTART, 7, // CAPSLOCK (keyup only)
  205. KMC_TEST_CODE, VK_CAPITAL,
  206. KMC_TEST_LASTCODE, 0x00,
  207. KMC_ACT_STATEBIT, GKEYSTATE_CAPSLOCK_BIT|KMC_BIT_INVERT,
  208. KMC_ACT_DONE,
  209. /* 16 */KMC_RECORDSTART, 7, // NUMLOCK (keyup only)
  210. KMC_TEST_CODE, VK_NUMLOCK,
  211. KMC_TEST_LASTCODE, 0x00,
  212. KMC_ACT_STATEBIT, GKEYSTATE_NUMLOCK_BIT|KMC_BIT_INVERT,
  213. KMC_ACT_DONE,
  214. /* 17 */KMC_RECORDSTART, 7, // SCROLLLOCK (keyup only)
  215. KMC_TEST_CODE, VK_SCROLL,
  216. KMC_TEST_LASTCODE, 0x00,
  217. KMC_ACT_STATEBIT, GKEYSTATE_SCROLLLOCK_BIT|KMC_BIT_INVERT,
  218. KMC_ACT_DONE,
  219. // Keyup, Repeat
  220. /* 18 */KMC_RECORDSTART, 18, // Clear any shifter keys that got through
  221. KMC_TEST_CODETABLE, 14, VK_SHIFT, VK_LSHIFT, VK_RSHIFT,
  222. VK_CONTROL, VK_LCONTROL, VK_RCONTROL,
  223. VK_MENU, VK_LMENU, VK_RMENU,
  224. VK_LWIN, VK_RWIN,
  225. VK_CAPITAL, VK_NUMLOCK, VK_SCROLL,
  226. KMC_ACT_RESET,
  227. KMC_ACT_STOP,
  228. /* 19 */KMC_RECORDSTART, 4, // Skip special codes 0x00 (Keyup) & 0x01 (Repeat)
  229. KMC_TEST_CODERANGE, 0x00, 0x01,
  230. KMC_ACT_STOP,
  231. /* 20 */KMC_RECORDSTART, 6, // Keyup
  232. KMC_ACT_STATEBIT, GKEYSTATE_KEYUP_BIT|KMC_BIT_CLEAR,
  233. KMC_TEST_LASTCODE, 0x00,
  234. KMC_ACT_STATEBIT, GKEYSTATE_KEYUP_BIT,
  235. /* 21 */KMC_RECORDSTART, 6, // Repeat
  236. KMC_ACT_STATEBIT, GKEYSTATE_REPEAT_BIT|KMC_BIT_CLEAR,
  237. KMC_TEST_LASTCODE, 0x01,
  238. KMC_ACT_STATEBIT, GKEYSTATE_REPEAT_BIT,
  239. // 0 - 9
  240. /* 22 */KMC_RECORDSTART, 7, // Alt 0-9
  241. KMC_TEST_ALT,
  242. KMC_TEST_CODERANGE, '0', '9',
  243. KMC_ACT_CHARADD, 10,
  244. KMC_ACT_STOP,
  245. /* 23 */KMC_RECORDSTART, 17, // Shifted 0-9
  246. KMC_TEST_SHIFT,
  247. KMC_TEST_CODERANGE, '0', '9',
  248. KMC_ACT_CHARTABLE, 10, ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
  249. KMC_ACT_DONE,
  250. /* 24 */KMC_RECORDSTART, 5, // 0 - 9
  251. KMC_TEST_CODERANGE, '0', '9',
  252. KMC_ACT_CHARCODE,
  253. KMC_ACT_DONE,
  254. // A - Z
  255. /* 25 */KMC_RECORDSTART, 7, // Control A-Z
  256. KMC_TEST_CTRL,
  257. KMC_TEST_CODERANGE, 'A', 'Z',
  258. KMC_ACT_CHARRANGE, 1,
  259. KMC_ACT_DONE,
  260. /* 26 */KMC_RECORDSTART, 7, // No Caps A-Z
  261. KMC_TEST_NOCAPS,
  262. KMC_TEST_CODERANGE, 'A', 'Z',
  263. KMC_ACT_CHARRANGE, 'a',
  264. KMC_ACT_DONE,
  265. /* 27 */KMC_RECORDSTART, 5, // Caps A-Z
  266. KMC_TEST_CODERANGE, 'A', 'Z',
  267. KMC_ACT_CHARCODE,
  268. KMC_ACT_DONE,
  269. // Number pad
  270. /* 28 */KMC_RECORDSTART, 7, // Alt Number pad
  271. KMC_TEST_ALT,
  272. KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9,
  273. KMC_ACT_CHARADD, 10,
  274. KMC_ACT_STOP,
  275. /* 29 */KMC_RECORDSTART, 5,
  276. KMC_TEST_ALT,
  277. KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE,
  278. KMC_ACT_STOP,
  279. /* 30 */KMC_RECORDSTART, 7, // Number pad with Numlock
  280. KMC_TEST_NUMLOCK,
  281. KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9,
  282. KMC_ACT_CHARRANGE, '0',
  283. KMC_ACT_DONE,
  284. /* 31 */KMC_RECORDSTART, 13,
  285. KMC_TEST_NUMLOCK,
  286. KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE,
  287. KMC_ACT_CHARTABLE, 6, '*', '+', GKEY_ENTER, '-', '.', '/',
  288. KMC_ACT_DONE,
  289. /* 32 */KMC_RECORDSTART, 4, // Number pad with no Numlock
  290. KMC_TEST_CODE, VK_NUMPAD5,
  291. KMC_ACT_RESET,
  292. KMC_ACT_STOP,
  293. /* 33 */KMC_RECORDSTART, 12,
  294. KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE,
  295. KMC_ACT_CHARTABLE, 6, '*', '+', GKEY_ENTER, '-', GKEY_DEL, '/',
  296. KMC_ACT_DONE,
  297. /* 34 */KMC_RECORDSTART, 18,
  298. KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9,
  299. KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT,
  300. KMC_ACT_CHARTABLE, 10, GKEY_INSERT, GKEY_END, GKEY_DOWN, GKEY_PAGEDOWN, GKEY_LEFT, '5', GKEY_RIGHT, GKEY_HOME, GKEY_UP, GKEY_PAGEUP,
  301. KMC_ACT_DONE,
  302. // Symbols
  303. /* 35 */KMC_RECORDSTART, 14, // Shifted Symbols
  304. KMC_TEST_SHIFT,
  305. KMC_TEST_CODERANGE, VK_OEM_1, VK_OEM_3,
  306. KMC_ACT_CHARTABLE, 7, ':', '+', '<', '_', '>', '?', '~',
  307. KMC_ACT_DONE,
  308. /* 36 */KMC_RECORDSTART, 11,
  309. KMC_TEST_SHIFT,
  310. KMC_TEST_CODERANGE, VK_OEM_4, VK_OEM_7,
  311. KMC_ACT_CHARTABLE, 4, '{', '|', '}', '"',
  312. KMC_ACT_DONE,
  313. /* 37 */KMC_RECORDSTART, 13, // Non-shifted Symbols
  314. KMC_TEST_CODERANGE, VK_OEM_1, VK_OEM_3,
  315. KMC_ACT_CHARTABLE, 7, ';', '=', ',', '-', '.', '/', '`',
  316. KMC_ACT_DONE,
  317. /* 38 */KMC_RECORDSTART, 10,
  318. KMC_TEST_CODERANGE, VK_OEM_4, VK_OEM_7,
  319. KMC_ACT_CHARTABLE, 4, '[', '\\', ']', '\'',
  320. KMC_ACT_DONE,
  321. // Special Keys
  322. // Extra special keys like Media and Browser keys are still to be implemented.
  323. /* 39 */KMC_RECORDSTART, 17, // Normal Control Type Keys
  324. KMC_TEST_CODETABLE, 6, VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE, VK_DELETE,
  325. KMC_ACT_CHARTABLE, 6, GKEY_BACKSPACE, GKEY_TAB, GKEY_ENTER, GKEY_ESC, GKEY_SPACE, GKEY_DEL,
  326. KMC_ACT_DONE,
  327. /* 40 */KMC_RECORDSTART, 35, // Special Keys
  328. KMC_TEST_CODETABLE, 14, VK_PRIOR, VK_NEXT,
  329. VK_HOME, VK_END,
  330. VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN,
  331. VK_INSERT,
  332. VK_SNAPSHOT, VK_SLEEP, VK_PAUSE, VK_CANCEL,
  333. VK_APPS,
  334. KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT,
  335. KMC_ACT_CHARTABLE, 14, GKEY_PAGEUP, GKEY_PAGEDOWN,
  336. GKEY_HOME, GKEY_END,
  337. GKEY_LEFT, GKEY_RIGHT, GKEY_UP, GKEY_DOWN,
  338. GKEY_INSERT,
  339. GKEY_PRINTSCREEN, GKEY_SLEEP, GKEY_CTRLPAUSE, GKEY_CTRLBREAK,
  340. GKEY_RIGHTCLICKKEY,
  341. KMC_ACT_DONE,
  342. /* 41 */KMC_RECORDSTART, 8, // F1 .. F15
  343. KMC_TEST_CODERANGE, VK_F1, VK_F15,
  344. KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT,
  345. KMC_ACT_CHARRANGE, GKEY_FN1,
  346. KMC_ACT_DONE,
  347. // Anything else
  348. /* 40 */KMC_RECORDSTART, 1, // Just send the scan code to the user
  349. KMC_ACT_DONE,
  350. // EOF
  351. KMC_RECORDSTART, 0
  352. };
  353. #elif !GKEYBOARD_LAYOUT_OFF
  354. #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
  355. #warning "The WIN32 keyboard driver is not using the layout engine. If no other keyboard is using it consider defining GKEYBOARD_LAYOUT_OFF=TRUE to save code size."
  356. #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
  357. COMPILER_WARNING("The WIN32 keyboard driver is not using the layout engine. If no other keyboard is using it consider defining GKEYBOARD_LAYOUT_OFF=TRUE to save code size.")
  358. #endif
  359. #endif
  360. // Forward definitions
  361. static bool_t Win32KeyboardInit(GKeyboard *k, unsigned driverinstance);
  362. static int Win32KeyboardGetData(GKeyboard *k, uint8_t *pch, int sz);
  363. const GKeyboardVMT const GKEYBOARD_DRIVER_VMT[1] = {{
  364. {
  365. GDRIVER_TYPE_KEYBOARD,
  366. GKEYBOARD_VFLG_NOPOLL, // GKEYBOARD_VFLG_DYNAMICONLY
  367. sizeof(GKeyboard),
  368. _gkeyboardInitDriver, _gkeyboardPostInitDriver, _gkeyboardDeInitDriver
  369. },
  370. // The Win32 keyboard layout
  371. #if GKEYBOARD_WIN32_NO_LAYOUT
  372. 0,
  373. #else
  374. GKEYBOARD_WIN32_DEFAULT_LAYOUT,
  375. #endif
  376. Win32KeyboardInit, // init
  377. 0, // deinit
  378. Win32KeyboardGetData, // getdata
  379. 0 // putdata void (*putdata)(GKeyboard *k, char ch); Optional
  380. }};
  381. static int keypos;
  382. static uint8_t keybuffer[8];
  383. static GKeyboard *keyboard;
  384. #endif
  385. static DWORD winThreadId;
  386. static volatile bool_t QReady;
  387. static HANDLE drawMutex;
  388. static HWND hWndParent = 0;
  389. /*===========================================================================*/
  390. /* Driver local routines . */
  391. /*===========================================================================*/
  392. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  393. #define WIN32_BUTTON_AREA 16
  394. #else
  395. #define WIN32_BUTTON_AREA 0
  396. #endif
  397. #define APP_NAME "uGFX"
  398. typedef struct winPriv {
  399. HWND hwnd;
  400. HDC dcBuffer;
  401. HBITMAP dcBitmap;
  402. HBITMAP dcOldBitmap;
  403. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  404. coord_t mousex, mousey;
  405. uint16_t mousebuttons;
  406. GMouse *mouse;
  407. bool_t mouseenabled;
  408. void (*capfn)(void * hWnd, GDisplay *g, uint16_t buttons, coord_t x, coord_t y);
  409. #endif
  410. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  411. uint8_t toggles;
  412. #endif
  413. #if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
  414. coord_t x0, y0, x1, y1;
  415. coord_t x, y;
  416. #endif
  417. } winPriv;
  418. void gfxEmulatorSetParentWindow(void *hwnd) {
  419. hWndParent = (HWND)hwnd;
  420. }
  421. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  422. void gfxEmulatorMouseInject(GDisplay *g, uint16_t buttons, coord_t x, coord_t y) {
  423. winPriv * priv;
  424. priv = (winPriv *)g->priv;
  425. priv->mousebuttons = buttons;
  426. priv->mousex = x;
  427. priv->mousey = y;
  428. if ((gmvmt(priv->mouse)->d.flags & GMOUSE_VFLG_NOPOLL)) // For normal setup this is always TRUE
  429. _gmouseWakeup(priv->mouse);
  430. }
  431. void gfxEmulatorMouseEnable(GDisplay *g, bool_t enabled) {
  432. ((winPriv *)g->priv)->mouseenabled = enabled;
  433. }
  434. void gfxEmulatorMouseCapture(GDisplay *g, void (*capfn)(void * hWnd, GDisplay *g, uint16_t buttons, coord_t x, coord_t y)) {
  435. ((winPriv *)g->priv)->capfn = capfn;
  436. }
  437. #endif
  438. static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  439. {
  440. HDC dc;
  441. PAINTSTRUCT ps;
  442. GDisplay * g;
  443. winPriv * priv;
  444. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  445. uint16_t btns;
  446. #endif
  447. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  448. HBRUSH hbrOn, hbrOff;
  449. HPEN pen;
  450. RECT rect;
  451. HGDIOBJ old;
  452. POINT p;
  453. coord_t pos;
  454. uint8_t bit;
  455. #endif
  456. switch (Msg) {
  457. case WM_CREATE:
  458. // Get our GDisplay structure and attach it to the window
  459. g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams;
  460. priv = (winPriv *)g->priv;
  461. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g);
  462. // Fill in the private area
  463. priv->hwnd = hWnd;
  464. dc = GetDC(hWnd);
  465. priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height);
  466. priv->dcBuffer = CreateCompatibleDC(dc);
  467. ReleaseDC(hWnd, dc);
  468. priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap);
  469. // Mark the window as ready to go
  470. g->flags |= GDISP_FLG_READY;
  471. break;
  472. #if GFX_USE_GINPUT && (GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE)
  473. case WM_LBUTTONDOWN:
  474. // Get our GDisplay structure
  475. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  476. priv = (winPriv *)g->priv;
  477. // Handle mouse down on the window
  478. #if GINPUT_NEED_MOUSE
  479. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  480. btns = priv->mousebuttons;
  481. btns |= GINPUT_MOUSE_BTN_LEFT;
  482. goto mousemove;
  483. }
  484. #endif
  485. // Handle mouse down on the toggle area
  486. #if GINPUT_NEED_TOGGLE
  487. if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
  488. bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width);
  489. priv->toggles ^= bit;
  490. rect.left = 0;
  491. rect.right = GDISP_SCREEN_WIDTH;
  492. rect.top = GDISP_SCREEN_HEIGHT;
  493. rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
  494. InvalidateRect(hWnd, &rect, FALSE);
  495. UpdateWindow(hWnd);
  496. #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
  497. ginputToggleWakeup();
  498. #endif
  499. }
  500. #endif
  501. break;
  502. case WM_LBUTTONUP:
  503. // Get our GDisplay structure
  504. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  505. priv = (winPriv *)g->priv;
  506. // Handle mouse up on the toggle area
  507. #if GINPUT_NEED_TOGGLE
  508. if ((g->flags & GDISP_FLG_HASTOGGLE)) {
  509. if ((priv->toggles & 0x0F)) {
  510. priv->toggles &= ~0x0F;
  511. rect.left = 0;
  512. rect.right = GDISP_SCREEN_WIDTH;
  513. rect.top = GDISP_SCREEN_HEIGHT;
  514. rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
  515. InvalidateRect(hWnd, &rect, FALSE);
  516. UpdateWindow(hWnd);
  517. #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
  518. ginputToggleWakeup();
  519. #endif
  520. }
  521. }
  522. #endif
  523. // Handle mouse up on the window
  524. #if GINPUT_NEED_MOUSE
  525. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  526. btns = priv->mousebuttons;
  527. btns &= ~GINPUT_MOUSE_BTN_LEFT;
  528. goto mousemove;
  529. }
  530. #endif
  531. break;
  532. #endif
  533. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  534. case WM_MBUTTONDOWN:
  535. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  536. priv = (winPriv *)g->priv;
  537. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  538. btns = priv->mousebuttons;
  539. btns |= GINPUT_MOUSE_BTN_MIDDLE;
  540. goto mousemove;
  541. }
  542. break;
  543. case WM_MBUTTONUP:
  544. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  545. priv = (winPriv *)g->priv;
  546. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  547. btns = priv->mousebuttons;
  548. btns &= ~GINPUT_MOUSE_BTN_MIDDLE;
  549. goto mousemove;
  550. }
  551. break;
  552. case WM_RBUTTONDOWN:
  553. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  554. priv = (winPriv *)g->priv;
  555. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  556. btns = priv->mousebuttons;
  557. btns |= GINPUT_MOUSE_BTN_RIGHT;
  558. goto mousemove;
  559. }
  560. break;
  561. case WM_RBUTTONUP:
  562. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  563. priv = (winPriv *)g->priv;
  564. if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
  565. btns = priv->mousebuttons;
  566. btns &= ~GINPUT_MOUSE_BTN_RIGHT;
  567. goto mousemove;
  568. }
  569. break;
  570. case WM_MOUSEMOVE:
  571. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  572. priv = (winPriv *)g->priv;
  573. if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT)
  574. break;
  575. btns = priv->mousebuttons;
  576. mousemove:
  577. if (priv->capfn)
  578. priv->capfn(hWnd, g, btns, (coord_t)LOWORD(lParam), (coord_t)HIWORD(lParam));
  579. if (priv->mouseenabled) {
  580. priv->mousebuttons = btns;
  581. priv->mousex = (coord_t)LOWORD(lParam);
  582. priv->mousey = (coord_t)HIWORD(lParam);
  583. if ((gmvmt(priv->mouse)->d.flags & GMOUSE_VFLG_NOPOLL)) // For normal setup this is always TRUE
  584. _gmouseWakeup(priv->mouse);
  585. }
  586. break;
  587. #endif
  588. #if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
  589. case WM_SYSKEYDOWN:
  590. case WM_SYSKEYUP:
  591. case WM_KEYDOWN:
  592. case WM_KEYUP:
  593. // A layout is being used: Send scan codes to the keyboard buffer
  594. if (keyboard && keyboard->pLayout && keypos < (int)sizeof(keybuffer)-1 && (wParam & 0xFF) > 0x01) {
  595. if (Msg == WM_KEYUP || Msg == WM_SYSKEYUP)
  596. keybuffer[keypos++] = 0x00; // Keyup
  597. else if (HIWORD(lParam) & KF_REPEAT)
  598. keybuffer[keypos++] = 0x01; // Repeat
  599. keybuffer[keypos++] = wParam;
  600. if ((gkvmt(keyboard)->d.flags & GKEYBOARD_VFLG_NOPOLL)) // For normal setup this is always TRUE
  601. _gkeyboardWakeup(keyboard);
  602. }
  603. return 0;
  604. case WM_CHAR:
  605. // A layout is not being used: Send character codes to the keyboard buffer
  606. if (keyboard && !keyboard->pLayout && keypos < (int)sizeof(keybuffer)) {
  607. wchar_t w;
  608. int len;
  609. // Convert from a UTF16 character to a UTF8 string.
  610. w = wParam;
  611. len = WideCharToMultiByte(CP_UTF8, 0, &w, 1, (char *)(keybuffer+keypos), sizeof(keybuffer)-keypos, 0, 0);
  612. keypos += len;
  613. if (len && (gkvmt(keyboard)->d.flags & GKEYBOARD_VFLG_NOPOLL)) // For normal setup this is always TRUE
  614. _gkeyboardWakeup(keyboard);
  615. }
  616. return 0;
  617. /*
  618. case WM_DEADCHAR:
  619. case WM_SYSCHAR:
  620. case WM_SYSDEADCHAR:
  621. break;
  622. */
  623. #endif
  624. case WM_ERASEBKGND:
  625. // Pretend we have erased the background.
  626. // We know we don't really need to do this as we
  627. // redraw the entire surface in the WM_PAINT handler.
  628. return TRUE;
  629. case WM_PAINT:
  630. // Get our GDisplay structure
  631. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  632. priv = (winPriv *)g->priv;
  633. // Paint the main window area
  634. WaitForSingleObject(drawMutex, INFINITE);
  635. dc = BeginPaint(hWnd, &ps);
  636. BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
  637. ps.rcPaint.right - ps.rcPaint.left,
  638. (ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top,
  639. priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
  640. // Paint the toggle area
  641. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  642. if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
  643. pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
  644. hbrOn = CreateSolidBrush(RGB(0, 0, 255));
  645. hbrOff = CreateSolidBrush(RGB(128, 128, 128));
  646. old = SelectObject(dc, pen);
  647. MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
  648. LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
  649. for(pos = 0, bit=1; pos < GDISP_SCREEN_WIDTH; pos=rect.right, bit <<= 1) {
  650. rect.left = pos;
  651. rect.right = pos + GDISP_SCREEN_WIDTH/8;
  652. rect.top = GDISP_SCREEN_HEIGHT;
  653. rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
  654. FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff);
  655. if (pos > 0) {
  656. MoveToEx(dc, rect.left, rect.top, &p);
  657. LineTo(dc, rect.left, rect.bottom);
  658. }
  659. }
  660. DeleteObject(hbrOn);
  661. DeleteObject(hbrOff);
  662. SelectObject(dc, old);
  663. }
  664. #endif
  665. EndPaint(hWnd, &ps);
  666. ReleaseMutex(drawMutex);
  667. break;
  668. case WM_DESTROY:
  669. // Get our GDisplay structure
  670. g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  671. priv = (winPriv *)g->priv;
  672. // Restore the window and free our bitmaps
  673. SelectObject(priv->dcBuffer, priv->dcOldBitmap);
  674. DeleteDC(priv->dcBuffer);
  675. DeleteObject(priv->dcBitmap);
  676. // Cleanup the private area
  677. gfxFree(priv);
  678. // Quit the application
  679. PostQuitMessage(0);
  680. // Actually the above doesn't work (who knows why)
  681. ExitProcess(0);
  682. break;
  683. default:
  684. return DefWindowProc(hWnd, Msg, wParam, lParam);
  685. }
  686. return 0;
  687. }
  688. static DWORD WINAPI WindowThread(void *param) {
  689. (void)param;
  690. MSG msg;
  691. // Establish this thread as a message queue thread
  692. winThreadId = GetCurrentThreadId();
  693. PeekMessage(&msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
  694. QReady = TRUE;
  695. // Create the window class
  696. {
  697. WNDCLASS wc;
  698. ATOM winClass;
  699. wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
  700. wc.lpfnWndProc = (WNDPROC)myWindowProc;
  701. wc.cbClsExtra = 0;
  702. wc.cbWndExtra = 0;
  703. wc.hInstance = GetModuleHandle(0);
  704. wc.hIcon = LoadIcon(0, IDI_APPLICATION);
  705. wc.hCursor = LoadCursor(0, IDC_ARROW);
  706. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  707. wc.lpszMenuName = 0;
  708. wc.lpszClassName = APP_NAME;
  709. winClass = RegisterClass(&wc);
  710. assert(winClass != 0);
  711. }
  712. do {
  713. // This is a high priority task - make sure other tasks get a go.
  714. Sleep(1);
  715. while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
  716. // Is this our special thread message to create a new window?
  717. if (!msg.hwnd && msg.message == WM_USER) {
  718. RECT rect;
  719. GDisplay *g;
  720. g = (GDisplay *)msg.lParam;
  721. // Set the window rectangle
  722. rect.top = 0; rect.bottom = g->g.Height;
  723. rect.left = 0; rect.right = g->g.Width;
  724. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  725. if ((g->flags & GDISP_FLG_HASTOGGLE))
  726. rect.bottom += WIN32_BUTTON_AREA;
  727. #endif
  728. AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
  729. // Create the window
  730. msg.hwnd = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, msg.wParam*DISPLAY_X_OFFSET, msg.wParam*DISPLAY_Y_OFFSET,
  731. rect.right-rect.left, rect.bottom-rect.top,
  732. hWndParent, 0,
  733. GetModuleHandle(0), g);
  734. assert(msg.hwnd != 0);
  735. // Or just a normal window message
  736. } else {
  737. TranslateMessage(&msg);
  738. DispatchMessage(&msg);
  739. }
  740. }
  741. } while (msg.message != WM_QUIT);
  742. ExitProcess(0);
  743. return msg.wParam;
  744. }
  745. /*===========================================================================*/
  746. /* Driver exported functions. */
  747. /*===========================================================================*/
  748. LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
  749. winPriv * priv;
  750. char buf[132];
  751. // Initialise the window thread and the window class (if it hasn't been done already)
  752. if (!QReady) {
  753. HANDLE hth;
  754. // Create the draw mutex
  755. drawMutex = CreateMutex(0, FALSE, 0);
  756. // Create the thread
  757. if (!(hth = CreateThread(0, 0, WindowThread, 0, CREATE_SUSPENDED, 0)))
  758. return FALSE;
  759. SetThreadPriority(hth, THREAD_PRIORITY_ABOVE_NORMAL);
  760. ResumeThread(hth);
  761. CloseHandle(hth);
  762. // Wait for our thread to be ready
  763. while (!QReady)
  764. Sleep(1);
  765. }
  766. // Initialise the GDISP structure
  767. g->g.Orientation = GDISP_ROTATE_0;
  768. g->g.Powermode = powerOn;
  769. g->g.Backlight = 100;
  770. g->g.Contrast = 50;
  771. g->g.Width = GDISP_SCREEN_WIDTH;
  772. g->g.Height = GDISP_SCREEN_HEIGHT;
  773. // Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows
  774. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  775. if (g->controllerdisplay < GINPUT_TOGGLE_CONFIG_ENTRIES) {
  776. g->flags |= GDISP_FLG_HASTOGGLE;
  777. toggleWindow = g;
  778. }
  779. #endif
  780. // Create a private area for this window
  781. priv = gfxAlloc(sizeof(winPriv));
  782. assert(priv != 0);
  783. memset(priv, 0, sizeof(winPriv));
  784. g->priv = priv;
  785. #if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
  786. // Initialise with an invalid window
  787. g->flags &= ~GDISP_FLG_WSTREAM;
  788. #endif
  789. g->board = 0; // no board interface for this controller
  790. // Create the window in the message thread
  791. PostThreadMessage(winThreadId, WM_USER, (WPARAM)g->controllerdisplay, (LPARAM)g);
  792. // Wait for the window creation to complete (for safety)
  793. while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
  794. Sleep(1);
  795. // Create the associated mouse
  796. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  797. priv->mouseenabled = hWndParent ? FALSE : TRUE;
  798. priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
  799. #endif
  800. sprintf(buf, APP_NAME " - %u", g->systemdisplay+1);
  801. SetWindowText(priv->hwnd, buf);
  802. ShowWindow(priv->hwnd, SW_SHOW);
  803. UpdateWindow(priv->hwnd);
  804. return TRUE;
  805. }
  806. #if GDISP_HARDWARE_FLUSH
  807. LLDSPEC void gdisp_lld_flush(GDisplay *g) {
  808. winPriv * priv;
  809. priv = g->priv;
  810. UpdateWindow(priv->hwnd);
  811. }
  812. #endif
  813. #if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
  814. void BAD_PARAMETER(const char *msg) {
  815. fprintf(stderr, "%s\n", msg);
  816. }
  817. #endif
  818. #if GDISP_HARDWARE_STREAM_WRITE
  819. LLDSPEC void gdisp_lld_write_start(GDisplay *g) {
  820. winPriv * priv;
  821. if (g->flags & GDISP_FLG_WSTREAM)
  822. BAD_PARAMETER("write_start: already in streaming mode");
  823. if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
  824. BAD_PARAMETER("write_start: bad window parameter");
  825. priv = g->priv;
  826. priv->x0 = g->p.x; priv->x1 = g->p.x + g->p.cx - 1;
  827. priv->y0 = g->p.y; priv->y1 = g->p.y + g->p.cy - 1;
  828. #if GDISP_HARDWARE_STREAM_POS
  829. priv->x = g->p.x-1; // Make sure these values are invalid (for testing)
  830. priv->y = g->p.y-1;
  831. #else
  832. priv->x = g->p.x;
  833. priv->y = g->p.y;
  834. #endif
  835. g->flags |= GDISP_FLG_WSTREAM;
  836. g->flags &= ~GDISP_FLG_WRAPPED;
  837. }
  838. LLDSPEC void gdisp_lld_write_color(GDisplay *g) {
  839. winPriv * priv;
  840. int x, y;
  841. COLORREF color;
  842. priv = g->priv;
  843. color = gdispColor2Native(g->p.color);
  844. if (!(g->flags & GDISP_FLG_WSTREAM))
  845. BAD_PARAMETER("write_color: not in streaming mode");
  846. if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
  847. BAD_PARAMETER("write_color: cursor outside streaming area");
  848. if (g->flags & GDISP_FLG_WRAPPED) {
  849. BAD_PARAMETER("write_color: Warning - Area wrapped.");
  850. g->flags &= ~GDISP_FLG_WRAPPED;
  851. }
  852. #if GDISP_NEED_CONTROL
  853. switch(g->g.Orientation) {
  854. case GDISP_ROTATE_0:
  855. default:
  856. x = priv->x;
  857. y = priv->y;
  858. break;
  859. case GDISP_ROTATE_90:
  860. x = priv->y;
  861. y = g->g.Width - 1 - priv->x;
  862. break;
  863. case GDISP_ROTATE_180:
  864. x = g->g.Width - 1 - priv->x;
  865. y = g->g.Height - 1 - priv->y;
  866. break;
  867. case GDISP_ROTATE_270:
  868. x = g->g.Height - 1 - priv->y;
  869. y = priv->x;
  870. break;
  871. }
  872. #else
  873. x = priv->x;
  874. y = priv->y;
  875. #endif
  876. // Draw the pixel on the screen and in the buffer.
  877. WaitForSingleObject(drawMutex, INFINITE);
  878. SetPixel(priv->dcBuffer, x, y, color);
  879. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  880. ReleaseMutex(drawMutex);
  881. {
  882. RECT r;
  883. r.left = x; r.right = x+1;
  884. r.top = y; r.bottom = y+1;
  885. InvalidateRect(priv->hwnd, &r, FALSE);
  886. }
  887. #else
  888. {
  889. HDC dc;
  890. dc = GetDC(priv->hwnd);
  891. SetPixel(dc, x, y, color);
  892. ReleaseDC(priv->hwnd, dc);
  893. ReleaseMutex(drawMutex);
  894. }
  895. #endif
  896. // Update the cursor
  897. if (++priv->x > priv->x1) {
  898. priv->x = priv->x0;
  899. if (++priv->y > priv->y1) {
  900. g->flags |= GDISP_FLG_WRAPPED;
  901. priv->y = priv->y0;
  902. }
  903. }
  904. }
  905. LLDSPEC void gdisp_lld_write_stop(GDisplay *g) {
  906. if (!(g->flags & GDISP_FLG_WSTREAM))
  907. BAD_PARAMETER("write_stop: not in streaming mode");
  908. g->flags &= ~GDISP_FLG_WSTREAM;
  909. }
  910. #if GDISP_HARDWARE_STREAM_POS
  911. LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
  912. winPriv * priv;
  913. priv = g->priv;
  914. if (!(g->flags & GDISP_FLG_WSTREAM))
  915. BAD_PARAMETER("write_pos: not in streaming mode");
  916. if (g->p.x < priv->x0 || g->p.x > priv->x1 || g->p.y < priv->y0 || g->p.y > priv->y1)
  917. BAD_PARAMETER("write_color: new cursor outside streaming area");
  918. priv->x = g->p.x;
  919. priv->y = g->p.y;
  920. }
  921. #endif
  922. #endif
  923. #if GDISP_HARDWARE_STREAM_READ
  924. LLDSPEC void gdisp_lld_read_start(GDisplay *g) {
  925. winPriv * priv;
  926. if (g->flags & GDISP_FLG_WSTREAM)
  927. BAD_PARAMETER("read_start: already in streaming mode");
  928. if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
  929. BAD_PARAMETER("read_start: bad window parameter");
  930. priv = g->priv;
  931. priv->x0 = g->p.x; priv->x1 = g->p.x + g->p.cx - 1;
  932. priv->y0 = g->p.y; priv->y1 = g->p.y + g->p.cy - 1;
  933. priv->x = g->p.x;
  934. priv->y = g->p.y;
  935. g->flags |= GDISP_FLG_WSTREAM;
  936. g->flags &= ~GDISP_FLG_WRAPPED;
  937. }
  938. LLDSPEC color_t gdisp_lld_read_color(GDisplay *g) {
  939. winPriv * priv;
  940. COLORREF color;
  941. priv = g->priv;
  942. if (!(g->flags & GDISP_FLG_WSTREAM))
  943. BAD_PARAMETER("read_color: not in streaming mode");
  944. if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
  945. BAD_PARAMETER("read_color: cursor outside streaming area");
  946. if (g->flags & GDISP_FLG_WRAPPED) {
  947. BAD_PARAMETER("read_color: Warning - Area wrapped.");
  948. g->flags &= ~GDISP_FLG_WRAPPED;
  949. }
  950. WaitForSingleObject(drawMutex, INFINITE);
  951. #if GDISP_NEED_CONTROL
  952. switch(g->g.Orientation) {
  953. case GDISP_ROTATE_0:
  954. default:
  955. color = GetPixel(priv->dcBuffer, priv->x, priv->y);
  956. break;
  957. case GDISP_ROTATE_90:
  958. color = GetPixel(priv->dcBuffer, priv->y, g->g.Width - 1 - priv->x);
  959. break;
  960. case GDISP_ROTATE_180:
  961. color = GetPixel(priv->dcBuffer, g->g.Width - 1 - priv->x, g->g.Height - 1 - priv->y);
  962. break;
  963. case GDISP_ROTATE_270:
  964. color = GetPixel(priv->dcBuffer, g->g.Height - 1 - priv->y, priv->x);
  965. break;
  966. }
  967. #else
  968. color = GetPixel(priv->dcBuffer, priv->x, priv->y);
  969. #endif
  970. ReleaseMutex(drawMutex);
  971. // Update the cursor
  972. if (++priv->x > priv->x1) {
  973. priv->x = priv->x0;
  974. if (++priv->y > priv->y1) {
  975. g->flags |= GDISP_FLG_WRAPPED;
  976. priv->y = priv->y0;
  977. }
  978. }
  979. return gdispNative2Color(color);
  980. }
  981. LLDSPEC void gdisp_lld_read_stop(GDisplay *g) {
  982. if (!(g->flags & GDISP_FLG_WSTREAM))
  983. BAD_PARAMETER("write_stop: not in streaming mode");
  984. g->flags &= ~GDISP_FLG_WSTREAM;
  985. }
  986. #endif
  987. #if GDISP_HARDWARE_DRAWPIXEL
  988. LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
  989. winPriv * priv;
  990. int x, y;
  991. COLORREF color;
  992. priv = g->priv;
  993. color = gdispColor2Native(g->p.color);
  994. #if GDISP_NEED_CONTROL
  995. switch(g->g.Orientation) {
  996. case GDISP_ROTATE_0:
  997. default:
  998. x = g->p.x;
  999. y = g->p.y;
  1000. break;
  1001. case GDISP_ROTATE_90:
  1002. x = g->p.y;
  1003. y = g->g.Width - 1 - g->p.x;
  1004. break;
  1005. case GDISP_ROTATE_180:
  1006. x = g->g.Width - 1 - g->p.x;
  1007. y = g->g.Height - 1 - g->p.y;
  1008. break;
  1009. case GDISP_ROTATE_270:
  1010. x = g->g.Height - 1 - g->p.y;
  1011. y = g->p.x;
  1012. break;
  1013. }
  1014. #else
  1015. x = g->p.x;
  1016. y = g->p.y;
  1017. #endif
  1018. // Draw the pixel on the screen and in the buffer.
  1019. WaitForSingleObject(drawMutex, INFINITE);
  1020. SetPixel(priv->dcBuffer, x, y, color);
  1021. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1022. ReleaseMutex(drawMutex);
  1023. {
  1024. RECT r;
  1025. r.left = x; r.right = x+1;
  1026. r.top = y; r.bottom = y+1;
  1027. InvalidateRect(priv->hwnd, &r, FALSE);
  1028. }
  1029. #else
  1030. {
  1031. HDC dc;
  1032. dc = GetDC(priv->hwnd);
  1033. SetPixel(dc, x, y, color);
  1034. ReleaseDC(priv->hwnd, dc);
  1035. ReleaseMutex(drawMutex);
  1036. }
  1037. #endif
  1038. }
  1039. #endif
  1040. /* ---- Optional Routines ---- */
  1041. #if GDISP_HARDWARE_FILLS
  1042. LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
  1043. winPriv * priv;
  1044. RECT rect;
  1045. HBRUSH hbr;
  1046. COLORREF color;
  1047. priv = g->priv;
  1048. color = gdispColor2Native(g->p.color);
  1049. hbr = CreateSolidBrush(color);
  1050. #if GDISP_NEED_CONTROL
  1051. switch(g->g.Orientation) {
  1052. case GDISP_ROTATE_0:
  1053. default:
  1054. rect.top = g->p.y;
  1055. rect.bottom = rect.top + g->p.cy;
  1056. rect.left = g->p.x;
  1057. rect.right = rect.left + g->p.cx;
  1058. break;
  1059. case GDISP_ROTATE_90:
  1060. rect.bottom = g->g.Width - g->p.x;
  1061. rect.top = rect.bottom - g->p.cx;
  1062. rect.left = g->p.y;
  1063. rect.right = rect.left + g->p.cy;
  1064. break;
  1065. case GDISP_ROTATE_180:
  1066. rect.bottom = g->g.Height - g->p.y;
  1067. rect.top = rect.bottom - g->p.cy;
  1068. rect.right = g->g.Width - g->p.x;
  1069. rect.left = rect.right - g->p.cx;
  1070. break;
  1071. case GDISP_ROTATE_270:
  1072. rect.top = g->p.x;
  1073. rect.bottom = rect.top + g->p.cx;
  1074. rect.right = g->g.Height - g->p.y;
  1075. rect.left = rect.right - g->p.cy;
  1076. break;
  1077. }
  1078. #else
  1079. rect.top = g->p.y;
  1080. rect.bottom = rect.top + g->p.cy;
  1081. rect.left = g->p.x;
  1082. rect.right = rect.left + g->p.cx;
  1083. #endif
  1084. WaitForSingleObject(drawMutex, INFINITE);
  1085. FillRect(priv->dcBuffer, &rect, hbr);
  1086. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1087. ReleaseMutex(drawMutex);
  1088. InvalidateRect(priv->hwnd, &rect, FALSE);
  1089. #else
  1090. {
  1091. HDC dc;
  1092. dc = GetDC(priv->hwnd);
  1093. FillRect(dc, &rect, hbr);
  1094. ReleaseDC(priv->hwnd, dc);
  1095. ReleaseMutex(drawMutex);
  1096. }
  1097. #endif
  1098. DeleteObject(hbr);
  1099. }
  1100. #endif
  1101. #if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL
  1102. static pixel_t *rotateimg(GDisplay *g, const pixel_t *buffer) {
  1103. pixel_t *dstbuf;
  1104. pixel_t *dst;
  1105. const pixel_t *src;
  1106. size_t sz;
  1107. coord_t i, j;
  1108. // Allocate the destination buffer
  1109. sz = (size_t)g->p.cx * (size_t)g->p.cy;
  1110. if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
  1111. return 0;
  1112. // Copy the bits we need
  1113. switch(g->g.Orientation) {
  1114. case GDISP_ROTATE_0:
  1115. default:
  1116. return 0; // not handled as it doesn't need to be.
  1117. case GDISP_ROTATE_90:
  1118. for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
  1119. dst = dstbuf+sz-g->p.cy+j;
  1120. for(i = 0; i < g->p.cx; i++, dst -= g->p.cy)
  1121. *dst = *src++;
  1122. }
  1123. break;
  1124. case GDISP_ROTATE_180:
  1125. for(dst = dstbuf+sz, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
  1126. for(i = 0; i < g->p.cx; i++)
  1127. *--dst = *src++;
  1128. break;
  1129. case GDISP_ROTATE_270:
  1130. for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
  1131. dst = dstbuf+g->p.cy-j-1;
  1132. for(i = 0; i < g->p.cx; i++, dst += g->p.cy)
  1133. *dst = *src++;
  1134. }
  1135. break;
  1136. }
  1137. return dstbuf;
  1138. }
  1139. #endif
  1140. #if GDISP_HARDWARE_BITFILLS
  1141. #if COLOR_SYSTEM != GDISP_COLORSYSTEM_TRUECOLOR || COLOR_TYPE_BITS <= 8
  1142. #error "GDISP Win32: This driver's bitblit currently only supports true-color with bit depths > 8 bits."
  1143. #endif
  1144. LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
  1145. winPriv * priv;
  1146. pixel_t * buffer;
  1147. RECT rect;
  1148. BITMAPV4HEADER bmpInfo;
  1149. // Make everything relative to the start of the line
  1150. priv = g->priv;
  1151. buffer = g->p.ptr;
  1152. buffer += g->p.x2*g->p.y1;
  1153. memset(&bmpInfo, 0, sizeof(bmpInfo));
  1154. bmpInfo.bV4Size = sizeof(bmpInfo);
  1155. bmpInfo.bV4Planes = 1;
  1156. bmpInfo.bV4BitCount = COLOR_TYPE_BITS;
  1157. bmpInfo.bV4AlphaMask = 0;
  1158. bmpInfo.bV4RedMask = RGB2COLOR(255,0,0);
  1159. bmpInfo.bV4GreenMask = RGB2COLOR(0,255,0);
  1160. bmpInfo.bV4BlueMask = RGB2COLOR(0,0,255);
  1161. bmpInfo.bV4V4Compression = BI_BITFIELDS;
  1162. bmpInfo.bV4XPelsPerMeter = 3078;
  1163. bmpInfo.bV4YPelsPerMeter = 3078;
  1164. bmpInfo.bV4ClrUsed = 0;
  1165. bmpInfo.bV4ClrImportant = 0;
  1166. bmpInfo.bV4CSType = 0; //LCS_sRGB;
  1167. #if GDISP_NEED_CONTROL
  1168. switch(g->g.Orientation) {
  1169. case GDISP_ROTATE_0:
  1170. default:
  1171. bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
  1172. bmpInfo.bV4Width = g->p.x2;
  1173. bmpInfo.bV4Height = -g->p.cy; /* top-down image */
  1174. rect.top = g->p.y;
  1175. rect.bottom = rect.top+g->p.cy;
  1176. rect.left = g->p.x;
  1177. rect.right = rect.left+g->p.cx;
  1178. break;
  1179. case GDISP_ROTATE_90:
  1180. if (!(buffer = rotateimg(g, buffer))) return;
  1181. bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
  1182. bmpInfo.bV4Width = g->p.cy;
  1183. bmpInfo.bV4Height = -g->p.cx; /* top-down image */
  1184. rect.bottom = g->g.Width - g->p.x;
  1185. rect.top = rect.bottom-g->p.cx;
  1186. rect.left = g->p.y;
  1187. rect.right = rect.left+g->p.cy;
  1188. break;
  1189. case GDISP_ROTATE_180:
  1190. if (!(buffer = rotateimg(g, buffer))) return;
  1191. bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
  1192. bmpInfo.bV4Width = g->p.cx;
  1193. bmpInfo.bV4Height = -g->p.cy; /* top-down image */
  1194. rect.bottom = g->g.Height-1 - g->p.y;
  1195. rect.top = rect.bottom-g->p.cy;
  1196. rect.right = g->g.Width - g->p.x;
  1197. rect.left = rect.right-g->p.cx;
  1198. break;
  1199. case GDISP_ROTATE_270:
  1200. if (!(buffer = rotateimg(g, buffer))) return;
  1201. bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
  1202. bmpInfo.bV4Width = g->p.cy;
  1203. bmpInfo.bV4Height = -g->p.cx; /* top-down image */
  1204. rect.top = g->p.x;
  1205. rect.bottom = rect.top+g->p.cx;
  1206. rect.right = g->g.Height - g->p.y;
  1207. rect.left = rect.right-g->p.cy;
  1208. break;
  1209. }
  1210. #else
  1211. bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
  1212. bmpInfo.bV4Width = g->p.x2;
  1213. bmpInfo.bV4Height = -g->p.cy; /* top-down image */
  1214. rect.top = g->p.y;
  1215. rect.bottom = rect.top+g->p.cy;
  1216. rect.left = g->p.x;
  1217. rect.right = rect.left+g->p.cx;
  1218. #endif
  1219. WaitForSingleObject(drawMutex, INFINITE);
  1220. SetDIBitsToDevice(priv->dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
  1221. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1222. ReleaseMutex(drawMutex);
  1223. InvalidateRect(priv->hwnd, &rect, FALSE);
  1224. #else
  1225. {
  1226. HDC dc;
  1227. dc = GetDC(priv->hwnd);
  1228. SetDIBitsToDevice(dc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
  1229. ReleaseDC(priv->hwnd, dc);
  1230. ReleaseMutex(drawMutex);
  1231. }
  1232. #endif
  1233. #if GDISP_NEED_CONTROL
  1234. if (buffer != (pixel_t *)g->p.ptr)
  1235. free(buffer);
  1236. #endif
  1237. }
  1238. #endif
  1239. #if GDISP_HARDWARE_PIXELREAD
  1240. LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
  1241. winPriv * priv;
  1242. COLORREF color;
  1243. priv = g->priv;
  1244. WaitForSingleObject(drawMutex, INFINITE);
  1245. #if GDISP_NEED_CONTROL
  1246. switch(g->g.Orientation) {
  1247. case GDISP_ROTATE_0:
  1248. default:
  1249. color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
  1250. break;
  1251. case GDISP_ROTATE_90:
  1252. color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
  1253. break;
  1254. case GDISP_ROTATE_180:
  1255. color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
  1256. break;
  1257. case GDISP_ROTATE_270:
  1258. color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
  1259. break;
  1260. }
  1261. #else
  1262. color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
  1263. #endif
  1264. ReleaseMutex(drawMutex);
  1265. return gdispNative2Color(color);
  1266. }
  1267. #endif
  1268. #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
  1269. LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
  1270. winPriv * priv;
  1271. RECT rect;
  1272. coord_t lines;
  1273. priv = g->priv;
  1274. #if GDISP_NEED_CONTROL
  1275. switch(g->g.Orientation) {
  1276. case GDISP_ROTATE_0:
  1277. default:
  1278. rect.top = g->p.y;
  1279. rect.bottom = rect.top+g->p.cy;
  1280. rect.left = g->p.x;
  1281. rect.right = rect.left+g->p.cx;
  1282. lines = -g->p.y1;
  1283. goto vertical_scroll;
  1284. case GDISP_ROTATE_90:
  1285. rect.bottom = g->g.Width - g->p.x;
  1286. rect.top = rect.bottom-g->p.cx;
  1287. rect.left = g->p.y;
  1288. rect.right = rect.left+g->p.cy;
  1289. lines = -g->p.y1;
  1290. goto horizontal_scroll;
  1291. case GDISP_ROTATE_180:
  1292. rect.bottom = g->g.Height - g->p.y;
  1293. rect.top = rect.bottom-g->p.cy;
  1294. rect.right = g->g.Width - g->p.x;
  1295. rect.left = rect.right-g->p.cx;
  1296. lines = g->p.y1;
  1297. vertical_scroll:
  1298. if (lines > 0) {
  1299. rect.bottom -= lines;
  1300. } else {
  1301. rect.top -= lines;
  1302. }
  1303. if (g->p.cy >= lines && g->p.cy >= -lines) {
  1304. WaitForSingleObject(drawMutex, INFINITE);
  1305. ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
  1306. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1307. ReleaseMutex(drawMutex);
  1308. InvalidateRect(priv->hwnd, &rect, FALSE);
  1309. #else
  1310. {
  1311. HDC dc;
  1312. dc = GetDC(priv->hwnd);
  1313. ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
  1314. ReleaseDC(priv->hwnd, dc);
  1315. ReleaseMutex(drawMutex);
  1316. }
  1317. #endif
  1318. }
  1319. break;
  1320. case GDISP_ROTATE_270:
  1321. rect.top = g->p.x;
  1322. rect.bottom = rect.top+g->p.cx;
  1323. rect.right = g->g.Height - g->p.y;
  1324. rect.left = rect.right-g->p.cy;
  1325. lines = g->p.y1;
  1326. horizontal_scroll:
  1327. if (lines > 0) {
  1328. rect.right -= lines;
  1329. } else {
  1330. rect.left -= lines;
  1331. }
  1332. if (g->p.cy >= lines && g->p.cy >= -lines) {
  1333. WaitForSingleObject(drawMutex, INFINITE);
  1334. ScrollDC(priv->dcBuffer, lines, 0, &rect, 0, 0, 0);
  1335. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1336. ReleaseMutex(drawMutex);
  1337. InvalidateRect(priv->hwnd, &rect, FALSE);
  1338. #else
  1339. {
  1340. HDC dc;
  1341. dc = GetDC(priv->hwnd);
  1342. ScrollDC(dc, lines, 0, &rect, 0, 0, 0);
  1343. ReleaseDC(priv->hwnd, dc);
  1344. ReleaseMutex(drawMutex);
  1345. }
  1346. #endif
  1347. }
  1348. break;
  1349. }
  1350. #else
  1351. rect.top = g->p.y;
  1352. rect.bottom = rect.top+g->p.cy;
  1353. rect.left = g->p.x;
  1354. rect.right = rect.left+g->p.cx;
  1355. lines = -g->p.y1;
  1356. if (lines > 0) {
  1357. rect.bottom -= lines;
  1358. } else {
  1359. rect.top -= lines;
  1360. }
  1361. if (g->p.cy >= lines && g->p.cy >= -lines) {
  1362. WaitForSingleObject(drawMutex, INFINITE);
  1363. ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
  1364. #if GDISP_WIN32_USE_INDIRECT_UPDATE
  1365. ReleaseMutex(drawMutex);
  1366. InvalidateRect(priv->hwnd, &rect, FALSE);
  1367. #else
  1368. {
  1369. HDC dc;
  1370. dc = GetDC(priv->hwnd);
  1371. ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
  1372. ReleaseDC(priv->hwnd, dc);
  1373. ReleaseMutex(drawMutex);
  1374. }
  1375. #endif
  1376. }
  1377. #endif
  1378. }
  1379. #endif
  1380. #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
  1381. LLDSPEC void gdisp_lld_control(GDisplay *g) {
  1382. switch(g->p.x) {
  1383. case GDISP_CONTROL_ORIENTATION:
  1384. if (g->g.Orientation == (orientation_t)g->p.ptr)
  1385. return;
  1386. switch((orientation_t)g->p.ptr) {
  1387. case GDISP_ROTATE_0:
  1388. case GDISP_ROTATE_180:
  1389. g->g.Width = GDISP_SCREEN_WIDTH;
  1390. g->g.Height = GDISP_SCREEN_HEIGHT;
  1391. break;
  1392. case GDISP_ROTATE_90:
  1393. case GDISP_ROTATE_270:
  1394. g->g.Height = GDISP_SCREEN_WIDTH;
  1395. g->g.Width = GDISP_SCREEN_HEIGHT;
  1396. break;
  1397. default:
  1398. return;
  1399. }
  1400. g->g.Orientation = (orientation_t)g->p.ptr;
  1401. return;
  1402. /*
  1403. case GDISP_CONTROL_POWER:
  1404. case GDISP_CONTROL_BACKLIGHT:
  1405. case GDISP_CONTROL_CONTRAST:
  1406. */
  1407. }
  1408. }
  1409. #endif
  1410. #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
  1411. static bool_t Win32MouseInit(GMouse *m, unsigned driverinstance) {
  1412. (void) m;
  1413. (void) driverinstance;
  1414. return TRUE;
  1415. }
  1416. static bool_t Win32MouseRead(GMouse *m, GMouseReading *pt) {
  1417. GDisplay * g;
  1418. winPriv * priv;
  1419. g = m->display;
  1420. priv = g->priv;
  1421. pt->x = priv->mousex;
  1422. pt->y = priv->mousey;
  1423. pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
  1424. pt->buttons = priv->mousebuttons;
  1425. #if GDISP_NEED_CONTROL
  1426. // If the self-rotation has been set in the VMT then do that here (TESTING ONLY)
  1427. if ((gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) { // For normal setup this is always False
  1428. coord_t t;
  1429. switch(gdispGGetOrientation(m->display)) {
  1430. case GDISP_ROTATE_0:
  1431. default:
  1432. break;
  1433. case GDISP_ROTATE_90:
  1434. t = pt->x;
  1435. pt->x = g->g.Width - 1 - pt->y;
  1436. pt->y = t;
  1437. break;
  1438. case GDISP_ROTATE_180:
  1439. pt->x = g->g.Width - 1 - pt->x;
  1440. pt->y = g->g.Height - 1 - pt->y;
  1441. break;
  1442. case GDISP_ROTATE_270:
  1443. t = pt->y;
  1444. pt->y = g->g.Height - 1 - pt->x;
  1445. pt->x = t;
  1446. break;
  1447. }
  1448. }
  1449. #endif
  1450. return TRUE;
  1451. }
  1452. #endif /* GINPUT_NEED_MOUSE */
  1453. #if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
  1454. static bool_t Win32KeyboardInit(GKeyboard *k, unsigned driverinstance) {
  1455. (void) driverinstance;
  1456. // Only one please
  1457. if (keyboard)
  1458. return FALSE;
  1459. keyboard = k;
  1460. return TRUE;
  1461. }
  1462. static int Win32KeyboardGetData(GKeyboard *k, uint8_t *pch, int sz) {
  1463. int i, j;
  1464. (void) k;
  1465. if (!keypos)
  1466. return 0;
  1467. for(i = 0; i < keypos && i < sz; i++)
  1468. pch[i] = keybuffer[i];
  1469. keypos -= i;
  1470. for(j=0; j < keypos; j++)
  1471. keybuffer[j] = keybuffer[i+j];
  1472. return i;
  1473. }
  1474. #endif
  1475. #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
  1476. #if GINPUT_TOGGLE_CONFIG_ENTRIES > 1
  1477. #error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must be 1 until Toggles can use GDriver"
  1478. #endif
  1479. const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
  1480. void ginput_lld_toggle_init(const GToggleConfig *ptc) {
  1481. // Save the associated window struct
  1482. //ptc->id = &GDISP_WIN32[ptc - GInputToggleConfigTable];
  1483. ((GToggleConfig *)ptc)->id = 0;
  1484. // We have 8 buttons per window.
  1485. ((GToggleConfig *)ptc)->mask = 0xFF;
  1486. // No inverse or special mode
  1487. ((GToggleConfig *)ptc)->invert = 0x00;
  1488. ((GToggleConfig *)ptc)->mode = 0;
  1489. }
  1490. unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) {
  1491. (void) ptc;
  1492. // This should use ID
  1493. if (!toggleWindow)
  1494. return 0;
  1495. return ((winPriv *)toggleWindow->priv)->toggles;
  1496. //return ((winPriv *)((GDisplay *)(ptc->id))->priv)->toggles;
  1497. }
  1498. #endif /* GINPUT_NEED_TOGGLE */
  1499. #endif /* GFX_USE_GDISP */