mirror of
https://github.com/IllusionMan1212/O2048.git
synced 2026-10-24 10:12:37 +00:00
zephr/os: finish windows port and adjust some thing about linux
This commit is contained in:
+21
-92
@@ -7,6 +7,8 @@ import x11 "vendor:x11/xlib"
|
|||||||
import "../glx"
|
import "../glx"
|
||||||
import "../xcursor"
|
import "../xcursor"
|
||||||
|
|
||||||
|
OsEvent :: x11.Cursor
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
PropModeReplace :: 0
|
PropModeReplace :: 0
|
||||||
@(private="file")
|
@(private="file")
|
||||||
@@ -32,8 +34,7 @@ x11_go_fullscreen :: proc() {
|
|||||||
// and properly fullscreen the window
|
// and properly fullscreen the window
|
||||||
size_hints := x11.XAllocSizeHints()
|
size_hints := x11.XAllocSizeHints()
|
||||||
|
|
||||||
zephr_ctx.window.pre_fullscreen_size.x = zephr_ctx.window.size.x
|
zephr_ctx.window.pre_fullscreen_size = zephr_ctx.window.size
|
||||||
zephr_ctx.window.pre_fullscreen_size.y = zephr_ctx.window.size.y
|
|
||||||
if (size_hints != nil) {
|
if (size_hints != nil) {
|
||||||
size_hints.flags = {.PPosition, .PSize}
|
size_hints.flags = {.PPosition, .PSize}
|
||||||
size_hints.width = cast(i32)zephr_ctx.window.size.x
|
size_hints.width = cast(i32)zephr_ctx.window.size.x
|
||||||
@@ -299,94 +300,6 @@ backend_shutdown :: proc() {
|
|||||||
x11.XCloseDisplay(x11_display)
|
x11.XCloseDisplay(x11_display)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
|
||||||
x11_mods_to_zephr_mods :: proc(scancode: Scancode, is_press: bool) -> KeyMod {
|
|
||||||
mods := zephr_ctx.keyboard.mods
|
|
||||||
|
|
||||||
if (is_press) {
|
|
||||||
if (scancode == .LEFT_SHIFT) {
|
|
||||||
mods |= {.LEFT_SHIFT, .SHIFT}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_SHIFT) {
|
|
||||||
mods |= {.RIGHT_SHIFT, .SHIFT}
|
|
||||||
}
|
|
||||||
if (scancode == .LEFT_CTRL) {
|
|
||||||
mods |= {.LEFT_CTRL, .CTRL}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_CTRL) {
|
|
||||||
mods |= {.RIGHT_CTRL, .CTRL}
|
|
||||||
}
|
|
||||||
if (scancode == .LEFT_ALT) {
|
|
||||||
mods |= {.LEFT_ALT, .ALT}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_ALT) {
|
|
||||||
mods |= {.RIGHT_ALT, .ALT}
|
|
||||||
}
|
|
||||||
if (scancode == .LEFT_META) {
|
|
||||||
mods |= {.LEFT_META, .META}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_META) {
|
|
||||||
mods |= {.RIGHT_META, .META}
|
|
||||||
}
|
|
||||||
if (scancode == .CAPS_LOCK) {
|
|
||||||
mods |= {.CAPS_LOCK}
|
|
||||||
}
|
|
||||||
if (scancode == .NUM_LOCK_OR_CLEAR) {
|
|
||||||
mods |= {.NUM_LOCK}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (scancode == .LEFT_SHIFT) {
|
|
||||||
mods &= ~{.LEFT_SHIFT}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_SHIFT) {
|
|
||||||
mods &= ~{.RIGHT_SHIFT}
|
|
||||||
}
|
|
||||||
if (!(.RIGHT_SHIFT in mods) && !(.LEFT_SHIFT in mods)) {
|
|
||||||
mods &= ~{.SHIFT}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scancode == .LEFT_CTRL) {
|
|
||||||
mods &= ~{.LEFT_CTRL}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_CTRL) {
|
|
||||||
mods &= ~{.RIGHT_CTRL}
|
|
||||||
}
|
|
||||||
if (!(.RIGHT_CTRL in mods) && !(.LEFT_CTRL in mods)) {
|
|
||||||
mods &= ~{.CTRL}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scancode == .LEFT_ALT) {
|
|
||||||
mods &= ~{.LEFT_ALT}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_ALT) {
|
|
||||||
mods &= ~{.RIGHT_ALT}
|
|
||||||
}
|
|
||||||
if (!(.RIGHT_ALT in mods) && !(.LEFT_ALT in mods)) {
|
|
||||||
mods &= ~{.ALT}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scancode == .LEFT_META) {
|
|
||||||
mods &= ~{.LEFT_META}
|
|
||||||
}
|
|
||||||
if (scancode == .RIGHT_META) {
|
|
||||||
mods &= ~{.RIGHT_META}
|
|
||||||
}
|
|
||||||
if (!(.RIGHT_META in mods) && !(.LEFT_META in mods)) {
|
|
||||||
mods &= ~{.META}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scancode == .CAPS_LOCK) {
|
|
||||||
mods &= ~{.CAPS_LOCK}
|
|
||||||
}
|
|
||||||
if (scancode == .NUM_LOCK_OR_CLEAR) {
|
|
||||||
mods &= ~{.NUM_LOCK}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zephr_ctx.keyboard.mods = mods
|
|
||||||
return mods
|
|
||||||
}
|
|
||||||
|
|
||||||
backend_swapbuffers :: proc() {
|
backend_swapbuffers :: proc() {
|
||||||
glx.SwapBuffers(x11_display, x11_window)
|
glx.SwapBuffers(x11_display, x11_window)
|
||||||
}
|
}
|
||||||
@@ -435,7 +348,7 @@ backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
|||||||
e_out.type = .KEY_PRESSED
|
e_out.type = .KEY_PRESSED
|
||||||
e_out.key.scancode = scancode
|
e_out.key.scancode = scancode
|
||||||
//e_out.key.code = keycode;
|
//e_out.key.code = keycode;
|
||||||
e_out.key.mods = x11_mods_to_zephr_mods(scancode, true)
|
e_out.key.mods = set_zephr_mods(scancode, true)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} else if xev.type == .KeyRelease {
|
} else if xev.type == .KeyRelease {
|
||||||
@@ -447,7 +360,7 @@ backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
|||||||
e_out.type = .KEY_RELEASED
|
e_out.type = .KEY_RELEASED
|
||||||
e_out.key.scancode = scancode
|
e_out.key.scancode = scancode
|
||||||
//e_out.key.code = keycode;
|
//e_out.key.code = keycode;
|
||||||
e_out.key.mods = x11_mods_to_zephr_mods(scancode, false)
|
e_out.key.mods = set_zephr_mods(scancode, false)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} else if xev.type == .ButtonPress {
|
} else if xev.type == .ButtonPress {
|
||||||
@@ -531,3 +444,19 @@ backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend_set_cursor :: proc() {
|
||||||
|
x11.XDefineCursor(x11_display, x11_window, zephr_ctx.cursors[zephr_ctx.cursor])
|
||||||
|
}
|
||||||
|
|
||||||
|
backend_init_cursors :: proc() {
|
||||||
|
zephr_ctx.cursors[.ARROW] = x11.XCreateFontCursor(x11_display, .XC_left_ptr)
|
||||||
|
zephr_ctx.cursors[.IBEAM] = x11.XCreateFontCursor(x11_display, .XC_xterm)
|
||||||
|
zephr_ctx.cursors[.CROSSHAIR] = x11.XCreateFontCursor(x11_display, .XC_crosshair)
|
||||||
|
zephr_ctx.cursors[.HAND] = x11.XCreateFontCursor(x11_display, .XC_hand1)
|
||||||
|
zephr_ctx.cursors[.HRESIZE] = x11.XCreateFontCursor(x11_display, .XC_sb_h_double_arrow)
|
||||||
|
zephr_ctx.cursors[.VRESIZE] = x11.XCreateFontCursor(x11_display, .XC_sb_v_double_arrow)
|
||||||
|
|
||||||
|
non-standard cursors
|
||||||
|
zephr_ctx.cursors[.DISABLED] = xcursor.LibraryLoadCursor(x11_display, "crossed_circle")
|
||||||
|
}
|
||||||
+146
-106
@@ -3,7 +3,6 @@
|
|||||||
package zephr
|
package zephr
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:fmt"
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
@@ -12,6 +11,15 @@ import win32 "core:sys/windows"
|
|||||||
|
|
||||||
import gl "vendor:OpenGL"
|
import gl "vendor:OpenGL"
|
||||||
|
|
||||||
|
// BUG: setting the cursor every frame messes with the cursor for resizing when on the edge of the window
|
||||||
|
// TODO: handle start window in fullscreen
|
||||||
|
// currently the way to "start" a window in fullscreen is to just create a regular window
|
||||||
|
// and immediately fullscreen it. This works fine but there's a moment where you can see the regular-sized window.
|
||||||
|
// Not a priority right now.
|
||||||
|
// TODO: only log debug when ODIN_DEBUG is true
|
||||||
|
|
||||||
|
OsCursor :: win32.HCURSOR
|
||||||
|
|
||||||
OsEvent :: struct {
|
OsEvent :: struct {
|
||||||
type: win32.UINT,
|
type: win32.UINT,
|
||||||
lparam: win32.LPARAM,
|
lparam: win32.LPARAM,
|
||||||
@@ -41,7 +49,33 @@ backend_get_screen_size :: proc() -> Vec2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backend_toggle_fullscreen :: proc(fullscreen: bool) {
|
backend_toggle_fullscreen :: proc(fullscreen: bool) {
|
||||||
// TODO:
|
context.logger = logger
|
||||||
|
// TODO: handle multiple monitors
|
||||||
|
|
||||||
|
if fullscreen {
|
||||||
|
w := cast(i32)zephr_ctx.window.pre_fullscreen_size.x
|
||||||
|
h := cast(i32)zephr_ctx.window.pre_fullscreen_size.y
|
||||||
|
|
||||||
|
win_style := (win32.WS_OVERLAPPEDWINDOW if !zephr_ctx.window.non_resizable else win32.WS_OVERLAPPEDWINDOW & ~win32.WS_MAXIMIZEBOX & ~win32.WS_THICKFRAME) | win32.WS_VISIBLE
|
||||||
|
|
||||||
|
// Adjust the rect to account for the window titlebar and frame sizes
|
||||||
|
rect := win32.RECT{0, 0, w, h}
|
||||||
|
win32.AdjustWindowRect(&rect, win_style, false)
|
||||||
|
|
||||||
|
w = rect.right - rect.left
|
||||||
|
h = rect.bottom - rect.top
|
||||||
|
x := cast(i32)(zephr_ctx.screen_size.x / 2 - cast(f32)w / 2)
|
||||||
|
y := cast(i32)(zephr_ctx.screen_size.y / 2 - cast(f32)h / 2)
|
||||||
|
|
||||||
|
win32.SetWindowLongPtrW(hwnd, win32.GWL_STYLE, cast(win32.LONG_PTR)(win_style))
|
||||||
|
win32.SetWindowPos(hwnd, nil, x, y, w, h, win32.SWP_FRAMECHANGED)
|
||||||
|
} else {
|
||||||
|
zephr_ctx.window.pre_fullscreen_size = zephr_ctx.window.size
|
||||||
|
w := cast(i32)zephr_ctx.screen_size.x
|
||||||
|
h := cast(i32)zephr_ctx.screen_size.y
|
||||||
|
result := win32.SetWindowLongPtrW(hwnd, win32.GWL_STYLE, cast(win32.LONG_PTR)(win32.WS_VISIBLE | win32.WS_POPUPWINDOW))
|
||||||
|
win32.SetWindowPos(hwnd, win32.HWND_TOP, 0, 0, w, h, win32.SWP_FRAMECHANGED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
@@ -116,7 +150,7 @@ init_legacy_gl :: proc(class_name: win32.wstring, hInstance: win32.HINSTANCE) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
init_gl :: proc(class_name: win32.wstring, window_title: win32.wstring, window_size: Vec2, hInstance: win32.HINSTANCE) {
|
init_gl :: proc(class_name: win32.wstring, window_title: win32.wstring, window_size: Vec2, window_non_resizable: bool, hInstance: win32.HINSTANCE) {
|
||||||
screen_size := Vec2{
|
screen_size := Vec2{
|
||||||
cast(f32)win32.GetSystemMetrics(win32.SM_CXSCREEN),
|
cast(f32)win32.GetSystemMetrics(win32.SM_CXSCREEN),
|
||||||
cast(f32)win32.GetSystemMetrics(win32.SM_CYSCREEN),
|
cast(f32)win32.GetSystemMetrics(win32.SM_CYSCREEN),
|
||||||
@@ -131,11 +165,13 @@ init_gl :: proc(class_name: win32.wstring, window_title: win32.wstring, window_s
|
|||||||
win_width := rect.right - rect.left
|
win_width := rect.right - rect.left
|
||||||
win_height := rect.bottom - rect.top
|
win_height := rect.bottom - rect.top
|
||||||
|
|
||||||
hwnd := win32.CreateWindowExW(
|
win_style := win32.WS_OVERLAPPEDWINDOW if !window_non_resizable else (win32.WS_OVERLAPPEDWINDOW & ~win32.WS_THICKFRAME & ~win32.WS_MAXIMIZEBOX)
|
||||||
|
|
||||||
|
hwnd = win32.CreateWindowExW(
|
||||||
0,
|
0,
|
||||||
class_name,
|
class_name,
|
||||||
window_title,
|
window_title,
|
||||||
win32.WS_OVERLAPPEDWINDOW,
|
win_style,
|
||||||
|
|
||||||
cast(i32)win_x, cast(i32)win_y, win_width, win_height,
|
cast(i32)win_x, cast(i32)win_y, win_width, win_height,
|
||||||
|
|
||||||
@@ -165,9 +201,7 @@ init_gl :: proc(class_name: win32.wstring, window_title: win32.wstring, window_s
|
|||||||
win32.WGL_DRAW_TO_WINDOW_ARB, 1,
|
win32.WGL_DRAW_TO_WINDOW_ARB, 1,
|
||||||
win32.WGL_SUPPORT_OPENGL_ARB, 1,
|
win32.WGL_SUPPORT_OPENGL_ARB, 1,
|
||||||
win32.WGL_DOUBLE_BUFFER_ARB, 1,
|
win32.WGL_DOUBLE_BUFFER_ARB, 1,
|
||||||
// TODO: test to see if EXCHANGE actually causes problems in fullscreen
|
win32.WGL_SWAP_METHOD_ARB, win32.WGL_SWAP_EXCHANGE_ARB,
|
||||||
/* WGL_SWAP_EXCHANGE_ARB causes problems with window menu in fullscreen */
|
|
||||||
win32.WGL_SWAP_METHOD_ARB, win32.WGL_SWAP_COPY_ARB,
|
|
||||||
win32.WGL_PIXEL_TYPE_ARB, win32.WGL_TYPE_RGBA_ARB,
|
win32.WGL_PIXEL_TYPE_ARB, win32.WGL_TYPE_RGBA_ARB,
|
||||||
win32.WGL_ACCELERATION_ARB, win32.WGL_FULL_ACCELERATION_ARB,
|
win32.WGL_ACCELERATION_ARB, win32.WGL_FULL_ACCELERATION_ARB,
|
||||||
win32.WGL_COLOR_BITS_ARB, 32,
|
win32.WGL_COLOR_BITS_ARB, 32,
|
||||||
@@ -318,7 +352,7 @@ backend_init :: proc(window_title: cstring, window_size: Vec2, icon_path: cstrin
|
|||||||
win32.SetProcessDpiAwarenessContext(win32.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
|
win32.SetProcessDpiAwarenessContext(win32.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
|
||||||
|
|
||||||
init_legacy_gl(class_name, hInstance)
|
init_legacy_gl(class_name, hInstance)
|
||||||
init_gl(class_name, window_title, window_size, hInstance)
|
init_gl(class_name, window_title, window_size, window_non_resizable, hInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
||||||
@@ -441,20 +475,26 @@ backend_get_os_events :: proc(e_out: ^Event) -> bool {
|
|||||||
return true
|
return true
|
||||||
case win32.WM_SYSKEYDOWN: fallthrough
|
case win32.WM_SYSKEYDOWN: fallthrough
|
||||||
case win32.WM_KEYDOWN:
|
case win32.WM_KEYDOWN:
|
||||||
log.debug(event.lparam)
|
|
||||||
// Bits 16-23 hold the scancode
|
// Bits 16-23 hold the scancode
|
||||||
system_scancode := (event.lparam & 0xFF0000) >> 16
|
system_scancode := (event.lparam & 0xFF0000) >> 16
|
||||||
|
is_extended := event.lparam & (1 << 24) != 0
|
||||||
|
|
||||||
scancode := scan1_scancode_to_zephr_scancode_map[system_scancode]
|
scancode := scan1_scancode_to_zephr_scancode_map(auto_cast system_scancode, is_extended)
|
||||||
|
|
||||||
log.debug(system_scancode)
|
e_out.key.scancode = scancode
|
||||||
log.debug(scancode)
|
e_out.key.mods = set_zephr_mods(scancode, true)
|
||||||
// TODO:
|
return true
|
||||||
case win32.WM_SYSKEYUP: fallthrough
|
case win32.WM_SYSKEYUP: fallthrough
|
||||||
case win32.WM_KEYUP:
|
case win32.WM_KEYUP:
|
||||||
// TODO:
|
// Bits 16-23 hold the scancode
|
||||||
// 0101 0010
|
system_scancode := (event.lparam & 0xFF0000) >> 16
|
||||||
//log.debug("released key")
|
is_extended := event.lparam & (1 << 24) != 0
|
||||||
|
|
||||||
|
scancode := scan1_scancode_to_zephr_scancode_map(auto_cast system_scancode, is_extended)
|
||||||
|
|
||||||
|
e_out.key.scancode = scancode
|
||||||
|
e_out.key.mods = set_zephr_mods(scancode, false)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +516,8 @@ backend_swapbuffers :: proc() {
|
|||||||
// https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
|
// https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
|
||||||
@(private="file")
|
@(private="file")
|
||||||
scan1_scancode_to_zephr_scancode_map :: proc(scancode: u8, is_extended: bool) -> Scancode {
|
scan1_scancode_to_zephr_scancode_map :: proc(scancode: u8, is_extended: bool) -> Scancode {
|
||||||
|
context.logger = logger
|
||||||
|
|
||||||
switch scancode {
|
switch scancode {
|
||||||
case 0: return .NULL
|
case 0: return .NULL
|
||||||
|
|
||||||
@@ -517,7 +559,7 @@ scan1_scancode_to_zephr_scancode_map :: proc(scancode: u8, is_extended: bool) ->
|
|||||||
case 0x0A: return .KEY_9
|
case 0x0A: return .KEY_9
|
||||||
case 0x0B: return .KEY_0
|
case 0x0B: return .KEY_0
|
||||||
|
|
||||||
case 0x1C: return .ENTER
|
case 0x1C: return .KP_ENTER if is_extended else .ENTER
|
||||||
case 0x01: return .ESCAPE
|
case 0x01: return .ESCAPE
|
||||||
case 0x0E: return .BACKSPACE // Says "Keyboard Delete" on microsoft.com but it's actually backspace
|
case 0x0E: return .BACKSPACE // Says "Keyboard Delete" on microsoft.com but it's actually backspace
|
||||||
case 0x0F: return .TAB
|
case 0x0F: return .TAB
|
||||||
@@ -534,7 +576,7 @@ scan1_scancode_to_zephr_scancode_map :: proc(scancode: u8, is_extended: bool) ->
|
|||||||
case 0x29: return .GRAVE
|
case 0x29: return .GRAVE
|
||||||
case 0x33: return .COMMA
|
case 0x33: return .COMMA
|
||||||
case 0x34: return .PERIOD
|
case 0x34: return .PERIOD
|
||||||
case 0x35: return .SLASH
|
case 0x35: return .KP_DIVIDE if is_extended else .SLASH
|
||||||
|
|
||||||
case 0x3A: return .CAPS_LOCK
|
case 0x3A: return .CAPS_LOCK
|
||||||
|
|
||||||
@@ -551,97 +593,95 @@ scan1_scancode_to_zephr_scancode_map :: proc(scancode: u8, is_extended: bool) ->
|
|||||||
case 0x57: return .F11
|
case 0x57: return .F11
|
||||||
case 0x58: return .F12
|
case 0x58: return .F12
|
||||||
|
|
||||||
case 0x54: return .PRINT_SCREEN
|
case 0x54: return .PRINT_SCREEN // Only emitted on KeyRelease
|
||||||
//case 0xE037 = .PRINT_SCREEN, // SysRq ???
|
case 0x46: return .PAUSE if is_extended else .SCROLL_LOCK
|
||||||
case 0x46: return .SCROLL_LOCK
|
case 0x45: return .NUM_LOCK_OR_CLEAR if is_extended else .PAUSE
|
||||||
case 0x45: return .PAUSE
|
|
||||||
//case 0xE046 = .PAUSE, // Break ??
|
|
||||||
//case 0xE11D45 = .PAUSE, // Some legacy stuff ???
|
//case 0xE11D45 = .PAUSE, // Some legacy stuff ???
|
||||||
case 0x52:
|
case 0x52: return .INSERT if is_extended else .KP_0
|
||||||
// INSERT
|
case 0x47: return .HOME if is_extended else .KP_7
|
||||||
// KP_0
|
case 0x49: return .PAGE_UP if is_extended else .KP_9
|
||||||
case 0x47:
|
case 0x53: return .DELETE if is_extended else .KP_PERIOD
|
||||||
// HOME
|
case 0x4F: return .END if is_extended else .KP_1
|
||||||
// KP_7
|
case 0x51: return .PAGE_DOWN if is_extended else .KP_3
|
||||||
case 0x49:
|
case 0x4D: return .RIGHT if is_extended else .KP_6
|
||||||
// PAGE_UP
|
case 0x4B: return .LEFT if is_extended else .KP_4
|
||||||
// KP_9
|
case 0x50: return .DOWN if is_extended else .KP_2
|
||||||
case 0x53:
|
case 0x48: return .UP if is_extended else .KP_8
|
||||||
// DELETE
|
case 0x37: return .PRINT_SCREEN if is_extended else .KP_MULTIPLY
|
||||||
// KP_PERIOD
|
case 0x4A: return .KP_MINUS
|
||||||
case 0x4F:
|
case 0x4E: return .KP_PLUS
|
||||||
// END
|
case 0x4C: return .KP_5
|
||||||
// KP_1
|
|
||||||
case 0x51:
|
case 0x56: return .NON_US_BACKSLASH
|
||||||
// PAGE_DOWN
|
case 0x5D:
|
||||||
// KP_3
|
if is_extended {
|
||||||
case 0x4D:
|
return .APPLICATION
|
||||||
// RIGHT
|
} else {
|
||||||
// KP_6
|
log.warnf("Pressed unmapped key: %d. Extended key: %s", scancode, is_extended)
|
||||||
case 0x4B:
|
|
||||||
// LEFT
|
|
||||||
// KP_4
|
|
||||||
case 0x50:
|
|
||||||
// DOWN
|
|
||||||
// KP_2
|
|
||||||
case 0xE048:
|
|
||||||
// UP
|
|
||||||
// KP_8
|
|
||||||
}
|
}
|
||||||
|
case 0x5E:
|
||||||
|
if is_extended {
|
||||||
|
return .POWER
|
||||||
|
} else {
|
||||||
|
log.warnf("Pressed unmapped key: %d. Extended key: %s", scancode, is_extended)
|
||||||
|
}
|
||||||
|
case 0x59: return .KP_EQUALS
|
||||||
|
case 0x64: return .F13
|
||||||
|
case 0x65: return .F14
|
||||||
|
case 0x66: return .F15
|
||||||
|
case 0x67: return .F16
|
||||||
|
case 0x68: return .F17
|
||||||
|
case 0x69: return .F18
|
||||||
|
case 0x6A: return .F19
|
||||||
|
case 0x6B: return .F20
|
||||||
|
case 0x6C: return .F21
|
||||||
|
case 0x6D: return .F22
|
||||||
|
case 0x6E: return .F23
|
||||||
|
case 0x76: return .F24
|
||||||
|
|
||||||
|
case 0x7E: return .KP_COMMA
|
||||||
|
case 0x73: return .INTERNATIONAL1
|
||||||
|
case 0x70: return .INTERNATIONAL2
|
||||||
|
case 0x7D: return .INTERNATIONAL3
|
||||||
|
case 0x79: return .INTERNATIONAL4
|
||||||
|
case 0x7B: return .INTERNATIONAL5
|
||||||
|
case 0x5C: return .RIGHT_META if is_extended else .INTERNATIONAL6
|
||||||
|
case 0x72: return .LANG1 // Only emitted on Key Release
|
||||||
|
case 0xF2: return .LANG1 // Legacy, Only emitted on Key Release
|
||||||
|
case 0x71: return .LANG2 // Only emitted on Key Release
|
||||||
|
case 0xF1: return .LANG2 // Legacy, Only emitted on Key Release
|
||||||
|
case 0x78: return .LANG3
|
||||||
|
case 0x77: return .LANG4
|
||||||
|
//case 0x76: return .LANG5 // Conflicts with F24
|
||||||
|
|
||||||
|
case 0x1D: return .RIGHT_CTRL if is_extended else .LEFT_CTRL
|
||||||
|
case 0x2A: return .LEFT_SHIFT
|
||||||
|
case 0x36: return .RIGHT_SHIFT
|
||||||
//0x45 = .NUM_LOCK_OR_CLEAR, // conflicts with Pause, Pause doesn't have the extended bit set. don't know about this
|
case 0x38: return .RIGHT_ALT if is_extended else .LEFT_ALT
|
||||||
//0xE045 = .NUM_LOCK_OR_CLEAR, // Legacy stuff
|
case 0x5B:
|
||||||
0xE035 = .KP_DIVIDE,
|
if is_extended {
|
||||||
0x37 = .KP_MULTIPLY,
|
return .LEFT_META
|
||||||
0x4A = .KP_MINUS,
|
} else {
|
||||||
0x4E = .KP_PLUS,
|
log.warnf("Pressed unmapped key: %d. Extended key: %s", scancode, is_extended)
|
||||||
0xE01C = .KP_ENTER,
|
}
|
||||||
0x4C = .KP_5,
|
|
||||||
|
|
||||||
0x56 = .NON_US_BACKSLASH,
|
|
||||||
0xE05D = .APPLICATION,
|
|
||||||
0xE05E = .POWER,
|
|
||||||
0x59 = .KP_EQUALS,
|
|
||||||
0x64 = .F13,
|
|
||||||
0x65 = .F14,
|
|
||||||
0x66 = .F15,
|
|
||||||
0x67 = .F16,
|
|
||||||
0x68 = .F17,
|
|
||||||
0x69 = .F18,
|
|
||||||
0x6A = .F19,
|
|
||||||
0x6B = .F20,
|
|
||||||
0x6C = .F21,
|
|
||||||
0x6D = .F22,
|
|
||||||
0x6E = .F23,
|
|
||||||
0x76 = .F24,
|
|
||||||
|
|
||||||
0x7E = .KP_COMMA,
|
|
||||||
0x73 = .INTERNATIONAL1,
|
|
||||||
0x70 = .INTERNATIONAL2,
|
|
||||||
0x7D = .INTERNATIONAL3,
|
|
||||||
0x79 = .INTERNATIONAL4,
|
|
||||||
0x7B = .INTERNATIONAL5,
|
|
||||||
0x5C = .INTERNATIONAL6,
|
|
||||||
0x72 = .LANG1, // Only emitted on Key Release
|
|
||||||
0xF2 = .LANG1, // Legacy, Only emitted on Key Release
|
|
||||||
0x71 = .LANG2, // Only emitted on Key Release
|
|
||||||
0xF1 = .LANG2, // Legacy, Only emitted on Key Release
|
|
||||||
0x78 = .LANG3,
|
|
||||||
0x77 = .LANG4,
|
|
||||||
//0x76 = .LANG5, // Conflicts with F24
|
|
||||||
|
|
||||||
0x1D = .LEFT_CTRL,
|
|
||||||
0x2A = .LEFT_SHIFT,
|
|
||||||
0x38 = .LEFT_ALT,
|
|
||||||
0xE05B = .LEFT_META,
|
|
||||||
0xE01D = .RIGHT_CTRL,
|
|
||||||
0x36 = .RIGHT_SHIFT,
|
|
||||||
0xE038 = .RIGHT_ALT,
|
|
||||||
0xE05C = .RIGHT_META,
|
|
||||||
// End of Keyboard/Keypad section on microsoft.com
|
// End of Keyboard/Keypad section on microsoft.com
|
||||||
// We currently don't map or care about the Consumer section
|
// We currently don't map or care about the Consumer section
|
||||||
|
}
|
||||||
|
|
||||||
|
return .NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
backend_set_cursor :: proc() {
|
||||||
|
win32.SetCursor(zephr_ctx.cursors[zephr_ctx.cursor])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
backend_init_cursors :: proc() {
|
||||||
|
zephr_ctx.cursors[.ARROW] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_ARROW, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.IBEAM] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_IBEAM, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.CROSSHAIR] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_CROSS, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.HAND] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_HAND, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.HRESIZE] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_SIZEWE, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.VRESIZE] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_SIZENS, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
|
zephr_ctx.cursors[.DISABLED] = auto_cast win32.LoadImageW(nil, auto_cast win32._IDC_NO, win32.IMAGE_CURSOR, 0, 0, win32.LR_DEFAULTSIZE | win32.LR_SHARED)
|
||||||
}
|
}
|
||||||
+92
-148
@@ -356,7 +356,7 @@ Context :: struct {
|
|||||||
keyboard: Keyboard,
|
keyboard: Keyboard,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
event_queue: queue.Queue(OsEvent),
|
event_queue: queue.Queue(OsEvent),
|
||||||
//cursors: [Cursor]x11.Cursor,
|
cursors: [Cursor]OsCursor,
|
||||||
ui: Ui,
|
ui: Ui,
|
||||||
|
|
||||||
/* ZephrKeyboard keyboard; */
|
/* ZephrKeyboard keyboard; */
|
||||||
@@ -666,15 +666,7 @@ init :: proc(font_path: cstring, icon_path: cstring, window_title: cstring, wind
|
|||||||
zephr_ctx.window.non_resizable = window_non_resizable
|
zephr_ctx.window.non_resizable = window_non_resizable
|
||||||
zephr_ctx.projection = orthographic_projection_2d(0, window_size.x, window_size.y, 0)
|
zephr_ctx.projection = orthographic_projection_2d(0, window_size.x, window_size.y, 0)
|
||||||
|
|
||||||
// zephr_ctx.cursors[.ARROW] = x11.XCreateFontCursor(x11_display, .XC_left_ptr)
|
backend_init_cursors()
|
||||||
// zephr_ctx.cursors[.IBEAM] = x11.XCreateFontCursor(x11_display, .XC_xterm)
|
|
||||||
// zephr_ctx.cursors[.CROSSHAIR] = x11.XCreateFontCursor(x11_display, .XC_crosshair)
|
|
||||||
// zephr_ctx.cursors[.HAND] = x11.XCreateFontCursor(x11_display, .XC_hand1)
|
|
||||||
// zephr_ctx.cursors[.HRESIZE] = x11.XCreateFontCursor(x11_display, .XC_sb_h_double_arrow)
|
|
||||||
// zephr_ctx.cursors[.VRESIZE] = x11.XCreateFontCursor(x11_display, .XC_sb_v_double_arrow)
|
|
||||||
|
|
||||||
// non-standard cursors
|
|
||||||
// zephr_ctx.cursors[.DISABLED] = xcursor.LibraryLoadCursor(x11_display, "crossed_circle")
|
|
||||||
|
|
||||||
zephr_ctx.screen_size = backend_get_screen_size()
|
zephr_ctx.screen_size = backend_get_screen_size()
|
||||||
start_internal_timer()
|
start_internal_timer()
|
||||||
@@ -727,150 +719,13 @@ swap_buffers :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backend_swapbuffers()
|
backend_swapbuffers()
|
||||||
//x11.XDefineCursor(x11_display, x11_window, zephr_ctx.cursors[zephr_ctx.cursor])
|
backend_set_cursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
iter_events :: proc(e_out: ^Event) -> bool {
|
iter_events :: proc(e_out: ^Event) -> bool {
|
||||||
return backend_get_os_events(e_out)
|
return backend_get_os_events(e_out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// iter_events :: proc(e_out: ^Event) -> bool {
|
|
||||||
// context.logger = logger
|
|
||||||
// xev: x11.XEvent
|
|
||||||
|
|
||||||
// for (cast(bool)x11.XPending(x11_display)) {
|
|
||||||
// x11.XNextEvent(x11_display, &xev)
|
|
||||||
|
|
||||||
// if xev.type == .ConfigureNotify {
|
|
||||||
// xce := xev.xconfigure
|
|
||||||
|
|
||||||
// if (xce.width != cast(i32)zephr_ctx.window.size.x || xce.height != cast(i32)zephr_ctx.window.size.y) {
|
|
||||||
// zephr_ctx.window.size = Vec2{cast(f32)xce.width, cast(f32)xce.height}
|
|
||||||
// zephr_ctx.projection = orthographic_projection_2d(0, zephr_ctx.window.size.x, zephr_ctx.window.size.y, 0)
|
|
||||||
// x11_resize_window()
|
|
||||||
|
|
||||||
// e_out.type = .WINDOW_RESIZED
|
|
||||||
// e_out.window.width = cast(u32)xce.width
|
|
||||||
// e_out.window.height = cast(u32)xce.height
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// } else if xev.type == .DestroyNotify {
|
|
||||||
// // window destroy event
|
|
||||||
// e_out.type = .WINDOW_CLOSED
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// } else if xev.type == .ClientMessage {
|
|
||||||
// // window close event
|
|
||||||
// if (cast(x11.Atom)xev.xclient.data.l[0] == zephr_ctx.window_delete_atom) {
|
|
||||||
// e_out.type = .WINDOW_CLOSED
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// } else if xev.type == .KeyPress {
|
|
||||||
// xke := xev.xkey
|
|
||||||
|
|
||||||
// evdev_keycode := xke.keycode - 8
|
|
||||||
// scancode := evdev_scancode_to_zephr_scancode_map[evdev_keycode]
|
|
||||||
|
|
||||||
// e_out.type = .KEY_PRESSED
|
|
||||||
// e_out.key.scancode = scancode
|
|
||||||
// //e_out.key.code = keycode;
|
|
||||||
// e_out.key.mods = x11_mods_to_zephr_mods(scancode, true)
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// } else if xev.type == .KeyRelease {
|
|
||||||
// xke := xev.xkey
|
|
||||||
|
|
||||||
// evdev_keycode := xke.keycode - 8
|
|
||||||
// scancode := evdev_scancode_to_zephr_scancode_map[evdev_keycode]
|
|
||||||
|
|
||||||
// e_out.type = .KEY_RELEASED
|
|
||||||
// e_out.key.scancode = scancode
|
|
||||||
// //e_out.key.code = keycode;
|
|
||||||
// e_out.key.mods = x11_mods_to_zephr_mods(scancode, false)
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// } else if xev.type == .ButtonPress {
|
|
||||||
// e_out.type = .MOUSE_BUTTON_PRESSED
|
|
||||||
// e_out.mouse.pos = Vec2{cast(f32)xev.xbutton.x, cast(f32)xev.xbutton.y}
|
|
||||||
// zephr_ctx.mouse.pressed = true
|
|
||||||
|
|
||||||
// switch (xev.xbutton.button) {
|
|
||||||
// case .Button1:
|
|
||||||
// e_out.mouse.button = .BUTTON_LEFT
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_LEFT
|
|
||||||
// case .Button2:
|
|
||||||
// e_out.mouse.button = .BUTTON_MIDDLE
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_MIDDLE
|
|
||||||
// case .Button3:
|
|
||||||
// e_out.mouse.button = .BUTTON_RIGHT
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_RIGHT
|
|
||||||
// case .Button4:
|
|
||||||
// e_out.type = .MOUSE_SCROLL
|
|
||||||
// e_out.mouse.scroll_direction = .UP
|
|
||||||
// case .Button5:
|
|
||||||
// e_out.type = .MOUSE_SCROLL
|
|
||||||
// e_out.mouse.scroll_direction = .DOWN
|
|
||||||
// case cast(x11.MouseButton)8: // Back
|
|
||||||
// e_out.mouse.button = .BUTTON_BACK
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_BACK
|
|
||||||
// case cast(x11.MouseButton)9: // Forward
|
|
||||||
// e_out.mouse.button = .BUTTON_FORWARD
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_FORWARD
|
|
||||||
// case:
|
|
||||||
// log.warnf("Unknown mouse button pressed: %d", xev.xbutton.button)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// } else if xev.type == .ButtonRelease {
|
|
||||||
// e_out.type = .MOUSE_BUTTON_RELEASED
|
|
||||||
// e_out.mouse.pos = Vec2{cast(f32)xev.xbutton.x, cast(f32)xev.xbutton.y}
|
|
||||||
// zephr_ctx.mouse.released = true
|
|
||||||
// zephr_ctx.mouse.pressed = false
|
|
||||||
|
|
||||||
// switch (xev.xbutton.button) {
|
|
||||||
// case .Button1:
|
|
||||||
// e_out.mouse.button = .BUTTON_LEFT
|
|
||||||
// case .Button2:
|
|
||||||
// e_out.mouse.button = .BUTTON_MIDDLE
|
|
||||||
// case .Button3:
|
|
||||||
// e_out.mouse.button = .BUTTON_RIGHT
|
|
||||||
// case .Button4:
|
|
||||||
// e_out.type = .MOUSE_SCROLL
|
|
||||||
// e_out.mouse.scroll_direction = .UP
|
|
||||||
// case .Button5:
|
|
||||||
// e_out.type = .MOUSE_SCROLL
|
|
||||||
// e_out.mouse.scroll_direction = .DOWN
|
|
||||||
// case cast(x11.MouseButton)8: // Back
|
|
||||||
// e_out.mouse.button = .BUTTON_BACK
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_BACK
|
|
||||||
// case cast(x11.MouseButton)9: // Forward
|
|
||||||
// e_out.mouse.button = .BUTTON_FORWARD
|
|
||||||
// zephr_ctx.mouse.button = .BUTTON_FORWARD
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// } else if xev.type == .MappingNotify {
|
|
||||||
// // input device mapping changed
|
|
||||||
// if (xev.xmapping.request != .MappingKeyboard) {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// x11.XRefreshKeyboardMapping(&xev.xmapping)
|
|
||||||
// /* x11_keyboard_map_update(); */
|
|
||||||
// break
|
|
||||||
// } else if xev.type == .MotionNotify {
|
|
||||||
// e_out.type = .MOUSE_MOVED
|
|
||||||
// e_out.mouse.pos = Vec2{cast(f32)xev.xmotion.x, cast(f32)xev.xmotion.y}
|
|
||||||
// zephr_ctx.mouse.pos = e_out.mouse.pos
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
|
|
||||||
get_window_size :: proc() -> Vec2 {
|
get_window_size :: proc() -> Vec2 {
|
||||||
return zephr_ctx.window.size
|
return zephr_ctx.window.size
|
||||||
}
|
}
|
||||||
@@ -924,3 +779,92 @@ logger_init :: proc() {
|
|||||||
|
|
||||||
logger = log.create_multi_logger(file_logger, term_logger)
|
logger = log.create_multi_logger(file_logger, term_logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@private
|
||||||
|
set_zephr_mods :: proc(scancode: Scancode, is_press: bool) -> KeyMod {
|
||||||
|
mods := zephr_ctx.keyboard.mods
|
||||||
|
|
||||||
|
if (is_press) {
|
||||||
|
if (scancode == .LEFT_SHIFT) {
|
||||||
|
mods |= {.LEFT_SHIFT, .SHIFT}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_SHIFT) {
|
||||||
|
mods |= {.RIGHT_SHIFT, .SHIFT}
|
||||||
|
}
|
||||||
|
if (scancode == .LEFT_CTRL) {
|
||||||
|
mods |= {.LEFT_CTRL, .CTRL}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_CTRL) {
|
||||||
|
mods |= {.RIGHT_CTRL, .CTRL}
|
||||||
|
}
|
||||||
|
if (scancode == .LEFT_ALT) {
|
||||||
|
mods |= {.LEFT_ALT, .ALT}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_ALT) {
|
||||||
|
mods |= {.RIGHT_ALT, .ALT}
|
||||||
|
}
|
||||||
|
if (scancode == .LEFT_META) {
|
||||||
|
mods |= {.LEFT_META, .META}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_META) {
|
||||||
|
mods |= {.RIGHT_META, .META}
|
||||||
|
}
|
||||||
|
if (scancode == .CAPS_LOCK) {
|
||||||
|
mods |= {.CAPS_LOCK}
|
||||||
|
}
|
||||||
|
if (scancode == .NUM_LOCK_OR_CLEAR) {
|
||||||
|
mods |= {.NUM_LOCK}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scancode == .LEFT_SHIFT) {
|
||||||
|
mods &= ~{.LEFT_SHIFT}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_SHIFT) {
|
||||||
|
mods &= ~{.RIGHT_SHIFT}
|
||||||
|
}
|
||||||
|
if (!(.RIGHT_SHIFT in mods) && !(.LEFT_SHIFT in mods)) {
|
||||||
|
mods &= ~{.SHIFT}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode == .LEFT_CTRL) {
|
||||||
|
mods &= ~{.LEFT_CTRL}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_CTRL) {
|
||||||
|
mods &= ~{.RIGHT_CTRL}
|
||||||
|
}
|
||||||
|
if (!(.RIGHT_CTRL in mods) && !(.LEFT_CTRL in mods)) {
|
||||||
|
mods &= ~{.CTRL}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode == .LEFT_ALT) {
|
||||||
|
mods &= ~{.LEFT_ALT}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_ALT) {
|
||||||
|
mods &= ~{.RIGHT_ALT}
|
||||||
|
}
|
||||||
|
if (!(.RIGHT_ALT in mods) && !(.LEFT_ALT in mods)) {
|
||||||
|
mods &= ~{.ALT}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode == .LEFT_META) {
|
||||||
|
mods &= ~{.LEFT_META}
|
||||||
|
}
|
||||||
|
if (scancode == .RIGHT_META) {
|
||||||
|
mods &= ~{.RIGHT_META}
|
||||||
|
}
|
||||||
|
if (!(.RIGHT_META in mods) && !(.LEFT_META in mods)) {
|
||||||
|
mods &= ~{.META}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode == .CAPS_LOCK) {
|
||||||
|
mods &= ~{.CAPS_LOCK}
|
||||||
|
}
|
||||||
|
if (scancode == .NUM_LOCK_OR_CLEAR) {
|
||||||
|
mods &= ~{.NUM_LOCK}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zephr_ctx.keyboard.mods = mods
|
||||||
|
|
||||||
|
return mods
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user