diff options
| author | Přemysl Janouch <p@janouch.name> | 2018-11-01 11:38:17 +0100 | 
|---|---|---|
| committer | Přemysl Janouch <p@janouch.name> | 2018-11-01 11:38:17 +0100 | 
| commit | 056391eecac57bbad667da476741b179d49552b0 (patch) | |
| tree | 97a42940d6e06cf4e393c260c284b27df8684558 /hpcu | |
| parent | f99615c850a0a3401699b79f856c1472ec11c749 (diff) | |
| download | haven-056391eecac57bbad667da476741b179d49552b0.tar.gz haven-056391eecac57bbad667da476741b179d49552b0.tar.xz haven-056391eecac57bbad667da476741b179d49552b0.zip | |
hpcu: the slightest cleanup
Diffstat (limited to 'hpcu')
| -rw-r--r-- | hpcu/main.go | 302 | 
1 files changed, 158 insertions, 144 deletions
| diff --git a/hpcu/main.go b/hpcu/main.go index 6240ef1..3aebb62 100644 --- a/hpcu/main.go +++ b/hpcu/main.go @@ -133,180 +133,194 @@ func requestOwnership(origin *selectionState, time xproto.Timestamp) {  	}  } -func handleEvent(ev nexgb.Event) { -	switch e := ev.(type) { -	case xfixes.SelectionNotifyEvent: -		state, ok := selections[e.Selection] -		if !ok { -			break -		} +func handleXfixesSelectionNotify(e xfixes.SelectionNotifyEvent) { +	state, ok := selections[e.Selection] +	if !ok { +		return +	} -		// Ownership request has been granted, don't ask ourselves for data. -		if e.Owner == wid { -			state.owning = e.SelectionTimestamp -			break -		} +	// Ownership request has been granted, don't ask ourselves for data. +	if e.Owner == wid { +		state.owning = e.SelectionTimestamp +		return +	} -		// This should always be true. -		if state.owning < e.SelectionTimestamp { -			state.owning = 0 -		} +	// This should always be true. +	if state.owning < e.SelectionTimestamp { +		state.owning = 0 +	} -		// Not checking whether we should give up when our current retrieval -		// attempt is interrupted--the timeout mostly solves this. -		if e.Owner == xproto.WindowNone { -			break -		} +	// Not checking whether we should give up when our current retrieval +	// attempt is interrupted--the timeout mostly solves this. +	if e.Owner == xproto.WindowNone { +		return +	} -		// Don't try to process two things at once. Each request gets a few -		// seconds to finish, then we move on, hoping that a property race -		// doesn't commence. Ideally we'd set up a separate queue for these -		// skipped requests and process them later. -		if state.inProgress != 0 && e.Timestamp-state.inProgress < 5000 { -			break -		} +	// Don't try to process two things at once. Each request gets a few +	// seconds to finish, then we move on, hoping that a property race +	// doesn't commence. Ideally we'd set up a separate queue for these +	// skipped requests and process them later. +	if state.inProgress != 0 && e.Timestamp-state.inProgress < 5000 { +		return +	} -		// ICCCM says we should ensure the named property doesn't exist. -		_ = xproto.DeleteProperty(X, e.Window, e.Selection) +	// ICCCM says we should ensure the named property doesn't exist. +	_ = xproto.DeleteProperty(X, e.Window, e.Selection) -		_ = xproto.ConvertSelection(X, e.Window, e.Selection, -			atomUTF8String, e.Selection, e.Timestamp) +	_ = xproto.ConvertSelection(X, e.Window, e.Selection, +		atomUTF8String, e.Selection, e.Timestamp) -		state.inProgress = e.Timestamp -		state.incr = false +	state.inProgress = e.Timestamp +	state.incr = false +} -	case xproto.SelectionNotifyEvent: -		state, ok := selections[e.Selection] -		if e.Requestor != wid || !ok || e.Time != state.inProgress { -			break -		} +func handleSelectionNotify(e xproto.SelectionNotifyEvent) { +	state, ok := selections[e.Selection] +	if e.Requestor != wid || !ok || e.Time != state.inProgress { +		return +	} -		state.inProgress = 0 -		if e.Property == xproto.AtomNone { -			break -		} +	state.inProgress = 0 +	if e.Property == xproto.AtomNone { +		return +	} -		state.buffer = nil -		reply, err := getProperty(e.Requestor, e.Property) -		if err != nil { -			break -		} +	state.buffer = nil +	reply, err := getProperty(e.Requestor, e.Property) +	if err != nil { +		return +	} -		// When you select a lot of text in VIM, it starts the ICCCM -		// INCR mechanism, from which there is no opt-out. -		if reply.Type == atomINCR { -			state.inProgress = e.Time -			state.incr = true -			state.incrFailed = false -		} else if appendText(state, reply) { -			requestOwnership(state, e.Time) -		} +	// When you select a lot of text in VIM, it starts the ICCCM +	// INCR mechanism, from which there is no opt-out. +	if reply.Type == atomINCR { +		state.inProgress = e.Time +		state.incr = true +		state.incrFailed = false +	} else if appendText(state, reply) { +		requestOwnership(state, e.Time) +	} -		_ = xproto.DeleteProperty(X, e.Requestor, e.Property) +	_ = xproto.DeleteProperty(X, e.Requestor, e.Property) +} -	case xproto.PropertyNotifyEvent: -		state, ok := selections[e.Atom] -		if e.Window != wid || e.State != xproto.PropertyNewValue || -			!ok || !state.incr { -			break -		} +func handlePropertyNotify(e xproto.PropertyNotifyEvent) { +	state, ok := selections[e.Atom] +	if e.Window != wid || e.State != xproto.PropertyNewValue || +		!ok || !state.incr { +		return +	} -		reply, err := getProperty(e.Window, e.Atom) -		if err != nil { -			state.incrFailed = true -			break -		} +	reply, err := getProperty(e.Window, e.Atom) +	if err != nil { +		state.incrFailed = true +		return +	} -		if !appendText(state, reply) { -			// We need to keep deleting the property. -			state.incrFailed = true -		} +	if !appendText(state, reply) { +		// We need to keep deleting the property. +		state.incrFailed = true +	} -		if reply.ValueLen == 0 { -			if !state.incrFailed { -				requestOwnership(state, e.Time) -			} -			state.inProgress = 0 -			state.incr = false +	if reply.ValueLen == 0 { +		if !state.incrFailed { +			requestOwnership(state, e.Time)  		} +		state.inProgress = 0 +		state.incr = false +	} -		_ = xproto.DeleteProperty(X, e.Window, e.Atom) +	_ = xproto.DeleteProperty(X, e.Window, e.Atom) -	case xproto.SelectionRequestEvent: -		property := e.Property -		if property == xproto.AtomNone { -			property = e.Target -		} +} -		state, ok := selections[e.Selection] -		if e.Owner != wid || !ok { -			break -		} +func handleSelectionRequest(e xproto.SelectionRequestEvent) { +	property := e.Property +	if property == xproto.AtomNone { +		property = e.Target +	} + +	state, ok := selections[e.Selection] +	if e.Owner != wid || !ok { +		return +	} -		var ( -			typ    xproto.Atom -			format byte -			data   []byte -		) +	var ( +		typ    xproto.Atom +		format byte +		data   []byte +	) -		// XXX: We should also support the MULTIPLE target but it seems to be -		// unimportant and largely abandoned today. -		targets := []xproto.Atom{atomTARGETS, atomTIMESTAMP, atomUTF8String} +	// XXX: We should also support the MULTIPLE target but it seems to be +	// unimportant and largely abandoned today. +	targets := []xproto.Atom{atomTARGETS, atomTIMESTAMP, atomUTF8String} -		switch e.Target { -		case atomTARGETS: -			typ = xproto.AtomAtom -			format = 32 +	switch e.Target { +	case atomTARGETS: +		typ = xproto.AtomAtom +		format = 32 -			data = make([]byte, len(targets)*4) -			for i, atom := range targets { -				nexgb.Put32(data[i*4:], uint32(atom)) -			} +		data = make([]byte, len(targets)*4) +		for i, atom := range targets { +			nexgb.Put32(data[i*4:], uint32(atom)) +		} -		case atomTIMESTAMP: -			typ = xproto.AtomInteger -			format = 32 +	case atomTIMESTAMP: +		typ = xproto.AtomInteger +		format = 32 -			data = make([]byte, 4) -			nexgb.Put32(data, uint32(state.owning)) +		data = make([]byte, 4) +		nexgb.Put32(data, uint32(state.owning)) -		case atomUTF8String: -			typ = atomUTF8String -			format = 8 +	case atomUTF8String: +		typ = atomUTF8String +		format = 8 -			data = []byte(contents) -		} +		data = []byte(contents) +	} -		response := xproto.SelectionNotifyEvent{ -			Time:      e.Time, -			Requestor: e.Requestor, -			Selection: e.Selection, -			Target:    e.Target, -			Property:  xproto.AtomNone, -		} +	response := xproto.SelectionNotifyEvent{ +		Time:      e.Time, +		Requestor: e.Requestor, +		Selection: e.Selection, +		Target:    e.Target, +		Property:  xproto.AtomNone, +	} -		if typ == 0 || len(data) > int(setup.MaximumRequestLength)*4-64 || -			state.owning == 0 || e.Time < state.owning { -			// TODO: Use the INCR mechanism for large data transfers instead -			// of refusing the request, or at least use PropModeAppend. -			// -			// According to the ICCCM we need to set up a queue for concurrent -			// (requestor, selection, target, timestamp) requests that differ -			// only in the target property, and process them in order. The ICCCM -			// has a nice rationale. It seems to only concern INCR. The queue -			// might be a map[(who, what, how, when)][](where, data, offset). -			// -			// NOTE: Even with BigRequests support, it may technically be -			// missing on the particular X server, and XGB copies buffers to yet -			// another buffer, making very large transfers a very bad idea. -		} else if xproto.ChangePropertyChecked(X, xproto.PropModeReplace, -			e.Requestor, property, typ, format, -			uint32(len(data)/int(format/8)), data).Check() == nil { -			response.Property = property -		} +	if typ == 0 || len(data) > int(setup.MaximumRequestLength)*4-64 || +		state.owning == 0 || e.Time < state.owning { +		// TODO: Use the INCR mechanism for large data transfers instead +		// of refusing the request, or at least use PropModeAppend. +		// +		// According to the ICCCM we need to set up a queue for concurrent +		// (requestor, selection, target, timestamp) requests that differ +		// only in the target property, and process them in order. The ICCCM +		// has a nice rationale. It seems to only concern INCR. The queue +		// might be a map[(who, what, how, when)][](where, data, offset). +		// +		// NOTE: Even with BigRequests support, it may technically be +		// missing on the particular X server, and XGB copies buffers to yet +		// another buffer, making very large transfers a very bad idea. +	} else if xproto.ChangePropertyChecked(X, xproto.PropModeReplace, +		e.Requestor, property, typ, format, +		uint32(len(data)/int(format/8)), data).Check() == nil { +		response.Property = property +	} -		_ = xproto.SendEvent(X, false /* propagate */, e.Requestor, -			0 /* event mask */, string(response.Bytes())) +	_ = xproto.SendEvent(X, false /* propagate */, e.Requestor, +		0 /* event mask */, string(response.Bytes())) +} + +func handleXEvent(ev nexgb.Event) { +	switch e := ev.(type) { +	case xfixes.SelectionNotifyEvent: +		handleXfixesSelectionNotify(e) +	case xproto.SelectionNotifyEvent: +		handleSelectionNotify(e) +	case xproto.PropertyNotifyEvent: +		handlePropertyNotify(e) +	case xproto.SelectionRequestEvent: +		handleSelectionRequest(e)  	}  } @@ -345,7 +359,7 @@ func main() {  			return  		}  		if ev != nil { -			handleEvent(ev) +			handleXEvent(ev)  		}  	}  } | 
