diff --git a/internal/config/desktop.go b/internal/config/desktop.go index 8dfe1d61..4a21674d 100644 --- a/internal/config/desktop.go +++ b/internal/config/desktop.go @@ -12,6 +12,8 @@ import ( type Desktop struct { Display string + Unminimize bool + ScreenWidth int ScreenHeight int ScreenRate int16 @@ -23,6 +25,11 @@ func (Desktop) Init(cmd *cobra.Command) error { return err } + cmd.PersistentFlags().Bool("desktop.unminimize", true, "automatically unminimize window when it is minimized") + if err := viper.BindPFlag("desktop.unminimize", cmd.PersistentFlags().Lookup("desktop.unminimize")); err != nil { + return err + } + return nil } @@ -30,6 +37,8 @@ func (s *Desktop) Set() { // Display is provided by env variable s.Display = os.Getenv("DISPLAY") + s.Unminimize = viper.GetBool("desktop.unminimize") + s.ScreenWidth = 1280 s.ScreenHeight = 720 s.ScreenRate = 30 diff --git a/internal/desktop/manager.go b/internal/desktop/manager.go index 906326be..dff9b9f6 100644 --- a/internal/desktop/manager.go +++ b/internal/desktop/manager.go @@ -45,6 +45,7 @@ func (manager *DesktopManagerCtx) Start() { Str("screen_size", fmt.Sprintf("%dx%d@%d", width, height, rate)). Msgf("setting initial screen size") + xevent.Unminimize = manager.config.Unminimize go xevent.EventLoop(manager.config.Display) // In case it was opened diff --git a/pkg/xevent/xevent.c b/pkg/xevent/xevent.c index 38dce306..991f6987 100644 --- a/pkg/xevent/xevent.c +++ b/pkg/xevent/xevent.c @@ -83,7 +83,7 @@ void XEventLoop(char *name) { if (event.type == ClientMessage) { Window window = event.xclient.window; - // check for window manager state change + // check for net window manager state (fullscreen, maximized, etc) if (event.xclient.message_type == XInternAtom(display, "_NET_WM_STATE", 0)) { // see documentation in XWindowManagerStateEvent Atom action = event.xclient.data.l[0]; @@ -122,6 +122,15 @@ void XEventLoop(char *name) { } } + // check for window manager change state (minimize, maximize, etc) + if (event.xclient.message_type == XInternAtom(display, "WM_CHANGE_STATE", 0)) { + int window_state = event.xclient.data.l[0]; + // NormalState - The client's top-level window is viewable. + // IconicState - The client's top-level window is iconic (whatever that means for this window manager). + // WithdrawnState - Neither the client's top-level window nor its icon is visible. + goXEventWMChangeState(display, window, window_state); + } + continue; } diff --git a/pkg/xevent/xevent.go b/pkg/xevent/xevent.go index 3cc6ff0b..91e449e4 100644 --- a/pkg/xevent/xevent.go +++ b/pkg/xevent/xevent.go @@ -15,6 +15,7 @@ import ( ) var Emmiter events.EventEmmiter +var Unminimize bool = false var file_chooser_dialog_window uint32 = 0 func init() { @@ -68,6 +69,17 @@ func goXEventUnmapNotify(window C.Window) { Emmiter.Emit("file-chooser-dialog-closed") } +//export goXEventWMChangeState +func goXEventWMChangeState(display *C.Display, window C.Window, window_state C.ulong) { + // if we just realized that window is minimized and we want it to be unminimized + if window_state != C.NormalState && Unminimize { + // we want to unmap and map the window to force it to redraw + C.XUnmapWindow(display, window) + C.XMapWindow(display, window) + C.XFlush(display) + } +} + //export goXEventError func goXEventError(event *C.XErrorEvent, message *C.char) { Emmiter.Emit("event-error", uint8(event.error_code), C.GoString(message), uint8(event.request_code), uint8(event.minor_code)) diff --git a/pkg/xevent/xevent.h b/pkg/xevent/xevent.h index 95097545..801e0e6e 100644 --- a/pkg/xevent/xevent.h +++ b/pkg/xevent/xevent.h @@ -12,6 +12,7 @@ extern void goXEventCursorChanged(XFixesCursorNotifyEvent event); extern void goXEventClipboardUpdated(); extern void goXEventConfigureNotify(Display *display, Window window, char *name, char *role); extern void goXEventUnmapNotify(Window window); +extern void goXEventWMChangeState(Display *display, Window window, ulong state); extern void goXEventError(XErrorEvent *event, char *message); extern int goXEventActive();