window_win32.odin 4.0 KB

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