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