Skip to content

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

@haydencj

Description

@haydencj

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions