PreviousUpNext

15.4.1665  src/lib/x-kit/xclient/src/window/xsocket-to-hostwindow-router-old.pkg

## 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;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext