Package focus

import "github.com/BurntSushi/wingo/focus"
Overview
Index

Overview ▾

package focus is responsible for maintaining a stack of all focusable clients in Wingo. It also implements focus protocols defined by the ICCCM, including the WM_TAKE_FOCUS protocol.

Variables

var (
    // A global representing the X connection.
    X *xgbutil.XUtil

    // All of the clients tracked by the focus package.
    Clients []Client
)
var (
    // A map from mode constants to human readable strings.
    // For the deets:
    // http://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html
    Modes = map[byte]string{
        xproto.NotifyModeNormal:       "NotifyNormal",
        xproto.NotifyModeGrab:         "NotifyGrab",
        xproto.NotifyModeUngrab:       "NotifyUngrab",
        xproto.NotifyModeWhileGrabbed: "NotifyWhileGrabbed",
    }

    // A map from detail constants to human readable strings.
    // For the deets:
    // http://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html
    Details = map[byte]string{
        xproto.NotifyDetailAncestor:         "NotifyAncestor",
        xproto.NotifyDetailVirtual:          "NotifyVirtual",
        xproto.NotifyDetailInferior:         "NotifyInferior",
        xproto.NotifyDetailNonlinear:        "NotifyNonlinear",
        xproto.NotifyDetailNonlinearVirtual: "NotifyNonlinearVirtual",
        xproto.NotifyDetailPointer:          "NotifyPointer",
        xproto.NotifyDetailPointerRoot:      "NotifyPointerRoot",
        xproto.NotifyDetailNone:             "NotifyNone",
    }
)

func Fallback

func Fallback(focusable func(c Client) bool)

Fallback determines which client in the focus stack should be focused, and asks for it to be focused. The list of possible clients to be focused is filtered by the predicate focusable.

This should be called after state changes (like when the current workspace is changed).

If no focusable client is found, Root() is called.

func Focus

func Focus(c Client)

Focus will speak the proper X mumbo jumbo to send input focus to the specified client. This is the appropriate function to call whenever you want to focus any particular client.

Focus has no effect if this is called on a client that was not added to the focus stack with InitialAdd. Focus also has no effect if the client cannot handle input focus (like `xclock` or `xeyes`).

func InitialAdd

func InitialAdd(c Client)

InitialAdd should be used whenever a client is being entered into the focus stack for the first time. It does NOT focus the client.

func Initialize

func Initialize(xu *xgbutil.XUtil)

Initialize sets up the state for the focus package. It MUST be called before any other functions in the package are used.

func Remove

func Remove(c Client)

Remove removes the specified client from the focus stack.

func Root

func Root()

Root emulates focus of the root window.

N.B. Technically, a special off-screen window maintained by Wingo gets focus, but you won't be able to tell the difference. (I hope.)

func SetFocus

func SetFocus(c Client)

SetFocus moves the given client to the top of the focus stack and does nothing else. This is a way to force the focus stack into a state that has been discovered via Focus{In,Out} events.

TODO(burntsushi): This is a hack. Try to move more of the focus logic into this package.

type Client

type Client interface {
    Id() xproto.Window
    Win() *xwindow.Window

    // Called whenever the client should represent themselves as having
    // the input focus.
    Focused()

    // Called whenever the client should represent themselves as NOT
    // having the input focus.
    Unfocused()

    // Returns true if the client should be considered for focus.
    CanFocus() bool

    // Returns true if the client participates in the WM_TAKE_FOCUS
    // protocol as specified by the ICCCM.
    SendFocusNotify() bool

    // Whatever action needs to occur before the client can accept input
    // focus. (Usually showing its workspace or deiconifying.)
    PrepareForFocus()

    // Whether the client believes it has input focus or not.
    IsActive() bool
}

Client is the minimal implementation necessary for any particular window to be tracked by the focus package.

func Current

func Current() Client

Returns the currently focused client, or nil if no client has focus.

func LastFocused

func LastFocused(focusable func(c Client) bool) Client

LastFocused returns the last client that was focused that satisfies the predicate focusable. This is only used in the commands package to retrieve the active window. (It's a hack to work around the fact that prompts can steal focus, which makes the GetActive command not work properly.)