mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
00c7e6dfb2
If X11 throws an error during screen config get/set, the default error handler at the time will be one which causes a program exit. This splits the error handler registration in xevent into its own call, allowing us to register our error handler earlier on. This results in the safe error handling logic actually being called instead of a full program exit.
139 lines
3.3 KiB
Go
139 lines
3.3 KiB
Go
package desktop
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/kataras/go-events"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/demodesk/neko/internal/config"
|
|
"github.com/demodesk/neko/pkg/types"
|
|
"github.com/demodesk/neko/pkg/xevent"
|
|
"github.com/demodesk/neko/pkg/xinput"
|
|
"github.com/demodesk/neko/pkg/xorg"
|
|
)
|
|
|
|
var mu = sync.Mutex{}
|
|
|
|
type DesktopManagerCtx struct {
|
|
logger zerolog.Logger
|
|
wg sync.WaitGroup
|
|
shutdown chan struct{}
|
|
emmiter events.EventEmmiter
|
|
config *config.Desktop
|
|
screenSize types.ScreenSize // cached screen size
|
|
input xinput.Driver
|
|
}
|
|
|
|
func New(config *config.Desktop) *DesktopManagerCtx {
|
|
var input xinput.Driver
|
|
if config.UseInputDriver {
|
|
input = xinput.NewDriver(config.InputSocket)
|
|
} else {
|
|
input = xinput.NewDummy()
|
|
}
|
|
|
|
return &DesktopManagerCtx{
|
|
logger: log.With().Str("module", "desktop").Logger(),
|
|
shutdown: make(chan struct{}),
|
|
emmiter: events.New(),
|
|
config: config,
|
|
screenSize: config.ScreenSize,
|
|
input: input,
|
|
}
|
|
}
|
|
|
|
func (manager *DesktopManagerCtx) Start() {
|
|
if xorg.DisplayOpen(manager.config.Display) {
|
|
manager.logger.Panic().Str("display", manager.config.Display).Msg("unable to open display")
|
|
}
|
|
|
|
// X11 can throw errors below, and the default error handler exits
|
|
xevent.SetupErrorHandler()
|
|
|
|
xorg.GetScreenConfigurations()
|
|
|
|
screenSize, err := xorg.ChangeScreenSize(manager.config.ScreenSize)
|
|
if err != nil {
|
|
manager.logger.Err(err).
|
|
Str("screen_size", screenSize.String()).
|
|
Msgf("unable to set initial screen size")
|
|
} else {
|
|
// cache screen size
|
|
manager.screenSize = screenSize
|
|
manager.logger.Info().
|
|
Str("screen_size", screenSize.String()).
|
|
Msgf("setting initial screen size")
|
|
}
|
|
|
|
err = manager.input.Connect()
|
|
if err != nil {
|
|
// TODO: fail silently to dummy driver?
|
|
manager.logger.Panic().Err(err).Msg("unable to connect to input driver")
|
|
}
|
|
|
|
// set up event listeners
|
|
xevent.Unminimize = manager.config.Unminimize
|
|
xevent.FileChooserDialog = manager.config.FileChooserDialog
|
|
go xevent.EventLoop(manager.config.Display)
|
|
|
|
// in case it was opened
|
|
if manager.config.FileChooserDialog {
|
|
go manager.CloseFileChooserDialog()
|
|
}
|
|
|
|
manager.OnEventError(func(error_code uint8, message string, request_code uint8, minor_code uint8) {
|
|
manager.logger.Warn().
|
|
Uint8("error_code", error_code).
|
|
Str("message", message).
|
|
Uint8("request_code", request_code).
|
|
Uint8("minor_code", minor_code).
|
|
Msg("X event error occured")
|
|
})
|
|
|
|
manager.wg.Add(1)
|
|
|
|
go func() {
|
|
defer manager.wg.Done()
|
|
|
|
ticker := time.NewTicker(1 * time.Second)
|
|
defer ticker.Stop()
|
|
|
|
const debounceDuration = 10 * time.Second
|
|
|
|
for {
|
|
select {
|
|
case <-manager.shutdown:
|
|
return
|
|
case <-ticker.C:
|
|
xorg.CheckKeys(debounceDuration)
|
|
manager.input.Debounce(debounceDuration)
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (manager *DesktopManagerCtx) OnBeforeScreenSizeChange(listener func()) {
|
|
manager.emmiter.On("before_screen_size_change", func(payload ...any) {
|
|
listener()
|
|
})
|
|
}
|
|
|
|
func (manager *DesktopManagerCtx) OnAfterScreenSizeChange(listener func()) {
|
|
manager.emmiter.On("after_screen_size_change", func(payload ...any) {
|
|
listener()
|
|
})
|
|
}
|
|
|
|
func (manager *DesktopManagerCtx) Shutdown() error {
|
|
manager.logger.Info().Msgf("shutdown")
|
|
|
|
close(manager.shutdown)
|
|
manager.wg.Wait()
|
|
|
|
xorg.DisplayClose()
|
|
return nil
|
|
}
|