Example #1
0
// WMGracefulClose will do all the necessary setup to implement the
// WM_DELETE_WINDOW protocol. This will prevent well-behaving window managers
// from killing your client whenever one of your windows is closed. (Killing
// a client is bad because it will destroy your X connection and any other
// clients you have open.)
// You must provide a callback function that is called when the window manager
// asks you to close your window. (You may provide some means of confirmation
// to the user, i.e., "Do you really want to quit?", but you should probably
// just wrap things up and call DestroyWindow.)
func (w *Window) WMGracefulClose(cb func(w *Window)) {
	// Get the current protocols so we don't overwrite anything.
	prots, _ := icccm.WmProtocolsGet(w.X, w.Id)

	// If WM_DELETE_WINDOW isn't here, add it. Otherwise, move on.
	wmdelete := false
	for _, prot := range prots {
		if prot == "WM_DELETE_WINDOW" {
			wmdelete = true
			break
		}
	}
	if !wmdelete {
		icccm.WmProtocolsSet(w.X, w.Id, append(prots, "WM_DELETE_WINDOW"))
	}

	// Attach a ClientMessage event handler. It will determine whether the
	// ClientMessage is a 'close' request, and if so, run the callback 'cb'
	// provided.
	xevent.ClientMessageFun(
		func(X *xgbutil.XUtil, ev xevent.ClientMessageEvent) {
			if icccm.IsDeleteProtocol(X, ev) {
				cb(w)
			}
		}).Connect(w.X, w.Id)
}
Example #2
0
func (w *Window) handleEvents() {
	var noX int32 = 1<<31 - 1
	noX++
	var lastX, lastY int32 = noX, 0
	var button wde.Button

	downKeys := map[string]bool{}

	for {
		e, err := w.conn.WaitForEvent()

		if err != nil {
			fmt.Println("[go.wde X error] ", err)
			continue
		}

		switch e := e.(type) {

		case xproto.ButtonPressEvent:
			button = button | buttonForDetail(e.Detail)
			var bpe wde.MouseDownEvent
			bpe.Which = buttonForDetail(e.Detail)
			bpe.Where.X = int(e.EventX)
			bpe.Where.Y = int(e.EventY)
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- bpe

		case xproto.ButtonReleaseEvent:
			button = button & ^buttonForDetail(e.Detail)
			var bue wde.MouseUpEvent
			bue.Which = buttonForDetail(e.Detail)
			bue.Where.X = int(e.EventX)
			bue.Where.Y = int(e.EventY)
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- bue

		case xproto.LeaveNotifyEvent:
			var wee wde.MouseExitedEvent
			wee.Where.X = int(e.EventX)
			wee.Where.Y = int(e.EventY)
			if lastX != noX {
				wee.From.X = int(lastX)
				wee.From.Y = int(lastY)
			} else {
				wee.From.X = wee.Where.X
				wee.From.Y = wee.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- wee
		case xproto.EnterNotifyEvent:
			var wee wde.MouseEnteredEvent
			wee.Where.X = int(e.EventX)
			wee.Where.Y = int(e.EventY)
			if lastX != noX {
				wee.From.X = int(lastX)
				wee.From.Y = int(lastY)
			} else {
				wee.From.X = wee.Where.X
				wee.From.Y = wee.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- wee

		case xproto.MotionNotifyEvent:
			var mme wde.MouseMovedEvent
			mme.Where.X = int(e.EventX)
			mme.Where.Y = int(e.EventY)
			if lastX != noX {
				mme.From.X = int(lastX)
				mme.From.Y = int(lastY)
			} else {
				mme.From.X = mme.Where.X
				mme.From.Y = mme.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			if button == 0 {
				w.events <- mme
			} else {
				var mde wde.MouseDraggedEvent
				mde.MouseMovedEvent = mme
				mde.Which = button
				w.events <- mde
			}

		case xproto.KeyPressEvent:
			var ke wde.KeyEvent
			code := keybind.LookupString(w.xu, e.State, e.Detail)
			ke.Key = keyForCode(code)
			w.events <- wde.KeyDownEvent(ke)
			downKeys[ke.Key] = true
			kpe := wde.KeyTypedEvent{
				KeyEvent: ke,
				Glyph:    letterForCode(code),
				Chord:    wde.ConstructChord(downKeys),
			}
			w.events <- kpe

		case xproto.KeyReleaseEvent:
			var ke wde.KeyUpEvent
			ke.Key = keyForCode(keybind.LookupString(w.xu, e.State, e.Detail))
			delete(downKeys, ke.Key)
			w.events <- ke

		case xproto.ConfigureNotifyEvent:
			var re wde.ResizeEvent
			re.Width = int(e.Width)
			re.Height = int(e.Height)
			if re.Width != w.width || re.Height != w.height {
				w.width, w.height = re.Width, re.Height

				w.bufferLck.Lock()
				w.buffer.Destroy()
				w.buffer = xgraphics.New(w.xu, image.Rect(0, 0, re.Width, re.Height))
				w.bufferLck.Unlock()

				w.events <- re
			}

		case xproto.ClientMessageEvent:
			if icccm.IsDeleteProtocol(w.xu, xevent.ClientMessageEvent{&e}) {
				w.events <- wde.CloseEvent{}
			}
		case xproto.DestroyNotifyEvent:
		case xproto.ReparentNotifyEvent:
		case xproto.MapNotifyEvent:
		case xproto.UnmapNotifyEvent:
		case xproto.PropertyNotifyEvent:

		default:
			fmt.Printf("unhandled event: type %T\n%+v\n", e, e)
		}

	}

	close(w.events)
}