Skip to content

Commit

Permalink
feat: apply edge margin only on primary display
Browse files Browse the repository at this point in the history
  • Loading branch information
leukipp committed Oct 7, 2023
1 parent 9816a90 commit 346a89b
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 37 deletions.
2 changes: 1 addition & 1 deletion store/corner.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func CreateCorner(name string, screenNum uint, x int, y int, w int, h int) *Corn
func CreateCorners() []*Corner {
corners := []*Corner{}

for i, s := range ViewPorts.Screens {
for i, s := range Displays.Screens {
xw, yw, ww, hw := s.Pieces()

// Corner dimensions
Expand Down
144 changes: 108 additions & 36 deletions store/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package store
import (
"time"

"github.com/BurntSushi/xgb/randr"
"github.com/BurntSushi/xgb/xproto"

"github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/ewmh"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/BurntSushi/xgbutil/xinerama"
"github.com/BurntSushi/xgbutil/xprop"
"github.com/BurntSushi/xgbutil/xrect"
"github.com/BurntSushi/xgbutil/xwindow"

"github.com/leukipp/cortile/common"

log "github.com/sirupsen/logrus"
Expand All @@ -25,7 +27,7 @@ var (
CurrentPointer *common.Pointer // Pointer position
ActiveWindow xproto.Window // Current active window
Windows []xproto.Window // List of client windows
ViewPorts Head // Physical connected monitors
Displays Heads // Physical connected displays
Corners []*Corner // Corners for pointer events
)

Expand All @@ -34,9 +36,16 @@ var (
stateCallbacksFun []func(string) // State events callback functions
)

type Heads struct {
Screens []Head // Screen dimensions (full display size)
Desktops []Head // Desktop dimensions (desktop without panels)
}

type Head struct {
Screens xinerama.Heads // Screen size (full monitor size)
Desktops xinerama.Heads // Desktop size (workarea without panels)
Id uint32 // Head output id (display id)
Name string // Head output name (display name)
Primary bool // Head primary flag (primary display)
xrect.Rect // Head dimensions (x/y/width/height)
}

func InitRoot() {
Expand All @@ -49,12 +58,12 @@ func InitRoot() {
CurrentDesk = CurrentDesktopGet(X)
ActiveWindow = ActiveWindowGet(X)
Windows = ClientListStackingGet(X)
ViewPorts = ViewPortsGet(X)
Displays = DisplaysGet(X)
Corners = CreateCorners()

// Attach root events
root := xwindow.New(X, X.RootWin())
root.Listen(xproto.EventMaskPropertyChange)
root.Listen(xproto.EventMaskSubstructureNotify | xproto.EventMaskPropertyChange)
xevent.PropertyNotifyFun(StateUpdate).Connect(X, root.Id)
}

Expand All @@ -66,6 +75,7 @@ func Connect() *xgbutil.XUtil {
if err != nil {
log.Fatal("Connection to X server failed ", err)
}
randr.Init(X.Conn())

// Check ewmh compliance
wm, err := ewmh.GetEwmhWM(X)
Expand Down Expand Up @@ -141,32 +151,37 @@ func ClientListStackingGet(X *xgbutil.XUtil) []xproto.Window {
return windows
}

func ViewPortsGet(X *xgbutil.XUtil) Head {
func DisplaysGet(X *xgbutil.XUtil) Heads {

// Get the geometry of the root window
// Get geometry of root window
rGeom, err := xwindow.New(X, X.RootWin()).Geometry()
if err != nil {
log.Fatal("Error retrieving root geometry ", err)
}

// Get the physical heads
screens := PhysicalHeadsGet(rGeom)
desktops := PhysicalHeadsGet(rGeom)
// Get physical heads
screens := PhysicalHeadsGet(X)
desktops := PhysicalHeadsGet(X)

// Adjust desktops geometry
// Get bounding rects
rects := []xrect.Rect{}
for _, desktop := range desktops {
rects = append(rects, desktop.Rect)
}

// Adjust desktop geometry
for _, win := range Windows {
strut, err := ewmh.WmStrutPartialGet(X, win)
if err != nil {
continue
}

// Apply in place struts to desktops
xrect.ApplyStrut(desktops, uint(rGeom.Width()), uint(rGeom.Height()),
// Apply in place struts to desktop
xrect.ApplyStrut(rects, uint(rGeom.Width()), uint(rGeom.Height()),
strut.Left, strut.Right, strut.Top, strut.Bottom,
strut.LeftStartY, strut.LeftEndY,
strut.RightStartY, strut.RightEndY,
strut.TopStartX, strut.TopEndX,
strut.BottomStartX, strut.BottomEndX)
strut.LeftStartY, strut.LeftEndY, strut.RightStartY, strut.RightEndY,
strut.TopStartX, strut.TopEndX, strut.BottomStartX, strut.BottomEndX,
)
}

// Update screen count
Expand All @@ -175,21 +190,75 @@ func ViewPortsGet(X *xgbutil.XUtil) Head {
log.Info("Screens ", screens)
log.Info("Desktops ", desktops)

return Head{Screens: screens, Desktops: desktops}
return Heads{Screens: screens, Desktops: desktops}
}

func PhysicalHeadsGet(rGeom xrect.Rect) xinerama.Heads {
func PhysicalHeadsGet(X *xgbutil.XUtil) []Head {

// Get screen resources
resources, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply()
if err != nil {
log.Fatal("Error retrieving screen resources ", err)
}

// Get primary output
primary, err := randr.GetOutputPrimary(X.Conn(), X.RootWin()).Reply()
if err != nil {
log.Fatal("Error retrieving primary screen ", err)
}
hasPrimary := false

// Get output heads
heads := []Head{}
biggest := Head{Rect: xrect.New(0, 0, 0, 0)}
for _, output := range resources.Outputs {
oinfo, err := randr.GetOutputInfo(X.Conn(), output, 0).Reply()
if err != nil {
log.Fatal("Error retrieving screen information ", err)
}

// Get the physical heads
heads := xinerama.Heads{rGeom}
if X.ExtInitialized("XINERAMA") {
heads, _ = xinerama.PhysicalHeads(X)
// Ignored screens (disconnected or off)
if oinfo.Connection != randr.ConnectionConnected || oinfo.Crtc == 0 {
continue
}

// Get crtc information (cathode ray tube controller)
cinfo, err := randr.GetCrtcInfo(X.Conn(), oinfo.Crtc, 0).Reply()
if err != nil {
log.Fatal("Error retrieving screen crtc information ", err)
}

// Append output heads
head := Head{
Id: uint32(output),
Name: string(oinfo.Name),
Primary: primary != nil && output == primary.Output,
Rect: xrect.New(
int(cinfo.X),
int(cinfo.Y),
int(cinfo.Width),
int(cinfo.Height),
),
}
heads = append(heads, head)

// Set helper variables
hasPrimary = head.Primary || hasPrimary
if head.Width()*head.Height() > biggest.Rect.Width()*biggest.Rect.Height() {
biggest = head
}
}

// Validate physical heads
if len(heads) == 0 {
log.Warn("Error retrieving screen dimensions")
return ViewPorts.Screens
// Set fallback primary output
if !hasPrimary {
for i, head := range heads {
if head.Id == biggest.Id {
heads[i].Primary = true
log.Info("Using fallback primary screen [", head.Name, "]")
}
}
} else {
log.Info("Using primary screen [", biggest.Name, "]")
}

return heads
Expand All @@ -214,7 +283,7 @@ func PointerGet(X *xgbutil.XUtil) *common.Pointer {
func ScreenNumGet(p *common.Pointer) uint {

// Check if point is inside screen rectangle
for screenNum, rect := range ViewPorts.Screens {
for screenNum, rect := range Displays.Screens {
if common.IsInsideRect(p, rect) {
return uint(screenNum)
}
Expand All @@ -224,18 +293,21 @@ func ScreenNumGet(p *common.Pointer) uint {
}

func DesktopDimensions(screenNum uint) (x, y, w, h int) {
if int(screenNum) >= len(ViewPorts.Desktops) {
if int(screenNum) >= len(Displays.Desktops) {
return
}
desktop := Displays.Desktops[screenNum]

// Get desktop dimensions
x, y, w, h = ViewPorts.Desktops[screenNum].Pieces()
x, y, w, h = desktop.Pieces()

// Add desktop margin
x += common.Config.EdgeMargin[3]
y += common.Config.EdgeMargin[0]
w -= common.Config.EdgeMargin[1] + common.Config.EdgeMargin[3]
h -= common.Config.EdgeMargin[2] + common.Config.EdgeMargin[0]
if desktop.Primary {
x += common.Config.EdgeMargin[3]
y += common.Config.EdgeMargin[0]
w -= common.Config.EdgeMargin[1] + common.Config.EdgeMargin[3]
h -= common.Config.EdgeMargin[2] + common.Config.EdgeMargin[0]
}

return
}
Expand Down Expand Up @@ -273,7 +345,7 @@ func StateUpdate(X *xgbutil.XUtil, e xevent.PropertyNotifyEvent) {
CurrentDesk = CurrentDesktopGet(X)
stateCallbacks(aname)
} else if common.IsInList(aname, []string{"_NET_DESKTOP_LAYOUT", "_NET_DESKTOP_GEOMETRY", "_NET_DESKTOP_VIEWPORT", "_NET_WORKAREA"}) {
ViewPorts = ViewPortsGet(X)
Displays = DisplaysGet(X)
Corners = CreateCorners()
stateCallbacks(aname)
} else if common.IsInList(aname, []string{"_NET_CLIENT_LIST_STACKING"}) {
Expand Down

0 comments on commit 346a89b

Please sign in to comment.