func (c *Client) handleClientMessage(name string, data []uint32) {
	switch name {
	case "WM_CHANGE_STATE":
		if data[0] == icccm.StateIconic && !c.iconified {
			c.IconifyToggle()
		}
	case "_NET_ACTIVE_WINDOW":
		c.Focus()
		c.Raise()
	case "_NET_CLOSE_WINDOW":
		c.Close()
	case "_NET_MOVERESIZE_WINDOW":
		// The data[0] element contains bit-packed information. See
		// EWMH _NET_MOVERESIZE_WINDOW for the deets.
		gravity := int(data[0] & 0xff)
		xflags := int((data[0] >> 8) & 0xf)
		x, y, w, h := frame.ClientToFrame(c.frame, gravity,
			int(data[1]), int(data[2]), int(data[3]), int(data[4]))
		c.LayoutMROpt(xflags, x, y, w, h)
	case "_NET_RESTACK_WINDOW":
		// We basically treat this as a request to stack the window.
		// We ignore the sibling. Maybe someday we can support that, but eh...
		c.Raise()
	case "_NET_WM_DESKTOP":
		if data[0] == 0xFFFFFFFF {
			c.stick()
			return
		}
		if wrk := wm.Heads.Workspaces.Get(int(data[0])); wrk != nil {
			wrk.Add(c)
		} else {
			logger.Warning.Printf(
				"_NET_WM_DESKTOP ClientMessage: No workspace indexed at '%d' "+
					"exists.", data[0])
		}
	case "_NET_WM_STATE":
		prop1, _ := xprop.AtomName(wm.X, xproto.Atom(data[1]))
		prop2, _ := xprop.AtomName(wm.X, xproto.Atom(data[2]))
		switch data[0] {
		case 0:
			c.updateStates("remove", prop1, prop2)
		case 1:
			c.updateStates("add", prop1, prop2)
		case 2:
			c.updateStates("toggle", prop1, prop2)
		default:
			logger.Warning.Printf(
				"_NET_WM_STATE: Unknown action '%d'.", data[0])
		}
	default:
		logger.Warning.Printf("Unknown ClientMessage for '%s': %s.", c, name)
	}
}
Exemple #2
0
func (a *atomic) PropValAtom(reply *xproto.GetPropertyReply, err error) (string, error) {
	if err != nil {
		return "", err
	}

	if reply.Format != 32 {
		return "", fmt.Errorf("PropValAtom: Expected format 32 but got %d", reply.Format)
	}

	return a.AtomName(xproto.Atom(xgb.Get32(reply.Value)))
}
Exemple #3
0
// TypeRead reads a byte slice into a Type value.
func TypeRead(buf []byte, v *Type) int {
	b := 0

	v.ResourceType = xproto.Atom(xgb.Get32(buf[b:]))
	b += 4

	v.Count = xgb.Get32(buf[b:])
	b += 4

	return b
}
Exemple #4
0
func (a *atomic) PropValAtoms(reply *xproto.GetPropertyReply, err error) ([]string, error) {
	if err != nil {
		return nil, err
	}
	if reply.Format != 32 {
		return nil, fmt.Errorf("PropValAtoms: Expected format 32 but got %d", reply.Format)
	}

	ids := make([]string, reply.ValueLen)
	vals := reply.Value
	for i := 0; len(vals) >= 4; i++ {
		ids[i], err = a.AtomName(xproto.Atom(xgb.Get32(vals)))
		if err != nil {
			return nil, err
		}

		vals = vals[4:]
	}
	return ids, nil
}
// IsFocusProtocol checks whether a ClientMessage event satisfies the
// WM_TAKE_FOCUS protocol.
func IsFocusProtocol(X *xgbutil.XUtil, ev xevent.ClientMessageEvent) bool {
	// Make sure the Format is 32. (Meaning that each data item is
	// 32 bits.)
	if ev.Format != 32 {
		return false
	}

	// Check to make sure the Type atom is WM_PROTOCOLS.
	typeName, err := xprop.AtomName(X, ev.Type)
	if err != nil || typeName != "WM_PROTOCOLS" { // not what we want
		return false
	}

	// Check to make sure the first data item is WM_TAKE_FOCUS.
	protocolType, err := xprop.AtomName(X,
		xproto.Atom(ev.Data.Data32[0]))
	if err != nil || protocolType != "WM_TAKE_FOCUS" {
		return false
	}

	return true
}
Exemple #6
0
func (s *screenImpl) run() {
	for {
		ev, err := s.xc.WaitForEvent()
		if err != nil {
			log.Printf("x11driver: xproto.WaitForEvent: %v", err)
			continue
		}

		noWindowFound := false
		switch ev := ev.(type) {
		case xproto.DestroyNotifyEvent:
			s.mu.Lock()
			delete(s.windows, ev.Window)
			s.mu.Unlock()

		case shm.CompletionEvent:
			s.mu.Lock()
			s.completionKeys = append(s.completionKeys, ev.Sequence)
			s.handleCompletions()
			s.mu.Unlock()

		case xproto.ClientMessageEvent:
			if ev.Type != s.atomWMProtocols || ev.Format != 32 {
				break
			}
			switch xproto.Atom(ev.Data.Data32[0]) {
			case s.atomWMDeleteWindow:
				// TODO.
			case s.atomWMTakeFocus:
				xproto.SetInputFocus(s.xc, xproto.InputFocusParent, ev.Window, xproto.Timestamp(ev.Data.Data32[1]))
			}

		case xproto.ConfigureNotifyEvent:
			if w := s.findWindow(ev.Window); w != nil {
				w.handleConfigureNotify(ev)
			} else {
				noWindowFound = true
			}

		case xproto.ExposeEvent:
			if w := s.findWindow(ev.Window); w != nil {
				// A non-zero Count means that there are more expose events
				// coming. For example, a non-rectangular exposure (e.g. from a
				// partially overlapped window) will result in multiple expose
				// events whose dirty rectangles combine to define the dirty
				// region. Go's paint events do not provide dirty regions, so
				// we only pass on the final X11 expose event.
				if ev.Count == 0 {
					w.handleExpose()
				}
			} else {
				noWindowFound = true
			}

		case xproto.FocusInEvent:
			// TODO: xw = ev.Event
		case xproto.FocusOutEvent:
			// TODO: xw = ev.Event

		case xproto.KeyPressEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleKey(ev.Detail, ev.State, key.DirPress)
			} else {
				noWindowFound = true
			}

		case xproto.KeyReleaseEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleKey(ev.Detail, ev.State, key.DirRelease)
			} else {
				noWindowFound = true
			}

		case xproto.ButtonPressEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirPress)
			} else {
				noWindowFound = true
			}

		case xproto.ButtonReleaseEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirRelease)
			} else {
				noWindowFound = true
			}

		case xproto.MotionNotifyEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, 0, ev.State, mouse.DirNone)
			} else {
				noWindowFound = true
			}
		}

		if noWindowFound {
			log.Printf("x11driver: no window found for event %T", ev)
		}
	}
}
Exemple #7
0
func (s *screenImpl) run() {
	for {
		ev, err := s.xc.WaitForEvent()
		if err != nil {
			log.Printf("x11driver: xproto.WaitForEvent: %v", err)
			continue
		}

		noWindowFound := false
		switch ev := ev.(type) {
		case xproto.DestroyNotifyEvent:
			s.mu.Lock()
			delete(s.windows, ev.Window)
			s.mu.Unlock()

		case shm.CompletionEvent:
			s.handleCompletion(ev)

		case xproto.ClientMessageEvent:
			if ev.Type != s.atomWMProtocols || ev.Format != 32 {
				break
			}
			switch xproto.Atom(ev.Data.Data32[0]) {
			case s.atomWMDeleteWindow:
				// TODO.
			case s.atomWMTakeFocus:
				xproto.SetInputFocus(s.xc, xproto.InputFocusParent, ev.Window, xproto.Timestamp(ev.Data.Data32[1]))
			}

		case xproto.ConfigureNotifyEvent:
			if w := s.findWindow(ev.Window); w != nil {
				w.handleConfigureNotify(ev)
			} else {
				noWindowFound = true
			}

		case xproto.ExposeEvent:
			// TODO: xw = ev.Window
		case xproto.FocusInEvent:
			// TODO: xw = ev.Event
		case xproto.FocusOutEvent:
			// TODO: xw = ev.Event
		case xproto.KeyPressEvent:
			// TODO: xw = ev.Event
		case xproto.KeyReleaseEvent:
			// TODO: xw = ev.Event

		case xproto.ButtonPressEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirPress)
			} else {
				noWindowFound = true
			}

		case xproto.ButtonReleaseEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirRelease)
			} else {
				noWindowFound = true
			}

		case xproto.MotionNotifyEvent:
			if w := s.findWindow(ev.Event); w != nil {
				w.handleMouse(ev.EventX, ev.EventY, 0, ev.State, mouse.DirNone)
			} else {
				noWindowFound = true
			}
		}

		if noWindowFound {
			log.Printf("x11driver: no window found for event %T", ev)
		}
	}
}
Exemple #8
0
func manage(xWin xp.Window, mapRequest bool) {
	callFocus := false
	w := findWindow(func(w *window) bool { return w.xWin == xWin })
	if w == nil {
		wmDeleteWindow, wmTakeFocus := false, false
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMProtocols,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			for v := prop.Value; len(v) >= 4; v = v[4:] {
				switch xp.Atom(u32(v)) {
				case atomWMDeleteWindow:
					wmDeleteWindow = true
				case atomWMTakeFocus:
					wmTakeFocus = true
				}
			}
		}

		transientFor := (*window)(nil)
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMTransientFor,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			if v := prop.Value; len(v) == 4 {
				transientForXWin := xp.Window(u32(v))
				transientFor = findWindow(func(w *window) bool {
					return w.xWin == transientForXWin
				})
			}
		}

		k := screens[0].workspace
		if p, err := xp.QueryPointer(xConn, rootXWin).Reply(); err != nil {
			log.Println(err)
		} else if p != nil {
			k = screenContaining(p.RootX, p.RootY).workspace
		}
		w = &window{
			transientFor: transientFor,
			xWin:         xWin,
			rect: xp.Rectangle{
				X:      offscreenXY,
				Y:      offscreenXY,
				Width:  1,
				Height: 1,
			},
			wmDeleteWindow: wmDeleteWindow,
			wmTakeFocus:    wmTakeFocus,
		}
		f := k.focusedFrame
		previous := k.dummyWindow.link[prev]
		if transientFor != nil {
			previous = transientFor
		} else if f.window != nil {
			previous = f.window
		}
		w.link[next] = previous.link[next]
		w.link[prev] = previous
		w.link[next].link[prev] = w
		w.link[prev].link[next] = w

		if transientFor != nil && transientFor.frame != nil {
			f = transientFor.frame
			f.window, transientFor.frame = nil, nil
		} else if f.window != nil {
			f = k.mainFrame.firstEmptyFrame()
		}
		if f != nil {
			f.window, w.frame = w, f
			callFocus = f == k.focusedFrame
		} else {
			pulseChan <- time.Now()
		}

		check(xp.ChangeWindowAttributesChecked(xConn, xWin, xp.CwEventMask,
			[]uint32{xp.EventMaskEnterWindow | xp.EventMaskStructureNotify},
		))
		w.configure()
		if transientFor != nil {
			transientFor.hasTransientFor = true
			transientFor.configure()
		}
	}
	if mapRequest {
		check(xp.MapWindowChecked(xConn, xWin))
	}
	if callFocus {
		focus(w)
	}
	makeLists()
	pulseChan <- time.Now()
}
Exemple #9
0
func main() {
	// Open the connection to the X server
	X, err := xgb.NewConn()
	if err != nil {
		log.Fatal(err)
	}
	defer X.Close()

	setup := xproto.Setup(X)
	// Get the first screen
	screen := setup.DefaultScreen(X)

	// Replace existing window manager
	wmName := fmt.Sprintf("WM_S%d", X.DefaultScreen)
	managerAtom, err := xproto.InternAtom(X, true, uint16(len(wmName)), wmName).Reply()
	if err != nil {
		log.Fatal(err)
	}

	fakeWindow, _ := xproto.NewWindowId(X)
	xproto.CreateWindow(X, // Connection
		screen.RootDepth, // Depth
		fakeWindow,       // Window Id
		screen.Root,      // Parent Window
		-1000, -1000,     // x, y
		1, 1, // width, height
		0, // border_width
		xproto.WindowClassInputOutput, // class
		screen.RootVisual,             // visual
		xproto.CwEventMask|xproto.CwOverrideRedirect,
		[]uint32{1, xproto.EventMaskPropertyChange}) // masks
	xproto.MapWindow(X, fakeWindow)
	err = xproto.SetSelectionOwnerChecked(X, fakeWindow, managerAtom.Atom, xproto.TimeCurrentTime).Check()
	if err != nil {
		fmt.Println("foo")
		log.Fatal(err)
	}

	arcs := []xproto.Arc{
		{10, 100, 60, 40, 0, 90 << 6},
		{90, 100, 55, 40, 0, 270 << 6}}

	// Create black (foreground) graphic context
	foreground, _ := xproto.NewGcontextId(X)
	mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures)
	values := []uint32{screen.BlackPixel, 0}
	xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values)

	// Ask for our window's Id
	win, _ := xproto.NewWindowId(X)
	winDrawable := xproto.Drawable(win)

	// Create the window
	mask = uint32(xproto.CwBackPixel | xproto.CwEventMask)
	values = []uint32{screen.WhitePixel, xproto.EventMaskExposure}
	xproto.CreateWindow(X, // Connection
		screen.RootDepth, // Depth
		win,              // Window Id
		screen.Root,      // Parent Window
		0, 0,             // x, y
		150, 150, // width, height
		10, // border_width
		xproto.WindowClassInputOutput, // class
		screen.RootVisual,             // visual
		mask, values)                  // masks

	// Map the window on the screen
	xproto.MapWindow(X, win)

	// Obey the window-delete protocol
	tp := "WM_PROTOCOLS"
	prp := "WM_DELETE_WINDOW"
	typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply()
	propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply()

	data := make([]byte, 4)
	xgb.Put32(data, uint32(propertyAtom.Atom))
	xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data)

	// Main loop
	for {
		evt, err := X.WaitForEvent()
		fmt.Printf("An event of type %T occured.\n", evt)

		if evt == nil && err == nil {
			fmt.Println("Exiting....")
			return
		} else if err != nil {
			log.Fatal(err)
		}

		switch event := evt.(type) {
		case xproto.ExposeEvent:
			/* We draw the arcs */
			xproto.PolyArc(X, winDrawable, foreground, arcs)
		case xproto.ClientMessageEvent:
			if len(event.Data.Data32) > 0 {
				data := xproto.Atom(event.Data.Data32[0])
				if data == propertyAtom.Atom {
					return
				} else {
					atomName, _ := xproto.GetAtomName(X, data).Reply()
					fmt.Println(atomName.Name)
				}
			} else {
				atomName, _ := xproto.GetAtomName(X, event.Type).Reply()
				fmt.Println(atomName.Name)
			}
		default:
			/* Unknown event type, ignore it */
		}
	}
	return
}
Exemple #10
0
func main() {
	// Open the connection to the X server
	X, err := xgb.NewConn()
	if err != nil {
		log.Fatal(err)
	}
	defer X.Close()

	// geometric objects
	points := []xproto.Point{
		{10, 10},
		{10, 20},
		{20, 10},
		{20, 20}}

	polyline := []xproto.Point{
		{50, 10},
		{5, 20}, // rest of points are relative
		{25, -20},
		{10, 10}}

	segments := []xproto.Segment{
		{100, 10, 140, 30},
		{110, 25, 130, 60}}

	rectangles := []xproto.Rectangle{
		{10, 50, 40, 20},
		{80, 50, 10, 40}}

	arcs := []xproto.Arc{
		{10, 100, 60, 40, 0, 90 << 6},
		{90, 100, 55, 40, 0, 270 << 6}}

	setup := xproto.Setup(X)
	// Get the first screen
	screen := setup.DefaultScreen(X)

	// Create black (foreground) graphic context
	foreground, _ := xproto.NewGcontextId(X)
	mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures)
	values := []uint32{screen.BlackPixel, 0}
	xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values)

	// Ask for our window's Id
	win, _ := xproto.NewWindowId(X)
	winDrawable := xproto.Drawable(win)

	// Create the window
	mask = uint32(xproto.CwBackPixel | xproto.CwEventMask)
	values = []uint32{screen.WhitePixel, xproto.EventMaskExposure}
	xproto.CreateWindow(X, // Connection
		screen.RootDepth, // Depth
		win,              // Window Id
		screen.Root,      // Parent Window
		0, 0,             // x, y
		150, 150, // width, height
		10, // border_width
		xproto.WindowClassInputOutput, // class
		screen.RootVisual,             // visual
		mask, values)                  // masks

	// Map the window on the screen
	xproto.MapWindow(X, win)

	// Obey the window-delete protocol
	tp := "WM_PROTOCOLS"
	prp := "WM_DELETE_WINDOW"
	typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply()
	propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply()

	// It turns out that we need the window ID as a byte-stream... WTF!!
	// xprop.ChangeProp(xu, win, 8, "WM_NAME", "STRING", ([]byte)(name))
	// ChangeProp(xu *xgbutil.XUtil, win xproto.Window, format byte, prop string, typ string, data []byte)
	data := make([]byte, 4)
	xgb.Put32(data, uint32(propertyAtom.Atom))
	xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data)

	for {
		evt, err := X.WaitForEvent()
		fmt.Printf("An event of type %T occured.\n", evt)

		if evt == nil && err == nil {
			fmt.Println("Exiting....")
			return
		} else if err != nil {
			log.Fatal(err)
		}

		switch event := evt.(type) {
		case xproto.ExposeEvent:
			/* We draw the points */
			xproto.PolyPoint(X, xproto.CoordModeOrigin, winDrawable, foreground, points)

			/* We draw the polygonal line */
			xproto.PolyLine(X, xproto.CoordModePrevious, winDrawable, foreground, polyline)

			/* We draw the segments */
			xproto.PolySegment(X, winDrawable, foreground, segments)

			/* We draw the rectangles */
			xproto.PolyRectangle(X, winDrawable, foreground, rectangles)

			/* We draw the arcs */
			xproto.PolyArc(X, winDrawable, foreground, arcs)
		case xproto.ClientMessageEvent:
			if len(event.Data.Data32) > 0 {
				data := xproto.Atom(event.Data.Data32[0])
				if data == propertyAtom.Atom {
					return
				} else {
					atomName, _ := xproto.GetAtomName(X, data).Reply()
					fmt.Println(atomName.Name)
				}
			} else {
				atomName, _ := xproto.GetAtomName(X, event.Type).Reply()
				fmt.Println(atomName.Name)
			}
		default:
			/* Unknown event type, ignore it */
		}
	}
	return
}