Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions app/dialogs/shortcuts/shortcuts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ import (

// NewShortcutsDialog creates and returns a new keyboard shortcuts dialog.
func NewShortcutsDialog() schwifty.ShortcutsDialog {
basic := []any{
ShortcutsItemFromAction(gettext.Get("Close"), "win.close"),
ShortcutsItemFromAction(gettext.Get("Quit"), "app.quit"),
}
if item := mainMenuShortcut(); item != nil {
basic = append(basic, item)
}
basic = append(basic,
ShortcutsItemFromAction(gettext.Get("Keyboard Shortcuts"), "app.shortcuts"),
ShortcutsItemFromAction(gettext.Get("Preferences"), "app.preferences"),
)

return ShortcutsDialog(
ShortcutsSection(
ShortcutsItemFromAction(gettext.Get("Close"), "win.close"),
ShortcutsItemFromAction(gettext.Get("Quit"), "app.quit"),
ShortcutsItemFromAction(gettext.Get("Main Menu"), "win.main-menu"),
ShortcutsItemFromAction(gettext.Get("Keyboard Shortcuts"), "app.shortcuts"),
ShortcutsItemFromAction(gettext.Get("Preferences"), "app.preferences"),
).Title(gettext.Get("Basic Shortcuts")),
ShortcutsSection(basic...).Title(gettext.Get("Basic Shortcuts")),
ShortcutsSection(
ShortcutsItemFromAction(gettext.Get("Back"), "win.navigate-back"),
ShortcutsItemFromAction(gettext.Get("Search"), "win.search"),
Expand Down
9 changes: 9 additions & 0 deletions app/dialogs/shortcuts/shortcuts_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build darwin

package shortcuts

import adwbindings "codeberg.org/dergs/tonearm/pkg/schwifty/bindings/adw"

// mainMenuShortcut returns nil on macOS — the in-app hamburger menu (and its
// F10 shortcut) doesn't exist there; the menu lives in NSMainMenu instead.
func mainMenuShortcut() adwbindings.ShortcutsItem { return nil }
13 changes: 13 additions & 0 deletions app/dialogs/shortcuts/shortcuts_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build !darwin

package shortcuts

import (
adwbindings "codeberg.org/dergs/tonearm/pkg/schwifty/bindings/adw"
. "codeberg.org/dergs/tonearm/pkg/schwifty/syntax"
"github.com/0skillallluck/scanline/internal/gettext"
)

func mainMenuShortcut() adwbindings.ShortcutsItem {
return ShortcutsItemFromAction(gettext.Get("Main Menu"), "win.main-menu")
}
1 change: 1 addition & 0 deletions app/windows/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func NewWindow(app *adw.Application, appCtx *appctx.AppContext) *Window {
}

window.installAppActions()
window.installNativeMenubar()

if appCtx.Manager.HasAccounts() {
window.showMainContent()
Expand Down
32 changes: 31 additions & 1 deletion app/windows/main_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,37 @@ func (w *Window) installAppActions() {
}))
w.AddAction(closeAction)
w.GetApplication().SetAccelsForAction("win.close", []string{accels.PrimaryMod + "w"})

minimizeAction := gio.NewSimpleAction("minimize", nil)
minimizeAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
w.Minimize()
}))
w.AddAction(minimizeAction)
w.GetApplication().SetAccelsForAction("win.minimize", []string{accels.PrimaryMod + "m"})

zoomAction := gio.NewSimpleAction("zoom", nil)
zoomAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
if w.IsMaximized() {
w.Unmaximize()
} else {
w.Maximize()
}
}))
w.AddAction(zoomAction)

bringAllAction := gio.NewSimpleAction("bring-all-to-front", nil)
bringAllAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
for node := w.GetApplication().GetWindows(); node != nil; node = node.Next {
gtk.WindowNewFromInternalPtr(node.Data).Present()
}
}))
w.GetApplication().Application.AddAction(bringAllAction)

// Bind accels for window actions referenced by the macOS menubar so the
// shortcut labels render — installWindowActions runs after the menubar
// is built, which is too late on macOS where NSMenu bakes in accels at
// conversion time.
w.GetApplication().SetAccelsForAction("win.search", []string{accels.PrimaryMod + "f"})
}

// installWindowActions installs actions that only make sense when main content is shown:
Expand Down Expand Up @@ -81,7 +112,6 @@ func (w *Window) installWindowActions() {
}
}))
w.AddAction(searchAction)
w.GetApplication().SetAccelsForAction("win.search", []string{accels.PrimaryMod + "f"})

routeMovieAction := gio.NewSimpleAction("route.movie", glib.NewVariantType("s"))
routeMovieAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
Expand Down
33 changes: 6 additions & 27 deletions app/windows/main_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"codeberg.org/dergs/tonearm/pkg/schwifty/state"
. "codeberg.org/dergs/tonearm/pkg/schwifty/syntax"
"codeberg.org/puregotk/puregotk/v4/adw"
"codeberg.org/puregotk/puregotk/v4/gio"
"codeberg.org/puregotk/puregotk/v4/gtk"
"github.com/0skillallluck/scanline/app/components"
"github.com/0skillallluck/scanline/app/preference"
Expand Down Expand Up @@ -41,15 +40,6 @@ func updateDecorationLayout() {
}
}

func (w *Window) buildMainMenu() *gio.Menu {
mainMenu := gio.NewMenu()
mainMenu.Append(gettext.Get("Select Sources"), "win.select-sources")
mainMenu.Append(gettext.Get("Preferences"), "app.preferences")
mainMenu.Append(gettext.Get("Keyboard Shortcuts"), "app.shortcuts")
mainMenu.Append(gettext.Get("About Scanline"), "app.about")
return mainMenu
}

func iconForSectionType(sectionType string) string {
switch sectionType {
case "movie":
Expand Down Expand Up @@ -181,8 +171,6 @@ func (w *Window) buildContentHeader() *gtk.Widget {
})
})

mainMenu := w.buildMainMenu()

gtkSettings := gtk.SettingsGetDefault()
gtkSettings.ConnectSignal("notify::gtk-decoration-layout", new(func() {
updateDecorationLayout()
Expand All @@ -191,7 +179,7 @@ func (w *Window) buildContentHeader() *gtk.Widget {

hasSources := len(mgr.EnabledSources()) > 0

headerbar := HeaderBar().
headerbarBuilder := HeaderBar().
BindDecorationLayout(decorationLayoutState).
CenteringPolicy(adw.CenteringPolicyStrictValue).
PackStart(
Expand Down Expand Up @@ -251,20 +239,11 @@ func (w *Window) buildContentHeader() *gtk.Widget {
}))
}),
).
TitleWidget(defaultToolbar).
PackEnd(
MenuButton().
IconName("open-menu-symbolic").
MenuModel(&mainMenu.MenuModel).
TooltipText(gettext.Get("Main Menu")).ConnectConstruct(func(mb *gtk.MenuButton) {
menuAction := gio.NewSimpleAction("main-menu", nil)
menuAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
mb.Popup()
}))
w.AddAction(menuAction)
w.GetApplication().SetAccelsForAction("win.main-menu", []string{"F10"})
}),
).
TitleWidget(defaultToolbar)

headerbarBuilder = w.packMainMenuButton(headerbarBuilder)

headerbar := headerbarBuilder.
ConnectDestroy(func(w gtk.Widget) {
gtkSettings.Unref()
})()
Expand Down
56 changes: 56 additions & 0 deletions app/windows/menubar_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//go:build darwin

package windows

import (
adwbindings "codeberg.org/dergs/tonearm/pkg/schwifty/bindings/adw"
"codeberg.org/puregotk/puregotk/v4/gio"
"codeberg.org/puregotk/puregotk/v4/glib"
"github.com/0skillallluck/scanline/internal/gettext"
)

// installNativeMenubar wires the application's menu model into NSMainMenu via
// gtk_application_set_menubar. GTK4's macOS backend auto-generates the
// application menu (About / Settings / Hide / Quit) from the standard Cocoa
// items, so we only contribute File / Edit / Help here — adding a "Scanline"
// submenu would render as a duplicate after the auto-generated app menu.
func (w *Window) installNativeMenubar() {
menubar := gio.NewMenu()

fileMenu := gio.NewMenu()
fileMenu.Append(gettext.Get("Select Sources…"), "win.select-sources")
appendSection(fileMenu, gettext.Get("Close Window"), "win.close")
menubar.AppendSubmenu(gettext.Get("File"), &fileMenu.MenuModel)

editMenu := gio.NewMenu()
editMenu.Append(gettext.Get("Find"), "win.search")
menubar.AppendSubmenu(gettext.Get("Edit"), &editMenu.MenuModel)

windowMenu := gio.NewMenu()
windowMenu.Append(gettext.Get("Minimize"), "win.minimize")
windowMenu.Append(gettext.Get("Zoom"), "win.zoom")
appendSection(windowMenu, gettext.Get("Bring All to Front"), "app.bring-all-to-front")
appendSection(windowMenu, gettext.Get("Close Window"), "win.close")
// gtk-macos-special=window-submenu opts the submenu into AppKit's native
// Window menu management (open-window list, standard window items).
windowItem := gio.NewMenuItemSubmenu(gettext.Get("Window"), &windowMenu.MenuModel)
windowItem.SetAttributeValue("gtk-macos-special", glib.NewVariantString("window-submenu"))
menubar.AppendItem(windowItem)

helpMenu := gio.NewMenu()
helpMenu.Append(gettext.Get("About Scanline"), "app.about")
helpMenu.Append(gettext.Get("Keyboard Shortcuts"), "app.shortcuts")
menubar.AppendSubmenu(gettext.Get("Help"), &helpMenu.MenuModel)

w.GetApplication().SetMenubar(&menubar.MenuModel)
}

func (w *Window) packMainMenuButton(b adwbindings.HeaderBar) adwbindings.HeaderBar {
return b
}

func appendSection(parent *gio.Menu, label, action string) {
section := gio.NewMenu()
section.Append(label, action)
parent.AppendSection("", &section.MenuModel)
}
39 changes: 39 additions & 0 deletions app/windows/menubar_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//go:build !darwin

package windows

import (
adwbindings "codeberg.org/dergs/tonearm/pkg/schwifty/bindings/adw"
. "codeberg.org/dergs/tonearm/pkg/schwifty/syntax"
"codeberg.org/puregotk/puregotk/v4/gio"
"codeberg.org/puregotk/puregotk/v4/gtk"
"github.com/0skillallluck/scanline/internal/gettext"
)

func (w *Window) installNativeMenubar() {}

func (w *Window) buildMainMenu() *gio.Menu {
mainMenu := gio.NewMenu()
mainMenu.Append(gettext.Get("Select Sources"), "win.select-sources")
mainMenu.Append(gettext.Get("Preferences"), "app.preferences")
mainMenu.Append(gettext.Get("Keyboard Shortcuts"), "app.shortcuts")
mainMenu.Append(gettext.Get("About Scanline"), "app.about")
return mainMenu
}

func (w *Window) packMainMenuButton(b adwbindings.HeaderBar) adwbindings.HeaderBar {
mainMenu := w.buildMainMenu()
return b.PackEnd(
MenuButton().
IconName("open-menu-symbolic").
MenuModel(&mainMenu.MenuModel).
TooltipText(gettext.Get("Main Menu")).ConnectConstruct(func(mb *gtk.MenuButton) {
menuAction := gio.NewSimpleAction("main-menu", nil)
menuAction.ConnectActivate(new(func(action gio.SimpleAction, parameter uintptr) {
mb.Popup()
}))
w.AddAction(menuAction)
w.GetApplication().SetAccelsForAction("win.main-menu", []string{"F10"})
}),
)
}
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func init() {
}

func main() {
glib.SetApplicationName("Scanline")
glib.SetPrgname("Scanline")

application := adw.NewApplication("dev.skillless.Scanline", gio.GApplicationDefaultFlagsValue)
defer application.Unref()
application.ConnectActivate(new(app.OnActivate(application)))
Expand Down