Add machinery for INCR
This commit is contained in:
parent
a376482293
commit
54ad3ebee6
81
v2/claim.go
81
v2/claim.go
@ -9,6 +9,16 @@ import "github.com/jezek/xgbutil/xprop"
|
||||
import "github.com/jezek/xgbutil/xevent"
|
||||
import "github.com/jezek/xgbutil/xwindow"
|
||||
|
||||
const format8bit byte = 8
|
||||
const format16bit byte = 16
|
||||
const format32bit byte = 32
|
||||
|
||||
type claimRequest struct {
|
||||
reader io.ReadSeekCloser
|
||||
ty xproto.Atom // must be "INCR"
|
||||
event xevent.SelectionRequestEvent
|
||||
}
|
||||
|
||||
// Claim represents a claim that a window has on a particular selection.
|
||||
type Claim struct {
|
||||
window *xwindow.Window
|
||||
@ -16,6 +26,8 @@ type Claim struct {
|
||||
selection xproto.Atom
|
||||
timestamp xproto.Timestamp
|
||||
active bool
|
||||
|
||||
requests map[xproto.Atom] claimRequest
|
||||
}
|
||||
|
||||
// NewClaim claims ownership of a specified selection, and allows using data
|
||||
@ -57,6 +69,7 @@ func NewClaim (window *xwindow.Window, selection xproto.Atom, data Data, timesta
|
||||
data: data,
|
||||
selection: selection,
|
||||
timestamp: timestamp,
|
||||
requests: make(map[xproto.Atom] claimRequest),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -165,7 +178,7 @@ func (claim *Claim) HandleSelectionRequest (
|
||||
// send that list to the requestor
|
||||
atomAtom, err := xprop.Atm(claim.window.X, "ATOM")
|
||||
if err != nil { die(); return }
|
||||
claim.fulfillSelectionRequest(data, 32, atomAtom, event)
|
||||
claim.fulfillSelectionRequest(data, format32bit, atomAtom, event)
|
||||
|
||||
default:
|
||||
// respond with data
|
||||
@ -175,7 +188,7 @@ func (claim *Claim) HandleSelectionRequest (
|
||||
data, err := io.ReadAll(reader)
|
||||
reader.Close()
|
||||
if err != nil { die() }
|
||||
claim.fulfillSelectionRequest(data, 8, event.Target, event)
|
||||
claim.fulfillSelectionRequest(data, format8bit, event.Target, event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +199,69 @@ func (claim *Claim) HandlePropertyNotify (
|
||||
connection *xgbutil.XUtil,
|
||||
event xevent.PropertyNotifyEvent,
|
||||
) {
|
||||
// TODO
|
||||
// The selection owner then:
|
||||
// ... Waits between each append for a PropertyNotify (state==Deleted)
|
||||
// event that shows that the requestor has read the data. The reason for
|
||||
// doing this is to limit the consumption of space in the server.
|
||||
|
||||
// FIXME check for state==Deleted
|
||||
// if the request does not exist, the property was either modified in
|
||||
// error or the request has already finished. either way, we simply
|
||||
// exit.
|
||||
request, ok := claim.requests[event.Atom]
|
||||
if !ok { return }
|
||||
|
||||
done := func () {
|
||||
request.reader.Close()
|
||||
delete(claim.requests, request.event.Property)
|
||||
}
|
||||
|
||||
die := func () {
|
||||
done()
|
||||
claim.refuseSelectionRequest(request.event)
|
||||
}
|
||||
|
||||
// FIXME change the length of this if maximum-request-size is smaller
|
||||
buffer := [1024]byte { }
|
||||
size, err := request.reader.Read(buffer[:])
|
||||
if err != nil { die(); return }
|
||||
dataRead := buffer[:size]
|
||||
|
||||
if len(dataRead) > 0 {
|
||||
// there is more data to send
|
||||
|
||||
// ... Appends the data in suitable-size chunks to the same property on
|
||||
// the same window as the selection reply with a type corresponding to
|
||||
// the actual type of the converted selection. The size should be less
|
||||
// than the maximum-request-size in the connection handshake.
|
||||
format := format8bit
|
||||
err = xproto.ChangePropertyChecked (
|
||||
claim.window.X.Conn(),
|
||||
xproto.PropModeAppend, request.event.Requestor,
|
||||
request.event.Property,
|
||||
request.ty, format,
|
||||
uint32(len(dataRead) / (int(format) / 8)), dataRead).Check()
|
||||
if err != nil { die(); return }
|
||||
|
||||
} else {
|
||||
// all data has been sent
|
||||
|
||||
// ... Waits (after the entire data has been transferred to the
|
||||
// server) until a PropertyNotify (state==Deleted) event that
|
||||
// shows that the data has been read by the requestor and then
|
||||
// writes zero-length data to the property.
|
||||
|
||||
format := format8bit
|
||||
err := xproto.ChangePropertyChecked (
|
||||
claim.window.X.Conn(),
|
||||
xproto.PropModeAppend, request.event.Requestor,
|
||||
request.event.Property,
|
||||
request.ty, format,
|
||||
0, nil).Check()
|
||||
if err != nil { die(); return }
|
||||
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
// While the selection claim is active, HandleSelectionClear should be called
|
||||
|
Loading…
Reference in New Issue
Block a user