andlabs / ui

Platform-native GUI library for Go.
Other
8.33k stars 651 forks source link

Minimal example of another package hooking into event loop with native system calls? #278

Open akamensky opened 6 years ago

akamensky commented 6 years ago

I know this has been raised many times, and to avoid any further struggle with this (as there is still no any good solution). I am wondering if you could provide a minimal example how another package could hook into ui's event loop while doing system calls (namely on macOS as this is where this issue most relevant).

I.e. I know of one functionality that is rather simple in native implementation and that fails due to non-main thread issue -- notification popups (it "fails" differently though, not a segfault, but simply no popup shown if called from non-main thread)

If I had that example I could work on separate package/lib that would work specifically with ui's event loop and provide those extra functionality (tray icon, notifications and what not). Which I think would be the way to go since no other package with native UI seems to be capable of providing those hooks.

andlabs commented 6 years ago

Do you want to just run code in the main loop? That would be ui.QueueMain(). I also plan on adding a ui.Timer() (see andlabs/libui#277) for having things done on a UI-bound clock (no guarantees about accuracy or precision, not as useful with Go, but still useful).

Do you want to have a custom main loop? I could make that happen with the fix to the multithreading stuff, which I still need to make a tracking issue for (even though I could just do it now; see golang/go#23112).

Do you mean injecting event sources into the event loop using OS-specific APIs like -[NSRunLoop addPort:forNode:]? I don't know yet.

akamensky commented 6 years ago

Apologies, I think I should have been more clear on what I meant.

I actually did not look at the code of libui yet, but I assume that there you use a native system event loop and in case of macOS using NSApplication or it's variants (NSApplicationMain or other App instance).

Now, if I just want to run some plain Go code inside your event loop, clearly I can use ui.QueueMain() for that. However, if I implement those UI functions, I will need to bridge Objective-C to Golang (or in case of Win/Linux C/C++ to Golang).

I am very comfortable writing in Go bridged to C/C++, and somewhat okay with Objective-C, but never done bridging of Objective-C and Go. Which is why I am wondering of minimal example of such 3rd party lib that can implement calls from Objective-C and can be added into the ui's event loop via Go.

Having such minimal example can help me to understand how it links better (as opposed trying to understand this from already big projects such as libui itself, which can be rather difficult). And that would give me a good start on implementing this lib/package myself, so that you probably would not need to be bothered by those issues showing up all the time.

andlabs commented 6 years ago

I'm sorry, I still don't understand what the confusion is. What do you mean by needing to "bridge Objective-C to Golang (or in case of Win/Linux C/C++ to Golang)"? The point of ui.QueueMain() is so that you can call any code on the main loop, including C code called via cgo.

ui.QueueMain(func() {
    cstr := C.CString("hello"); defer C.free(unsafe.Pointer(cstr))
    C.showNotification(window.Handle(), cstr)
})
akamensky commented 6 years ago

Nevermind, I figured that out and made a package that can be used nicely with ui for notifications (on macos for now only). Also found that NSUserNotification does not actually depend on main thread, but instead depends on application having valid bundle ID, but that is another story.

Can close this issue. Sorry for much chatter and distractions.

parro-it commented 6 years ago

I'm not sure I understood you're problem, but in libui-node I integrated GUI event loop with node one, which is based on libuv.

You should look at latest version in next-loop branch