From b2d8d37a600cc3d8ba69840ecc639f577f60a131 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Tue, 15 Oct 2024 10:54:26 +0700 Subject: [PATCH] Odin window manager --- DESIGN.org | 30 ++++++++++++------ cpp-version/main.cpp | 2 ++ odin-version/tide.odin | 16 +++++++--- odin-version/wm.odin | 71 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 odin-version/wm.odin diff --git a/DESIGN.org b/DESIGN.org index 69dda20..fc6e3ac 100644 --- a/DESIGN.org +++ b/DESIGN.org @@ -1,24 +1,36 @@ - * Keymapping system -** Keymap Stacking +** X11 Window Manager +- Run launcher +- Basic Window Management +- Buffer-or-x11win +** If only it had a good text editor... +- SDL2 +** IMTUI Lib +- Autolayout system +** Custom Language VM +- LSP +- Treesitter +- Coroutines with the event loop +** Keymap System +*** Keymap Stacking There shouldn't be modes, there would be keymaps and a stack. Insert mode would be at the bottom of the stack. Adding a new mode means pushing onto the stack, and when a keybinding event is raised, you iterate over the stack from top to bottom to find the correct keybinding. The vim nomenclature wouldn't work in this case as you don't "leave insert mode". Rather, you pop the "normal mode" keymap ontop of the "insert mode" keymap. -** Passthrough/Blocking +*** Passthrough/Blocking The keymap object should have additional settings that dictate its behavior when a key is found and not found. -*** Found -**** Pop +**** Found +***** Pop The default could be to pop from the stack. -**** Keep +***** Keep Keep the keymap on the stack. This is useful for both normal mode and transient like modes where you need to explicitly pop it from the stack. -*** Not found -**** Passthrough +**** Not found +***** Passthrough Allow the loop to go to the next keymap -**** Block +***** Block Ignore missing key, don't pop the keymap, maybe report an error diff --git a/cpp-version/main.cpp b/cpp-version/main.cpp index d140c2b..56dd7e9 100644 --- a/cpp-version/main.cpp +++ b/cpp-version/main.cpp @@ -13,6 +13,8 @@ using namespace std; const int SCREEN_WIDTH = 1024; const int SCREEN_HEIGHT = 768; +char *test_string = "This is a test string for fide"; + enum KeyPressSurfaces { KEY_PRESS_SURFACE_DEFAULT, diff --git a/odin-version/tide.odin b/odin-version/tide.odin index cf62c31..25ee1a7 100644 --- a/odin-version/tide.odin +++ b/odin-version/tide.odin @@ -84,7 +84,7 @@ sdl_init :: proc() -> (ok: bool) { bt := new(BufferText) bt.builder = strings.builder_make(0, 512) ctx.buffer_text = bt - append(&bt.builder.buf, "// Code goes here...\ntest more stuff ok") + append(&bt.builder.buf, "// Code goes here...") str := strings.to_cstring(&ctx.buffer_text.builder) color := sdl.Color{ 0, 0, 0, 255} ctx.text_surface = ttf.RenderUTF8_Blended_Wrapped(ctx.font, str, color, 900); @@ -105,8 +105,10 @@ process_input :: proc() { case .ESCAPE: ctx.should_close = true case .BACKSPACE: - strings.pop_rune(&ctx.buffer_text.builder) - state.buffer_dirty = true + if strings.builder_len(ctx.buffer_text.builder) > 0 { + strings.pop_rune(&ctx.buffer_text.builder) + state.buffer_dirty = true + } case .RETURN: strings.write_rune(&ctx.buffer_text.builder, '\n') state.buffer_dirty = true @@ -124,7 +126,13 @@ update :: proc() { color := sdl.Color{ 0, 0, 0, 255} - str := strings.to_cstring(&ctx.buffer_text.builder) + str: cstring + if strings.builder_len(ctx.buffer_text.builder) > 0 { + str = strings.to_cstring(&ctx.buffer_text.builder) + } else { + str = cstring(" ") + } + ctx.text_surface = ttf.RenderUTF8_Blended_Wrapped(ctx.font, str, color, 900); if (ctx.text_surface == nil) { log.errorf(sdl.GetErrorString()) diff --git a/odin-version/wm.odin b/odin-version/wm.odin new file mode 100644 index 0000000..690b9c6 --- /dev/null +++ b/odin-version/wm.odin @@ -0,0 +1,71 @@ +package wm + +import fmt "core:fmt" +import "core:os" +import "core:log" +import "core:math" +import "core:strings" +import x "vendor:x11/xlib" + + +main :: proc () { + display: ^x.Display + root: x.Window + attr: x.XWindowAttributes + start: x.XButtonEvent + + display = x.OpenDisplay(nil) + if display == nil { + fmt.println("Could not open display") + os.exit(1) + } + + x.GrabKey(display, i32(x.KeysymToKeycode(display, x.StringToKeysym("F1"))), {.Mod1Mask}, + x.DefaultRootWindow(display), true, .GrabModeAsync, .GrabModeAsync); + // x.GrabButton(display, 1, Mod1Mask, DefaultRootWindow(dpy), true, + // ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); + // XGrabButton(display, 3, Mod1Mask, DefaultRootWindow(display), true, + // ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); + // x.SelectInput + // display, + // root, + // {.SubstructureRedirect, .SubstructureNotify}); + // x.Synchronize(display, false); + + for { + e: x.XEvent + x.NextEvent(display, &e) + fmt.println("Received Event: ", e) + + #partial switch e.type { + case .KeyPress: + x.RaiseWindow(display, e.xkey.subwindow) + case .ButtonPress: + x.GetWindowAttributes(display, e.xbutton.subwindow, &attr) + start = e.xbutton + case .MotionNotify: + xdiff := e.xbutton.x_root - start.x_root; + ydiff := e.xbutton.y_root - start.y_root; + xpos := attr.x + (start.button==.Button1 ? xdiff : 0) + ypos := attr.y + (start.button==.Button1 ? ydiff : 0) + width := u32(max(1, attr.width + (start.button==.Button2 ? xdiff : 0))) + height := u32(max(1, attr.height + (start.button==.Button2 ? ydiff : 0))) + x.MoveResizeWindow(display, start.subwindow, xpos, ypos, width, height) + case .ButtonRelease: + // start.subwindow = nil; + } + // else if(ev.xbutton.subwindow != None) + // else if(ev.type == MotionNotify && start.subwindow != None) + // { + // int xdiff = ev.xbutton.x_root - start.x_root; + // int ydiff = ev.xbutton.y_root - start.y_root; + // XMoveResizeWindow(dpy, start.subwindow, + // attr.x + (start.button==1 ? xdiff : 0), + // attr.y + (start.button==1 ? ydiff : 0), + // MAX(1, attr.width + (start.button==3 ? xdiff : 0)), + // MAX(1, attr.height + (start.button==3 ? ydiff : 0))); + // } + // else if(ev.type == ButtonRelease) + // start.subwindow = None; + } +}