From bfcf382edf0645984133e87b39636a76f2aff63f Mon Sep 17 00:00:00 2001 From: leukipp Date: Sat, 17 Aug 2024 16:56:07 +0200 Subject: [PATCH] feat: move active window to screen #67 --- desktop/layout.go | 1 + desktop/tracker.go | 25 ++++-- input/action.go | 180 ++++++++++++++++++++++++++----------------- input/dbusbinding.go | 8 +- input/traybinding.go | 4 +- store/client.go | 16 +++- store/manager.go | 13 ++++ 7 files changed, 163 insertions(+), 84 deletions(-) diff --git a/desktop/layout.go b/desktop/layout.go index db15726..2a9cd80 100644 --- a/desktop/layout.go +++ b/desktop/layout.go @@ -11,6 +11,7 @@ type Layout interface { RemoveClient(c *store.Client) MakeMaster(c *store.Client) SwapClient(c1 *store.Client, c2 *store.Client) + ActiveClient() *store.Client NextClient() *store.Client PreviousClient() *store.Client IncreaseMaster() diff --git a/desktop/tracker.go b/desktop/tracker.go index efcf88e..e6c0b21 100644 --- a/desktop/tracker.go +++ b/desktop/tracker.go @@ -35,6 +35,13 @@ type Handlers struct { SwapScreen *Handler // Stores client for screen swap } +func (h *Handlers) Reset() { + h.ResizeClient.Reset() + h.MoveClient.Reset() + h.SwapClient.Reset() + h.SwapScreen.Reset() +} + type Handler struct { Dragging bool // Indicates pointer dragging event Source interface{} // Stores moved/resized client @@ -194,6 +201,17 @@ func (tr *Tracker) ClientAt(ws *Workspace, p common.Point) *store.Client { return nil } +func (tr *Tracker) ActiveClient() *store.Client { + c, exists := tr.Clients[store.Windows.Active.Id] + + // Validate client + if !exists { + return nil + } + + return c +} + func (tr *Tracker) unlockClients() { ws := tr.ActiveWorkspace() mg := ws.ActiveLayout().GetManager() @@ -486,7 +504,7 @@ func (tr *Tracker) onStateUpdate(state string, desktop uint, screen uint) { // Update sticky windows for _, c := range tr.Clients { if store.IsSticky(c.Latest) && c.Latest.Location.Desktop != store.Workplace.CurrentDesktop { - c.MoveDesktop(^uint32(0)) + c.MoveToDesktop(^uint32(0)) } } } @@ -494,10 +512,7 @@ func (tr *Tracker) onStateUpdate(state string, desktop uint, screen uint) { if viewportChanged || clientsChanged || focusChanged { // Deactivate handlers - tr.Handlers.ResizeClient.Reset() - tr.Handlers.MoveClient.Reset() - tr.Handlers.SwapClient.Reset() - tr.Handlers.SwapScreen.Reset() + tr.Handlers.Reset() // Unlock clients tr.unlockClients() diff --git a/input/action.go b/input/action.go index cfed61e..e89aebc 100644 --- a/input/action.go +++ b/input/action.go @@ -50,6 +50,8 @@ func ExecuteAction(action string, tr *desktop.Tracker, ws *desktop.Workspace) bo success = ToggleDecoration(tr, ws) case "restore": success = Restore(tr, ws) + case "reset": + success = Reset(tr, ws) case "cycle_next": success = CycleNext(tr, ws) case "cycle_previous": @@ -66,30 +68,32 @@ func ExecuteAction(action string, tr *desktop.Tracker, ws *desktop.Workspace) bo success = MaximizedLayout(tr, ws) case "layout_fullscreen": success = FullscreenLayout(tr, ws) + case "slave_increase": + success = IncreaseSlave(tr, ws) + case "slave_decrease": + success = DecreaseSlave(tr, ws) + case "master_increase": + success = IncreaseMaster(tr, ws) + case "master_decrease": + success = DecreaseMaster(tr, ws) + case "window_next": + success = NextWindow(tr, ws) + case "window_previous": + success = PreviousWindow(tr, ws) + case "screen_next": + success = NextScreen(tr, ws) + case "screen_previous": + success = PreviousScreen(tr, ws) case "master_make": success = MakeMaster(tr, ws) case "master_make_next": success = MakeMasterNext(tr, ws) case "master_make_previous": success = MakeMasterPrevious(tr, ws) - case "master_increase": - success = IncreaseMaster(tr, ws) - case "master_decrease": - success = DecreaseMaster(tr, ws) - case "slave_increase": - success = IncreaseSlave(tr, ws) - case "slave_decrease": - success = DecreaseSlave(tr, ws) case "proportion_increase": success = IncreaseProportion(tr, ws) case "proportion_decrease": success = DecreaseProportion(tr, ws) - case "window_next": - success = NextWindow(tr, ws) - case "window_previous": - success = PreviousWindow(tr, ws) - case "reset": - success = Reset(tr, ws) case "restart": success = Restart(tr) case "exit": @@ -217,6 +221,19 @@ func Restore(tr *desktop.Tracker, ws *desktop.Workspace) bool { return true } +func Reset(tr *desktop.Tracker, ws *desktop.Workspace) bool { + if ws.TilingDisabled() { + return false + } + ws.ResetLayouts() + tr.Tile(ws) + + ui.ShowLayout(ws) + ui.UpdateIcon(ws) + + return true +} + func CycleNext(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false @@ -353,47 +370,30 @@ func FullscreenLayout(tr *desktop.Tracker, ws *desktop.Workspace) bool { return true } -func MakeMaster(tr *desktop.Tracker, ws *desktop.Workspace) bool { - if ws.TilingDisabled() { - return false - } - if c, ok := tr.Clients[store.Windows.Active.Id]; ok { - ws.ActiveLayout().MakeMaster(c) - tr.Tile(ws) - return true - } - - return false -} - -func MakeMasterNext(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func IncreaseSlave(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - c := ws.ActiveLayout().NextClient() - if c == nil { - return false - } - - ws.ActiveLayout().MakeMaster(c) + ws.ActiveLayout().IncreaseSlave() tr.Tile(ws) - return NextWindow(tr, ws) + ui.ShowLayout(ws) + ui.UpdateIcon(ws) + + return true } -func MakeMasterPrevious(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func DecreaseSlave(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - c := ws.ActiveLayout().PreviousClient() - if c == nil { - return false - } - - ws.ActiveLayout().MakeMaster(c) + ws.ActiveLayout().DecreaseSlave() tr.Tile(ws) - return PreviousWindow(tr, ws) + ui.ShowLayout(ws) + ui.UpdateIcon(ws) + + return true } func IncreaseMaster(tr *desktop.Tracker, ws *desktop.Workspace) bool { @@ -422,53 +422,86 @@ func DecreaseMaster(tr *desktop.Tracker, ws *desktop.Workspace) bool { return true } -func IncreaseSlave(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func NextWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - ws.ActiveLayout().IncreaseSlave() - tr.Tile(ws) + c := ws.ActiveLayout().NextClient() + if c == nil { + return false + } - ui.ShowLayout(ws) - ui.UpdateIcon(ws) + store.ActiveWindowSet(store.X, c.Window) return true } -func DecreaseSlave(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func PreviousWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - ws.ActiveLayout().DecreaseSlave() - tr.Tile(ws) + c := ws.ActiveLayout().PreviousClient() + if c == nil { + return false + } - ui.ShowLayout(ws) - ui.UpdateIcon(ws) + store.ActiveWindowSet(store.X, c.Window) return true } -func IncreaseProportion(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func NextScreen(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - ws.ActiveLayout().IncreaseProportion() - tr.Tile(ws) + c := tr.ActiveClient() + if c == nil { + return false + } - return true + screen := int(c.Latest.Location.Screen) + 1 + if screen > int(store.Workplace.ScreenCount)-1 { + return false + } + tr.Handlers.Reset() + + return c.MoveToScreen(uint32(screen)) } -func DecreaseProportion(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func PreviousScreen(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - ws.ActiveLayout().DecreaseProportion() + c := tr.ActiveClient() + if c == nil { + return false + } + + screen := int(c.Latest.Location.Screen) - 1 + if screen < 0 { + return false + } + tr.Handlers.Reset() + + return c.MoveToScreen(uint32(screen)) +} + +func MakeMaster(tr *desktop.Tracker, ws *desktop.Workspace) bool { + if ws.TilingDisabled() { + return false + } + c := ws.ActiveLayout().ActiveClient() + if c == nil { + return false + } + + ws.ActiveLayout().MakeMaster(c) tr.Tile(ws) return true } -func NextWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func MakeMasterNext(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } @@ -477,12 +510,13 @@ func NextWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { return false } - store.ActiveWindowSet(store.X, c.Window) + ws.ActiveLayout().MakeMaster(c) + tr.Tile(ws) - return true + return NextWindow(tr, ws) } -func PreviousWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func MakeMasterPrevious(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } @@ -491,20 +525,28 @@ func PreviousWindow(tr *desktop.Tracker, ws *desktop.Workspace) bool { return false } - store.ActiveWindowSet(store.X, c.Window) + ws.ActiveLayout().MakeMaster(c) + tr.Tile(ws) - return true + return PreviousWindow(tr, ws) } -func Reset(tr *desktop.Tracker, ws *desktop.Workspace) bool { +func IncreaseProportion(tr *desktop.Tracker, ws *desktop.Workspace) bool { if ws.TilingDisabled() { return false } - ws.ResetLayouts() + ws.ActiveLayout().IncreaseProportion() tr.Tile(ws) - ui.ShowLayout(ws) - ui.UpdateIcon(ws) + return true +} + +func DecreaseProportion(tr *desktop.Tracker, ws *desktop.Workspace) bool { + if ws.TilingDisabled() { + return false + } + ws.ActiveLayout().DecreaseProportion() + tr.Tile(ws) return true } diff --git a/input/dbusbinding.go b/input/dbusbinding.go index f3abaf2..23288c3 100644 --- a/input/dbusbinding.go +++ b/input/dbusbinding.go @@ -92,8 +92,7 @@ func (m Methods) WindowToDesktop(id int32, desktop int32) (string, *dbus.Error) // Move window to desktop valid := desktop >= 0 && uint(desktop) < store.Workplace.DesktopCount if c, ok := m.Tracker.Clients[xproto.Window(id)]; ok && valid { - c.MoveDesktop(uint32(desktop)) - success = true + success = c.MoveToDesktop(uint32(desktop)) } // Return result @@ -108,10 +107,7 @@ func (m Methods) WindowToScreen(id int32, screen int32) (string, *dbus.Error) { // Move window to screen valid := screen >= 0 && uint(screen) < store.Workplace.ScreenCount if c, ok := m.Tracker.Clients[xproto.Window(id)]; ok && valid { - p := store.Workplace.Displays.Screens[screen].Geometry.Center() - ewmh.MoveWindow(store.X, c.Window.Id, int(p.X), int(p.Y)) - store.Pointer.Press() - success = true + success = c.MoveToScreen(uint32(screen)) } // Return result diff --git a/input/traybinding.go b/input/traybinding.go index 920a2f7..62e10da 100644 --- a/input/traybinding.go +++ b/input/traybinding.go @@ -27,7 +27,6 @@ var ( ) type Menu struct { - Exit *systray.MenuItem // Exit application Toggle *systray.MenuItem // Toggle checkbox item Decoration *systray.MenuItem // Decoration checkbox item Actions []*systray.MenuItem // Actions for commands @@ -189,9 +188,10 @@ func items(tr *desktop.Tracker) { case "decoration": item = systray.AddMenuItemCheckbox(text, text, common.Config.WindowDecoration) menu.Decoration = item + case "restart": + item = systray.AddMenuItem(text, text) case "exit": item = systray.AddMenuItem(text, text) - menu.Exit = item default: item = systray.AddMenuItem(text, text) menu.Actions = append(menu.Actions, item) diff --git a/store/client.go b/store/client.go index 5d8d655..002eec6 100644 --- a/store/client.go +++ b/store/client.go @@ -195,7 +195,7 @@ func (c *Client) UnMaximize() bool { return true } -func (c *Client) MoveDesktop(desktop uint32) { +func (c *Client) MoveToDesktop(desktop uint32) bool { if desktop == ^uint32(0) { ewmh.WmStateReq(X, c.Window.Id, ewmh.StateAdd, "_NET_WM_STATE_STICKY") } @@ -203,6 +203,18 @@ func (c *Client) MoveDesktop(desktop uint32) { // Set client desktop ewmh.WmDesktopSet(X, c.Window.Id, uint(desktop)) ewmh.ClientEvent(X, c.Window.Id, "_NET_WM_DESKTOP", int(desktop), int(2)) + + return true +} + +func (c *Client) MoveToScreen(screen uint32) bool { + center := Workplace.Displays.Screens[screen].Geometry.Center() + + // Move window and simulate tracker pointer press + ewmh.MoveWindow(X, c.Window.Id, int(center.X), int(center.Y)) + Pointer.Press() + + return true } func (c *Client) MoveWindow(x, y, w, h int) { @@ -278,7 +290,7 @@ func (c *Client) Restore(flag uint8) { // Restore window states if flag == Cached { if IsSticky(c.Cached) { - c.MoveDesktop(^uint32(0)) + c.MoveToDesktop(^uint32(0)) } } diff --git a/store/manager.go b/store/manager.go index 135f846..1019894 100644 --- a/store/manager.go +++ b/store/manager.go @@ -163,6 +163,19 @@ func (mg *Manager) SwapClient(c1 *Client, c2 *Client) { } } +func (mg *Manager) ActiveClient() *Client { + clients := mg.Clients(Stacked) + + // Get active client + for _, c := range clients { + if c.Window.Id == Windows.Active.Id { + return c + } + } + + return nil +} + func (mg *Manager) NextClient() *Client { clients := mg.Clients(Stacked) last := len(clients) - 1