Mercurial > games > semicongine
comparison semiconginev2/old/platform/linux/window.nim @ 1218:56781cc0fc7c compiletime-tests
did: renamge main package
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 21:01:37 +0700 |
parents | semicongine/old/platform/linux/window.nim@a3eb305bcac2 |
children |
comparison
equal
deleted
inserted
replaced
1217:f819a874058f | 1218:56781cc0fc7c |
---|---|
1 import std/options | |
2 import std/tables | |
3 import std/strformat | |
4 import std/logging | |
5 | |
6 import ../../thirdparty/x11/xlib | |
7 import ../../thirdparty/x11/xutil | |
8 import ../../thirdparty/x11/keysym | |
9 import ../../thirdparty/x11/x | |
10 import ../../thirdparty/x11/xkblib | |
11 | |
12 import ../../core | |
13 import ../../events | |
14 | |
15 import ./symkey_map | |
16 | |
17 export keysym | |
18 | |
19 var deleteMessage*: Atom | |
20 | |
21 type | |
22 NativeWindow* = object | |
23 display*: ptr xlib.Display | |
24 window*: x.Window | |
25 emptyCursor: Cursor | |
26 | |
27 template checkXlibResult(call: untyped) = | |
28 let value = call | |
29 if value == 0: | |
30 raise newException(Exception, "Xlib error: " & astToStr(call) & | |
31 " returned " & $value) | |
32 | |
33 proc XErrorLogger(display: PDisplay, event: PXErrorEvent): cint {.cdecl.} = | |
34 error &"Xlib: {event[]}" | |
35 | |
36 proc CreateWindow*(title: string): NativeWindow = | |
37 checkXlibResult XInitThreads() | |
38 let display = XOpenDisplay(nil) | |
39 if display == nil: | |
40 quit "Failed to open display" | |
41 discard XSetErrorHandler(XErrorLogger) | |
42 | |
43 let rootWindow = display.XDefaultRootWindow() | |
44 discard display.XkbSetDetectableAutoRepeat(true, nil) | |
45 var | |
46 attribs: XWindowAttributes | |
47 width = cuint(800) | |
48 height = cuint(600) | |
49 checkXlibResult display.XGetWindowAttributes(rootWindow, addr(attribs)) | |
50 | |
51 var attrs = XSetWindowAttributes() | |
52 let window = XCreateWindow( | |
53 display, | |
54 rootWindow, | |
55 (attribs.width - cint(width)) div 2, (attribs.height - cint(height)) div 2, | |
56 width, height, | |
57 0, | |
58 CopyFromParent, | |
59 InputOutput, | |
60 cast[PVisual](CopyFromParent), | |
61 0, # CWOverrideRedirect, | |
62 addr attrs, | |
63 # foregroundColor, backgroundColor | |
64 ) | |
65 checkXlibResult XSetStandardProperties(display, window, title, "window", 0, nil, 0, nil) | |
66 checkXlibResult XSelectInput(display, window, PointerMotionMask or ButtonPressMask or ButtonReleaseMask or KeyPressMask or KeyReleaseMask or ExposureMask) | |
67 checkXlibResult XMapWindow(display, window) | |
68 | |
69 deleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", XBool(false)) | |
70 checkXlibResult XSetWMProtocols(display, window, addr(deleteMessage), 1) | |
71 | |
72 var data = "\0".cstring | |
73 var pixmap = display.XCreateBitmapFromData(window, data, 1, 1) | |
74 var color: XColor | |
75 var empty_cursor = display.XCreatePixmapCursor(pixmap, pixmap, addr(color), addr(color), 0, 0) | |
76 checkXlibResult display.XFreePixmap(pixmap) | |
77 return NativeWindow(display: display, window: window, emptyCursor: empty_cursor) | |
78 | |
79 proc SetTitle*(window: NativeWindow, title: string) = | |
80 checkXlibResult XSetStandardProperties(window.display, window.window, title, "window", 0, nil, 0, nil) | |
81 | |
82 proc Fullscreen*(window: var NativeWindow, enable: bool) = | |
83 var | |
84 wm_state = window.display.XInternAtom("_NET_WM_STATE", 0) | |
85 wm_fullscreen = window.display.XInternAtom("_NET_WM_STATE_FULLSCREEN", 0) | |
86 var | |
87 xev: XEvent | |
88 xev.xclient = XClientMessageEvent( | |
89 message_type: wm_state, | |
90 format: 32, | |
91 window: window.window, | |
92 data: XClientMessageData( | |
93 l: [ | |
94 int(not enable) xor 1, | |
95 clong(wm_fullscreen), | |
96 0, | |
97 0, | |
98 0 | |
99 ] | |
100 ) | |
101 ) | |
102 xev.theType = ClientMessage | |
103 | |
104 checkXlibResult window.display.XSendEvent( | |
105 window.display.DefaultRootWindow(), | |
106 0, | |
107 SubstructureRedirectMask or SubstructureNotifyMask, | |
108 addr xev | |
109 ) | |
110 checkXlibResult window.display.XFlush() | |
111 | |
112 proc HideSystemCursor*(window: NativeWindow) = | |
113 checkXlibResult XDefineCursor(window.display, window.window, window.emptyCursor) | |
114 checkXlibResult window.display.XFlush() | |
115 | |
116 proc ShowSystemCursor*(window: NativeWindow) = | |
117 checkXlibResult XUndefineCursor(window.display, window.window) | |
118 checkXlibResult window.display.XFlush() | |
119 | |
120 proc Destroy*(window: NativeWindow) = | |
121 checkXlibResult window.display.XFreeCursor(window.emptyCursor) | |
122 checkXlibResult window.display.XDestroyWindow(window.window) | |
123 discard window.display.XCloseDisplay() # always returns 0 | |
124 | |
125 proc Size*(window: NativeWindow): (int, int) = | |
126 var attribs: XWindowAttributes | |
127 checkXlibResult XGetWindowAttributes(window.display, window.window, addr(attribs)) | |
128 return (int(attribs.width), int(attribs.height)) | |
129 | |
130 proc PendingEvents*(window: NativeWindow): seq[Event] = | |
131 var event: XEvent | |
132 while window.display.XPending() > 0: | |
133 discard window.display.XNextEvent(addr(event)) | |
134 case event.theType | |
135 of ClientMessage: | |
136 if cast[Atom](event.xclient.data.l[0]) == deleteMessage: | |
137 result.add(Event(eventType: Quit)) | |
138 of KeyPress: | |
139 let keyevent = cast[PXKeyEvent](addr(event)) | |
140 let xkey = int(keyevent.keycode) | |
141 result.add Event(eventType: KeyPressed, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) | |
142 of KeyRelease: | |
143 let keyevent = cast[PXKeyEvent](addr(event)) | |
144 let xkey = int(keyevent.keycode) | |
145 result.add Event(eventType: KeyReleased, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) | |
146 of ButtonPress: | |
147 let button = int(cast[PXButtonEvent](addr(event)).button) | |
148 if button == Button4: | |
149 result.add Event(eventType: MouseWheel, amount: 1'f32) | |
150 elif button == Button5: | |
151 result.add Event(eventType: MouseWheel, amount: -1'f32) | |
152 else: | |
153 result.add Event(eventType: MousePressed, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) | |
154 of ButtonRelease: | |
155 let button = int(cast[PXButtonEvent](addr(event)).button) | |
156 result.add Event(eventType: MouseReleased, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) | |
157 of MotionNotify: | |
158 let motion = cast[PXMotionEvent](addr(event)) | |
159 result.add Event(eventType: MouseMoved, x: motion.x, y: motion.y) | |
160 of ConfigureNotify, Expose: | |
161 result.add Event(eventType: ResizedWindow) | |
162 else: | |
163 discard | |
164 | |
165 | |
166 proc GetMousePosition*(window: NativeWindow): Option[Vec2f] = | |
167 var | |
168 root: x.Window | |
169 win: x.Window | |
170 rootX: cint | |
171 rootY: cint | |
172 winX: cint | |
173 winY: cint | |
174 mask: cuint | |
175 onscreen = XQueryPointer( | |
176 window.display, | |
177 window.window, | |
178 addr(root), | |
179 addr(win), | |
180 addr(rootX), | |
181 addr(rootY), | |
182 addr(winX), | |
183 addr(winY), | |
184 addr(mask), | |
185 ) | |
186 if onscreen != 0: | |
187 result = some(Vec2f([float32(winX), float32(winY)])) | |
188 |