// findPresumedWorkspace inspects a client before it is fully managed to // see which workspace it should go to. Basically, if _NET_WM_DESKTOP is // to a valid workspace number, then we grant the request. Otherwise, we use // the current workspace. func (c *Client) findPresumedWorkspace() workspace.Workspacer { d, err := ewmh.WmDesktopGet(wm.X, c.Id()) if err != nil { return wm.Workspace() } if d == 0xFFFFFFFF { return wm.StickyWrk } if d < 0 || d >= uint(len(wm.Heads.Workspaces.Wrks)) { return wm.Workspace() } return wm.Heads.Workspaces.Get(int(d)) }
func (cmd Resize) Run() gribble.Value { return syncRun(func() gribble.Value { w, wok := parseDim(wm.Workspace().Geom(), cmd.Width, false) h, hok := parseDim(wm.Workspace().Geom(), cmd.Height, true) if !wok || !hok { return nil } withClient(cmd.Client, func(c *xclient.Client) { c.EnsureUnmax() c.LayoutResize(w, h) }) return nil }) }
func (cmd Move) Run() gribble.Value { return syncRun(func() gribble.Value { x, xok := parsePos(wm.Workspace().Geom(), cmd.X, false) y, yok := parsePos(wm.Workspace().Geom(), cmd.Y, true) if !xok || !yok { return nil } withClient(cmd.Client, func(c *xclient.Client) { c.EnsureUnmax() c.LayoutMove(x, y) }) return nil }) }
func (c *Client) unstick() { c.sticky = false c.workspace = nil wm.Workspace().Add(c) c.removeState("_NET_WM_STATE_STICKY") }
func (cmd MovePointerRelative) Run() gribble.Value { return syncRun(func() gribble.Value { geom := wm.Workspace().Geom() x, xok := parsePos(geom, cmd.X, false) y, yok := parsePos(geom, cmd.Y, true) if !xok || !yok { return nil } xproto.WarpPointer(wm.X.Conn(), 0, wm.X.RootWin(), 0, 0, 0, 0, int16(geom.X()+x), int16(geom.Y()+y)) return nil }) }
func (cmd MoveRelative) Run() gribble.Value { return syncRun(func() gribble.Value { geom := wm.Workspace().Geom() x, xok := parsePos(geom, cmd.X, false) y, yok := parsePos(geom, cmd.Y, true) if !xok || !yok { return nil } withClient(cmd.Client, func(c *xclient.Client) { c.EnsureUnmax() c.LayoutMove(geom.X()+x, geom.Y()+y) }) return nil }) }
func handleMotionNotify(X *xgbutil.XUtil, ev xevent.MotionNotifyEvent) { qp, err := xproto.QueryPointer(X.Conn(), X.RootWin()).Reply() if err != nil { logger.Warning.Printf("Could not query pointer: %s", err) return } geom := xrect.New(int(qp.RootX), int(qp.RootY), 1, 1) if wrk := wm.Heads.FindMostOverlap(geom); wrk != nil { if wrk != wm.Workspace() { wm.SetWorkspace(wrk, false) wm.FocusFallback() } } }
func (cmd Input) Run() gribble.Value { inputted := make(chan string, 0) response := func(inp *prompt.Input, text string) { inputted <- text inp.Hide() } canceled := func(inp *prompt.Input) { inputted <- "" } geom := wm.Workspace().Geom() if !wm.Prompts.Input.Show(geom, cmd.Label, response, canceled) { return "" } return <-inputted }
func (c *Client) PrepareForFocus() { // There are only two ways a *managed* client is not prepared for focus: // 1) It belongs to any workspace except for the active one. // 2) It is iconified. // It is possible to be both. Check for both and remedy the situation. // We must check for (1) before (2), since a window cannot toggle its // iconification status if its workspace is not the current workspace. if c.workspace != wm.Workspace() { // This isn't applicable if we're sticky. if wrk, ok := c.workspace.(*workspace.Workspace); ok { wm.SetWorkspace(wrk, false) } } if c.iconified { c.IconifyToggle() } }
func (cmd GetWorkspacePrefix) Run() gribble.Value { return syncRun(func() gribble.Value { hasPre := func(wrk *workspace.Workspace, prefix string) bool { return strings.HasPrefix(strings.ToLower(wrk.Name), prefix) } preAndHidden := func(wrk *workspace.Workspace, prefix string) bool { return !wrk.IsVisible() && hasPre(wrk, prefix) } needle := strings.ToLower(cmd.Prefix) cur := wm.Workspace() if hasPre(cur, needle) { past := false for _, wrk := range wm.Heads.Workspaces.Wrks { if past { if preAndHidden(wrk, needle) { return wrk.Name } continue } if wrk == cur { past = true } } // Nothing? Now look for one before 'cur'... for _, wrk := range wm.Heads.Workspaces.Wrks { if wrk == cur { // we've gone too far... return "" } if preAndHidden(wrk, needle) { return wrk.Name } } } else { for _, wrk := range wm.Heads.Workspaces.Wrks { if preAndHidden(wrk, needle) { return wrk.Name } } } return "" }) }
func (cmd GetWorkspace) Run() gribble.Value { return syncRun(func() gribble.Value { return wm.Workspace().Name }) }
func (cmd GetHead) Run() gribble.Value { return syncRun(func() gribble.Value { return wm.Heads.VisibleIndex(wm.Workspace()) }) }
func rootInit(X *xgbutil.XUtil) { var err error // Listen to Root. It is all-important. evMasks := xproto.EventMaskPropertyChange | xproto.EventMaskFocusChange | xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskStructureNotify | xproto.EventMaskSubstructureNotify | xproto.EventMaskSubstructureRedirect if wm.Config.FfmHead { evMasks |= xproto.EventMaskPointerMotion } err = xwindow.New(X, X.RootWin()).Listen(evMasks) if err != nil { logger.Error.Fatalf("Could not listen to Root window events: %s", err) } // Update state when the root window changes size wm.RootGeomChangeFun().Connect(X, wm.Root.Id) // Oblige map request events xevent.MapRequestFun( func(X *xgbutil.XUtil, ev xevent.MapRequestEvent) { xclient.New(ev.Window) }).Connect(X, wm.Root.Id) // Oblige configure requests from windows we don't manage. xevent.ConfigureRequestFun( func(X *xgbutil.XUtil, ev xevent.ConfigureRequestEvent) { // Make sure we aren't managing this client. if wm.FindManagedClient(ev.Window) != nil { return } xwindow.New(X, ev.Window).Configure(int(ev.ValueMask), int(ev.X), int(ev.Y), int(ev.Width), int(ev.Height), ev.Sibling, ev.StackMode) }).Connect(X, wm.Root.Id) xevent.FocusInFun( func(X *xgbutil.XUtil, ev xevent.FocusInEvent) { if ignoreRootFocus(ev.Mode, ev.Detail) { return } if len(wm.Workspace().Clients) == 0 { return } wm.FocusFallback() }).Connect(X, wm.Root.Id) // Listen to Root client message events. This is how we handle all // of the EWMH bullshit. xevent.ClientMessageFun(handleClientMessages).Connect(X, wm.Root.Id) // Check where the pointer is on motion events. If it's crossed a monitor // boundary, switch the focus of the head. if wm.Config.FfmHead { xevent.MotionNotifyFun(handleMotionNotify).Connect(X, wm.Root.Id) } }