window_win32.odin 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #+build windows
  2. #+private file
  3. package karl2d
  4. @(private="package")
  5. WINDOW_INTERFACE_WIN32 :: Window_Interface {
  6. state_size = win32_state_size,
  7. init = win32_init,
  8. window_handle = win32_window_handle,
  9. process_events = win32_process_events,
  10. get_events = win32_get_events,
  11. clear_events = win32_clear_events,
  12. set_position = win32_set_position,
  13. set_size = win32_set_size,
  14. set_internal_state = win32_set_internal_state,
  15. }
  16. import win32 "core:sys/windows"
  17. import "base:runtime"
  18. win32_state_size :: proc() -> int {
  19. return size_of(Win32_State)
  20. }
  21. win32_init :: proc(window_state: rawptr, window_width: int, window_height: int, window_title: string, allocator := context.allocator) {
  22. assert(window_state != nil)
  23. s = (^Win32_State)(window_state)
  24. s.allocator = allocator
  25. s.events = make([dynamic]Window_Event, allocator)
  26. s.custom_context = context
  27. win32.SetProcessDPIAware()
  28. CLASS_NAME :: "karl2d"
  29. instance := win32.HINSTANCE(win32.GetModuleHandleW(nil))
  30. cls := win32.WNDCLASSW {
  31. lpfnWndProc = window_proc,
  32. lpszClassName = CLASS_NAME,
  33. hInstance = instance,
  34. hCursor = win32.LoadCursorA(nil, win32.IDC_ARROW),
  35. }
  36. win32.RegisterClassW(&cls)
  37. r: win32.RECT
  38. r.right = i32(window_width)
  39. r.bottom = i32(window_height)
  40. style := win32.WS_OVERLAPPEDWINDOW | win32.WS_VISIBLE
  41. win32.AdjustWindowRect(&r, style, false)
  42. hwnd := win32.CreateWindowW(CLASS_NAME,
  43. win32.utf8_to_wstring(window_title),
  44. style,
  45. 100, 10, r.right - r.left, r.bottom - r.top,
  46. nil, nil, instance, nil,
  47. )
  48. assert(hwnd != nil, "Failed creating window")
  49. s.hwnd = hwnd
  50. }
  51. win32_shutdown :: proc() {
  52. delete(s.events)
  53. win32.DestroyWindow(s.hwnd)
  54. }
  55. win32_window_handle :: proc() -> Window_Handle {
  56. return Window_Handle(s.hwnd)
  57. }
  58. win32_process_events :: proc() {
  59. msg: win32.MSG
  60. for win32.PeekMessageW(&msg, nil, 0, 0, win32.PM_REMOVE) {
  61. win32.TranslateMessage(&msg)
  62. win32.DispatchMessageW(&msg)
  63. }
  64. }
  65. win32_get_events :: proc() -> []Window_Event {
  66. return s.events[:]
  67. }
  68. win32_clear_events :: proc() {
  69. runtime.clear(&s.events)
  70. }
  71. win32_set_position :: proc(x: int, y: int) {
  72. // TODO: Does x, y respect monitor DPI?
  73. win32.SetWindowPos(
  74. s.hwnd,
  75. {},
  76. i32(x),
  77. i32(y),
  78. 0,
  79. 0,
  80. win32.SWP_NOACTIVATE | win32.SWP_NOZORDER | win32.SWP_NOSIZE,
  81. )
  82. }
  83. win32_set_size :: proc(w, h: int) {
  84. win32.SetWindowPos(
  85. s.hwnd,
  86. {},
  87. 0,
  88. 0,
  89. i32(w),
  90. i32(h),
  91. win32.SWP_NOACTIVATE | win32.SWP_NOZORDER | win32.SWP_NOMOVE,
  92. )
  93. }
  94. win32_set_internal_state :: proc(state: rawptr) {
  95. assert(state != nil)
  96. s = (^Win32_State)(state)
  97. }
  98. Win32_State :: struct {
  99. allocator: runtime.Allocator,
  100. custom_context: runtime.Context,
  101. hwnd: win32.HWND,
  102. window_should_close: bool,
  103. events: [dynamic]Window_Event,
  104. }
  105. s: ^Win32_State
  106. window_proc :: proc "stdcall" (hwnd: win32.HWND, msg: win32.UINT, wparam: win32.WPARAM, lparam: win32.LPARAM) -> win32.LRESULT {
  107. context = s.custom_context
  108. switch msg {
  109. case win32.WM_DESTROY:
  110. win32.PostQuitMessage(0)
  111. case win32.WM_CLOSE:
  112. append(&s.events, Window_Event_Close_Wanted{})
  113. case win32.WM_KEYDOWN:
  114. key := WIN32_VK_MAP[wparam]
  115. append(&s.events, Window_Event_Key_Went_Down {
  116. key = key,
  117. })
  118. return 0
  119. case win32.WM_KEYUP:
  120. key := WIN32_VK_MAP[wparam]
  121. append(&s.events, Window_Event_Key_Went_Up {
  122. key = key,
  123. })
  124. return 0
  125. case win32.WM_MOUSEMOVE:
  126. x := win32.GET_X_LPARAM(lparam)
  127. y := win32.GET_Y_LPARAM(lparam)
  128. append(&s.events, Window_Event_Mouse_Move {
  129. position = {f32(x), f32(y)},
  130. })
  131. return 0
  132. case win32.WM_MOUSEWHEEL:
  133. delta := f32(win32.GET_WHEEL_DELTA_WPARAM(wparam))/win32.WHEEL_DELTA
  134. append(&s.events, Window_Event_Mouse_Wheel {
  135. delta = delta,
  136. })
  137. case win32.WM_SIZE:
  138. width := win32.LOWORD(lparam)
  139. height := win32.HIWORD(lparam)
  140. append(&s.events, Window_Event_Resize {
  141. width = int(width),
  142. height = int(height),
  143. })
  144. }
  145. return win32.DefWindowProcW(hwnd, msg, wparam, lparam)
  146. }
  147. WIN32_VK_MAP := [255]Keyboard_Key {
  148. win32.VK_F1 = .F1,
  149. win32.VK_F2 = .F2,
  150. win32.VK_F3 = .F3,
  151. win32.VK_F4 = .F4,
  152. win32.VK_F5 = .F5,
  153. win32.VK_F6 = .F6,
  154. win32.VK_F7 = .F7,
  155. win32.VK_F8 = .F8,
  156. win32.VK_F9 = .F9,
  157. win32.VK_F10 = .F10,
  158. win32.VK_F11 = .F11,
  159. win32.VK_F12 = .F12,
  160. win32.VK_A = .A,
  161. win32.VK_B = .B,
  162. win32.VK_C = .C,
  163. win32.VK_D = .D,
  164. win32.VK_E = .E,
  165. win32.VK_F = .F,
  166. win32.VK_G = .G,
  167. win32.VK_H = .H,
  168. win32.VK_I = .I,
  169. win32.VK_J = .J,
  170. win32.VK_K = .K,
  171. win32.VK_L = .L,
  172. win32.VK_M = .M,
  173. win32.VK_N = .N,
  174. win32.VK_O = .O,
  175. win32.VK_P = .P,
  176. win32.VK_Q = .Q,
  177. win32.VK_R = .R,
  178. win32.VK_S = .S,
  179. win32.VK_T = .T,
  180. win32.VK_U = .U,
  181. win32.VK_V = .V,
  182. win32.VK_W = .W,
  183. win32.VK_X = .X,
  184. win32.VK_Y = .Y,
  185. win32.VK_Z = .Z,
  186. win32.VK_SPACE = .Space,
  187. win32.VK_LEFT = .Left,
  188. win32.VK_RIGHT = .Right,
  189. win32.VK_UP = .Up,
  190. win32.VK_DOWN = .Down,
  191. win32.VK_RETURN = .Enter,
  192. }