X11SelectionOwner.mesa
Copyright Ó 1990, 1991 by Xerox Corporation. All rights reserved.
Christian Jacobi, November 12, 1990 5:42 pm PST
Christian Jacobi, August 14, 1991 2:02 pm PDT
DIRECTORY Rope, Xl, XTk;
X11SelectionOwner: CEDAR DEFINITIONS ~
BEGIN
Duties of a selection owner according to ICCCM.
Main differences to Xt intrinsics:
Increased parallelism.
Completely hidden usage of the INCR protocol, because clients ought not know.
Show usage of MULTIPLE protocol, because some clients DO want to know.
More useful done proc.
Result: TYPE = {ok, timeout, failed};
Request: TYPE = REF RequestSequence; --state of a particular conversion
RequestSequence: TYPE = RECORD [
--Represents state of handling a particular conversion request.
--public fields for transfer of data
oh: OwnershipHandle,  --describes owner of selection.
event: Xl.SelectionRequestEvent, --might be multiple, don't look for target or property.
ownerData: REF ¬ NIL,  --reserved for owner; ignored internally.
refuse: BOOL ¬ FALSE,  --option for selection owner to refuse request.
anyFailed: BOOL ¬ FALSE, --TRUE in done procedure if any received # ok.
--private internal fields
transferTQ: Xl.TQ ¬ NIL,  --
--private, internally useful fields; monitored on transferTQ.
next: PRIVATE Request ¬ NIL,  --queue of requests to prevent multiple
isInQueue: PRIVATE BOOL ¬ FALSE,  --synchrounous serving of same requestor.
isDelayed: PRIVATE BOOL ¬ FALSE,  --in case of incompatible requests.
index: PRIVATE INT ¬ -1,  --state in transfering mulitiple.
multiSeq: PRIVATE REF Xl.Card32Sequence ¬ NIL, --private for impl.
transferMatch: PRIVATE Xl.Match ¬ NIL, --needed to unregister event catching.
timeOutData: PRIVATE REF ¬ NIL,  --timer state protected by transferTQ.
--per target data
targets: SEQUENCE length: NAT OF TargetRec
];
TargetRec: TYPE = RECORD [
--inputs to selection owners convert proc (setup internally according to request).
target: Xl.XAtom,  --from request
property: Xl.XAtom,  --from request
--outputs from selection owners convert proc (moved to server by impl).
response: REF ¬ NIL,   --place for the response, or, $Failed
type: Xl.XAtom ¬ [0],  --of response
start: INT ¬ 0,  --start unit in response
num: INT ¬ 0 --set to INT.LAST--, --number of units used, limited by length...
--private internal fields (state to implement INCR protocol)
incr: PRIVATE BOOL ¬ FALSE, --using incr protocol
unit: PRIVATE INT ¬ 0,  --unit size in bytes
next: PRIVATE INT ¬ 0,  --unit where to start in response
remain: PRIVATE INT ¬ 0, --number of units, limited by length...
state: PRIVATE REF ¬ NIL, --
--inputs to selection owners done proc (specifying acknowledgements)
received: Result ¬ ok,
--space for data of the selection owner; shared in convert and done proc
data: REF ¬ NIL   --reserved for owner; ignored by impl
];
RequestProc: TYPE = PROC [request: Request];
Use for request of conversion and for acknowledgements.
GotOwnershipNotifyProc: TYPE = PROC [ --call back on successful AquireOwnership.
oh: OwnershipHandle,
timeStamp: Xl.TimeStamp, --latest time stamp when selection got aquired.
previouslyOwned: BOOL,  --whether same widget previously owned selection.
previousTime: Xl.TimeStamp --previous time stamp, valid if previouslyOwned.
];
LostOwnershipNotifyProc: TYPE = PROC [ --passed on for a selectionClear event.
oh: OwnershipHandle,
timeStamp: Xl.TimeStamp, --use it! it is always an error not to do so.
event: Xl.SelectionClearEvent ¬ NIL, --set if initiated by an event.
previousTime: Xl.TimeStamp  --believed last aquired time by this widget.
];
GetTQProc: TYPE = PROC [ --called on a selectionRequest event, running on serviceTQ.
oh: OwnershipHandle,
event: Xl.SelectionRequestEvent ¬ NIL
] RETURNS [transferTQ: Xl.TQ ¬ NIL]; --NIL causes usage of OwnershipRec.sharedTransferTQ
ApplicationClass: TYPE = REF ApplicationClassRec; --neither widget nor connection specific
ApplicationClassRec: TYPE = RECORD [
--Modifications after per widget data is established may or may not be ignored and is bad style.
selection: Rope.ROPE,  --which this code is supporting.
--Actual procedures for selection value transfer
convert: RequestProc,  --called on transferTQ; request for selection.
done: RequestProc ¬ NIL,  --called on transferTQ; acknowledgement of transfer.
--Feedback procedures for selection ownership.
--Clients are expected to give visual feedback whether they own a selection.
--Warning: gotOnwership and lostOwnership calls are not necessarily "correctly bracketed".
gotOnwership: GotOwnershipNotifyProc ¬ NIL, --called on initiateTQ.
lostOwnership: LostOwnershipNotifyProc ¬ NIL, --called on initiateTQ to announce server lost ownership. Warning: lostOwnership may be called denoting the previous selection. A request for a new ownership does a server roundtrip, while the AquireOwnership proc still holds the initiateTQ lock; therefore the new aquire may come through before the lostOwnership notification does. Watch those time stamps!.
getTransferTQ: GetTQProc ¬ NIL, --If available, called on serviceTQ to return a transferTQ used for this transaction. If this procedure is defaulted, uses oh.sharedTransferTQ.
--Other parametrizations.
checkTime: BOOL ¬ TRUE, --automatically refuse requests with bad time.
defaultTimeoutMsec: INT ¬ 12000, --can be overwritten on a per ownership base
targets: LIST OF Rope.ROPE ¬ NIL, --useful for TARGETS target
classData: REF ¬ NIL  --reserved for the client; ignored by impl
];
OwnershipHandle: TYPE = REF OwnershipRec;
OwnershipRec: TYPE = RECORD [
--Represents the per widget / per selection data.
--Clients must NOT modify any data as this might cause confusion.
w: XTk.Widget,  --might be handy for clients (not internally used)
ac: ApplicationClass,
selection: Xl.XAtom ¬ [0], --internalized on active connection from ac
timeoutMsec: INT ¬ 0,  --timeout selection requests; initialized from ac
ownershipData: REF ¬ NIL, --reserved for the client (not internally used)
iHaveIt: BOOL ¬ FALSE,   --clients must not change
ownedSince: Xl.TimeStamp ¬ [0], --clients must not change
--All following fields ought to be un-interesting for clients
initiateTQ: Xl.TQ,
sharedTransferTQ: Xl.TQ, --NIL means each requests gets new transferTQ
wod: PRIVATE WidgetOData ¬ NIL, --per widget data shared by all selections
serviceQueue: PRIVATE Request ¬ NIL, --monitored on sharedTransferTQ, if ~NIL
reserved: PRIVATE REF ¬ NIL--prevent recompilation on experiments
];
PreEstablishServiceTQ: PROC [w: XTk.Widget, serviceTQ: Xl.TQ ¬ NIL];
Establishes ThreadQueue listening for requests on all selections of a particular widget. Optional, but if used it must be called before first call of EstablishSelectionOwnerProtocol.
I'm not yet sure whether it is really worthwhile sharing a ThreadQueue for all selections.
WARNING: Selection requests with large side effects have to use the INSERT←SELECTION convention. ICCCM 2.6.3.2. As I want to hide this knowledge from selection requestors (Do I want to?) ownership could be established hiddenly)
EstablishSelectionOwnerProtocol: PROC [w: XTk.Widget, ac: ApplicationClass, initiateTQ: Xl.TQ ¬ NIL, transferTQ: Xl.TQ ¬ NIL, ownershipData: REF ¬ NIL] RETURNS [oh: OwnershipHandle];
Install ownership duties for a particular selection. This does not actually aquire ownership but registers the procedures necessary to aquire it. Must not be called more then once per widget and selection tuple.
Any subset of ThreadQueues in {serviceTQ, initiateTQ, transferTQ, rootTQ} may be equal; choice is only a matter of robustness on errors and limitations to parallelism. A NIL transferTQ means different requests are handled in parallel.
DeEstablishSelectionOwnerProtocol: PROC [oh: OwnershipHandle];
Undoes EstablishSelectionOwnerProtocol.
ChangeTimeOut: PROC [oh: OwnershipHandle, timeoutMsec: INT];
...but only for actions not yet started.
AquireOwnership: PROC [oh: OwnershipHandle, time: Xl.TimeStamp] RETURNS [success: BOOL ¬ FALSE];
Aquires active selection ownership.
OwnershipHandle must have been previously established.
Do not use Xl.currentTime.
ReleaseOwnership: PROC [oh: OwnershipHandle, time: Xl.TimeStamp ¬ Xl.currentTime];
Voluntarily releases selection ownership.
OwnershipHandle must have been previously established.
It is ok but not specially clever to use Xl.currentTime.
WidgetOData: PRIVATE TYPE = REF WidgetODataRec;
WidgetODataRec: PRIVATE TYPE;
FillSomeTargets: PROC [request: Request, targetIdx: NAT, assignFailed: BOOL ¬ FALSE] RETURNS [success: BOOL];
Conveniant procedure to fill out some standard targets in a request. See the documentation for a list of target types this procedure will handle.
request, targetIdx: denote which target this procedure should answer.
assignFailed: whether procedure should assign $Failed to response if it can't handle it.
Returns success: "procedure new what to do for target".
The proposed method how to handle some targets in a non-standard way, is to not call FillSomeTargets for those targets.
END.