## xsocket-to-hostwindow-router-old.pkg
#
# Replaced by
src/lib/x-kit/xclient/src/window/xevent-router-ximp.pkg#
# Primary functionality
# =====================
#
# For the big picture, see the dataflow diagram in:
#
#
src/lib/x-kit/xclient/src/window/xclient-ximps.pkg#
# We receive X events from the xsession decode_xpackets_imp
# and decide what action to take for them. The
# decode_xpackets_imp collapses expose event trains
# into single expose events); we are the first link
# in the chain which actually responds to X events
# on a semantic level.
#
# Typically we route an X event to the toplevel
# window containing the relevant widget. More
# precisely, to the hostwindow_to_widget_router
# instance for that hostwindow -- see
#
#
src/lib/x-kit/xclient/src/window/hostwindow-to-widget-router-old.pkg#
# To do this we maintain a
#
# window_id_to_window_info_map
#
# which tracks all windows created by the application,
# keyed by their associated X-server IDs (xids), so that
# we can translate the xid in the event to the proper
# hostwindow_to_widget_router input slot for delivery.
#
# In particular we track, for each window, the route
# needed to reach it down the window hierarchy, and
# deliver X events down that route, thus giving each
# ancestor of the target widget a chance to rewrite
# the event.
#
# We find out about newly created toplevel windows via our
#
# note_new_hostwindow
#
# fn, which is called by the hostwindow-creation functions
#
# make_simple_top_window
# make_simple_popup_window
# make_transient_window
# in
#
src/lib/x-kit/xclient/src/window/window-old.pkg#
# We find out about newly created subwindows via
# CREATE_NOTIFY
# xevents from the X server, and about destroyed
# windows (toplevel and subwindow both) via
# DESTROY_NOTIFY
# xevents from the X server.
#
# There are also a few X events which we divert to
# specialized imps for processing:
#
# o The following three X events get redirected
# to our selection imp:
# SELECTION_CLEAR
# SELECTION_REQUEST
# SELECTION_NOTIFY
#
# o The following X events get redirected
# to our property imp:
# PROPERTY_NOTIFY
#
#
# Secondary functionality
# =======================
#
# This file also implements a facility to
# freeze selected windows, with draw commands
# to them queueing up until they are unlocked:
# See make_overlay_buffer in
#
src/lib/x-kit/xclient/src/window/draw-imp-old.pkg
#
# The idea might have been to allow XOR-implemented
# rubber-banding selection to work without anomalies
# due to the window contents changing between draw
# and undraw calls.
#
# The lock_window_tree entrypoint is called
# nowhere in the codebase, so this is apparently
# code that was just being phased in when
# development ceased.
#
# Compiled by:
#
src/lib/x-kit/xclient/xclient-internals.sublib# TODO XXX BUGGO FIXME
# - refresh the keymap on ModifierMappingNotifyXEvt and KeyboardMappingNotifyXEvt
# events.
# - think about the relation of locks and changes in the tree structure
# also locking already locked windows.
stipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package xt = xtypes; # xtypes is from
src/lib/x-kit/xclient/src/wire/xtypes.pkg package hx = hash_xid; # hash_xid is from
src/lib/x-kit/xclient/src/stuff/hash-xid.pkg package xet = xevent_types; # xevent_types is from
src/lib/x-kit/xclient/src/wire/xevent-types.pkg package dy = display_old; # display_old is from
src/lib/x-kit/xclient/src/wire/display-old.pkg package xok = xsocket_old; # xsocket_old is from
src/lib/x-kit/xclient/src/wire/xsocket-old.pkg package g2d = geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg package xtr = xlogger; # xlogger is from
src/lib/x-kit/xclient/src/stuff/xlogger.pkg #
package xm = xt::xid_map; # Map where key::Key == xt::Xid.
trace = xtr::log_if xtr::xsocket_to_hostwindow_router_tracing 0; # Conditionally write strings to tracing.log or whatever.
#
# To debug via tracelogging, near startup do
#
# enable xtr::xsocket_to_hostwindow_router_tracing;
#
# and then annotate the code with lines like
#
# trace {. sprintf "foo/top: bar d=%d" bar; };
herein
package xsocket_to_hostwindow_router_old
: (weak) Xsocket_To_Hostwindow_Router_Old # Xsocket_To_Hostwindow_Router_Old is from
src/lib/x-kit/xclient/src/window/xsocket-to-hostwindow-router-old.api {
Envelope_Route
= ENVELOPE_ROUTE_END xt::Window_Id
| ENVELOPE_ROUTE (xt::Window_Id, Envelope_Route)
;
stipulate
package plea {
#
Mail
= NOTE_NEW_HOSTWINDOW (xt::Window_Id, g2d::Window_Site)
| GET_WINDOW_SITE (xt::Window_Id, /* reply_oneshot: */ Oneshot_Maildrop(g2d::Box))
#
| GET_''SEEN_FIRST_EXPOSE''_ONESHOT (xt::Window_Id, /* reply_oneshot: */ Oneshot_Maildrop( Null_Or(Oneshot_Maildrop(Void))) )
| NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT (xt::Window_Id, /* reply_oneshot: */ Oneshot_Maildrop( Void ))
#
| GET_''GUI_STARTUP_COMPLETE''_ONESHOT /* reply_oneshot: */ Oneshot_Maildrop( Oneshot_Maildrop(Void) )
;
};
Window_Info
=
WINDOW_INFO
{
window_id: xt::Window_Id, # 29-bit X id for this particular window.
route: Envelope_Route, # Path needed to reach this window, starting at its hostwindow.
parent_info: Null_Or( Window_Info ),
#
children: Ref( List(Window_Info) ),
lock: Ref( Bool ),
site: Ref( g2d::Box ),
#
to_hostwindow_slot: Mailslot( (Envelope_Route, xet::x::Event) ), # Where to send events headed for this window.
#
seen_first_expose: Ref( Bool ), # We set this TRUE on first EXPOSE event.
seen_first_expose_oneshot: Ref( Null_Or(Oneshot_Maildrop(Void)) ) # We set this on first EXPOSE event.
};
# The seen_first_expose* stuff is part of the
# infrastructure allowing a widget client to wait
# until the widget is fully operational before
# submitting requests to it. We presume that a
# widget is operational when we see an EXPOSE
# x event for it -- it had better be!
#
# See also seen_first_redraw_slot_of in
#
src/lib/x-kit/widget/old/basic/widget.api # The various things we can
# do with a given X event:
#
Xevent_Action
#
= SEND_TO_WINDOW xt::Window_Id # Forward event to given window via all of its ancestors from hostwindow down.
| NOTE_SITE_CHANGE_AND_SEND_TO_WINDOW (xt::Window_Id, g2d::Box)
# Note new size+position of window, then forward event normally.
| NOTE_EXPOSE_AND_SEND_TO_WINDOW xt::Window_Id
# Note EXPOSE (if first for window) then forward event normally.
| NOTE_WINDOW_DESTRUCTION xt::Window_Id
| SEND_TO_KEYMAP_IMP
# This appears to be unused at present.
| SEND_TO_WINDOW_PROPERTY_IMP
| SEND_TO_SELECTION_IMP
| SEND_TO_ALL_WINDOWS
# So everyone hears about changes in modifier key, keyboard and pointer mappings.
| IGNORE
| NOTE_NEW_WINDOW
{ parent_window_id: xt::Window_Id,
created_window_id: xt::Window_Id,
box: g2d::Box
}
;
# Discard instances of an X-event that
# are the product of SubstructureNotify,
# instead of StructureNotify.
#
fun ignore_substructure_notify_xevents (window_id1, window_id2)
=
if (xt::same_xid (window_id1, window_id2)) SEND_TO_WINDOW window_id1;
else IGNORE;
fi;
# Decide what action to take for given X event. Here
#
# event_window_id
#
# is the window corresponding to the widget which
# should actually handle the event, as determined
# by the X server; the X server algorithm is
# described on pages 76-77 of
#
# http://mythryl.org/pub/exene/X-protocol-R6.pdf
#
fun pick_xevent_action (xet::x::KEY_PRESS { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::KEY_RELEASE { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
# pick_xevent_action (xet::x::BUTTON_PRESS { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
# pick_xevent_action (xet::x::BUTTON_RELEASE { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::BUTTON_PRESS { event_window_id, ... } ) => { # trace {. sprintf "pick_xevent_action/BUTTON_PRESS: event_window_id s=%s" (xt::xid_to_string event_window_id); };
SEND_TO_WINDOW event_window_id; };
pick_xevent_action (xet::x::BUTTON_RELEASE { event_window_id, ... } ) => { # trace {. sprintf "pick_xevent_action/BUTTON_RELEASE: event_window_id s=%s" (xt::xid_to_string event_window_id); };
SEND_TO_WINDOW event_window_id; };
pick_xevent_action (xet::x::MOTION_NOTIFY { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::ENTER_NOTIFY { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::LEAVE_NOTIFY { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::FOCUS_IN { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
pick_xevent_action (xet::x::FOCUS_OUT { event_window_id, ... } ) => SEND_TO_WINDOW event_window_id;
# pick_xevent_action (xet::x::KeymapNotify {, ... } ) =
# pick_xevent_action (xet::x::GraphicsExpose ??
# pick_xevent_action (xet::x::NoExpose {, ... } ) =
# pick_xevent_action (xet::x::MapRequest {, ... } ) =
# pick_xevent_action (xet::x::ConfigureRequest {, ... } ) =
# pick_xevent_action (xet::x::ResizeRequest {, ... } ) =
# pick_xevent_action (xet::x::CirculateRequest {, ... } ) =
pick_xevent_action (xet::x::EXPOSE { exposed_window_id, ... } ) => NOTE_EXPOSE_AND_SEND_TO_WINDOW exposed_window_id;
pick_xevent_action (xet::x::VISIBILITY_NOTIFY { changed_window_id, ... } ) => SEND_TO_WINDOW changed_window_id;
pick_xevent_action (xet::x::CREATE_NOTIFY { parent_window_id, created_window_id, box, ... } )
=>
{
# trace {. sprintf "pick_xevent_action/CREATE_NOTIFY: parent_window_id s=%s created_window_id x=%s" (xt::xid_to_string parent_window_id) (xt::xid_to_string created_window_id); };
NOTE_NEW_WINDOW { parent_window_id, created_window_id, box };
};
pick_xevent_action (xet::x::DESTROY_NOTIFY { event_window_id, destroyed_window_id, ... } )
=>
xt::same_xid (event_window_id, destroyed_window_id)
##
?? NOTE_WINDOW_DESTRUCTION event_window_id # Remove window from registry.
:: SEND_TO_WINDOW event_window_id; # Report to parent that child is dead.
pick_xevent_action (xet::x::UNMAP_NOTIFY { event_window_id, unmapped_window_id, ... } )
=>
ignore_substructure_notify_xevents (event_window_id, unmapped_window_id);
pick_xevent_action (xet::x::MAP_NOTIFY { event_window_id, mapped_window_id, ... } )
=>
ignore_substructure_notify_xevents (event_window_id, mapped_window_id);
pick_xevent_action (xet::x::REPARENT_NOTIFY _)
=>
IGNORE;
pick_xevent_action (xet::x::CONFIGURE_NOTIFY { event_window_id, configured_window_id, box, ... } )
=>
case (ignore_substructure_notify_xevents (event_window_id, configured_window_id))
#
SEND_TO_WINDOW _ => NOTE_SITE_CHANGE_AND_SEND_TO_WINDOW (configured_window_id, box);
_ => IGNORE;
esac;
pick_xevent_action (xet::x::GRAVITY_NOTIFY { event_window_id, moved_window_id, ... } )
=>
ignore_substructure_notify_xevents (event_window_id, moved_window_id);
pick_xevent_action (xet::x::CIRCULATE_NOTIFY { event_window_id, circulated_window_id, ... } )
=>
ignore_substructure_notify_xevents (event_window_id, circulated_window_id);
pick_xevent_action (xet::x::PROPERTY_NOTIFY _) => SEND_TO_WINDOW_PROPERTY_IMP; # We may have other uses of PropertyNotify someday.
pick_xevent_action (xet::x::SELECTION_CLEAR _) => SEND_TO_SELECTION_IMP;
pick_xevent_action (xet::x::SELECTION_REQUEST _) => SEND_TO_SELECTION_IMP;
pick_xevent_action (xet::x::SELECTION_NOTIFY _) => SEND_TO_SELECTION_IMP;
pick_xevent_action (xet::x::COLORMAP_NOTIFY { window_id, ... } ) => SEND_TO_WINDOW window_id;
pick_xevent_action (xet::x::CLIENT_MESSAGE { window_id, ... } ) => SEND_TO_WINDOW window_id;
pick_xevent_action xet::x::MODIFIER_MAPPING_NOTIFY => SEND_TO_ALL_WINDOWS;
pick_xevent_action (xet::x::KEYBOARD_MAPPING_NOTIFY _) => SEND_TO_ALL_WINDOWS;
pick_xevent_action xet::x::POINTER_MAPPING_NOTIFY => SEND_TO_ALL_WINDOWS;
pick_xevent_action e => {
xgripe::warning (string::cat [
"[xsocket-to-topwin: unexpected ", xevent_to_string::xevent_name e, " event]\n"]);
IGNORE;};
end;
# +DEBUG
# Define a tracelogging version of
#
# pick_xevent_action
#
stipulate
#
fun xevent_action_to_string (SEND_TO_WINDOW w)
=>
("SEND_TO_WINDOW(" + xt::xid_to_string w + ")");
xevent_action_to_string (NOTE_EXPOSE_AND_SEND_TO_WINDOW w)
=>
("NOTE_EXPOSE_AND_SEND_TO_WINDOW(" + xt::xid_to_string w + ")");
xevent_action_to_string (NOTE_SITE_CHANGE_AND_SEND_TO_WINDOW (w,_))
=>
("NOTE_SITE_CHANGE_AND_SEND_TO_WINDOW(" + xt::xid_to_string w + ")");
xevent_action_to_string (NOTE_NEW_WINDOW { parent_window_id, created_window_id, box } )
=>
string::cat
[
"NOTE_NEW_WINDOW { parent=", xt::xid_to_string parent_window_id,
", new_window=", xt::xid_to_string created_window_id,
"}"
];
xevent_action_to_string (NOTE_WINDOW_DESTRUCTION w) => ("NOTE_WINDOW_DESTRUCTION(" + xt::xid_to_string w + ")");
xevent_action_to_string SEND_TO_KEYMAP_IMP => "SEND_TO_KEYMAP_IMP";
xevent_action_to_string SEND_TO_WINDOW_PROPERTY_IMP => "SEND_TO_WINDOW_PROPERTY_IMP";
xevent_action_to_string SEND_TO_SELECTION_IMP => "SEND_TO_SELECTION_IMP";
xevent_action_to_string SEND_TO_ALL_WINDOWS => "SEND_TO_ALL_WINDOWS";
xevent_action_to_string IGNORE => "IGNORE";
end;
herein
#
pick_xevent_action
=
\\ xevent
=
{ xevent_action = pick_xevent_action xevent;
trace {.
#
cat [ "xsocket_to_hostwindow_router: ", xevent_to_string::xevent_name xevent,
" => ", xevent_action_to_string xevent_action
];
};
xevent_action;
};
end;
# -DEBUG
herein
Xsocket_To_Hostwindow_Router
=
XSOCKET_TO_HOSTWINDOW_ROUTER
{
plea_slot: Mailslot( plea::Mail ),
reply_slot: Mailslot( Mailop( (Envelope_Route, xet::x::Event) ) ),
lock_slot: Mailslot( Bool )
};
stipulate
#
fun set_window_subtree_locks_to
(bool: Bool)
=
set
where
fun set (WINDOW_INFO { lock, children, ... } )
=
{ lock := bool;
set_list *children;
}
also
fun set_list (wd ! r)
=>
{ set wd;
set_list r;
};
set_list []
=>
();
end;
end;
herein
lock_tree = set_window_subtree_locks_to TRUE;
unlock_tree = set_window_subtree_locks_to FALSE;
end;
# This is called exactly one place, in
#
src/lib/x-kit/xclient/src/window/xsession-old.pkg #
fun make_xsocket_to_hostwindow_router
{
xdisplay => { xsocket, ... }: dy::Xdisplay,
keymap_imp,
to_window_property_imp_slot,
to_selection_imp_slot
}
=
{ take_xevent' = xok::take_xevent' xsocket;
#
plea_slot = make_mailslot ();
reply_slot = make_mailslot ();
lock_slot = make_mailslot ();
plea_in' = take_from_mailslot' plea_slot;
# log::note_on_stderr {. sprintf "make_xsocket_to_hostwindow_router/AAAaa -- xsocket-to-hostwindow-router-old.pkg"; };
# log::note {. sprintf "make_xsocket_to_hostwindow_router/AAAa -- xsocket-to-hostwindow-router-old.pkg"; };
# trace {. sprintf "make_xsocket_to_hostwindow_router/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# if SOON
# wid_to_winfo = xm::empty: xm::Map( Window_Info ); # "wid_to_winfo" == "window id to window info map"
# else
wid_to_winfo = hx::make_map (): hx::Xid_Map( Window_Info ); # "wid_to_winfo" == "window id to window info map"
get_info = hx::get wid_to_winfo;
set_info = hx::set wid_to_winfo;
drop_info = hx::drop wid_to_winfo;
get_and_drop_info = hx::get_and_drop wid_to_winfo;
# endif
# log::note {. sprintf "make_xsocket_to_hostwindow_router/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
#
# This is our primary state, mapping
# Window_Id to Window_Info values.
wid_to_pleas # "wid_to_pleas" == "window id to window pleas map"
=
hx::make_map ()
:
hx::Xid_Map( List( plea::Mail ) )
;
get_pleas = hx::get wid_to_pleas;
set_pleas = hx::set wid_to_pleas;
get_and_drop_pleas = hx::get_and_drop wid_to_pleas;
#
# If a plea for a window arrives before we've
# registered it, we hold it in this until it is
# registered, giving us the we have the info
# needed to process the plea.
wid_to_1shot = hx::make_map (): hx::Xid_Map( Oneshot_Maildrop(Void) ); # "wid_to_1shot" == "window id to oneshot map"
#
get_from_oneshot_map = hx::get wid_to_1shot;
set_in_oneshot_map = hx::set wid_to_1shot;
drop_from_oneshot_map = hx::drop wid_to_1shot;
#
# There is an unfortunate race condition in which
# NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT
# requests on a window_id may arrive from a client
# thread before we have seen the
# NOTE_NEW_WINDOW
# from the X server which creates the
# wid_to_winfo
# entry for that window_id. We use the above
# wid_to_1shot
# map to hold such "prematurely registered" requests
# pending arrival of the corresponding NOTE_NEW_WINDOW.
gui_startup_complete_oneshot
=
make_oneshot_maildrop (): Oneshot_Maildrop( Void );
#
# This maildrop exists to give application threads
# something to wait on before presuming that the
# GUI widgettree windows, threads etc are ready for action.
#
# Currently we set this when we first
# get an EXPOSE X event from the X server.
#
seen_first_expose_xevent_of_session
=
REF FALSE;
fun loop ( wid_to_winfo,
wid_to_pleas,
wid_to_1shot
)
=
{ do_one_mailop
[
plea_in' ==> do_plea,
take_xevent' ==> do_xevent
];
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
}
where
fun do_plea (plea::NOTE_NEW_HOSTWINDOW (window_id, window_site))
=>
{ # Log a new top-level window:
#
to_hostwindow_slot = make_mailslot ();
# Handle any prematurely-registered oneshot.
# I'm not sure a hostwindow will ever get an
# EXPOSE event, so this may be pointless:
#
oneshot = { oneshot = get_from_oneshot_map window_id;
drop_from_oneshot_map window_id;
THE oneshot;
}
except
lib_base::NOT_FOUND
=
NULL;
# if SOON
# log::note {. sprintf "loop/AAA -- xsocket-to-hostwindow-router-old.pkg -- xsocket-to-hostwindow-router-old.pkg"; };
# wi__to_winfo
# =
# xm::set
# ( wid_to_winfo,
# window_id,
# WINDOW_INFO
# {
# window_id,
# to_hostwindow_slot,
# route => ENVELOPE_ROUTE_END window_id,
# parent_info => NULL,
# children => REF [],
# lock => REF FALSE,
# site => REF (g2d::site_to_box window_site),
# #
# seen_first_expose => REF( FALSE ),
# seen_first_expose_oneshot => REF( oneshot )
# }
# );
# put_in_mailslot (reply_slot, take_from_mailslot' to_hostwindow_slot);
# log::note {. sprintf "loop/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
# };
# else
# log::note {. sprintf "loop/AAA -- xsocket-to-hostwindow-router-old.pkg -- xsocket-to-hostwindow-router-old.pkg"; };
set_info
( window_id,
WINDOW_INFO
{
window_id,
to_hostwindow_slot,
route => ENVELOPE_ROUTE_END window_id,
parent_info => NULL,
children => REF [],
lock => REF FALSE,
site => REF (g2d::site_to_box window_site),
#
seen_first_expose => REF( FALSE ),
seen_first_expose_oneshot => REF( oneshot )
}
);
# log::note {. sprintf "loop/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
put_in_mailslot (reply_slot, take_from_mailslot' to_hostwindow_slot);
}
except lib_base::NOT_FOUND = ();
# endif
do_plea (plea::NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT (window_id, oneshot))
=>
{ # Note the oneshot used to signal receipt
# of the first EXPOSE event on a window:
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/TOP: window_id s=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
{
# if SOON
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => { winfo -> WINDOW_INFO {
# seen_first_expose => REF( seen_first_expose ),
# seen_first_expose_oneshot,
# ...
# };
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/MID: window_id s=%s, first_expose b=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id) case seen_first_expose TRUE => "TRUE"; _ => "FALSE"; esac; };
# seen_first_expose_oneshot := THE oneshot;
# if seen_first_expose
# #
# put_in_oneshot (oneshot, ()); # This shouldn't happen.
# fi;
# };
# NULL => {
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/MUD: window_id s=%s: WINDOW_INFO record does not exist yet, parking the oneshot -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
# set_in_oneshot_map (window_id, oneshot); # WINDOW_INFO record doesn't exist yet, so park oneshot for now.
# };
# esac;
# };
# else
(get_info window_id)
->
WINDOW_INFO {
seen_first_expose => REF( seen_first_expose ),
seen_first_expose_oneshot,
...
};
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/MID: window_id s=%s, first_expose b=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id) case seen_first_expose TRUE => "TRUE"; _ => "FALSE"; esac; };
seen_first_expose_oneshot := THE oneshot;
if seen_first_expose
#
put_in_oneshot (oneshot, ()); # This shouldn't happen.
fi;
}
except lib_base::NOT_FOUND
=
{
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/MUD: window_id s=%s: WINDOW_INFO record does not exist yet, parking the oneshot -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
set_in_oneshot_map (window_id, oneshot); # WINDOW_INFO record doesn't exist yet, so park oneshot for now.
};
# endif
# log::note {. sprintf "NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT/BOT: window_id s=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
};
do_plea (plea::GET_WINDOW_SITE (window_id, reply_oneshot))
=>
{
# log::note_in_ramlog {. "do_plea GET_WINDOW_SITE/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# if SOON
# log::note {. sprintf "get_window_site/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => { winfo -> WINDOW_INFO { site, ... };
# put_in_oneshot (reply_oneshot, *site);
# };
# NULL => {
# log::note_on_stderr {. "do_plea GET_WINDOW_SITE/except ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg"; };
# log::note_in_ramlog {. "do_plea GET_WINDOW_SITE/except ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg"; };
# log::fatal ( "do_plea GET_WINDOW_SITE/except ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg" );
# };
# esac;
# log::note {. sprintf "get_window_site/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# };
# else
# log::note {. sprintf "get_window_site/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
(get_info window_id)
->
WINDOW_INFO { site, ... };
# log::note {. "do_plea GET_WINDOW_SITE/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
result =
put_in_oneshot (reply_oneshot, *site);
# log::note {. "do_plea GET_WINDOW_SITE/ZZZ -- xsocket-to-hostwindow-router-old.pkg"; };
result;
}
except
lib_base::NOT_FOUND
=
{
log::note_on_stderr {. "do_plea GET_WINDOW_SITE/except window_id NOT_FOUND ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg"; };
log::note_in_ramlog {. "do_plea GET_WINDOW_SITE/except window_id NOT_FOUND ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg"; };
log::fatal ( "do_plea GET_WINDOW_SITE/except window_id NOT_FOUND ERROR!! GET_WINDOW_SITE -- xsocket-to-hostwindow-router-old.pkg" );
# log::note {. sprintf "ERROR!! GET_WINDOW_SITE: window_id %s not yet registered" (xt::xid_to_string window_id); };
(); # We probably should be either returning NULL or generating an exception in client thread here. XXX BUGGO FIXME
# XXX BUGGO FIXME I think maybe we should be registering window ids here before putting
# them into circulation, so as to basically eliminate the possibility of this error.
# [ MUCH LATER ]:
# I think maybe we need a deferral mechanism here matching that for
# the seen-first-expose case.
};
# endif
do_plea (plea::GET_''SEEN_FIRST_EXPOSE''_ONESHOT (window_id, reply_oneshot))
=>
{
# if SOON
# log::note {. sprintf "get seen first expose/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => { winfo -> WINDOW_INFO { seen_first_expose_oneshot, ... };
# put_in_oneshot (reply_oneshot, *seen_first_expose_oneshot);
# };
# NULL => { put_in_oneshot (reply_oneshot, THE (get_from_oneshot_map window_id))
# except
# lib_base::NOT_FOUND
# =
# {
# log::note_on_stderr {. "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg"; };
# log::note_in_ramlog {. "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg"; };
# log::fatal ( "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg" );
# put_in_oneshot (reply_oneshot, NULL); # We probably should be generating an exception in client thread here. XXX BUGGO FIXME
# # XXX BUGGO FIXME I think maybe we should be registering window ids here before putting
# # them into circulation, so as to basically eliminate the possibility of this error.
# };
# };
# esac;
# log::note {. sprintf "get seen first expose/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# };
# else
# log::note {. sprintf "get seen first expose/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
(get_info window_id)
->
WINDOW_INFO { seen_first_expose_oneshot, ... };
# log::note {. sprintf "get seen first expose/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
put_in_oneshot (reply_oneshot, *seen_first_expose_oneshot);
}
except lib_base::NOT_FOUND
=
{ put_in_oneshot (reply_oneshot, THE (get_from_oneshot_map window_id))
except
lib_base::NOT_FOUND
=
{
log::note_on_stderr {. "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg"; };
log::note_in_ramlog {. "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg"; };
log::fatal ( "do_plea GET_''SEEN_FIRST_EXPOSE''_ONESHOT/except ERROR!! -- xsocket-to-hostwindow-router-old.pkg" );
put_in_oneshot (reply_oneshot, NULL); # We probably should be generating an exception in client thread here. XXX BUGGO FIXME
# XXX BUGGO FIXME I think maybe we should be registering window ids here before putting
# them into circulation, so as to basically eliminate the possibility of this error.
};
};
# endif
do_plea (plea::GET_''GUI_STARTUP_COMPLETE''_ONESHOT reply_oneshot)
=>
put_in_oneshot (reply_oneshot, gui_startup_complete_oneshot);
end;
#
fun note_new_subwindow (wid_to_winfo, parent_window_id, child_window_id, box)
=
{
# if SOON
# log::note {. sprintf "note new subwindow/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# parent_info = case (xm::get (wid_to_winfo, parent_window_id))
# #
# THE winfo => winfo;
# NULL => { log::note_on_stderr {. sprintf "note_new_subwindow: 'impossible:' parent_window_id not found! -- xsocket-to-hostwindow-router-old.pkg"; };
# log::fatal ( sprintf "note_new_subwindow: 'impossible:' parent_window_id not found! -- xsocket-to-hostwindow-router-old.pkg" );
# raise exception DIE "note_new_subwindow: 'impossible:' parent_window_id not found!";
# };
# esac;
#
# parent_info -> WINDOW_INFO { route, to_hostwindow_slot, children, lock, ... };
# log::note {. sprintf "note new subwindow/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# else
# log::note {. sprintf "note new subwindow/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
parent_info = (get_info parent_window_id)
except
lib_base::NOT_FOUND
=
{ log::fatal ( "note_new_subwindow get_info parent_window_id raised NOT_FOUND! -- xsocket-to-hostwindow-router-old.pkg" );
raise exception lib_base::NOT_FOUND;
};
parent_info -> WINDOW_INFO { route, to_hostwindow_slot, children, lock, ... };
# log::note {. sprintf "note new subwindow/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# endif
#
fun extend_route (ENVELOPE_ROUTE_END window_id) => ENVELOPE_ROUTE (window_id, ENVELOPE_ROUTE_END child_window_id);
extend_route (ENVELOPE_ROUTE (window_id, route)) => ENVELOPE_ROUTE (window_id, extend_route route);
end;
child_route = extend_route route;
# Handle any prematurely-registered oneshot:
#
oneshot = { oneshot = get_from_oneshot_map child_window_id;
drop_from_oneshot_map child_window_id;
# log::note {. sprintf "note_new_subwindow: window_id s=%s PICKING UP PREMATURELY REGISTERED ONESHOT -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string child_window_id); };
THE oneshot;
}
except
lib_base::NOT_FOUND
=
NULL;
child_info
=
WINDOW_INFO
{
window_id => child_window_id,
route => child_route,
site => REF box,
parent_info => THE parent_info,
children => REF [],
lock => REF *lock,
#
to_hostwindow_slot,
#
seen_first_expose => REF( FALSE ),
seen_first_expose_oneshot => REF( oneshot )
};
children := child_info ! *children;
# if SOON
# log::note {. sprintf "note_new_subwindow/DDD -- xsocket-to-hostwindow-router-old.pkg"; };
# wid_to_winfo = xm::set (wid_to_winfo, child_window_id, child_info);
#
# log::note {. sprintf "note_new_subwindow/EEE -- xsocket-to-hostwindow-router-old.pkg"; };
# # error error error THIS WILL NOT WORK because caller needs note_new_subwindow to return!!
# # loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
# else
# log::note {. sprintf "note_new_subwindow/DDD -- xsocket-to-hostwindow-router-old.pkg"; };
set_info (child_window_id, child_info);
# log::note {. sprintf "note_new_subwindow/EEE -- xsocket-to-hostwindow-router-old.pkg"; };
# endif
wid_to_winfo;
};
#
fun note_site_change (window_id, box)
=
# if SOON
# {
# log::note {. sprintf "note site change/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => { winfo -> WINDOW_INFO { site, ... };
# log::note {. sprintf "note site change/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# site := box;
# };
# NULL => ();
# esac;
# log::note {. sprintf "note site change/CCC -- xsocket-to-hostwindow-router-old.pkg"; };
# };
# else
{
# log::note {. sprintf "note site change/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
(get_info window_id) -> WINDOW_INFO { site, ... };
# log::note {. sprintf "note site change/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
site := box;
}
except
lib_base::NOT_FOUND = ();
# endif
#
fun maybe_note_first_expose_event window_id
=
{
# If this is the first EXPOSE event seen for
# this X session, broadcast that fact for
# anyone waiting:
#
if (not *seen_first_expose_xevent_of_session)
#
seen_first_expose_xevent_of_session := TRUE;
#
put_in_oneshot (gui_startup_complete_oneshot, ());
fi;
# If this is the first EXPOSE event for window,
# remember that we've seen it and set the
# condition variable seen_first_expose_oneshot
# to notify any threads waiting for the
# EXPOSE -- see seen_first_redraw_oneshot_of in
#
src/lib/x-kit/widget/old/basic/widget.api #
# if SOON
# log::note {. sprintf "maybe_note_first_expose_event/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => { winfo -> WINDOW_INFO
# { seen_first_expose => seen_first_expose,
# seen_first_expose_oneshot => REF seen_first_expose_oneshot,
# ...
# };
#
# log::note {. sprintf "maybe_note_first_expose_event/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# case seen_first_expose
# #
# REF TRUE => (); # Nothing to do.
#
# REF FALSE =>
# {
# seen_first_expose := TRUE;
# # log::note {. sprintf "maybe_note_first_expose_event: window_id s=%s, first_expose b=%s FIRST EXPOSE NOTED -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id) case seen_first_expose REF TRUE => "TRUE"; _ => "FALSE"; esac; };
#
# case seen_first_expose_oneshot
# #
# THE oneshot => put_in_oneshot (oneshot, ()); # Tell all waiting threads this widget is GO for action. :-)
# NULL => (); # Oneshot not yet registered -- shouldn't really happen,
# esac; # but no big deal, we'll set it when it arrives.
# };
# esac;
# };
# NULL => { ();
# # What we should probably be doing instead of preceding -- but right now it crashes us: -- 2013-05-20 CrT
# # log::note_on_stderr {. sprintf "maybe_note_first_expose_event: 'impossible:' parent_window_id not found! -- xsocket-to-hostwindow-router-old.pkg"; };
# # log::fatal ( sprintf "maybe_note_first_expose_event: 'impossible:' parent_window_id not found! -- xsocket-to-hostwindow-router-old.pkg" );
# # raise exception DIE "maybe_note_first_expose_event: 'impossible:' parent_window_id not found!";
# };
# esac;
#
# };
# else
# log::note {. sprintf "maybe_note_first_expose_event/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
(get_info window_id)
->
WINDOW_INFO
{ seen_first_expose => seen_first_expose,
seen_first_expose_oneshot => REF seen_first_expose_oneshot,
...
};
# log::note {. sprintf "maybe_note_first_expose_event/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
case seen_first_expose
#
REF TRUE => (); # Nothing to do.
REF FALSE =>
{
seen_first_expose := TRUE;
# log::note {. sprintf "maybe_note_first_expose_event: window_id s=%s, first_expose b=%s FIRST EXPOSE NOTED -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id) case seen_first_expose REF TRUE => "TRUE"; _ => "FALSE"; esac; };
case seen_first_expose_oneshot
#
THE oneshot => put_in_oneshot (oneshot, ()); # Tell all waiting threads this widget is GO for action. :-)
NULL => (); # Oneshot not yet registered -- shouldn't really happen,
esac; # but no big deal, we'll set it when it arrives.
};
esac;
# log::note {. sprintf "maybe_note_first_expose_event: window_id s=%s, first_expose b=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id) case seen_first_expose REF TRUE => "TRUE"; _ => "FALSE"; esac; };
}
except
lib_base::NOT_FOUND = ();
# endif
#
fun route_xevent_per_window_info (e, WINDOW_INFO { route, to_hostwindow_slot, ... } )
=
put_in_mailslot (to_hostwindow_slot, (route, e));
#
fun route_xevent_to_window_id (xevent, window_id)
=
# if SOON
# {
# log::note {. sprintf "route_xevent_to_window_id/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get (wid_to_winfo, window_id))
# #
# THE winfo => route_xevent_per_window_info (xevent, winfo);
# NULL => ();
# esac;
# log::note {. sprintf "route_xevent_to_window_id/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
# };
# else
{
# log::note {. sprintf "route_xevent_to_window_id/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
route_xevent_per_window_info (xevent, get_info window_id);
# log::note {. sprintf "route_xevent_to_window_id/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
}
except
lib_base::NOT_FOUND = ();
# endif
#
fun do_xevent xevent
=
case (pick_xevent_action xevent)
#
SEND_TO_WINDOW window_id
=>
{ route_xevent_to_window_id (xevent, window_id);
#
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
};
NOTE_EXPOSE_AND_SEND_TO_WINDOW window_id
=>
{
maybe_note_first_expose_event window_id;
#
route_xevent_to_window_id (xevent, window_id);
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
};
NOTE_SITE_CHANGE_AND_SEND_TO_WINDOW (window_id, box)
=>
{ note_site_change (window_id, box); # Window has changed size and/or position.
#
route_xevent_to_window_id (xevent, window_id);
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
};
NOTE_NEW_WINDOW { parent_window_id, created_window_id, box }
=>
{ wid_to_winfo = note_new_subwindow (wid_to_winfo, parent_window_id, created_window_id, box);
#
route_xevent_to_window_id (xevent, parent_window_id);
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
};
NOTE_WINDOW_DESTRUCTION window_id
=>
# if SOON
# {
# log::note {. sprintf "note window destruction/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
# case (xm::get_and_drop (wid_to_winfo, window_id))
# #
# (wid_to_winfo, THE (window_info as WINDOW_INFO { parent_info => THE (WINDOW_INFO { children, ... } ), ... } ))
# =>
# { children := remove_child *children;
# #
# route_xevent_per_window_info (xevent, window_info);
#
# loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
# }
# where
# fun remove_child ((window_info' as WINDOW_INFO { window_id => window_id', ... } ) ! rest)
# =>
# if (xt::same_xid (window_id', window_id)) rest ;
# else (window_info' ! (remove_child rest));
# fi;
#
# remove_child []
# =>
# { xgripe::warning "[xsocket-to-topwin: missing child]";
# [];
# };
# end;
# end;
#
# (wid_to_winfo, THE window_info)
# =>
# { route_xevent_per_window_info (xevent, window_info);
# #
# loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
# };
#
# (wid_to_winfo, NULL)
# =>
# loop (wid_to_winfo, wid_to_pleas, wid_to_1shot); # Shouldn't happen.
# esac;
# };
# else
{
# log::note {. sprintf "note window destruction/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
case (get_and_drop_info window_id)
#
THE (window_info as WINDOW_INFO { parent_info => THE (WINDOW_INFO { children, ... } ), ... } )
=>
{ children := remove_child *children;
#
route_xevent_per_window_info (xevent, window_info);
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
}
where
fun remove_child ((window_info' as WINDOW_INFO { window_id => window_id', ... } ) ! rest)
=>
if (xt::same_xid (window_id', window_id)) rest ;
else (window_info' ! (remove_child rest));
fi;
remove_child []
=>
{ xgripe::warning "[xsocket-to-topwin: missing child]";
[];
};
end;
end;
THE window_info
=>
{ route_xevent_per_window_info (xevent, window_info);
#
loop (wid_to_winfo, wid_to_pleas, wid_to_1shot);
};
NULL => loop (wid_to_winfo, wid_to_pleas, wid_to_1shot); # Shouldn't happen.
esac;
};
# endif
SEND_TO_KEYMAP_IMP
=>
{ xgripe::warning "[xsocket-to-topwin: unexpected SEND_TO_KEYMAP_IMP]";
();
};
SEND_TO_WINDOW_PROPERTY_IMP => put_in_mailslot (to_window_property_imp_slot, xevent);
SEND_TO_SELECTION_IMP => put_in_mailslot (to_selection_imp_slot, xevent);
IGNORE => ();
SEND_TO_ALL_WINDOWS
=>
{
# log::note {. sprintf "sent to all windows/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
apply (\\ (_, window_info) = route_xevent_per_window_info (xevent, window_info))
# if SOON
# (xm::keyvals_list wid_to_winfo);
# else
(hx::keyvals_list wid_to_winfo);
# endif
# log::note {. sprintf "sent to all windows/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
};
esac; # fun do_xevent
# log::note {. "xsocket_to_hostwindow_router: loop: Top."; };
end; # fun loop
xtr::make_thread "xsocket-to-topwin" {.
#
loop ( wid_to_winfo,
wid_to_pleas,
wid_to_1shot
);
};
XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, reply_slot, lock_slot };
}; # fun make_xsocket_to_hostwindow_router
# Add 'hostwindow' to wid_to_winfo
# and return the event slot through which we will feed
# X events to that window and its subwindows.
#
# This function is called (only) from make_hostwindow_to_widget_router in
#
#
src/lib/x-kit/xclient/src/window/hostwindow-to-widget-router-old.pkg #
fun note_new_hostwindow
( XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, reply_slot, ... },
hostwindow_id,
site
)
=
{ put_in_mailslot (plea_slot, plea::NOTE_NEW_HOSTWINDOW (hostwindow_id, site));
#
take_from_mailslot reply_slot;
};
#
fun get_window_site (XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, ... }, window_id)
=
{
# log::note_in_ramlog {. "get_window_site/AAA -- xsocket-to-hostwindow-router-old.pkg"; };
reply_oneshot = make_oneshot_maildrop ();
# log::note_in_ramlog {. "get_window_site/BBB -- xsocket-to-hostwindow-router-old.pkg"; };
put_in_mailslot (plea_slot, plea::GET_WINDOW_SITE (window_id, reply_oneshot));
#
# log::note_in_ramlog {. "get_window_site/CCC -- xsocket-to-hostwindow-router-old.pkg"; };
result =
get_from_oneshot reply_oneshot;
# log::note_in_ramlog {. "get_window_site/ZZZ -- xsocket-to-hostwindow-router-old.pkg"; };
result;
};
# This call is infrastructure.
#
# We often want to wait until a widget is fully
# operational before sending pleas to it.
#
# A practical definition of "operational" is
# "has received its first EXPOSE X event".
#
# We maintain a oneshot in widgets which
# clients may wait on for this purpose; see
# seen_first_redraw_oneshot_of
# in
#
src/lib/x-kit/widget/old/basic/widget.api #
# The oneshot in question originates at widget
# creation time -- make_widget in
#
#
src/lib/x-kit/widget/old/basic/widget.pkg #
# At realization time, which is when a widget
# for the first time becomes associated with an
# X window, it registers its oneshot with us
# via this call: See realize_widget in widget.pkg.
# This ensures that we have the onehost on hand
# when we receive a window's first EXPOSE event.
#
fun note_window's_''seen_first_expose''_oneshot
(XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, ... }, window_id, oneshot)
=
{
# log::note {. sprintf "note_window's_seen_first_expose_oneshot/TOP: window_id s=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
put_in_mailslot (plea_slot, plea::NOTE_''SEEN_FIRST_EXPOSE''_ONESHOT (window_id, oneshot));
# log::note {. sprintf "note_window's_seen_first_expose_oneshot/BOT: window_id s=%s -- xsocket-to-hostwindow-router-old.pkg" (xt::xid_to_string window_id); };
};
#
fun get_''seen_first_expose''_oneshot_of (XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, ... }, window_id)
=
{ reply_oneshot = make_oneshot_maildrop ();
#
put_in_mailslot (plea_slot, plea::GET_''SEEN_FIRST_EXPOSE''_ONESHOT (window_id, reply_oneshot));
#
get_from_oneshot reply_oneshot;
};
#
fun get_''gui_startup_complete''_oneshot_of (XSOCKET_TO_HOSTWINDOW_ROUTER { plea_slot, ... })
=
{ reply_oneshot = make_oneshot_maildrop ();
#
put_in_mailslot (plea_slot, plea::GET_''GUI_STARTUP_COMPLETE''_ONESHOT reply_oneshot);
#
get_from_oneshot reply_oneshot;
};
end; # stipulate
}; # package xsocket_to_hostwindow_router
end;