Beispiel #1
0
func (c *Client) Focused() {
	c.attnStop()
	c.frame.Active()
	c.state = frame.Active
	focus.SetFocus(c)
	ewmh.ActiveWindowSet(wm.X, c.Id())
	c.addState("_NET_WM_STATE_FOCUSED")

	event.Notify(event.FocusedClient{c.Id()})
	event.Notify(event.ChangedActiveClient{c.Id()})
	c.FireHook(hook.Focused)
}
Beispiel #2
0
func (c *Client) Unfocused() {
	wasFocused := c.state == frame.Active

	c.frame.Inactive()
	c.state = frame.Inactive
	ewmh.ActiveWindowSet(wm.X, 0)
	c.removeState("_NET_WM_STATE_FOCUSED")

	if wasFocused {
		event.Notify(event.UnfocusedClient{c.Id()})
		event.Notify(event.ChangedActiveClient{0})
		c.FireHook(hook.Unfocused)
	}
}
Beispiel #3
0
func (c *Client) refreshName() {
	var newName string

	defer func() {
		if newName != c.name {
			c.name = newName
			c.frames.full.UpdateTitle()
			c.prompts.updateName()
			ewmh.WmVisibleNameSet(wm.X, c.Id(), c.name)

			event.Notify(event.ChangedClientName{c.Id()})
		}
	}()

	newName, _ = ewmh.WmNameGet(wm.X, c.Id())
	if len(newName) > 0 {
		return
	}

	newName, _ = icccm.WmNameGet(wm.X, c.Id())
	if len(newName) > 0 {
		return
	}

	newName = "Unnamed Window"
}
Beispiel #4
0
func (wrk *Workspace) AutoCycle() {
	if wrk.State == AutoTiling {
		wrk.curAutoTiler = (wrk.curAutoTiler + 1) % len(wrk.autoTilers)
		wrk.LayoutAutoTiler().Place()

		event.Notify(event.ChangedLayout{wrk.Name})
	}
}
Beispiel #5
0
func ewmhDesktopNames() {
	names := make([]string, len(Heads.Workspaces.Wrks))
	for i, wrk := range Heads.Workspaces.Wrks {
		names[i] = wrk.Name
	}
	ewmh.DesktopNamesSet(X, names)

	event.Notify(event.ChangedWorkspaceNames{})
}
Beispiel #6
0
func (c *Client) Map() {
	if c.IsMapped() {
		return
	}
	c.win.Map()
	c.frame.Map()
	icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateNormal})

	event.Notify(event.MappedClient{c.Id()})
}
Beispiel #7
0
func ewmhVisibleDesktops() {
	visibles := Heads.VisibleWorkspaces()
	desks := make([]uint, len(visibles))
	for i, wrk := range visibles {
		desks[i] = uint(workspaceIndex(wrk))
	}
	ewmh.VisibleDesktopsSet(X, desks)

	event.Notify(event.ChangedVisibleWorkspace{})
}
Beispiel #8
0
func (c *Client) Unmap() {
	if !c.IsMapped() {
		return
	}
	c.unmapIgnore++
	c.frame.Unmap()
	c.win.Unmap()
	icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateIconic})

	event.Notify(event.UnmappedClient{c.Id()})
}
Beispiel #9
0
func RemoveWorkspace(wrk *workspace.Workspace) error {
	if len(Heads.Workspaces.Wrks) == Heads.NumHeads() {
		return fmt.Errorf("Cannot have fewer workspaces than active monitors.")
	}
	if len(wrk.Clients) > 0 {
		return fmt.Errorf("Non-empty workspace '%s' cannot be removed.", wrk)
	}
	Heads.RemoveWorkspace(wrk)

	ewmhDesktopNames()
	ewmhNumberOfDesktops()
	ewmhVisibleDesktops()
	Heads.EwmhWorkarea()
	event.Notify(event.RemovedWorkspace{wrk.Name})
	return nil
}
Beispiel #10
0
func AddWorkspace(name string) error {
	if len(name) == 0 {
		return fmt.Errorf("workspaces must have a name of length at least one.")
	}
	if Heads.Workspaces.Find(name) != nil {
		return fmt.Errorf("a workspace with name '%s' already exists.", name)
	}
	wrk := Heads.NewWorkspace(name)
	wrk.PromptSlctGroup = Prompts.Slct.AddGroup(wrk)
	wrk.PromptSlctItem = Prompts.Slct.AddChoice(wrk)

	Heads.AddWorkspace(wrk)

	ewmhDesktopNames()
	ewmhNumberOfDesktops()
	ewmhVisibleDesktops()
	Heads.EwmhWorkarea()

	event.Notify(event.AddedWorkspace{wrk.Name})
	return nil
}
Beispiel #11
0
func (c *Client) unmanage() {
	wm.X.Grab()
	defer wm.X.Ungrab()

	go func() {
		c.frames.destroy()
		c.prompts.destroy()
	}()

	logger.Message.Printf("Unmanaging client: %s", c)

	infoWorkspace := c.workspace.String()
	infoClass := c.Class().Class
	infoInstance := c.Class().Instance
	infoName := c.Name()

	c.frame.Unmap()
	c.win.Detach()
	icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateWithdrawn})
	focus.Remove(c)
	wm.FocusFallback()
	stack.Remove(c)
	c.workspace.Remove(c)
	wm.RemoveClient(c)
	c.attnStop()
	xproto.ChangeSaveSetChecked(
		wm.X.Conn(), xproto.SetModeDelete, c.Id()).Check()

	if c.hadStruts {
		wm.Heads.ApplyStruts(wm.Clients)
	}

	event.Notify(event.UnmanagedClient{
		Id:        c.Id(),
		Name:      infoName,
		Workspace: infoWorkspace,
		Class:     infoClass,
		Instance:  infoInstance,
	})
}
Beispiel #12
0
func (wrk *Workspace) LayoutStateSet(state int) {
	if !wrk.IsVisible() {
		return
	}

	if state == wrk.State {
		// If it's an AutoTiler, then just call Place again.
		if wrk.State == AutoTiling {
			wrk.LayoutAutoTiler().Place()
		}
		return
	}

	// First undo the current layout.
	switch wrk.State {
	case Floating:
		wrk.LayoutFloater().Save()
		wrk.LayoutFloater().Unplace()
	case AutoTiling:
		wrk.LayoutAutoTiler().Unplace()
	default:
		panic("Layout state not implemented.")
	}

	// Now apply the new layout.
	switch state {
	case Floating:
		wrk.State = state
		wrk.LayoutFloater().Place()
		wrk.LayoutFloater().Reposition()
	case AutoTiling:
		wrk.State = state
		wrk.LayoutAutoTiler().Place()
	default:
		panic("Layout state not implemented.")
	}

	event.Notify(event.ChangedLayout{wrk.Name})
}
Beispiel #13
0
func New(id xproto.Window) *Client {
	wm.X.Grab()
	defer wm.X.Ungrab()

	// If this is an override redirect, skip...
	attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), id).Reply()
	if err != nil {
		logger.Warning.Printf("Could not get window attributes for '%d': %s",
			id, err)
	} else {
		if attrs.OverrideRedirect {
			logger.Message.Printf(
				"Not managing override redirect window %d", id)
			return nil
		}
	}

	if client := wm.FindManagedClient(id); client != nil {
		logger.Message.Printf("Already managing client: %s", client)
		return nil
	}

	win := xwindow.New(wm.X, id)
	if _, err := win.Geometry(); err != nil {
		logger.Warning.Printf("Could not manage client %d because: %s", id, err)
		return nil
	}

	c := &Client{
		win:         win,
		name:        "N/A",
		state:       frame.Inactive,
		layer:       stack.LayerDefault,
		maximized:   false,
		iconified:   false,
		unmapIgnore: 0,
		floating:    false,
		fullscreen:  false,
		skipTaskbar: false,
		skipPager:   false,
		demanding:   false,
		attnQuit:    make(chan struct{}, 0),
	}

	c.manage()

	// We don't fire the managed hook on startup since it can lead to
	// unintuitive state changes.
	// If someone really wants it, we can add a new "startup_managed" hook
	// or something.
	if !wm.Startup {
		event.Notify(event.ManagedClient{c.Id()})
		c.FireHook(hook.Managed)
	}
	if !c.iconified {
		c.Map()
		if !wm.Startup && c.PrimaryType() == TypeNormal {
			if !wm.Config.Ffm || wm.Config.FfmStartupFocus {
				c.Focus()
			}
		}
	}

	return c
}
Beispiel #14
0
func main() {
	if flagWriteConfig {
		writeConfigFiles()
		os.Exit(0)
	}

	X, err := xgbutil.NewConn()
	if err != nil {
		logger.Error.Println(err)
		logger.Error.Fatalln("Error connecting to X, quitting...")
	}
	defer X.Conn().Close()

	if flagShowSocket {
		showSocketPath(X)
		return
	}

	// Do this first! Attempt to retrieve window manager ownership.
	// This includes waiting for any existing window manager to die.
	// 'own' also sets up handlers for quitting when a window manager tries
	// to replace *us*.
	if err := own(X, flagReplace); err != nil {
		logger.Error.Fatalf(
			"Could not establish window manager ownership: %s", err)
	}

	if len(flagConfigDir) > 0 {
		misc.ConfigPaths.Override = flagConfigDir
	}
	if len(flagDataDir) > 0 {
		misc.DataPaths.Override = flagDataDir
	}
	misc.ReadData()

	keybind.Initialize(X)
	mousebind.Initialize(X)
	focus.Initialize(X)
	stack.Initialize(X)
	cursors.Initialize(X)
	wm.Initialize(X, commands.Env, newHacks())
	hook.Initialize(commands.Env, misc.ConfigFile("hooks.wini"))

	// Initialize event handlers on the root window.
	rootInit(X)

	// Tell everyone what we support.
	setSupported()

	// Start up the IPC command listener.
	go ipc(X)

	// And start up the IPC event notifier.
	go event.Notifier(X, socketFilePath(X))

	// Just before starting the main event loop, check to see if there are
	// any clients that already exist that we should manage.
	manageExistingClients()

	// Now make sure that clients are in the appropriate visible state.
	for _, wrk := range wm.Heads.Workspaces.Wrks {
		if wrk.IsVisible() {
			wrk.Show()
		} else {
			wrk.Hide()
		}
	}
	wm.Heads.ApplyStruts(wm.Clients)

	wm.FocusFallback()
	wm.Startup = false
	pingBefore, pingAfter, pingQuit := xevent.MainPing(X)

	if len(flagCpuProfile) > 0 {
		f, err := os.Create(flagCpuProfile)
		if err != nil {
			logger.Error.Fatalf("%s\n", err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if flagWingoRestarted {
		hook.Fire(hook.Restarted, hook.Args{})
	} else {
		hook.Fire(hook.Startup, hook.Args{})
	}

EVENTLOOP:
	for {
		select {
		case <-pingBefore:
			// Wait for the event to finish processing.
			<-pingAfter
		case f := <-commands.SafeExec:
			commands.SafeReturn <- f()
		case <-pingQuit:
			break EVENTLOOP
		}
	}
	if wm.Restart {
		event.Notify(event.Restarting{})
		for _, client := range wm.Clients {
			c := client.(*xclient.Client)

			if _, ok := c.Frame().(*frame.Full); ok {
				c.FrameNada()
			}
		}
		time.Sleep(1 * time.Second)

		// We need to tell the next invocation of Wingo that it is being
		// *restarted*. (So that we don't refire the startup hook.)
		// Thus, search os.Args for "--wingo-restarted". If it doesn't exist,
		// add it.
		found := false
		for _, arg := range os.Args {
			if strings.ToLower(strings.TrimSpace(arg)) == "--wingo-restarted" {
				found = true
			}
		}
		if !found {
			os.Args = append(os.Args, "--wingo-restarted")
		}
		logger.Message.Println("The user has told us to restart...\n\n\n")
		if err := syscall.Exec(os.Args[0], os.Args, os.Environ()); err != nil {
			logger.Error.Fatalf("Could not exec '%s': %s",
				strings.Join(os.Args, " "), err)
		}
	}
}
Beispiel #15
0
func ewmhCurrentDesktop() {
	ewmh.CurrentDesktopSet(X, uint(workspaceIndex(Workspace())))
	event.Notify(event.ChangedWorkspace{})
}