Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Systray Run conflicts with GLFW’s requirement for the main thread (macOS) #284

Open
haydencj opened this issue Jan 5, 2025 · 0 comments

Comments

@haydencj
Copy link

haydencj commented Jan 5, 2025

I’m trying to use systray alongside GLFW in an OpenGL-based application. Both frameworks require the main thread:

  • GLFW: OpenGL calls and event handling (glfw.PollEvents()) must happen on the main thread.
  • Systray: Run blocks the main thread, preventing GLFW from functioning.

On macOS, this becomes more problematic because all UI must run on the main thread.

I’ve explored systray.Register as an alternative, but the lack of an explicit event polling mechanism makes integration with GLFW challenging.

Below is a simplified version of my code.

package main

import (
	"log"
	"github.com/getlantern/systray"
	"github.com/go-gl/glfw/v3.3/glfw"
	_ "embed"
)

// Embed the tray icon
//go:embed assets/icon.png
var iconData []byte

func main() {
	// Systray initialization
	log.Println("Starting systray...")
	systray.Run(onReady, onExit) // Blocks the main thread

	// GLFW initialization
	if err := glfw.Init(); err != nil {
		log.Fatalf("Failed to initialize GLFW: %v", err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(800, 600, "OpenGL App", nil, nil)
	if err != nil {
		log.Fatalf("Failed to create GLFW window: %v", err)
	}
	window.MakeContextCurrent()

	// Main loop
	for !window.ShouldClose() {
		glfw.PollEvents()
		window.SwapBuffers()
	}
}

func onReady() {
	systray.SetIcon(iconData)
	systray.SetTitle("Tray App")
	systray.SetTooltip("An example tray application")

	start := systray.AddMenuItem("Start", "Start something")
	quit := systray.AddMenuItem("Quit", "Quit the application")

	go func() {
		for {
			select {
			case <-start.ClickedCh:
				log.Println("Start clicked")
			case <-quit.ClickedCh:
				systray.Quit()
			}
		}
	}()
}

func onExit() {
	log.Println("Exiting systray...")
}

Attempted Solutions

  1. Using systray.Register:
  • I tried moving systray logic to a separate goroutine with systray.Register, but it lacks an explicit event polling mechanism.
  1. Exploring External Libraries:
  • I came across golang-design/mainthread as a potential solution for coordinating main-thread tasks, but I have not continued with this yet.

Request

Could systray provide:
1. A way to manually poll systray events (similar to glfw.PollEvents)?
4. Better support for sharing the main thread with libraries like GLFW?

Any guidance on integrating systray with frameworks requiring main-thread access would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant