Example #1
0
// moveToProperHead is used to make sure a newly managed client is placed on
// the correct monitor.
//
// Before adding the client into our data structures, we should first
// make sure it's located on the right head. We do this by finding where
// it *is* placed and convert it into the coordinate space of where it
// *should* be placed.
//
// Note that presumedWorkspace MUST be visible.
func (c *Client) moveToProperHead(presumedWorkspace workspace.Workspacer) {
	if c.PrimaryType() != TypeNormal {
		return
	}
	if _, ok := presumedWorkspace.(*workspace.Sticky); ok {
		return
	}
	if !presumedWorkspace.IsVisible() {
		return
	}

	oughtHeadGeom := presumedWorkspace.HeadGeom()
	cgeom := c.frame.Geom()
	if wrk := wm.Heads.FindMostOverlap(cgeom); wrk != nil {
		if wrk != presumedWorkspace {
			isHeadGeom := wrk.HeadGeom()
			ngeom := heads.Convert(cgeom, isHeadGeom, oughtHeadGeom)
			c.MoveResizeValid(
				ngeom.X(), ngeom.Y(), ngeom.Width(), ngeom.Height())
		}
	} else {
		// If we're here, that means the client *ought* to belong to a visible
		// workspace but it could not be found to overlap with *any* visible
		// workspace. Therefore, just use a hammer and move it to the root
		// coordinates of the presumed workspace.
		geom := presumedWorkspace.Geom()
		c.Move(geom.X(), geom.Y())
	}
}
Example #2
0
func (c *Client) maybeInitPlace(presumedWorkspace workspace.Workspacer) {
	// This is a hack. Before a client gets sucked into some layout, we
	// always want to have some floating state to fall back on to. However,
	// by the time we're "allowed" to save the client's state, it will have
	// already been placed in the hands of some layout---which may or may
	// not be floating. So we inject our own state forcefully here.
	defer func() {
		wrk := presumedWorkspace
		if wrk.IsVisible() {
			c.states["last-floating"] = clientState{
				geom:      xrect.New(xrect.Pieces(c.frame.Geom())),
				headGeom:  xrect.New(xrect.Pieces(wrk.HeadGeom())),
				frame:     c.frame,
				maximized: c.maximized,
			}
		} else if wm.Startup {
			// This is a bit tricky. If the window manager is starting up and
			// has to manage existing clients, then we need to find which
			// head the client is on and save its state. This is so future
			// workspace switches will be able to place the client
			// appropriately.
			// (This is most common on a Wingo restart.)
			// We refer to detected workspace as "fake" because the client
			// isn't on a visible workspace (see above), and therefore the
			// visible workspace returned by FindMostOverlap *cannot* contain
			// this client. Therefore, we're only using the fake workspace
			// to get the geometry.
			// (This would make more sense if FindMostOverlap returned a head
			// geometry, but it turns out that a workspace geometry is more
			// useful.)
			cgeom := c.frame.Geom()
			if fakeWrk := wm.Heads.FindMostOverlap(cgeom); fakeWrk != nil {
				c.states["last-floating"] = clientState{
					geom:      xrect.New(xrect.Pieces(c.frame.Geom())),
					headGeom:  xrect.New(xrect.Pieces(fakeWrk.HeadGeom())),
					frame:     c.frame,
					maximized: c.maximized,
				}
			}
		}
	}()

	// Any client that isn't normal doesn't get placed.
	// Let it do what it do, baby.
	if c.PrimaryType() != TypeNormal {
		return
	}

	// If it's sticky, let it do what it do.
	if _, ok := presumedWorkspace.(*workspace.Sticky); ok {
		return
	}

	// Transients never get placed.
	if c.transientFor != nil {
		return
	}

	// If a user/program position is specified, do not place.
	if c.nhints.Flags&icccm.SizeHintUSPosition > 0 ||
		c.nhints.Flags&icccm.SizeHintPPosition > 0 {

		return
	}

	// We're good, do a placement unless we're already mapped or on a
	// hidden workspace..
	if !presumedWorkspace.IsVisible() || !c.isAttrsUnmapped() {
		return
	}
	w := presumedWorkspace.(*workspace.Workspace)
	w.LayoutFloater().InitialPlacement(c)
}