window_windows.odin 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package karl2d
  2. import win32 "core:sys/windows"
  3. import "base:runtime"
  4. import "core:slice"
  5. Window_Handle :: distinct uintptr
  6. Window_State :: struct {
  7. custom_context: runtime.Context,
  8. hwnd: win32.HWND,
  9. window_should_close: bool,
  10. events: [dynamic]Window_Event,
  11. }
  12. Window_Event_Key_Went_Down :: struct {
  13. key: Keyboard_Key,
  14. }
  15. Window_Event_Key_Went_Up :: struct {
  16. key: Keyboard_Key,
  17. }
  18. Window_Event :: union {
  19. Window_Event_Key_Went_Down,
  20. Window_Event_Key_Went_Up,
  21. }
  22. window_state_size :: proc() -> int {
  23. return size_of(Window_State)
  24. }
  25. // TODO rename to "ws"
  26. @(private="file")
  27. s: ^Window_State
  28. window_init :: proc(ws_in: rawptr, window_width: int, window_height: int, window_title: string) {
  29. assert(ws_in != nil)
  30. s = (^Window_State)(ws_in)
  31. s.custom_context = context
  32. win32.SetProcessDPIAware()
  33. CLASS_NAME :: "karl2d"
  34. instance := win32.HINSTANCE(win32.GetModuleHandleW(nil))
  35. cls := win32.WNDCLASSW {
  36. lpfnWndProc = _win32_window_proc,
  37. lpszClassName = CLASS_NAME,
  38. hInstance = instance,
  39. hCursor = win32.LoadCursorA(nil, win32.IDC_ARROW),
  40. }
  41. win32.RegisterClassW(&cls)
  42. r: win32.RECT
  43. r.right = i32(window_width)
  44. r.bottom = i32(window_height)
  45. style := win32.WS_OVERLAPPEDWINDOW | win32.WS_VISIBLE
  46. win32.AdjustWindowRect(&r, style, false)
  47. hwnd := win32.CreateWindowW(CLASS_NAME,
  48. win32.utf8_to_wstring(window_title),
  49. style,
  50. 100, 10, r.right - r.left, r.bottom - r.top,
  51. nil, nil, instance, nil,
  52. )
  53. assert(hwnd != nil, "Failed creating window")
  54. s.hwnd = hwnd
  55. }
  56. window_shutdown :: proc() {
  57. win32.DestroyWindow(s.hwnd)
  58. }
  59. window_set_position :: proc(x: int, y: int) {
  60. // TODO: Does x, y respect monitor DPI?
  61. win32.SetWindowPos(
  62. s.hwnd,
  63. {},
  64. i32(x),
  65. i32(y),
  66. 0,
  67. 0,
  68. win32.SWP_NOACTIVATE | win32.SWP_NOZORDER | win32.SWP_NOSIZE,
  69. )
  70. }
  71. window_handle :: proc() -> Window_Handle {
  72. return Window_Handle(s.hwnd)
  73. }
  74. // TODO: perhaps this should be split into several procs later
  75. window_process_events :: proc(allocator := context.temp_allocator) -> []Window_Event {
  76. msg: win32.MSG
  77. for win32.PeekMessageW(&msg, nil, 0, 0, win32.PM_REMOVE) {
  78. win32.TranslateMessage(&msg)
  79. win32.DispatchMessageW(&msg)
  80. }
  81. return slice.clone(s.events[:], allocator)
  82. }
  83. _window_should_close :: proc() -> bool {
  84. return s.window_should_close
  85. }
  86. _win32_window_proc :: proc "stdcall" (hwnd: win32.HWND, msg: win32.UINT, wparam: win32.WPARAM, lparam: win32.LPARAM) -> win32.LRESULT {
  87. context = s.custom_context
  88. switch msg {
  89. case win32.WM_DESTROY:
  90. win32.PostQuitMessage(0)
  91. s.window_should_close = true
  92. case win32.WM_CLOSE:
  93. s.window_should_close = true
  94. case win32.WM_KEYDOWN:
  95. key := VK_MAP[wparam]
  96. append(&s.events, Window_Event_Key_Went_Down {
  97. key = key,
  98. })
  99. case win32.WM_KEYUP:
  100. key := VK_MAP[wparam]
  101. append(&s.events, Window_Event_Key_Went_Up {
  102. key = key,
  103. })
  104. }
  105. return win32.DefWindowProcW(hwnd, msg, wparam, lparam)
  106. }
  107. VK_MAP := [255]Keyboard_Key {
  108. win32.VK_A = .A,
  109. win32.VK_B = .B,
  110. win32.VK_C = .C,
  111. win32.VK_D = .D,
  112. win32.VK_E = .E,
  113. win32.VK_F = .F,
  114. win32.VK_G = .G,
  115. win32.VK_H = .H,
  116. win32.VK_I = .I,
  117. win32.VK_J = .J,
  118. win32.VK_K = .K,
  119. win32.VK_L = .L,
  120. win32.VK_M = .M,
  121. win32.VK_N = .N,
  122. win32.VK_O = .O,
  123. win32.VK_P = .P,
  124. win32.VK_Q = .Q,
  125. win32.VK_R = .R,
  126. win32.VK_S = .S,
  127. win32.VK_T = .T,
  128. win32.VK_U = .U,
  129. win32.VK_V = .V,
  130. win32.VK_W = .W,
  131. win32.VK_X = .X,
  132. win32.VK_Y = .Y,
  133. win32.VK_Z = .Z,
  134. win32.VK_LEFT = .Left,
  135. win32.VK_RIGHT = .Right,
  136. win32.VK_UP = .Up,
  137. win32.VK_DOWN = .Down,
  138. }