diff --git a/desktop/tracker.go b/desktop/tracker.go index bc24bf9..17b18d3 100644 --- a/desktop/tracker.go +++ b/desktop/tracker.go @@ -304,5 +304,12 @@ func (tr *Tracker) isTracked(w xproto.Window) bool { } func (tr *Tracker) isTrackable(w xproto.Window) bool { - return !store.IsHidden(w) && !store.IsModal(w) && !store.IsIgnored(w) && store.IsInsideViewPort(w) + info := store.GetInfo(w) + if info.Class == store.UNKNOWN { + return false + } + + // Check if window is allowed and inside viewport + isAllowed := !store.IsModal(info) && !store.IsHidden(info) && !store.IsFloating(info) && !store.IsPinned(info) && !store.IsIgnored(info) + return isAllowed && store.IsInsideViewPort(w) } diff --git a/store/client.go b/store/client.go index 921c6f4..b45aca4 100644 --- a/store/client.go +++ b/store/client.go @@ -235,12 +235,53 @@ func IsMaximized(w xproto.Window) bool { return false } -func IsHidden(w xproto.Window) bool { +func IsInsideViewPort(w xproto.Window) bool { info := GetInfo(w) if info.Class == UNKNOWN { - return true + return false + } + + // Window dimensions + wGeom, err := xwindow.New(common.X, w).DecorGeometry() + if err != nil { + log.Warn(err) + return false + } + + // Viewport dimensions + vRect := xrect.New(common.ScreenDimensions()) + + // Substract viewport rectangle (r2) from window rectangle (r1) + sRects := xrect.Subtract(wGeom, vRect) + + // If r1 does not overlap r2, then only one rectangle is returned which is equivalent to r1 + isOutsideViewport := false + if len(sRects) == 1 { + isOutsideViewport = reflect.DeepEqual(sRects[0], wGeom) + } + + if isOutsideViewport { + log.Info("Ignore window outside viewport [", info.Class, "]") + } + + return !isOutsideViewport +} + +func IsModal(info Info) bool { + + // Check model dialog windows + for _, state := range info.States { + if state == "_NET_WM_STATE_MODAL" { + log.Info("Ignore modal window", " [", info.Name, "]") + return true + } } + return false +} + +func IsHidden(info Info) bool { + // Check hidden windows for _, state := range info.States { if state == "_NET_WM_STATE_HIDDEN" { @@ -252,16 +293,12 @@ func IsHidden(w xproto.Window) bool { return false } -func IsModal(w xproto.Window) bool { - info := GetInfo(w) - if info.Class == UNKNOWN { - return true - } +func IsFloating(info Info) bool { - // Check model dialog windows + // Check floating state for _, state := range info.States { - if state == "_NET_WM_STATE_MODAL" { - log.Info("Ignore modal window", " [", info.Name, "]") + if state == "_NET_WM_STATE_ABOVE" { + log.Info("Ignore floating window", " [", info.Name, "]") return true } } @@ -269,12 +306,19 @@ func IsModal(w xproto.Window) bool { return false } -func IsIgnored(w xproto.Window) bool { - info := GetInfo(w) - if info.Class == UNKNOWN { +func IsPinned(info Info) bool { + + // Check pinned windows + if info.Desk > common.DeskCount { + log.Info("Ignore pinned window [", info.Class, "]") return true } + return false +} + +func IsIgnored(info Info) bool { + // Check ignored windows for _, s := range common.Config.WindowIgnore { conf_class := s[0] @@ -297,41 +341,3 @@ func IsIgnored(w xproto.Window) bool { return false } - -func IsInsideViewPort(w xproto.Window) bool { - info := GetInfo(w) - if info.Class == UNKNOWN { - return true - } - - // Ignore pinned windows - if info.Desk > common.DeskCount { - log.Info("Ignore pinned window [", info.Class, "]") - return false - } - - // Window dimensions - wGeom, err := xwindow.New(common.X, w).DecorGeometry() - if err != nil { - log.Warn(err) - return false - } - - // Viewport dimensions - vRect := xrect.New(common.ScreenDimensions()) - - // Substract viewport rectangle (r2) from window rectangle (r1) - sRects := xrect.Subtract(wGeom, vRect) - - // If r1 does not overlap r2, then only one rectangle is returned which is equivalent to r1 - isOutsideViewport := false - if len(sRects) == 1 { - isOutsideViewport = reflect.DeepEqual(sRects[0], wGeom) - } - - if isOutsideViewport { - log.Info("Ignore window outside viewport [", info.Class, "]") - } - - return !isOutsideViewport -}