{"id":13430287,"url":"https://github.com/alexflint/gallium","last_synced_at":"2025-05-14T00:04:47.591Z","repository":{"id":47387811,"uuid":"68566550","full_name":"alexflint/gallium","owner":"alexflint","description":"Build desktop applications in Go and HTML.","archived":false,"fork":false,"pushed_at":"2025-01-01T12:47:31.000Z","size":7020,"stargazers_count":3669,"open_issues_count":16,"forks_count":135,"subscribers_count":123,"default_branch":"master","last_synced_at":"2025-05-12T05:39:44.688Z","etag":null,"topics":["chromium","desktop-application","desktop-notifications","dock-icon","golang","menus"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexflint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-19T03:38:03.000Z","updated_at":"2025-04-16T07:25:53.000Z","dependencies_parsed_at":"2025-01-17T18:00:45.048Z","dependency_job_id":"dc512d5f-7a1d-43bf-83b7-1ae77556cc4b","html_url":"https://github.com/alexflint/gallium","commit_stats":{"total_commits":119,"total_committers":6,"mean_commits":"19.833333333333332","dds":"0.050420168067226934","last_synced_commit":"bfa1ecd9241eb3b9f203869fb317c55c3c0c360f"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexflint%2Fgallium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexflint%2Fgallium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexflint%2Fgallium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexflint%2Fgallium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexflint","download_url":"https://codeload.github.com/alexflint/gallium/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043298,"owners_count":22004917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chromium","desktop-application","desktop-notifications","dock-icon","golang","menus"],"created_at":"2024-07-31T02:00:51.840Z","updated_at":"2025-05-14T00:04:47.570Z","avatar_url":"https://github.com/alexflint.png","language":"Go","funding_links":[],"categories":["Go","golang","Libraries"],"sub_categories":[],"readme":"[![GoDoc](https://godoc.org/github.com/alexflint/gallium?status.svg)](https://godoc.org/github.com/alexflint/gallium)\n[![Build Status](https://travis-ci.org/alexflint/gallium.svg?branch=master)](https://travis-ci.org/alexflint/gallium)\n\nWrite desktop applications in Go, HTML, Javascript, and CSS.\n\nGallium is a Go library for managing windows, menus, dock icons, and desktop notifications. Each window contains a webview component, in which you code your UI in HTML. Under the hood, the webview is running Chromium.\n\n### Warning\n\nThis is an extremely early version of Gallium. Most APIs will probably change\nbefore the 1.0 release, and much of the functionality that is already implemented\nremains unstable.\n\n### Platforms\n\nOnly OSX is supported right now. I intend to add support for Windows and Linux\nsoon.\n\n### Discussion\n\nJoin the `#gallium` channel over at the Gophers slack. (You can request an invite to\nthe Gophers slack team [here](https://gophersinvite.herokuapp.com/).)\n\n### Installation\n\nRequires go \u003e= 1.7\n\nFirst install git large file storage, then install Gallium:\n```shell\n$ brew install git-lfs\n$ git lfs install\n$ go get github.com/alexflint/gallium  # will not work without git lfs!\n```\n\nThis will fetch a 92MB framework containing a binary distribution\nof the Chromium content module, so it may take a few moments. This\nis also why git large file storage must be installed (github has\na limit on file size.)\n\n### Quickstart\n\n```go\npackage main\n\nimport (\n  \"os\"\n  \"runtime\"\n\n  \"github.com/alexflint/gallium\"\n)\n\nfunc main() {\n  runtime.LockOSThread()         // must be the first statement in main - see below\n  gallium.Loop(os.Args, onReady) // must be called from main function\n}\n\nfunc onReady(app *gallium.App) {\n  app.OpenWindow(\"http://example.com/\", gallium.FramedWindow)\n}\n```\n\nTo run the example as a full-fledged UI application, you need to build\nan app bundle:\n```shell\n$ go build ./example\n$ go install github.com/alexflint/gallium/cmd/gallium-bundle\n$ gallium-bundle example\n$ open example.app\n```\n\n![Result of the example](https://cloud.githubusercontent.com/assets/640247/18623245/c71c2d26-7def-11e6-9ad3-1a5541d7fc86.png)\n\nIf you run the executable directly without building an app bundle then\nmany UI elements, such as menus, will not work correctly.\n\n```shell\n$ go run example.go\n```\n\n### Menus\n\n```go\nfunc main() {\n  runtime.LockOSThread()\n  gallium.Loop(os.Args, onReady)\n}\n\nfunc onReady(app *gallium.App) {\n  app.OpenWindow(\"http://example.com/\", gallium.FramedWindow)\n  app.SetMenu([]gallium.Menu{\n    gallium.Menu{\n      Title: \"demo\",\n      Entries: []gallium.MenuEntry{\n        gallium.MenuItem{\n          Title:    \"About\",\n          OnClick:  handleMenuAbout,\n        },\n        gallium.Separator,\n        gallium.MenuItem{\n          Title:    \"Quit\",\n          Shortcut: \"Cmd+q\",\n          OnClick:  handleMenuQuit,\n        },\n      },\n    },\n  })\n}\n\nfunc handleMenuAbout() {\n  log.Println(\"about clicked\")\n  os.Exit(0)\n}\n\nfunc handleMenuQuit() {\n  log.Println(\"quit clicked\")\n  os.Exit(0)\n}\n```\n\n![Menu demo](https://cloud.githubusercontent.com/assets/640247/20243830/17fbaa8e-a91d-11e6-8eca-7ae7c1418a7e.png)\n\n### Status Bar\n\n```go\nfunc main() {\n  runtime.LockOSThread()\n  gallium.Loop(os.Args, onReady)\n}\n\nfunc onReady(app *gallium.App) {\n  app.OpenWindow(\"http://example.com/\", gallium.FramedWindow)\n  app.AddStatusItem(\n    20,\n    \"statusbar\",\n    true,\n    gallium.MenuItem{\n      Title:   \"Do something\",\n      OnClick: handleDoSomething,\n    },\n    gallium.MenuItem{\n      Title:   \"Do something else\",\n      OnClick: handleDoSomethingElse,\n    },\n  )\n}\n\nfunc handleDoSomething() {\n  log.Println(\"do something\")\n}\n\nfunc handleDoSomethingElse() {\n  log.Println(\"do something else\")\n}\n```\n\n![Statusbar demo](https://cloud.githubusercontent.com/assets/640247/18698431/06e9d88c-7f7f-11e6-9fa5-d6be40a07840.png)\n\n### Desktop Notifications\n\nNote that the OSX Notification Center determines whether or not to show any\ngiven desktop notification, so you may need to open the notification center\nand scroll to the bottom in order to see notifications during development.\n\n```go\nfunc main() {\n  runtime.LockOSThread()\n  gallium.Loop(os.Args, onReady)\n}\n\nfunc onReady(app *gallium.App) {\n  img, err := gallium.ImageFromPNG(pngBuffer)\n  if err != nil {\n    ...\n  }\n\n  app.Post(gallium.Notification{\n    Title:    \"Wow this is a notification\",\n    Subtitle: \"The subtitle\",\n    Image:    img,\n  })\n}\n```\n\n### Dock icons\n\nTo add a dock icon, create a directory named `myapp.iconset` containing the following files:\n```\nicon_16x16.png          # 16 x 16\nicon_16x16@2x.png       # 32 x 32\nicon_32x32.png          # 32 x 32\nicon_32x32@2x.png       # 64 x 64\nicon_128x128.png        # 128 x 128\nicon_128x128@2x.png     # 256 x 256\nicon_256x256.png        # 256 x 256\nicon_256x256@2x.png     # 512 x 512\nicon_512x512.png        # 512 x 512\nicon_512x512@2x.png     # 1024 x 1024\n```\n\nThen build you app with\n```shell\ngallium-bundle myapp --icon myapp.iconset\n```\n\nAlternatively, if you have a `.icns` file:\n```shell\ngallium-bundle myapp --icon myapp.icns\n```\n\n### Writing native code\n\nYou can write C or Objective-C code that interfaces directly with native\nwindowing APIs. The following example uses the macOS native API `[NSWindow\nsetAlphaValue]` to create a semi-transparent window.\n\n```go\npackage main\n\nimport (\n  \"log\"\n  \"os\"\n  \"runtime\"\n\n  \"github.com/alexflint/gallium\"\n)\n\n/*\n#cgo CFLAGS: -x objective-c\n#cgo CFLAGS: -framework Cocoa\n#cgo LDFLAGS: -framework Cocoa\n\n#include \u003cCocoa/Cocoa.h\u003e\n#include \u003cdispatch/dispatch.h\u003e\n\nvoid SetAlpha(void* window, float alpha) {\n  // Cocoa requires that all UI operations happen on the main thread. Since\n  // gallium.Loop will have initiated the Cocoa event loop, we can can use\n  // dispatch_async to run code on the main thread.\n  dispatch_async(dispatch_get_main_queue(), ^{\n    NSWindow* w = (NSWindow*)window;\n    [w setAlphaValue:alpha];\n  });\n}\n*/\nimport \"C\"\n\nfunc onReady(ui *gallium.App) {\n  window, err := ui.OpenWindow(\"http://example.com/\", gallium.FramedWindow)\n  if err != nil {\n    log.Fatal(err)\n  }\n  C.SetAlpha(window.NativeWindow(), 0.5)\n}\n\nfunc main() {\n  runtime.LockOSThread()\n  gallium.Loop(os.Args, onReady)\n}\n```\n\n### Relationship to other projects\n\n[Electron](http://electron.atom.io/) is a well-known framework for writing desktop applications in node.js. Electron and Gallium are similar in that the core UI is developed in HTML and javascript, but with Gallium the \"outer layer\" of logic is written in Go. Both Electron and Gallium use Chromium under the hood, and some of the C components for Gallium were ported from Electron.\n\nThe [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef) is a C framework for embedding Chromium into other applications. I investigated CEF as a basis for Gallium but decided to use [libchromiumcontent](https://github.com/electron/libchromiumcontent) instead.\n\n[cef2go](https://github.com/cztomczak/cef2go) is a Go wrapper for Chromium based on CEF, but so far it still requires some manual steps to use as a library.\n\n### Rationale\n\nThe goal of Gallium is to make it possible to write cross-platform\ndesktop UI applications in Go.\n\n### Troubleshooting\n\n**\"file was built for unsupported file format\"**\n\nIf you see the following error:\n```\nld: warning: ignoring file go/src/github.com/alexflint/gallium/dist/Gallium.framework/Gallium, file was built for unsupported file format ( 0x76 0x65 0x72 0x73 0x69 0x6F 0x6E 0x20 0x68 0x74 0x74 0x70 0x73 0x3A 0x2F 0x2F ) which is not the architecture being linked (x86_64): go/src/github.com/alexflint/gallium/dist/Gallium.framework/Gallium\n```\nthen you probably have an issue with `git lfs`. You can confirm that this is\nthe problem by checking the size of the file in the error message: it should\nbe over 1 MB, but if you see a much smaller file then this is your problem.\n\nTo fix this, try re-installing `git lfs` as described in the installation\nsection above, then delete and re-install gallium.\n\n**No console output**\n\nWhen you run an app bundle with `open Foo.app`, OSX launch services discards\nstandard output and standard error. If you need to see this output for\ndebugging purposes, use a redirect:\n```\ngallium.RedirectStdoutStderr(\"output.log\")\n```\n\n**App does not start**\n\nWhen you run an app bundle with `open Foo.app`, OSX launch services will only\nstart your app if there is not already another instance of the same\napplication running, so if your app refuses to start then try checking the\nactivity monitor for an already running instance.\n\n**Menus not visible**\n\nIf you run the binary directly without building an app\nbundle then your menus will not show up, and the window will initially appear\nbehind other applications.\n\n### UI thread issues and runtime.LockOSThread\n\nIt is very important that the first statement in your main function\nbe `runtime.LockOSThread()`. The reason is that gallium calls\nout to various C functions in order to create and manage OSX UI elements,\nand many of these are required to be called from the first thread\ncreated by the process. But the Go runtime creates many threads and any\none piece of Go code could end up running on any thread. The solution\nis `runtime.LockOSThread`, which tells the Go scheduler to lock the\ncurrent goroutine so that it will only ever run on the current thread.\nSince the main function always starts off on the main thread, this wil\nguarantee that the later call to `gallium.Loop` will also be on the main\nthread. At this point gallium takes ownership of this thread for its main\nevent loop and calls the `OnReady` callback in a separate goroutine.\nFrom this point forward it is safe to call gallium functions from any\ngoroutine.\n\n### Shared libraries and linking issues\n\nGallium is based on Chromium, which it accesses via `Gallium.framework`.\nThat framework in turn contains `libchromiumcontent.dylib`, which is a \nshared library containing the chromium content module and is distributed\nin binary form by the same folks responsible for the excellent Electron\nframework. When you build your Go executable, the directives in\n`Gallium.framework` instruct the linker to set up the executable to look for\n`Gallium.framework` in two places at runtime:\n 1. `\u003cdir containing executable\u003e/../Frameworks/Gallium.framework`: this\n     will resolve correctly if you choose to build and run your app as a\n     bundle (and also means you can distribute the app bundle as a\n     self-contained unit).\n 2. `$GOPATH/src/github.com/alexflint/dist/Gallium.framework`: this will\n     resolve if you choose to run your executable directly.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexflint%2Fgallium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexflint%2Fgallium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexflint%2Fgallium/lists"}