DIRECTORY Ascii, Atom, Random, Rope, RopeList, Xl, XlICCCMTypes, XlConventions, XlDispatch, XlPredefinedAtoms, XTk, XTkDB, XTkIcon, XTkFriends, XTkMigration, XTkNotification, XTkPrivate, XTkShellWidgets; XTkShellWidgetsImpl: CEDAR MONITOR IMPORTS Atom, Random, Rope, RopeList, XlDispatch, Xl, XlConventions, XTk, XTkDB, XTkFriends, XTkIcon, XTkMigration, XTkNotification, XTkPrivate EXPORTS XTkShellWidgets SHARES Xl, XTk = BEGIN OPEN Xl, XTk, XTkShellWidgets; shellClass: ImplementorClass ¬ XTkFriends.CreateClass[[key: $top, wDataNum: 1, preferredSizeLR: ShellPreferredSizeLR, preStopFastAccess: ShellPreStopFastAccess, configureLR: ShellConfigureLR, initInstPart: ShellInitInstPart, className: ShellClassName, eventMask: [structureNotify: TRUE], backgroundKey: $white, removeChildLR: ShellRemoveChildLR, internalEnumerateChildren: ShellInternalEnumerateChildren, forgetScreenLR: ShellForgetScreenLR, bindScreenLX: ShellBindScreenLX]]; ToWindow: PROC [x: REF READONLY ANY] RETURNS [w: Xl.Window ¬ Xl.nullWindow] = { WITH x SELECT FROM widget: REF READONLY WidgetRep => w ¬ widget.window; window: REF READONLY Window => w ¬ window­; ENDCASE => {}; }; IsShell: PUBLIC PROC [w: XTk.Widget] RETURNS [BOOL] = { RETURN [XTk.HasClass[w, shellClass]]; }; connectionDeadSet: EventFilter ~ Xl.CreateEventFilter[finalEvent]; ConnectionDiedHandler: EventProcType = {--on rootTQ SELECT event.type FROM finalEvent => { ev: Xl.FinalEvent ~ NARROW[event]; shell: Widget ~ NARROW[clientData]; IF ~ev.refCountTransition AND shell.connection=ev.connection AND shell.state<=screened THEN { shellIP: ShellInstPart ~ GetShellInstPart[shell]; closure: REF Closure ¬ shellIP.connectionDiedClosure; XTkFriends.PreStopFastAccess[shell, errorConnection]; shellIP.connection ¬ NIL; IF closure=NIL THEN DestroyShell[shell] ELSE closure.proc[shell, closure.registerData, $connectionDied, ev]; }; }; ENDCASE => {}; }; shellRootEvents: Xl.EventFilter ~ Xl.CreateEventFilter[destroyNotify, configureNotify]; shellOtherEvents: Xl.EventFilter ~ Xl.CreateEventFilter[clientMessage]; OtherShellEvents: <> Xl.EventProcType = { shell: Widget ~ NARROW[clientData]; shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF shell.state>realized OR shell.fastAccessAllowed#ok THEN RETURN; SELECT event.type FROM clientMessage => { client: Xl.ClientMessageEvent ~ NARROW[event]; IF client.window#shell.window OR client.format#32 THEN RETURN; IF client.typeAtom#shellIP.wmProtocolsAtom THEN RETURN; SELECT client.w[0] FROM shellIP.cachedWmAtom => { SetFocus[shell, [client.w[1]], NIL]; }; Xl.MakeAtom[shell.connection, "WM_DELETE_WINDOW"] => { IF shellIP.deletionProtocol THEN { closure: REF Closure ¬ shellIP.wmDeletionClosure; IF closure=NIL THEN DestroyByWindowManager[shell, NIL, $wmDeleteWindow, client] ELSE closure.proc[shell, closure.registerData, $wmDeleteWindow, client]; }; }; ENDCASE => RETURN; }; ENDCASE => {}; }; ShellEventLR: <> Xl.EventProcType = { ENABLE ABORTED => GOTO oops; shell: Widget ~ NARROW[clientData]; shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF shell.state>realized OR shell.fastAccessAllowed#ok THEN RETURN; SELECT event.type FROM configureNotify => { g: Geometry; cn: ConfigureNotifyEvent ~ NARROW[event]; IF shellIP.crazyShell THEN { IF cn.window#shellIP.parentWindow THEN RETURN; } ELSE { IF cn.window#shell.window THEN RETURN; shell.actual.pos ¬ cn.geometry.pos; shell.actual.borderWidth ¬ cn.geometry.borderWidth; }; IF shell.actual.size#cn.geometry.size THEN { g ¬ [size: cn.geometry.size, pos: [dontUse, dontUse], borderWidth: dontUse]; ShellCheatConfigureLR[shell, g]; }; }; destroyNotify => { d: Xl.DestroyNotifyEvent ~ NARROW[event]; SELECT d.window FROM shellIP.parentWindow, shell.window => { closure: REF Closure ¬ shellIP.windowDiedClosure; IF shell.connection#d.connection OR shell.state>screened THEN RETURN; XTkFriends.PreStopFastAccess[shell, errorWindow]; IF closure=NIL THEN DestroyShell[shell] ELSE closure.proc[shell, closure.registerData, $destroyNotify, d]; }; ENDCASE => {} }; ENDCASE => {}; EXITS oops => NULL; }; ShellRemoveChildLR: XTk.RemoveChildProc = { shellIP: ShellInstPart ~ GetShellInstPart[widget]; oldChild: XTk.Widget ¬ shellIP.child; IF oldChild#NIL THEN { shellIP.child ¬ NIL; done ¬ TRUE; XTkFriends.ForgetScreenLR[oldChild]; }; }; AddChildLR: PROC [shell: XTk.Widget, newChild: Widget] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; oldChild: Widget ¬ shellIP.child; IF oldChild=newChild THEN RETURN; SELECT newChild.parent FROM NIL, shell => XTkFriends.AssignParentAndCheckScreenLR[newChild, shell]; ENDCASE => ERROR; IF oldChild#NIL THEN { shellIP.child ¬ NIL; XTkFriends.OrphanizeLR[oldChild, normal]; }; IF newChild.s.mapping=dontUse THEN newChild.s.mapping ¬ mapped; shellIP.child ¬ newChild; NoteChildChange[shell]; XTkFriends.ReconfigureChildrenLR[shell]; }; ShellInternalEnumerateChildren: XTk.InternalEnumerateChildrenProc = { child: XTk.Widget ¬ ShellChild[self]; IF child#NIL AND child.state> XTk.WidgetNotifyProc = { IF widget.fastAccessAllowed=ok THEN { XTkFriends.PreStopFastAccess[widget, normal]; IF widget.actualMapping=mapped THEN { Xl.UnmapWindow[widget.connection, widget.window, XTkPrivate.detailsForNoErrors]; }; }; DestroyShell[widget]; }; ShellChild: PROC [shell: ShellWidget] RETURNS [Widget¬NIL] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; RETURN [shellIP.child]; }; ShellPreferredSizeLR: PreferredSizeProc = { child: Widget = ShellChild[widget]; maySkip[x] ¬ TRUE; maySkip[y] ¬ TRUE; IF widget.s.geometry.size.width > 0 THEN { maySkip[w] ¬ TRUE; proposed.size.width ¬ widget.s.geometry.size.width; }; IF widget.s.geometry.size.height > 0 THEN { maySkip[h] ¬ TRUE; proposed.size.height ¬ widget.s.geometry.size.height; }; IF widget.s.geometry.pos.x # dontUse THEN { proposed.pos.x ¬ widget.s.geometry.pos.x; }; IF widget.s.geometry.pos.y # dontUse THEN { proposed.pos.y ¬ widget.s.geometry.pos.y; }; IF widget.s.geometry.borderWidth # dontUse THEN { maySkip[b] ¬ TRUE; proposed.borderWidth ¬ widget.s.geometry.borderWidth; }; IF child = NIL OR (maySkip[w] AND maySkip[h] AND maySkip[b]) THEN RETURN [proposed] ELSE { g: Geometry ¬ XTkFriends.PreferredSizeLR[child, NIL, proposed, maySkip]; IF g.borderWidth<0 THEN g.borderWidth ¬ 0; preferred.size.width ¬ SELECT TRUE FROM widget.s.geometry.size.width>0 => widget.s.geometry.size.width, g.size.width>0 => g.size.width + g.borderWidth*2, ENDCASE => dontUse; preferred.size.height ¬ SELECT TRUE FROM widget.s.geometry.size.height>0 => widget.s.geometry.size.height, g.size.height>0 => g.size.height + g.borderWidth*2, ENDCASE => dontUse; }; preferred.pos ¬ widget.s.geometry.pos; preferred.borderWidth ¬ widget.s.geometry.borderWidth; }; EnsureRootThread: PROC [inq: Xl.TQ] RETURNS [tq: Xl.TQ] = { IF inq=NIL THEN { tq ¬ Xl.CreateTQ[$root, XTk.rootLockingOrder, FALSE] } ELSE { tq ¬ inq; IF Xl.GetLockOrderNum[tq] MyCreateConnection[NIL, a]; r: Rope.ROPE => MyCreateConnection[r]; rt: REF READONLY TEXT => MyCreateConnection[Rope.FromRefText[rt]]; xc: Xl.Connection => c ¬ xc; ENDCASE => ERROR; IF ~Xl.Alive[c] THEN { err: REF Xl.EventRep.errorNotify ~ NEW[Xl.EventRep.errorNotify]; err.connection ¬ c; err.errorKind ¬ requestFromDeadConnection; err.explanation ¬ "XTk.BindScreenShell using dead connection"; ERROR Xl.XError[err]; }; shell.connection ¬ shellIP.connection ¬ c; }; shellIP.parentWindow ¬ parentWindow; screenDepth ¬ Xl.QueryScreenDepth[c, shellIP.parentWindow]; IF parentWindow=Xl.nullWindow THEN { screen: Xl.Screen ¬ screenDepth.screen; IF screenDepth.depth#1 AND screenDepth.depth#8 THEN { FOR sdl: Xl.ScreenDepthL ¬ screen.screenDepthL, sdl.rest WHILE sdl#NIL DO IF sdl.first.screen=screen AND sdl.first.nVisualTypes>0 THEN { IF sdl.first.depth=1 OR sdl.first.depth=8 THEN { screenDepth ¬ sdl.first }; }; ENDLOOP; }; }; XTkFriends.BindScreenLR[widget: shell, rootTQ: shellIP.originalRootTQ, screen: screenDepth.screen, screenDepth: screenDepth]; IF mustDecrementRefCount THEN Xl.DecRefCount[c, refCountObject]; }; ShellBindScreenLX: XTk.BindScreenProc = { shellIP: ShellInstPart ~ GetShellInstPart[widget]; shellIP.connectionWatcherMatch ¬ NEW[Xl.MatchRep ¬ [proc: ConnectionDiedHandler, handles: connectionDeadSet, tq: rootTQ, data: widget]]; XlDispatch.AddMatch[screen.connection, Xl.nullWindow, shellIP.connectionWatcherMatch, Xl.unspecifiedEvents, XTkPrivate.detailsForNoErrors]; Xl.IncRefCount[screen.connection, widget]; IF ~shellIP.dontQueryGeometry THEN { g: Xl.Geometry ¬ XTkDB.GetGeometryFromDB[widget]; IF g.size.width>0 THEN widget.s.geometry.size.width ¬ g.size.width; IF g.size.height>0 THEN widget.s.geometry.size.height ¬ g.size.height; IF g.pos.x>=0 THEN widget.s.geometry.pos.x ¬ g.pos.x; IF g.pos.y>=0 THEN widget.s.geometry.pos.y ¬ g.pos.y; IF g.borderWidth>=0 THEN widget.s.geometry.borderWidth ¬ g.borderWidth; IF g.size.width>0 AND g.size.height>0 THEN { h: REF XTkShellWidgets.ICCCMHints ~ GetHints[widget]; h.wmNormalHints.userSize ¬ h.wmNormalHints.clientSize ¬ TRUE; h.wmNormalHintsChanged ¬ TRUE; }; IF g.pos.y>=0 AND g.pos.x>=0 THEN { h: REF XTkShellWidgets.ICCCMHints ~ GetHints[widget]; h.wmNormalHints.userPos ¬ h.wmNormalHints.clientPos ¬ TRUE; h.wmNormalHintsChanged ¬ TRUE; }; }; }; ForgetScreenShell: PUBLIC PROC [shell: ShellWidget] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; action: PROC = { shellIP.connection ¬ NIL; XTkFriends.ForgetScreenLR[shell] }; Xl.CallWithLock[shellIP.originalRootTQ, action]; }; RefCountData: TYPE = RECORD [c: Xl.Connection, object: REF]; ShellForgetScreenLR: XTk.TerminateProc = { c: Xl.Connection ¬ widget.connection; shellIP: ShellInstPart ~ GetShellInstPart[widget]; ForgetHints[shellIP.hints]; IF Xl.Alive[c] THEN { rcd: REF RefCountData ~ NEW[RefCountData ¬ [c, widget]]; --Save the connection-object pair as the original widget.connection might change before QueuedDecrementRefCount is done. wm: Xl.Match ¬ shellIP.connectionWatcherMatch; IF wm#NIL THEN { XlDispatch.RemoveMatch[c, Xl.nullWindow, wm, XTkPrivate.detailsForNoErrors]; shellIP.connectionWatcherMatch ¬ NIL; }; Xl.Enqueue[tq: widget.rootTQ, proc: QueuedDecrementRefCount, data: rcd]; }; }; QueuedDecrementRefCount<>: Xl.EventProcType = { rcd: REF RefCountData ¬ NARROW[clientData]; Xl.DecRefCount[rcd.c, rcd.object]; }; CreateInteroperabilityShell: PUBLIC PROC [widgetSpec: WidgetSpec ¬ [], child: Widget ¬ NIL, className: ATOM ¬ NIL, rootTQ: TQ ¬ NIL] RETURNS [widget: Widget] = { widget ¬ XTk.CreateWidget[widgetSpec, shellClass]; rootTQ ¬ EnsureRootThread[rootTQ]; BEGIN shellIP: ShellInstPart ~ GetShellInstPart[widget]; shellIP.crazyShell ¬ TRUE; shellIP.originalRootTQ ¬ rootTQ; shellIP.dontQueryGeometry ¬ TRUE; shellIP.className ¬ (IF className#NIL THEN className ELSE $InterOpShell); END; IF child#NIL THEN AddChildLR[shell: widget, newChild: child]; }; BindInteroperabilityShell: PUBLIC PROC [shell: ShellWidget, connection: Xl.Connection, foreignParent: Xl.Window] = { BindScreenShell[shell, connection, foreignParent]; }; SetShellChild: PUBLIC PROC [shell: ShellWidget, child: Widget] = { action: PROC = { IF child.s.mapping=dontUse THEN child.s.mapping ¬ mapped; AddChildLR[shell: shell, newChild: child] }; shellIP: ShellInstPart ~ GetShellInstPart[shell]; Xl.CallWithLock[shellIP.originalRootTQ, action]; }; ConfigureRec: TYPE = RECORD [widget: Widget, geometry: Xl.Geometry, mapping: Mapping, reConsiderChildren: BOOL]; ForkRealizeShell: PUBLIC PROC [shell: ShellWidget, geometry: Xl.Geometry, mapping: Mapping, reConsiderChildren: BOOL] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; cr: REF ConfigureRec ¬ NEW[ConfigureRec ¬ [shell, geometry, mapping, reConsiderChildren]]; Xl.Enqueue[shellIP.originalRootTQ, ForkedRealizeShell, cr]; }; ForkedRealizeShell<>: Xl.EventProcType = { cr: REF ConfigureRec ¬ NARROW[clientData]; ReallyRealizeShellLR[cr.widget, cr.geometry, cr.mapping, cr.reConsiderChildren]; }; RealizeShell: PUBLIC PROC [shell: ShellWidget, geometry: Xl.Geometry, mapping: Mapping, reConsiderChildren: BOOL] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; action: PROC = {ReallyRealizeShellLR[shell, geometry, mapping, reConsiderChildren]}; Xl.CallWithLock[shellIP.originalRootTQ, action]; }; ReallyRealizeShellLR: PROC [shell: ShellWidget, geometry: Xl.Geometry, mapping: Mapping, reConsiderChildren: BOOL] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF mapping=dontUse THEN { IF shell.actualMapping>=dontUse THEN mapping ¬ mapped }; IF shell.state>screened THEN BindScreenShell[shell]; XTkIcon.SetIconName[shell, TRUE, shellIP.iconName]; XTkIcon.SetIconMask[shell, TRUE, shellIP.packageName, shellIP.shortName]; XTkFriends.ConfigureLR[shell, geometry, mapping, reConsiderChildren]; BEGIN c: Xl.Connection ¬ shell.connection; IF Xl.Alive[c] THEN Xl.Flush[c, TRUE]; END; }; DestroyShell: PUBLIC PROC [shell: ShellWidget] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; action: PROC = {XTkFriends.DestroyWidgetLR[shell]}; Xl.CallWithLock[shellIP.originalRootTQ, action]; }; ShellPreStopFastAccess: TerminateProc = { shellIP: ShellInstPart ~ GetShellInstPart[widget]; shellIP.focusTime ¬ [0]; IF ~shellIP.finallyUnmapped AND widget.window#nullWindow THEN { shellIP.finallyUnmapped ¬ TRUE; IF reason=normal AND Xl.Alive[widget.connection] THEN Xl.UnmapWindow[widget.connection, widget.window, XTkPrivate.detailsForFlushSoonNoErrors]; }; WITH shellIP.focusGoal SELECT FROM w: XTk.Widget => {}; ENDCASE => shellIP.focusGoal ¬ NIL; }; GetShellInstPart: PROC [w: Widget] RETURNS [ShellInstPart] = INLINE { RETURN [ NARROW[XTkFriends.InstPart[w, shellClass]] ]; }; EntryTrackCM: ENTRY PROC [shell: ShellWidget, shellIP: ShellInstPart, w: Widget] = { ENABLE UNWIND => NULL; IF shellIP#NIL THEN { cnt: INT ¬ 1; lag: LIST OF Widget ¬ shellIP.childrenWithColorMap; IF w#NIL THEN { lag ¬ CONS[w, lag]; FOR l: LIST OF Widget ¬ lag, lag.rest WHILE l#NIL DO IF l.first=w THEN RETURN; ENDLOOP }; WHILE lag#NIL AND lag.first.state>=dead DO lag ¬ lag.rest; ENDLOOP; shellIP.childrenWithColorMap ¬ lag; IF lag=NIL THEN RETURN; DO IF lag.rest=NIL THEN EXIT; IF lag.rest.first.state>=dead THEN lag.rest ¬ lag.rest.rest ELSE {lag ¬ lag.rest; cnt ¬ cnt+1} ENDLOOP; IF shell.fastAccessAllowed=ok THEN { d: REF Xl.Card32Sequence ¬ MakeColorMapData[shellIP, cnt]; PutTheColorMapProp[shell, d ! Xl.XError => CONTINUE]; buffer ¬ d; } }; }; buffer: REF Xl.Card32Sequence ¬ NIL; MakeColorMapData: INTERNAL PROC [shellIP: ShellInstPart, cnt: INT] RETURNS [d: REF Xl.Card32Sequence ¬ NIL] = { IF cnt>0 THEN { lw: LIST OF Widget ¬ shellIP.childrenWithColorMap; IF buffer#NIL AND buffer.leng>=cnt THEN {d ¬ buffer; buffer ¬ NIL} ELSE d ¬ NEW[Card32Sequence[cnt]]; FOR i: INT IN [0..cnt) DO IF lw#NIL THEN {d[i] ¬ lw.first.window; lw ¬ lw.rest} ELSE d[i] ¬ Xl.nullWindow; ENDLOOP }; }; PutTheColorMapProp: PROC [shell: ShellWidget, value: REF Xl.Card32Sequence] = { IF value#NIL THEN { propertyKey: XAtom ¬ Xl.MakeAtom[shell.connection, "WM_COLORMAP_WINDOWS"]; Xl.ChangeProperty[shell.connection, shell.window, propertyKey, XlPredefinedAtoms.window, replace, value]; }; }; TrackColorMap: PUBLIC PROC [shell: ShellWidget, w: Widget] = { IF shell=NIL THEN shell ¬ XTk.RootWidget[w]; IF shell#NIL AND shell.fastAccessAllowed=ok THEN { shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF shellIP.crazyShell THEN RETURN; --don't know how... EntryTrackCM[shell, shellIP, w]; }; }; ShellClassName: ClassNameProc = { shellIP: ShellInstPart ~ GetShellInstPart[widget]; RETURN [shellIP.className]; }; AddRope: PROC [r: Rope.ROPE, list: LIST OF Rope.ROPE] RETURNS [LIST OF Rope.ROPE] = { IF ~RopeList.Memb[list, r] THEN list ¬ CONS[r, list]; RETURN [list] }; SetFocusMethod: PUBLIC PROC [shell: ShellWidget, focusProtocol, inputHint: Xl.BOOL3 ¬ illegal] = { h: REF XTkShellWidgets.ICCCMHints ¬ GetHints[shell]; IF focusProtocol#illegal THEN { wmTakeFocus: Rope.ROPE ¬ "WM_TAKE_FOCUS"; SELECT focusProtocol FROM true => { h.protocols ¬ AddRope[wmTakeFocus, h.protocols]; h.protocolsChanged ¬ TRUE }; false => { h.protocols ¬ RopeList.DRemove[h.protocols, wmTakeFocus]; h.protocolsChanged ¬ TRUE }; ENDCASE => {}; }; IF inputHint#illegal THEN { SELECT inputHint FROM true => {h.wmHints.input ¬ 1; h.wmHintsChanged ¬ TRUE}; false => {h.wmHints.input ¬ 0; h.wmHintsChanged ¬ TRUE}; ENDCASE => {}; }; UpdateHints[shell]; }; SetFocusTarget: PUBLIC PROC [shell: ShellWidget, child: REF, time: Xl.TimeStamp] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF ValidTime[shellIP.focusTime, time] THEN shellIP.focusGoal ¬ child }; ValidTime: PROC [lastTime, eventTime: Xl.TimeStamp] RETURNS [BOOL] = { RETURN [ Xl.Period[from: lastTime, to: eventTime]>=0 OR eventTime=Xl.currentTime OR lastTime=Xl.currentTime OR --this is it! We want to prevent invalid times. But we want to survive if a crazy server did not get an event for LAST[TimeStamp]/2. So we assume a 2 minutes is the maximum delay which invalid times could be caused due to unsynchronized nonsense Xl.Period[from: eventTime, to: lastTime]>120000 ] }; SetFocus: PUBLIC PROC [shell: ShellWidget, time: Xl.TimeStamp, child: REF] = { w: Window; shellIP: ShellInstPart ~ GetShellInstPart[shell]; IF ValidTime[shellIP.focusTime, time] THEN { IF child=NIL THEN child ¬ shellIP.focusGoal ELSE shellIP.focusGoal ¬ child; w ¬ ToWindow[child]; IF w#Xl.nullWindow THEN { shellIP.focusTime ¬ time; IF shell.fastAccessAllowed=ok THEN Xl.SetInputFocus[shell.connection, w, parent, time, XTkPrivate.detailsForFlushNoErrors]; }; }; }; FocusTime: PUBLIC PROC [shell: ShellWidget] RETURNS [Xl.TimeStamp] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; RETURN [shellIP.focusTime]; }; Iconify: PUBLIC PROC [shell: ShellWidget] = { IF shell.state>=dead THEN RETURN; shell.s.mapping ¬ mapped; SetIconicHint[shell, TRUE]; --irrelevant if open or iconic, useful if was withdrawn... IF shell.state=realized AND shell.fastAccessAllowed=ok THEN { root: Xl.Window ¬ shell.screenDepth.screen.root; atom: Xl.XAtom ¬ Xl.MakeAtom[shell.connection, "WM_CHANGE_STATE"]; Xl.SendClientMessage32[c: shell.connection, destination: root, propagate: FALSE, eventMask: [substructureRedirect: TRUE, substructureNotify: TRUE], window: shell.window, type: atom, data: [3, 0, 0, 0, 0], details: XTkPrivate.detailsForFlushSoonNoErrors ]; }; }; OpenIcon: PUBLIC PROC [shell: ShellWidget] = { IF shell.state>=dead THEN RETURN; SetIconicHint[shell, FALSE]; --irrelevant if iconic or opened; useful if withdrawn... shell.s.mapping ¬ mapped; IF shell.state=realized AND shell.fastAccessAllowed=ok THEN { Xl.MapWindow[shell.connection, shell.window, XTkPrivate.detailsForFlushNoErrors]; } }; WithDraw: PUBLIC PROC [shell: ShellWidget] = { IF shell.state>=dead THEN RETURN; shell.s.mapping ¬ unmapped; IF shell.state=realized AND shell.fastAccessAllowed=ok THEN { root: Xl.Window ¬ shell.screenDepth.screen.root; eb: Xl.EventRep.unmapNotify; eb.eventWindow ¬ root; eb.window ¬ shell.window; eb.fromConfigure ¬ FALSE; Xl.UnmapWindow[shell.connection, shell.window]; Xl.SendEvent[c: shell.connection, destination: root, propagate: FALSE, eventMask: [substructureRedirect: TRUE, substructureNotify: TRUE], eventBody: eb, details: XTkPrivate.detailsForFlushSoonNoErrors]; }; }; SetIconicHint: PROC [shell: ShellWidget, iconic: BOOL] = { shellIP: ShellInstPart ~ GetShellInstPart[shell]; h: REF XTkShellWidgets.ICCCMHints ¬ GetHints[shell]; h.wmHints.initialState ¬ IF iconic THEN 3 ELSE 1; h.wmHintsChanged ¬ TRUE; UpdateHints[shell]; }; SetHeader: PUBLIC PROC [shell: ShellWidget, header: ROPE] = { h: REF XTkShellWidgets.ICCCMHints ¬ GetHints[shell]; h.windowHeader ¬ header; h.windowHeaderChanged ¬ TRUE; UpdateHints[shell]; }; SetIconName: PUBLIC PROC [shell: ShellWidget, header: ROPE] = { h: REF XTkShellWidgets.ICCCMHints ¬ GetHints[shell]; h.iconNameChanged ¬ TRUE; UpdateHints[shell]; }; END. °XTkShellWidgetsImpl.mesa Copyright Σ 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, October 18, 1988 11:22:01 am PDT Christian Jacobi, August 13, 1993 10:30 am PDT --Note: The sizing has not yet happened! . already maySkip[x] _ TRUE; already maySkip[y] _ TRUE; --my own direct events --my parents events: we need to know about resizing --Note (except for creation): -- Ordering new size with Configure is a rare event -- Normally sizing has already happened by window manager! --order new size anyway --normal shells only --This is a convention by which the environment gets a chance to fill in the connection, or, make a readable error message. --The created connection has a ref count increased which needs to be undone Try to select a more favorable screenDepth --enqueued to be last thing on rootTQ, and, connection stays alive for our continuation (e.g. super classes TerminateProc). --prevent duplications Might consider caching iconic/open state to suppress unnecessary operation. However, then we would need to keep atomically track of state. I'm not against it, but I'm not yet sure whether it is worth the effort. --Forget about such things as using rootTQ. We never know iconic state atomically anyway since interactive actions of user through window manager are not synchronized. --ELSE wont open and iconify shell; just make sure shell will be iconic on realization --Forget about such things as using rootTQ. We never know iconic state atomically anyway since interactive actions of user through window manager are not synchronized. --ELSE wont realize shell; just make sure shell will be opened on realization --Forget about such things as using rootTQ. We never know iconic state atomically anyway since interactive actions of user through window manager are not synchronized. --ELSE shell stays withdrawn; however OpenIcon and Iconify will be delayed until realization. Κ"ϊ•NewlineDelimiter –(cedarcode) style˜code™Kšœ ΟeœI™TK™=K™.—K˜šΟk œ˜ K˜K˜K˜K˜K˜ K˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜K˜K˜Kšœ˜K˜ K˜ Kšœ˜Kšœ ˜ Kšœ˜K˜—šΟnœžœžœ˜#Kšžœˆ˜Kšžœ˜Kšžœ ˜—Kšžœžœ˜$K˜Kšœ™žœΏ˜άK™š Ÿœžœžœžœžœžœ#˜Ošžœžœž˜Kšœžœžœ ˜4Kšœžœžœ˜+Kšžœ˜—K˜—K˜š Ÿœžœžœžœžœ˜7Kšžœ˜%K˜K˜—KšœB˜BšŸœΟc ˜3šžœ ž˜šœ˜Kšœžœ žœ˜"Kšœžœ ˜#šžœžœ žœžœ˜]Kšœ2˜2Kšœ žœ)˜5Kšœ$Πbfœ˜5Kšœžœ˜šžœ žœ˜Kšžœ˜KšžœA˜E—K˜—K˜—Kšžœ˜—K˜—K˜K˜W˜GK˜—šŸœ%˜5Kšœžœ ˜#K˜1Kšžœžœžœžœ˜Bšžœ ž˜˜Kšœ žœ˜.Kšžœžœžœžœ˜>Kšžœ)žœžœ˜7šžœ ž˜šœ˜Kšœžœ˜$K˜—˜6šžœžœ˜"Kšœ žœ%˜1šžœ žœ˜Kšžœžœ˜@KšžœD˜H—K˜—K˜—Kšžœžœ˜—K˜—Kšžœ˜—K˜—K˜šŸ œ$˜0Kšžœžœžœ˜Kšœžœ ˜#K˜1Kšžœžœžœžœ˜Bšžœ ž˜˜Kšœ ˜ Kšœžœ˜)šžœ˜šžœ˜KšžœΟbœžœžœ˜.Kšœ˜—šžœ˜Kšžœžœžœ˜&K˜#K˜3Kšœ˜——šžœ$žœ˜,K˜LKš œ"™*Kšœ ˜ K˜—K˜—˜Kšœžœ˜)šžœ ž˜˜'Kšœ žœ%˜1Kšžœžœžœžœ˜EKšœ$‘ œ˜1šžœ žœ˜Kšžœ˜Kšžœ?˜C—K˜—Kšžœ˜ —K˜—Kšžœ˜—Kšžœ žœ˜K˜—K˜šŸœ˜+Kšœ2˜2K˜%šžœ žœžœ˜Kšœžœ˜Kšœžœ˜ Kšœ$˜$Kšœ˜—Kšœ˜—K˜šŸ œžœ*˜:Kšœ1˜1K˜!Kšžœžœžœ˜!šžœž˜KšžœD˜GKšžœžœ˜—šžœ žœžœ˜Kšœžœ˜Kšœ)˜)K˜—Kšžœžœ˜?K˜Kšœ˜Kšœ(˜(K˜—K˜šŸœ'˜EK˜%šžœžœžœžœ˜)K˜$K˜—Kšœ˜—K˜šŸœžœ,˜GšŸœ˜#Kšžœžœ&˜FKšžœžœ&˜FKšžœžœ0˜UKšžœ žœ2˜XKšžœ žœ2˜XKšžœžœ ˜9šž˜K˜%K˜K˜:Kšžœ˜—Kšœ"žœ˜)Kš‘8˜8Kšžœžœ˜@K˜—Kšžœ%žœ˜EKšžœ%žœ˜EKšžœ/žœ˜TKšžœ1žœ ˜WKšžœ1žœ ˜Wšžœ<žœ˜DKšœ+žœ˜2K˜—Kšœ˜—K˜šŸœ)˜?šžœžœ˜%Kšœ-˜-šžœžœ˜&K˜PK˜—K˜—Kšœ˜K˜—K˜šŸ œžœžœ žœ˜>Kšœ1˜1Kšžœ˜K˜—K˜šŸœ˜+K˜#Kšœ žœžœ˜%šžœ"žœ˜*Kšœ žœ˜K˜3K˜—šžœ#žœ˜+Kšœ žœ˜K˜5K˜—šžœ#žœ˜+Kšœžœ™K˜)K˜—šžœ#žœ˜+Kšœžœ™K˜)K˜—šžœ)žœ˜1Kšœ žœ˜K˜5K˜—š žœ žœžœ žœ žœ ˜=Kšžœžœ ˜šžœ˜Kšœ0žœ˜HKšžœžœ˜*šœžœžœž˜'K˜?K˜2Kšžœ ˜—šœžœžœž˜(K˜AK˜4Kšžœ ˜——K˜—K˜&K˜6K˜—K˜š Ÿœžœ žœžœ žœ˜;šžœžœ˜ šžœ˜Kšœ.Πbkœ˜4K˜—šžœ˜K˜ Kšžœ-žœžœ˜:K˜——K˜—K˜šŸœžœ-˜MKšœ.˜.KšœA ˜[Kšžœžœ˜7Kšžœžœ˜7Kšžœžœ ˜Cšžœžœ˜$Kšœžœ;˜Y—šžœžœ˜%Kšœžœ<˜[—K™K˜ˆK™3Kšœ.žœw˜¨K˜ΚKšœ"žœ˜(šžœžœ˜%K˜LK˜—K˜K˜—Kš œžœžœžœžœžœ˜=šŸœžœ-˜LKšœžœžœžœ˜Kšžœ˜K˜—K˜*K˜—K˜$K˜;šžœžœ˜$Jšœ*™*K˜'šžœžœžœ˜5šžœ6žœžœž˜Išžœžœžœ˜>šžœžœžœ˜0K˜Kšœ˜—K˜—Kšžœ˜—K˜—K˜—Kšœ}˜}Kšžœžœ#˜@K˜K™—šŸœ˜)Kšœ3˜3Kšœ!žœd˜ˆKšœ'’ œW˜‹Kšœ*˜*šžœžœ˜$K˜1Kšžœžœ-˜CKšžœžœ/˜FKšžœ žœ#˜5Kšžœ žœ#˜5Kšžœžœ/˜Gšžœžœžœ˜,Kšœžœ/˜5Kšœ8žœ˜=Kšœžœ˜Kšœ˜—šžœ žœ žœ˜#Kšœžœ/˜5Kšœ6žœ˜;Kšœžœ˜K˜—Kšœ˜—K˜—K˜šŸœžœžœ˜7Kšœ2˜2šœžœ˜Kšœžœ˜Kšœ ˜ Kšœ˜—Kšœ0˜0K˜—K˜Kšœžœžœžœ˜Kšžœžœžœ˜,šžœžœžœžœ˜2Kšœ1˜1Kšžœžœžœ ˜6K˜ K˜—˜K˜——šŸœ˜!Kšœ2˜2Kšžœ˜K˜—K˜šŸœžœ žœžœžœžœžœžœžœžœ˜UKšžœžœžœ ˜5Kšžœ˜ K˜—K˜šŸœžœžœ3žœ˜bKšœžœ.˜4šžœžœ˜Kšœžœ˜)šžœž˜˜ K˜1Kšœž˜Kšœ˜—˜ K˜:Kšœž˜Kšœ˜—Kšžœ˜—K˜—šžœžœ˜šžœ ž˜Kšœ1žœ˜7Kšœ2žœ˜8Kšžœ˜—K˜—Kšœ˜Kšœ˜K˜—šŸœžœžœžœ˜TKšœ1˜1Kšžœ$žœ˜DK˜K˜—šŸ œžœ%žœžœ˜Fšžœ˜Kšœ,˜,Kšžœžœ˜7šžœ φ˜ωKšœ2˜2——K˜—K˜K˜šŸœžœžœ1žœ˜NK˜ K˜1šžœ$žœ˜,Kšžœžœžœžœ˜KK˜šžœžœ˜K˜šžœž˜"K˜X—K˜—K˜—K˜—K˜šŸ œžœžœžœ˜FK˜1Kšžœ˜K˜—K˜J™ΥšŸœžœžœ˜-J™§Kšžœžœžœ˜!K˜Kšœžœ :˜Všžœžœžœžœ˜=K˜0K˜BšœJžœ˜QKšœ"žœžœ˜CK˜K˜ K˜K˜/K˜—K˜KšžœP™V—K˜—K˜šŸœžœžœ˜.J™§Kšžœžœžœ˜!Kšœžœ 8˜UK˜šžœžœžœžœ˜>K˜QKšžœG™MK˜—K˜K˜—šŸœžœžœ˜.J™§Kšžœžœžœ˜!K˜šžœžœžœžœ˜=K˜0Kšœ˜K˜K˜Kšœžœ˜Kšœ/˜/Kšœ@žœ$žœžœC˜ΚK˜KšžœW™]—K˜—K˜šŸ œžœžœ˜:Kšœ1˜1Kšœžœ.˜4Kšœžœžœžœ˜1Kšœžœ˜Kšœ˜K˜—K˜šŸ œž œžœ ˜=Kšœžœ.˜4K˜Kšœžœ˜Kšœ˜K˜K™—šŸ œž œžœ˜?Kšœžœ.˜4Kšœžœ˜Kšœ˜K˜K˜—K˜Kšžœ˜K˜K˜—…—†°²