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