PreviousUpNext

15.3.719  src/lib/x-kit/xclient/xclient.api

## xclient.api
#

# Compiled by:
#     src/lib/x-kit/xclient/xclient.sublib

###               "You don't understand anything until you learn it more than one way."
###
###                                                      -- Marvin Minsky



###                "It is the mark of an educated mind to be able
###                 to entertain a thought without accepting it."
###
###                                      -- Aristotle



###                      "This ink of the scholar is more sacred than the blood of the martyr."
###
###                                                            -- Mohammed



###            "Classes struggle,
###             some classes triumph,
###             others are eliminated."
###
###                  -- Mao Zedong


###                    "A good workman is known by his tools."
###
###                                         -- proverb


###         "The right word may be effective,
###          but no word was ever as effective
###          as a rightly timed pause."
###
###                -- Mark Twain's Speeches



###             "I fear the the new object-oriented systems
###              may suffer the fate of LISP, in that they
###              can do many things, but the complexity of
###              the class hierarchies may cause them to
###              collapse under their own weight."
###
###                                       -- Bill Joy



stipulate
    include threadkit;
    #
    package xg =  xgeometry;                            # Xgeometry                     is from   src/lib/std/2d/xgeometry.api
herein

    api  Xclient {



        # Core xkit types and fns.

        version:  { major:    Int,
                    minor:    Int,
                    reverse:  Int,
                    date:     String
                  };

        version_name:  String;

        # Opaque types:
        #
        Xsession;                                       # Xsession                      def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        Screen;                                         # Screen                        def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        Window;                                         # Window                        def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        Font;                                           # Font                          def in    src/lib/x-kit/xclient/src/window/font-base.pkg
        Rw_Pixmap;                                      # Rw_Pixmap                     def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        Ro_Pixmap;                                      # Ro_Pixmap                     def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        Xcursor;                                        # Xcursor                       def in    src/lib/x-kit/xclient/src/window/cursors.pkg
        Rgb8;                                           # Rgb8                          def in    src/lib/x-kit/xclient/src/color/rgb8.pkg
        #
        eqtype Standard_Xcursor;                        # Standard_Xcursor              def in    src/lib/x-kit/xclient/src/window/cursors.pkg
        eqtype Atom;                                    # Atom                          def in    src/lib/x-kit/xclient/src/wire/xtypes.pkg

        exception NO_CHAR_INFO;                         # NO_CHAR_INFO                  def in    src/lib/x-kit/xclient/src/window/font-base.pkg
        exception FONT_PROPERTY_NOT_FOUND;              # FONT_PROPERTY_NOT_FOUND       def in    src/lib/x-kit/xclient/src/window/font-base.pkg
        exception FONT_NOT_FOUND;                       # FONT_NOT_FOUND                def in    src/lib/x-kit/xclient/src/window/font-imp.pkg

        open_font:  Xsession -> String -> Font;         # open_font                     def in    src/lib/x-kit/xclient/src/window/xsession.pkg

        # Font drawing direction:
        #
        Font_Drawing_Direction
          = DRAW_FONT_LEFT_TO_RIGHT
          | DRAW_FONT_RIGHT_TO_LEFT
          ;

        # Font properties 
        #
        Font_Prop
            =
            FONT_PROP
              {
                name:  Atom,                            # Name of the property.
                value:  one_word_unt::Unt                       # Value of the property: interpret according to the property. 
              };

        # Per-character font info: 
        #
        Char_Info
            =
            CHAR_INFO
              {
                left_bearing:   Int,
                right_bearing:  Int,
                char_width:     Int,
                ascent:         Int,
                descent:        Int,
                attributes:     Unt
              };

        font_property_of:  Font -> Atom -> one_word_unt::Unt;

        font_info_of
            :
            Font
            ->
            { min_bounds:  Char_Info,
              max_bounds:  Char_Info,
              #
              min_char:  Int,
              max_char:  Int
            };

        char_info_of:  Font -> Int    -> Char_Info;
        text_width:    Font -> String -> Int;
        char_width:    Font -> Char   -> Int;

        substr_width:  Font -> (String, Int, Int) -> Int;

        char_positions:  Font -> String -> List(Int);

        text_extents
            :
            Font
            ->
            String
            ->
            { dir:          Font_Drawing_Direction,
              #
              font_ascent:  Int,
              font_descent: Int,
              #
              overall_info: Char_Info
            };

        font_high
            :
            Font
            ->
            { ascent:   Int,
              descent:  Int
            };

        # Graphics functions -- the sixteen
        # possible functions of two boolean inputs:
        #
        Graphics_Op
          = OP_CLR              #  0 
          | OP_AND              #  src AND dst 
          | OP_AND_NOT          #  src AND NOT dst 
          | OP_COPY             #  src 
          | OP_AND_INVERTED     #  NOT src AND dst 
          | OP_NOP              #  Dst 
          | OP_XOR              #  src XOR dst 
          | OP_OR               #  src OR dst 
          | OP_NOR              #  NOT src AND NOT dst 
          | OP_EQUIV            #  NOT src XOR dst 
          | OP_NOT              #  NOT dst 
          | OP_OR_NOT           #  src OR NOT dst 
          | OP_COPY_NOT         #  NOT src 
          | OP_OR_INVERTED      #  NOT src OR dst 
          | OP_NAND             #  NOT src OR NOT dst 
          | OP_SET              #  1 
          ;

        Plane_Mask = PLANEMASK  Unt;    # This may belong elsewhere

        Shape = COMPLEX_SHAPE | NONCONVEX_SHAPE | CONVEX_SHAPE;

        #    "X attempts to provide a portable model of input devices;
        #     part of this support includes support for ``modifier keys'';
        #     i.e., keys that do not have an individual meaning, but which
        #     modify the meaning of other keys.  The following datatype
        #     represents the modifier keys."
        #
        #             -- p26 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        #
        Modifier_Key
          = SHIFT_KEY | LOCK_KEY | CONTROL_KEY
          | MOD1KEY | MOD2KEY | MOD3KEY | MOD4KEY | MOD5KEY
          | ANY_MODIFIER
          ;

        #     "The state of the modifier buttons (i.e., which are depressed)
        #      is represented by:"
        #
        #             -- p26 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        eqtype Modifier_Keys_State;

        # Keysyms are portable keycap representations:
        #
        Keysym = KEYSYM  Int | NO_SYMBOL;

        # Keycodes
        #
        Keycode = KEYCODE  Int;

        # Mouse buttons 
        #
        Mousebutton = MOUSEBUTTON  Int;

        # Mouse-d button states 
        #
        eqtype Mousebuttons_State;

        # Window stacking modes:
        #
        Stack_Mode = ABOVE
                   | BELOW
                   | TOP_IF
                   | BOTTOM_IF
                   | OPPOSITE
                   ;

        Drawable;

        #    "The X-protocol provides two operations for copying a rectangle
        #     from one drawable to another: CopyArea and CopyPlane.
        #
        #    "To further complicate things, these operations can have replies
        #     in the form of GraphicsExpose and NoExpose X-events.  When the
        #     source drawable is a window, then it is possible that some or
        #     all of the source rectangle might be obscured; in this case,
        #     the portions of the destination that did not get updated need
        #     to be redrawn.
        #
        #    "In [x-kit] we provde three versions of four operations, which
        #     are fully synchronous."
        #
        #             -- p21 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)

        # Sources for bitblt operations 
        #
        Draw_From
          = FROM_WINDOW          Window
          | FROM_RW_PIXMAP    Rw_Pixmap
          | FROM_RO_PIXMAP    Ro_Pixmap
          ;


        # Destinations for drawing operations.

        #    "A drawable [window] is an abstract type that collects
        #         together windows, [pixmaps] and overlays."
        #
        #             -- p20 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #

        drawable_of_rw_pixmap:  Rw_Pixmap -> Drawable;
        drawable_of_window:        Window -> Drawable;

        depth_of_drawable:   Drawable -> Int;



        # Create a locked version of the given window.
        # This provides exclusive access to its drawing
        # surface (and that of its descendents) during
        # OP_XOR rubber-banding.  Usually used in conjunction
        # with unbuffered drawing (below).      
        # 
        # The first result is the locked window on which to draw,
        # the second is the unlock operation for the drawable.
        # By convention, the overlay drawable is unbuffered.
        #
        # This call appears to be unused at present, but see
        # much related-looking "overlay" code in
        #     src/lib/x-kit/xclient/src/window/draw-imp.pkg
        # this may be a half-implemented idea.
        #
        make_locked_window
            :
            Window
            ->
            { drawable:  Drawable,
              release:   Void -> Void
            };

        make_unbuffered_drawable:  Drawable -> Drawable;
            #
            # An unbuffered drawable is used to provide immediate
            # graphical response to user interaction.  (Currently
            # this is implemented by transparently adding a flush
            # command after each draw command.)
            #
            # This call is used in many of the src/lib/x-kit/tut
            # programs, for example:
            #
            #     src/lib/x-kit/widget/fancy/graphviz/get-mouse-selection.pkg


        # X server timestamps.
        #
        package xserver_timestamp:    api {
                                          Xserver_Timestamp;

                                          to_float:  Xserver_Timestamp -> Float;

                                          +  : (Xserver_Timestamp, Xserver_Timestamp) -> Xserver_Timestamp;
                                          -  : (Xserver_Timestamp, Xserver_Timestamp) -> Xserver_Timestamp;

                                          # If you use these, remember that X server timestamps
                                          # WRAP AROUND MONTHLY, so you cannot assume that
                                          #
                                          #     timestamp1 < timestamp2
                                          #     =>                              # DANGER!
                                          #     timestamp1  earlier_than  timestamp2
                                          #
                                          <  : (Xserver_Timestamp, Xserver_Timestamp) -> Bool;
                                          <= : (Xserver_Timestamp, Xserver_Timestamp) -> Bool;
                                          >  : (Xserver_Timestamp, Xserver_Timestamp) -> Bool;
                                          >= : (Xserver_Timestamp, Xserver_Timestamp) -> Bool;
                                      };

        # Xauthentication information. 
        # This type actually gets defined in:
        #
        #     src/lib/x-kit/xclient/src/wire/xtypes.pkg
        #
        # At runtime this information gets extracted from
        #
        #     ~/.Xauthority
        #
        # by code (e.g. get_xdisplay_string_and_xauthentication) in
        #
        #     src/lib/x-kit/xclient/src/stuff/authentication.pkg
        #
        # and then passed successively to:
        #
        #     root_window::make_root_window                     in    src/lib/x-kit/widget/basic/root-window.pkg
        #     xession::open_xsession                            in    src/lib/x-kit/xclient/src/window/xsession.pkg
        #     display::open_xdisplay                            in    src/lib/x-kit/xclient/src/wire/display.pkg
        #     value_to_wire::encode_xserver_connection_request  in    src/lib/x-kit/xclient/src/wire/value-to-wire.pkg
        #
        # and ultimately to the X server.       
        #
        Xauthentication
            =
            XAUTHENTICATION
              {
                family:   Int,                                          # E.g. xauthentication::family_internet
                address:  String,                                               # E.g. "127.0.0.1"
                display:  String,                                               # E.g. "0"
                name:     String,                                               # E.g. "MIT-MAGIC-COOKIE-1"
                data:     vector_of_one_byte_unts::Vector                               # For   MIT-MAGIC-COOKIE-1 this is 16 bytes (128 bits) of random data.
              };

        # This is our preferred vanilla color representation,
        # based on a (red, green, blue) float triple representation:
        Rgb;
        #
        # Predefine a few common colors for convenience:
        #
        black:   Rgb;
        white:   Rgb;
        red:     Rgb;
        green:   Rgb;
        blue:    Rgb;
        cyan:    Rgb;
        magenta: Rgb;
        yellow:  Rgb;
        #
        rgb8_color0:   Rgb8;
        rgb8_color1:   Rgb8;
        rgb8_white:    Rgb8;
        rgb8_black:    Rgb8;
        rgb8_red:      Rgb8;
        rgb8_green:    Rgb8;
        rgb8_blue:     Rgb8;
        rgb8_cyan:     Rgb8;
        rgb8_magenta:  Rgb8;
        rgb8_yellow:   Rgb8;
        #
        rgb_normalize:     Rgb -> Rgb;
        #
        rgb_from_unts:    (Unt, Unt, Unt) -> Rgb;
        rgb_to_unts:       Rgb -> (Unt, Unt, Unt);
        #
        rgb_from_floats:  (Float, Float, Float) -> Rgb;
        rgb_to_floats:    Rgb -> (Float, Float, Float);

        rgb8_from_ints: (Int, Int, Int) -> Rgb8;
        rgb8_from_int:  Int             -> Rgb8;
        rgb8_from_name: String          -> Rgb8;
        rgb8_from_rgb:  Rgb             -> Rgb8;
        #
        rgb8_to_ints:   Rgb8 -> (Int, Int, Int);
        rgb8_to_int:    Rgb8 -> Int;

        # Identity tests:
        #
        same_xsession: (Xsession, Xsession) -> Bool;                            # same_xsession                                         def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        same_screen:   (Screen, Screen)     -> Bool;                            # same_screen                                           def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        same_window:   (Window, Window)     -> Bool;                            # same_window                                           def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        same_font:     (Font, Font)         -> Bool;                            # same_font                                             def in    src/lib/x-kit/xclient/src/window/font-base.pkg
        same_cursor:   (Xcursor, Xcursor)   -> Bool;                            # same_cursor                                           def in    src/lib/x-kit/xclient/src/window/cursors.pkg
        same_rgb:      (Rgb, Rgb)           -> Bool;                            # same_rgb                                              def in    src/lib/x-kit/xclient/src/color/rgb.pkg 
        same_rgb8:     (Rgb8, Rgb8)         -> Bool;                            # same_rgb8                                             def in    src/lib/x-kit/xclient/src/color/rgb8.pkg
        #
        same_rw_pixmap                                                          # same_rw_pixmap                                        def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
            :
            ( Rw_Pixmap,
              Rw_Pixmap
            )
            ->
            Bool;

        same_ro_pixmap                                                          # same_ro_pixmap                                        def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
            :
            ( Ro_Pixmap,
              Ro_Pixmap
            )
            ->
            Bool;


        # Xsession operations
        #
        exception XSERVER_CONNECT_ERROR  String;
        #
        open_xsession:     (String, Null_Or(Xauthentication)) -> Xsession;      # open_xsession                                         def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        close_xsession:     Xsession -> Void;                                   # close_xesession                                       def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        default_screen_of:  Xsession -> Screen;                                 # default_screen_of                                     def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        screens_of:         Xsession -> List( Screen );                         # screens_of                                            def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        ring_bell:          Xsession -> Int -> Void;                            # ring_bell                                             def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        max_request_length: Xsession -> Int;                                    # max_request_length                                    def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        get_''gui_startup_complete''_oneshot_of_xsession                        # get_''gui_startup_complete''_oneshot_of_xsesion       def in    src/lib/x-kit/xclient/src/window/xsession.pkg
            :
            Xsession -> Oneshot_Maildrop(Void);                                 # See comments in   src/lib/x-kit/xclient/src/window/xsocket-to-topwindow-router.api

        # Get/set location of mouse pointer
        # relative to root window:
        #
        get_mouse_location: Xsession -> xg::Point;                              # get_mouse_location                                    def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        set_mouse_location: Xsession -> xg::Point -> Void;                      # set_mouse_location                                    def in    src/lib/x-kit/xclient/src/window/xsession.pkg

        # Screen operations:
        #
        xsession_of_screen: Screen -> Xsession;                                 # xsession_of_screen                                    def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        size_of_screen:     Screen -> xg::Size;                                 # size_of_screen                                        def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        mm_size_of_screen:  Screen -> xg::Size;                                 # mm_size_of_screen                                     def in    src/lib/x-kit/xclient/src/window/xsession.pkg
        depth_of_screen:    Screen -> Int;                                      # depth_of_screen                                       def in    src/lib/x-kit/xclient/src/window/xsession.pkg


        Display_Class
          = STATIC_GRAY
          | GRAY_SCALE
          | STATIC_COLOR
          | PSEUDO_COLOR
          | TRUE_COLOR
          | DIRECT_COLOR
          ;

         display_class_of_screen                                                # display_class_of_screen                               def in    src/lib/x-kit/xclient/src/window/xsession.pkg
            :
            Screen -> Display_Class;


        # Window, rw_pixmap and ro_pixmap geometry functions:
        #
        depth_of_window:          Window -> Int;                                # depth_of_window                                       def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        depth_of_rw_pixmap:    Rw_Pixmap -> Int;                                # depth_of_rw_pixmap                                    def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        depth_of_ro_pixmap:    Ro_Pixmap -> Int;                                # depth_of_ro_pixmap                                    def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        #
        size_of_window:           Window -> xg::Size;                           # size_of_pixmap                                        def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        size_of_rw_pixmap:     Rw_Pixmap -> xg::Size;                           # size_of_rw_pixmap                                     def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        size_of_ro_pixmap:     Ro_Pixmap -> xg::Size;                           # size_of_ro_pixmap                                     def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        #
        shape_of_window:          Window -> {  upperleft: xg::Point,  size: xg::Size,  depth: Int,  border_thickness: Int  };   # "                                     "
        shape_of_rw_pixmap:    Rw_Pixmap -> {  upperleft: xg::Point,  size: xg::Size,  depth: Int,  border_thickness: Int  };   # "                                     "
        shape_of_ro_pixmap:    Ro_Pixmap -> {  upperleft: xg::Point,  size: xg::Size,  depth: Int,  border_thickness: Int  };   # "                                     "
        #
        id_of_window:          Window -> Int;                           # id_of_window                  def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        id_of_rw_pixmap:    Rw_Pixmap -> Int;                           # id_of_rw_pixmap               def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
        id_of_ro_pixmap:    Ro_Pixmap -> Int;                           # id_of_ro_pixmap               def in    src/lib/x-kit/xclient/src/window/draw-types.pkg
            #
            # These give windows etc distinguishing marks
            # visible at the application programmer level,
            # which is essential for tracelog debugging.



        #  Client-side windows:
        #
        Cs_Pixmap
            =
            CS_PIXMAP
              {
                size:  xg::Size,
                data:  List( List( vector_of_one_byte_unts::Vector ))
              };

        exception BAD_CS_PIXMAP_DATA;

        make_clientside_pixmap_from_ascii                                               # make_clientside_pixmap_from_ascii     def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
            :
            (Int, List( List( String ) ))
            ->
            Cs_Pixmap;


        # Rw_Pixmap and ro_pixmap operations:
        #
        exception BAD_PIXMAP_PARAMETER;

        make_readwrite_pixmap:                         Screen -> (xg::Size, Int)            -> Rw_Pixmap;               # make_readwrite_pixmap                         def in    src/lib/x-kit/xclient/src/window/rw-pixmap.pkg
        make_readwrite_pixmap_from_ascii_data:         Screen -> (Int, List( List(String))) -> Rw_Pixmap;               # make_readwrite_pixmap_from_ascii_data         def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
        make_readwrite_pixmap_from_clientside_pixmap:  Screen -> Cs_Pixmap                  -> Rw_Pixmap;               # make_readwrite_pixmap_from_clientside_pixmap  def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg

        destroy_rw_pixmap:                              Rw_Pixmap -> Void;                                              # destroy_rw_pixmap                             def in    src/lib/x-kit/xclient/src/window/rw-pixmap.pkg

        make_readonly_pixmap_from_ascii:                Screen -> (Int, List(List(String))) -> Ro_Pixmap;               # make_readonly_pixmap_from_ascii               def in    src/lib/x-kit/xclient/src/window/ro-pixmap.pkg
        make_readonly_pixmap_from_clientside_pixmap:    Screen -> Cs_Pixmap                 -> Ro_Pixmap;               # make_ro_pixmal_from_clientside_pixmap         def in    src/lib/x-kit/xclient/src/window/ro-pixmap.pkg
        make_readonly_pixmap_from_readwrite_pixmap:     Rw_Pixmap                           -> Ro_Pixmap;               # make_ro_pixmal_from_rw_pixmap                 def in    src/lib/x-kit/xclient/src/window/ro-pixmap.pkg

        make_clientside_pixmap_from_readwrite_pixmap:   Rw_Pixmap -> Cs_Pixmap;                                         # make_clientside_pixmap_from_readwrite_pixmap  def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
        make_clientside_pixmap_from_readonly_pixmap:    Ro_Pixmap -> Cs_Pixmap;                                         # make_clientside_pixmap_from_readonly_pixmap   def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
        make_clientside_pixmap_from_window:   (xg::Box, Window)   -> Cs_Pixmap;                                         # make_clientside_pixmap_from_window            def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg

        same_cs_pixmap:                             (Cs_Pixmap, Cs_Pixmap) -> Bool;                                     # same_cs_pixmap                                def in    src/lib/x-kit/xclient/src/window/cs-pixmap.pkg

        # Window hashtables:

        Window_Map(X);

        exception WINDOW_NOT_FOUND;

        make_map: Void -> Window_Map(X);
        set:      Window_Map(X) -> ((Window, X)) -> Void;
        get:      Window_Map(X) -> Window -> X;
        remove:   Window_Map(X) -> Window -> X;
        list:     Window_Map(X) -> List(X);


        # Colors.
        #
        #    "This release of [x-kit] supports the most basic
        #     use of color supported by X: read-only access to
        #     the default colormap using either RGB values or
        #     names to specify the color.  A devide-independent
        #     mechanism for specifying colors is part of the
        #     X11R5 standard.  We plan to use this as the basis
        #     for future color support in [x-kit]."
        #
        #    "To determine whether a screen supports color, one
        #     can use the function display_class_of_screen to determine
        #     the screen's display class.  A monochrome screen,
        #     for example, will usually have the display class
        #     StaticGray and a depth of one."
        #
        #    "Colors are specified either by name or RGB value,
        #     using the Color_Spec datatype.  The values 'black'
        #     and 'white' specify their respecive colors.  A
        #     Color_Spec is mapped to an abstract Color value
        #     using the function color_of_screen.  The functions
        #     black_of_screen and white_of_screen return the black
        #     and white colors for the given screen.  The colors
        #     'color0' and 'color1' represent the 0 and 1 pixel
        #     values, and are used to draw on [Pixmap]s."
        #
        #             -- p24 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        #
        Color_Spec
          = CMS_NAME  String
          | CMS_RGB  { red:  Unt, green:  Unt, blue:  Unt }
          ;

        get_color:  Color_Spec -> Rgb;


        # Cursors:

        get_standard_xcursor:   Xsession -> Standard_Xcursor -> Xcursor;
            #
            # These are currently the only cursors
            # supported by x-kit.

        recolor_cursor
            :
            { cursor:  Xcursor,
              #
              foreground_rgb:  Rgb,
              background_rgb:  Rgb
            }
            ->
            Void;


        change_active_grab_cursor:  Xsession -> Xcursor -> Void;
            #
            # Change the cursor during an "active grab" of the mouse.

        # Gravity (both window and bit):
        #
        Gravity
          = FORGET_GRAVITY       #  Bit gravity only 
          | UNMAP_GRAVITY        #  window gravity only 
          | NORTHWEST_GRAVITY
          | NORTH_GRAVITY
          | NORTHEAST_GRAVITY
          | WEST_GRAVITY
          | CENTER_GRAVITY
          | EAST_GRAVITY
          | SOUTHWEST_GRAVITY
          | SOUTH_GRAVITY
          | SOUTHEAST_GRAVITY
          | STATIC_GRAVITY
          ;

        keysym_to_keycode: (Xsession, Keysym) -> Null_Or(Keycode);


        ################ start of authentication stuff #################
        # Motivation
        # ----------
        #
        # When I started programming in the 1970s workstations were shipped
        # with X configured to accept all client connections and most people
        # left them that way;  consequently, in general anyone anywhere on
        # the ARPANET could in open up an X window on any other machine
        # connected to the ARPANET.  Requiring passwords to log onto a machine
        # was considered by many people to be anti-social;  Stallman used to
        # advertise that he used an accountname of "rms" and password also "rms"
        # as protest against the imposition of passwords.  As late as 1990 muds
        # were resisting the use of passwords. 
        #
        # That was a different era;  such openness is not very practical on
        # today's savage Internet.  Consequently some way must be found to
        # restrict the set of people/machines allowed to connect to a given
        # X server.  The typical X authentication scheme used these days is
        # MIT-MAGIC-COOKIE-1, which works roughly so:
        #
        #  o When an X server is started, it is given a list of
        #    128-bit random numbers ("cookies"); it will accept
        #    any X client presenting one of those cookies.
        #
        #  o At user login XDM stores the cookie for the machine in the
        #    user's ~/.Xauthority file, keyed by machine address.  This
        #    file may contain multiple cookies to allow connection to
        #    multiple X servers.
        #
        #  o When an X client program is run, it looks up the X server
        #    (typically obtained from the DISPLAY environment variable)
        #    in ~/.Xauthority, locates the corresponding cookie, and
        #    forwards it as part of the X connection request message to
        #    the X server.  For X clients written in C this is usually
        #    handled transparently by xlib.
        #
        # (xlib and the X server do no encryption themselves, consequently it
        # is best to use ssh X forwarding to avoid sending cookies in the clear.)
        #
        # In this file we define an API to functionality for fetching cookies
        # from ~/.Xauthority, plus related functionality for finding the proper
        # .Xauthority file and parsing X server addresses obtained from DISPLAY
        # environment variables.  Typical usage:
        #
        #     my (display, cookie) = get_xdisplay_string_and_xauthentication NULL;
        #
        #     root_window = make_root_window (display, cookie);
        #
        # or simply
        #
        #     root_window = make_root_window (get_xdisplay_string_and_xauthentication NULL);
        #
        # See for example the code in:
        #
        #     src/lib/x-kit/widget/lib/run-in-x-window.pkg

        # The different network protocol families:
        #
        family_internet:  Int;
        family_decnet:    Int;
        family_chaos:     Int;
        family_local:     Int;
        family_wild:      Int;

        get_xauthority_filename:  Void -> String;
            #
            # Return the default name of the authentication file (either
            # specified by the XAUTHORITY dictionary variable, or the
            # file $HOME/.Xauthority.  If neither XAUTHORITY or HOME 
            # are defined, then ".Xauthority" is returned.


        get_xauthority_file_entry_by_address
            :
            { family:   Int,                    # family_wild, family_local, family_internet ...
              address:  String,                 # Identity of our workstation, from gethostname(2) or such.
              display:  String                  # E.g. "0" -- from "localhost:0.1" DISPLAY string or such.
            }
            ->
            Null_Or( Xauthentication );
            #
            # Search the default xauthority file for the first entry that
            # matches the family, network address and display number.  If no
            # such match is found, then NULL is returned.  The * value family_wild
            # matches anything, as do the empty strings when given for address or display.


        get_best_xauthority_file_entry_by_address
            :
            { family:      Int,                 # family_wild, family_local, family_internet ...
              address:     String,              # Identity of our workstation, from gethostname(2) or such.
              display:     String,              # E.g. "0" -- from "localhost:0.1" DISPLAY string or such.
              #         
              acceptable_authentication_methods:  List( String )        # E.g.  [ "MIT-MAGIC-COOKIE-1" ]
            }
            ->
            Null_Or( Xauthentication );
            #
            # This is similar to get_xauthority_file_entry_by_address,
            # except that a list of acceptable authentication methods
            # is specified by the list acceptable_authentication_methods.
            # This contains one or more strings like
            #
            #     "MIT-MAGIC-COOKIE-1"
            #     "XDM-AUTHORIZATION-1"
            #     "SUN-DES-1"
            #     "MIT-KERBEROS-5"
            #
            # to match literally against the contents of ~/.Xauthority entries.
            #
            # Not all of these are available everywhere; the de facto standard
            # method is MIT-MAGIC-COOKIE-1.  For more information about the
            # various authentication methods see (e.g.):
            #
            #     man 7 Xsecurity
            #     http://manpages.ubuntu.com/manpages/jaunty/man7/Xsecurity.7.html
            #
            # We return the matching authentication info that matches the earliest
            # name on the list.
            #
            # We return NULL if no match is found.


        get_selected_xauthority_file_entries
            :
            (Xauthentication -> Bool)
            ->
            String
            ->
            List( Xauthentication );
            #
            # Read the specified authentication file
            # (usually ~/.Xauthority) and return a list
            # of the entries that satisfy the given predicate.


        # Parse a string specifying an
        # X display into its components:
        #
        parse_xdisplay_string
            :
            String
            ->
            { host:    String,
              display: String,
              screen:  String
            };

        # Given an optional display name, return
        # the display and authentication information.
        #
        # If the argument is NULL we use the unix DISPLAY
        # environment variable if defined else  "".
        #
        get_xdisplay_string_and_xauthentication
            :
            Null_Or( String )
            ->
            (String, Null_Or( Xauthentication ));

        ################ end of authentication stuff #################



        # X cursor stuff gets its own subpackage:
        #
        package cursors: api {

            # The "names" of the standard cursors supplied by the X server.
            #
            # Currently these are the only cursors supported by x-kit.

            x_cursor:            Standard_Xcursor;
            arrow:               Standard_Xcursor;
            based_arrow_down:    Standard_Xcursor;
            based_arrow_up:      Standard_Xcursor;
            boat:                Standard_Xcursor;
            bogosity:            Standard_Xcursor;
            bottom_left_corner:  Standard_Xcursor;
            bottom_right_corner: Standard_Xcursor;
            bottom_side:         Standard_Xcursor;
            bottom_tee:          Standard_Xcursor;
            box_spiral:          Standard_Xcursor;
            center_ptr:          Standard_Xcursor;
            circle:              Standard_Xcursor;
            clock:               Standard_Xcursor;
            coffee_mug:          Standard_Xcursor;
            cross:               Standard_Xcursor;
            cross_reverse:       Standard_Xcursor;
            crosshair:           Standard_Xcursor;
            diamond_cross:       Standard_Xcursor;
            dot:                 Standard_Xcursor;
            dotbox:              Standard_Xcursor;
            double_arrow:        Standard_Xcursor;
            draft_large:         Standard_Xcursor;
            draft_small:         Standard_Xcursor;
            draped_box:          Standard_Xcursor;
            exchange:            Standard_Xcursor;
            fleur:               Standard_Xcursor;
            gobbler:             Standard_Xcursor;
            gumby:               Standard_Xcursor;
            hand1:               Standard_Xcursor;
            hand2:               Standard_Xcursor;
            heart:               Standard_Xcursor;
            icon:                Standard_Xcursor;
            iron_cross:          Standard_Xcursor;
            left_ptr:            Standard_Xcursor;
            left_side:           Standard_Xcursor;
            left_tee:            Standard_Xcursor;
            leftbutton:          Standard_Xcursor;
            ll_angle:            Standard_Xcursor;
            lr_angle:            Standard_Xcursor;
            man:                 Standard_Xcursor;
            middlebutton:        Standard_Xcursor;
            mouse:               Standard_Xcursor;
            pencil:              Standard_Xcursor;
            pirate:              Standard_Xcursor;
            plus:                Standard_Xcursor;
            question_arrow:      Standard_Xcursor;
            right_ptr:           Standard_Xcursor;
            right_side:          Standard_Xcursor;
            right_tee:           Standard_Xcursor;
            rightbutton:         Standard_Xcursor;
            rtl_logo:            Standard_Xcursor;
            sailboat:            Standard_Xcursor;
            sb_down_arrow:       Standard_Xcursor;
            sb_h_double_arrow:   Standard_Xcursor;
            sb_left_arrow:       Standard_Xcursor;
            sb_right_arrow:      Standard_Xcursor;
            sb_up_arrow:         Standard_Xcursor;
            sb_v_double_arrow:   Standard_Xcursor;
            shuttle:             Standard_Xcursor;
            sizing:              Standard_Xcursor;
            spider:              Standard_Xcursor;
            spraycan:            Standard_Xcursor;
            star:                Standard_Xcursor;
            target:              Standard_Xcursor;
            tcross:              Standard_Xcursor;
            top_left_arrow:      Standard_Xcursor;
            top_left_corner:     Standard_Xcursor;
            top_right_corner:    Standard_Xcursor;
            top_side:            Standard_Xcursor;
            top_tee:             Standard_Xcursor;
            trek:                Standard_Xcursor;
            ul_angle:            Standard_Xcursor;
            umbrella:            Standard_Xcursor;
            ur_angle:            Standard_Xcursor;
            watch:               Standard_Xcursor;
            xterm:               Standard_Xcursor;
        };                                                      # package cursors



        ################ start of draw stuff #################
        #

        package p: api {
            #
            Pen_Trait
              = FUNCTION  Graphics_Op
              | PLANE_MASK  Plane_Mask
              | FOREGROUND  Rgb8
              | BACKGROUND  Rgb8
              | LINE_WIDTH  Int
              | LINE_STYLE_SOLID
              | LINE_STYLE_ON_OFF_DASH
              | LINE_STYLE_DOUBLE_DASH
              | CAP_STYLE_NOT_LAST
              | CAP_STYLE_BUTT
              | CAP_STYLE_ROUND
              | CAP_STYLE_PROJECTING
              | JOIN_STYLE_MITER
              | JOIN_STYLE_ROUND
              | JOIN_STYLE_BEVEL
              | FILL_STYLE_SOLID
              | FILL_STYLE_TILED
              | FILL_STYLE_STIPPLED
              | FILL_STYLE_OPAQUE_STIPPLED
              | FILL_RULE_EVEN_ODD
              | FILL_RULE_WINDING
              | ARC_MODE_CHORD
              | ARC_MODE_PIE_SLICE
              | CLIP_BY_CHILDREN
              | INCLUDE_INFERIORS
              | RO_PIXMAP  Ro_Pixmap
              | STIPPLE  Ro_Pixmap
              | STIPPLE_ORIGIN  xg::Point
              | CLIP_ORIGIN     xg::Point
              | CLIP_MASK_NONE
              | CLIP_MASK  Ro_Pixmap
              | CLIP_MASK_UNSORTED_BOXES  List( xg::Box )
              | CLIP_MASK_YSORTED_BOXES   List( xg::Box )
              | CLIP_MASK_YXSORTED_BOXES  List( xg::Box )
              | CLIP_MASK_YXBANDED_BOXES  List( xg::Box )
              | DASH_OFFSET Int
              | DASH_FIXED  Int
              | DASH_LIST   List( Int )
              ;
        };

        # This api brings together all of the
        # drawing-related types and operations.
        #
        # For Gansner+Reppy's original 1993 drawing docs
        # see Chapter 5 (page 16) in their eXene library manual:
        #
        #     http:://mythryl.org/pub/exene/1993-lib.ps
        #

        # This api is implemented in
        #
        #     src/lib/x-kit/xclient/xclient.pkg
        #
        # with the bulk of the code coming from:
        #
        #     src/lib/x-kit/xclient/src/window/draw.pkg

        Pen;

        exception BAD_PEN_TRAIT;

        make_pen:          List(p::Pen_Trait) -> Pen;
        clone_pen:   (Pen, List(p::Pen_Trait)) -> Pen;          # Make a copy of given pen, with given differences.
        default_pen:   Pen;






        # Drawing operations.
        #
        #     "The semantics are essentially the same as in xlib,
        #      although the names are different.
        #
        #     "Functions that draw ``paths'' treat their List(Point)
        #      argument as a list of relative coordinates.  The
        #      first element specifies an absolute coordinate and
        #      each successive element specifies an offset relative
        #      to the previous coordinate.
        #
        #     "All other operations use absolute coordinates.. 
        #
        #     "The exception BAD_DRAW_PARAMETER is raised if the
        #      argument to a drawable is invalid."
        #
        #             -- p20 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        exception BAD_DRAW_PARAMETER;

        draw_points:      Drawable -> Pen -> List( xg::Point ) -> Void;
        draw_point_path:  Drawable -> Pen -> List( xg::Point ) -> Void;
        draw_point:       Drawable -> Pen ->       xg::Point   -> Void;

        draw_lines:    Drawable -> Pen -> List( xg::Point ) -> Void;
        draw_path:     Drawable -> Pen -> List( xg::Point ) -> Void;
        draw_segs:     Drawable -> Pen -> List( xg::Line  ) -> Void;
        draw_seg:      Drawable -> Pen ->       xg::Line    -> Void;

        fill_polygon:  Drawable -> Pen -> { verts: List( xg::Point ), shape:  Shape } -> Void;
        fill_path:     Drawable -> Pen -> { path:  List( xg::Point ), shape:  Shape } -> Void;

        draw_boxes:    Drawable -> Pen -> List( xg::Box ) -> Void;
        draw_box:      Drawable -> Pen ->       xg::Box   -> Void;
        fill_boxes:    Drawable -> Pen -> List( xg::Box ) -> Void;
        fill_box:      Drawable -> Pen ->       xg::Box   -> Void;

        draw_arcs:     Drawable -> Pen -> List( xg::Arc ) -> Void;
        draw_arc:      Drawable -> Pen ->       xg::Arc   -> Void;
        fill_arcs:     Drawable -> Pen -> List( xg::Arc ) -> Void;
        fill_arc:      Drawable -> Pen ->       xg::Arc   -> Void;

        draw_circle:   Drawable -> Pen -> { center:  xg::Point, rad:  Int } -> Void;
        fill_circle:   Drawable -> Pen -> { center:  xg::Point, rad:  Int } -> Void;


        # Polytext drawing.
        #
        #    "There are two styles of text drawing: opaque and transparent.
        #
        #    "Opaque text [...] is drawn by first filling in the bounding box
        #     with the background color and then drawing the text with the
        #     foreground color.  The function and fill-style of the pen are
        #     ignored, replaced in effect by OP_COPY and pen::FILL_STYLE_SOLID
        #
        #    "In transparent text [...] the pixels corresponding to bits set in
        #     a character's glyph are drawn using the foreground color in the
        #     context of the other relevant pen values, while the other pixels
        #     are unmodified.
        #
        #    "The [draw_transparent_text] function provides a user-level batching
        #     mechanism for drawing multiple strings of the same line with possible
        #     intervening font changes or horizontal shifts."
        #
        #             -- p22-3 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        package t: api {
            #
            Text      = TEXT         (Font, List(Text_Item))
            #
            also
            Text_Item = FONT         (Font, List(Text_Item))
                      | STRING        String
                      | BLANK_PIXELS  Int                       # Skip this many pixels before next STRING.
                      ;
        };

        draw_opaque_string:        Drawable -> Pen -> Font -> (xg::Point, String ) -> Void;
        draw_transparent_string:   Drawable -> Pen -> Font -> (xg::Point, String ) -> Void;
        draw_transparent_text:     Drawable -> Pen ->         (xg::Point, t::Text) -> Void;




        exception DEPTH_MISMATCH;
        exception BAD_PLANE;

        # *_mailop versions
        # =================
        #
        # The synchronous (non- _mailop) versions of the
        # blt operations can be slow because they have
        # wait for a reply from the X server.  If the
        # X server is remote, this can involve a network
        # round-trip of tens or even hundreds of milliseconds.
        # Even if the X server is local, it can involve two
        # or more slow process switches.
        #
        # We address this problem by providing asynchronous
        # _mailop versions of these operations:
        #
        #     pixel_blt_mailop
        #     bitblt_mailop
        #     plane_blt_mailop
        #     copy_blt_mailop
        #
        # These return mailops which will evaluate to the
        # result boxlists when the relevant X events arrive
        # from the X server:  By doing a block_until_mailop_fires() on them
        # in a throwaway thread, or by doing a select() on
        # themspinning off

        pixel_blt
            :  Drawable
            -> Pen
            -> { from:      Draw_From,
                 from_box:  xg::Box,
                 to_pos:    xg::Point
               }
            -> List( xg::Box )
            ;
            # Provides CopyArea semantics.
            # Raises DEPTH_MISMATCH if 'to' and 'from'
            # drawables do not have same depth.
            #
            # Return value is list of rectangles on
            # 'to' which need to be redrawn because
            # the corresponding 'from' areas were
            # obscured. (This can only happen when
            # 'from' is an onscreen window.)
            #
            # If 'from' is smaller than the 'to' box,
            # the unspecified pixels are zero-filled
            # -- color0.

        pixel_blt_mailop
            :  Drawable
            -> Pen
            -> { from:       Draw_From,
                 from_box:   xg::Box,
                 to_pos:     xg::Point
               }
            ->  threadkit::Mailop( List( xg::Box ) )
            ;
            # pixel_blt with asynchronous resultlist
            # handling for performance:  Do a select()
            # or block_until_mailop_fires() on the result to obtain
            # and redraw the resulting boxlist. list.
            #
            # If 'to' is known not to be a Window
            # (i.e., if it is an Pixmap
            # or Ro_Pixmap) -- or if it is known
            # not to be obscured -- then the returned
            # mailop can simply be discarded, since
            # is the obtained boxlist will always be
            # empty.

        bitblt
            :  Drawable
            -> Pen
            -> { from:      Draw_From,
                 from_box:  xg::Box,
                 to_pos:    xg::Point
               }
            ->  List( xg::Box )
            ;
            # Same as plane_blt with 'plane' == 0.

        bitblt_mailop
            :  Drawable
            -> Pen
            -> { from:       Draw_From,
                 from_box:   xg::Box,
                 to_pos:     xg::Point
               }
            -> threadkit::Mailop( List( xg::Box ) )
            ;
            # bit_blt with asynchronous resultlist
            # handling for performance:  Do a select()
            # or block_until_mailop_fires() on the result to obtain
            # and redraw the resulting boxlist. list.
            #
            # If 'to' is known not to be a Window
            # (i.e., if it is a Rw_Pixmap
            # or Ro_Pixmap) -- or if it is known
            # not to be obscured -- then the returned
            # mailop can simply be discarded, since
            # is the obtained boxlist will always be
            # empty.

        plane_blt
            :  Drawable
            -> Pen
            -> { from:      Draw_From,
                 from_box:  xg::Box,
                 to_pos:    xg::Point,
                 plane:     Int
               }
            -> List( xg::Box )
            ;   #
                # Provides CopyPlane semantics;
                # Raises BAD_PLANE if 'plane' is not
                # a legal bitplan in 'from'.
                #
                # Return value is list of rectangles on
                # 'to' which need to be redrawn because
                # the corresponding 'from' areas were
                # obscured. This can only happen when
                # 'from' is an onscreen Sindow: if it
                # is an Rw_Pixmap or Ro_Pixmap
                # the return list will always be empty.
                #
                # If 'from' is smaller than the 'to' box,
                # the unspecified pixels are zero-filled
                # -- color0.

        plane_blt_mailop
            :  Drawable
            -> Pen
            -> { from:      Draw_From,
                 from_box:  xg::Box,
                 to_pos:    xg::Point,
                 plane:     Int
               }
            -> threadkit::Mailop( List( xg::Box ) )
            ;
            # plane_blt with asynchronous resultlist
            # handling for performance:  Do a select()
            # or block_until_mailop_fires() on the result to obtain
            # and redraw the resulting boxlist. list.
            #
            # If 'to' is known not to be a Window
            # (i.e., if it is a Rw_Pixmap
            # or Ro_Pixmap) -- or if it is known
            # not to be obscured -- then the returned
            # mailop can simply be discarded, since
            # is the obtained boxlist will always be
            # empty.


        texture_blt:  Drawable -> Pen -> { from:  Ro_Pixmap, to_pos:  xg::Point } -> Void;
        tile_blt:     Drawable -> Pen -> { from:  Ro_Pixmap, to_pos:  xg::Point } -> Void;
            #
            # tile_blt is a bitblt where 'from'
            # is all of a depth-1 Ro_Pixmap. 

        copy_blt
            :  Drawable
            -> Pen
            -> { to_pos:    xg::Point,
                 from_box:  xg::Box
               }
            -> List( xg::Box )
            ;
            # A pixel_blt where 'to' and 'from'
            # are the same drawable.

        copy_blt_mailop
            :  Drawable
            -> Pen
            -> { to_pos:   xg::Point,
                 from_box: xg::Box
               }
            -> threadkit::Mailop( List( xg::Box ) )
            ;
            # copy_blt with asynchronous resultlist
            # handling for performance:  Do a select()
            # or block_until_mailop_fires() on the result to obtain
            # and redraw the resulting boxlist. list.
            #
            # If 'to' is known not to be a Window
            # (i.e., if it is a Rw_Pixmap
            # or Ro_Pixmap) -- or if it is known
            # not to be obscured -- then the returned
            # mailop can simply be discarded, since
            # is the obtained boxlist will always be
            # empty.


        #     "Clear a rectangular region (or all) of a drawable.
        #
        #     "For a window, these functions will with the background color;
        #      For an offscreen window, they fill with 0.
        #
        #     "If the retangle's width is zero, then the cleared rectangle
        #      is extended to the right edge of the drawable, and if the
        #      height is zero, then the cleared rectangle is extended to
        #      the bottom of the drawable."
        #
        #             -- p21 http:://mythryl.org/pub/exene/1993-lib.ps
        #            (Reppy + Gansner's 1993 eXene library manual.)
        #
        clear_box:       Drawable -> xg::Box -> Void;
        clear_drawable:  Drawable -> Void;                      # Clear entire drawable.


        # Flush all queued draw commands to X server.
        # Normally the draw imp sends them in batches
        # as a network optimization, flushing the
        # the buffer every 40ms; this call will flush
        # immediately:
        #
        flush:           Drawable -> Void;

        drawimp_thread_id_of:    Drawable -> Int;
            #
            # This lets the application programmer tell
            # which drawables use which draw imps, which
            # is occasionally important when debugging,
            # for example to decide if you're flushing
            # the right draw imp(s) before doing a GetImage
            # request to the X server.


        ################ end of draw stuff #################



        ################ start of input stuff #################
        #
        #

        # Types and operations to support user interaction
        # and other external X-events.

        make_modifier_keys_state:  List(Modifier_Key) -> Modifier_Keys_State;

        union_of_modifier_keys_states:         (Modifier_Keys_State, Modifier_Keys_State) -> Modifier_Keys_State;
        intersection_of_modifier_keys_states:  (Modifier_Keys_State, Modifier_Keys_State) -> Modifier_Keys_State;

        modifier_keys_state_is_empty:  Modifier_Keys_State -> Bool;
        shift_key_is_set:              Modifier_Keys_State -> Bool;
        shiftlock_key_is_set:          Modifier_Keys_State -> Bool;
        control_key_is_set:            Modifier_Keys_State -> Bool;

        modifier_key_is_set:  (Modifier_Keys_State, Int) -> Bool;

        # Keysym to ASCII translations:
        #
        Keysym_To_Ascii_Mapping;

        default_keysym_to_ascii_mapping:  Keysym_To_Ascii_Mapping;

        rebind_keysym:  Keysym_To_Ascii_Mapping -> (Keysym, List(Modifier_Key), String) -> Keysym_To_Ascii_Mapping;

        exception KEYSYM_NOT_FOUND;

        map_keysym_to_ascii:  Keysym_To_Ascii_Mapping -> (Keysym, Modifier_Keys_State) -> String;



        make_mousebutton_state:  List(Mousebutton) -> Mousebuttons_State;

        union_of_mousebutton_states:         (Mousebuttons_State, Mousebuttons_State) -> Mousebuttons_State;
        intersection_of_mousebutton_states:  (Mousebuttons_State, Mousebuttons_State) -> Mousebuttons_State;

        invert_button_in_mousebutton_state:  (Mousebuttons_State, Mousebutton) -> Mousebuttons_State;

        no_mousebuttons_set:     Mousebuttons_State -> Bool;
        some_mousebutton_is_set: Mousebuttons_State -> Bool;
        #
        mousebutton_1_is_set:    Mousebuttons_State -> Bool;
        mousebutton_2_is_set:    Mousebuttons_State -> Bool;
        mousebutton_3_is_set:    Mousebuttons_State -> Bool;
        mousebutton_4_is_set:    Mousebuttons_State -> Bool;
        mousebutton_5_is_set:    Mousebuttons_State -> Bool;
        #
        mousebutton_is_set:     (Mousebuttons_State, Mousebutton) -> Bool;


        # Keyboard messages:
        #
        Keyboard_Mail
          = KEY_PRESS    (Keysym, Modifier_Keys_State)
          | KEY_RELEASE  (Keysym, Modifier_Keys_State)
          | KEY_CONFIG_SYNC
          ;

        # Mouse messages:
        #
        Mouse_Mail
          #
          = MOUSE_MOTION  {
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_FIRST_DOWN  {
                mouse_button:  Mousebutton,                     # Button that is in transition 
                window_point:  xg::Point,                       # Mouse position in window coords 
                screen_point:  xg::Point,                       # Mouse position in screen coords 
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_LAST_UP  {
                mouse_button:  Mousebutton,                     # Button that is in transition.
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_DOWN  {
                mouse_button:  Mousebutton,                     # Button that is in transition.
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                state:         Mousebuttons_State,              # State of the mouse buttons.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_UP  {
                mouse_button:  Mousebutton,                     # Button that is in transition.
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                state:         Mousebuttons_State,              # State of the mouse buttons.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_ENTER  {
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_LEAVE  {
                window_point:  xg::Point,                       # Mouse position in window coords.
                screen_point:  xg::Point,                       # Mouse position in screen coords.
                timestamp:     xserver_timestamp::Xserver_Timestamp
              }

          | MOUSE_CONFIG_SYNC
          ;


        # Command/control messages from parent 
        #
        Other_Mail
          = ETC_REDRAW  List( xg::Box )
          | ETC_RESIZE        xg::Box
          #     
          | ETC_CHILD_BIRTH   Window
          | ETC_CHILD_DEATH   Window
          | ETC_OWN_DEATH
          ;

        # Command/control messages to parent (really requests) 
        #
        Mail_To_Mom
          = REQ_RESIZE                  # Ask mom to resize our window.
          | REQ_DESTRUCTION
          ;


        # Envelopes are delivered hop-by-hop down
        # the topwindow's widget hierarchy according
        # to the route recorded on the envelope.

        # Mail envelopes for hop-by-hop routing.
        #
        # These also carry sequence numbers so
        # the original order of keyboard vs mouse
        # events can be recovered when necessary:
        #
        Envelope X;

        # Hop-by-hop envelope routing -- return
        # value for route_envelope():
        #
        Pass_To X
          = TO_SELF   X                 # Envelope has reached its target window/widget.
          | TO_CHILD  Envelope(X)               # Envelope needs to be passed on down the widget hierarchy.
          ;

        route_envelope:   Envelope(X) ->  Pass_To(X);
            #
            # Figure out next step in delivering
            # an envelope -- either it is for us,
            # or else it needs to be passed to
            # one of our kids.

        to_window:    (Envelope(X), Window) -> Bool;
            #
            # Compare envelope to window and return
            # TRUE iff envelope should be routed to
            # that window for delivery.

        exception NO_MATCH_WINDOW;

        next_stop_for_envelope:  List( (Window, X) ) ->  Envelope(Y) -> X;
            #
            # Search a list of child windows
            # and return the one matching the
            # given envelope's delivery route.
            #
            # Raise NO_MATCH_WINDOW if there
            # is no match. (Shouldn't happen.)
            #
            # This function does a linear sequential
            # search which is usually fast enough;
            # if a window has too many children for
            # this to be sensible, use instead
            #
            #    next_stop_for_envelope_via_hashtable

        next_stop_for_envelope_via_hashtable:   Window_Map(X) ->  Envelope(Y) -> X;
            #
            # Faster version of above, used in
            #
            #     src/lib/x-kit/widget/basic/xevent-mail-router.pkg

        envelope_before:   (Envelope(X),  Envelope(X)) -> Bool;
            #
            # Compare envelopes by sequence number.
            #
            # Since keyboard- and mouse-event envelopes
            # get routed down separate streams, it is
            # possible for them to be delivered out of
            # order.  Most widgets do not care, but those
            # which do can use this function to recover
            # the original ordering.
            #
            # (No code currently uses this.  I'm dubious
            # about it -- a widget cannot know how long
            # to wait for possible out-of-order envelopes
            # to arrive before responding, and any waiting
            # will increase system response latency, which
            # is not where we want to be going.
            #     I suspect mouse and keyboard streams
            # should be combined into one to guarantee
            # in-order delivery, with suitable interface
            # sugar to make this equally easy for client
            # code to use. 2010-01-14 CrT. XXX BUGGO FIXME)

        envelope_contents:   Envelope(X) -> X;


        # Widget cables:
        #
        Kidplug
            =
            KIDPLUG
              {
                from_keyboard': Mailop(  Envelope(  Keyboard_Mail) ),
                from_mouse':    Mailop(  Envelope(  Mouse_Mail   ) ),
                from_other':    Mailop(  Envelope(  Other_Mail   ) ),
                #
                to_mom:         Mail_To_Mom -> Mailop( Void )
              };

        Momplug
            =
            MOMPLUG
              {
                keyboard_sink: Envelope( Keyboard_Mail ) ->  Mailop( Void ),
                mouse_sink:    Envelope(    Mouse_Mail ) ->  Mailop( Void ),
                other_sink:    Envelope(    Other_Mail ) ->  Mailop( Void ),
                #
                from_kid':     Mailop( Mail_To_Mom )
              };

         make_widget_cable
            :
            Void -> { kidplug:  Kidplug,
                      momplug:  Momplug
                    };

         # Often a window will want to ignore a given
         # input stream, but since communication is
         # synchronous it must still read messages to
         # avoid locking its parent.
         #
         # The following operations attach null threads
         # to the given input streams, discarding all
         # messages on them, and substitute a dummy stream
         # that will have no traffic: 
         #     
         ignore_mouse:                Kidplug -> Kidplug;
         ignore_keyboard:             Kidplug -> Kidplug;
         ignore_mouse_and_keyboard:   Kidplug -> Kidplug;
         ignore_all:                  Kidplug -> Kidplug;

         # Make a clone of the given kidplug
         # in which the given stream has been
         # replaced by another:
         #
         replace_mouse:      (Kidplug, Mailop( Envelope( Mouse_Mail   ))) -> Kidplug;
         replace_keyboard:   (Kidplug, Mailop( Envelope( Keyboard_Mail))) -> Kidplug;
         replace_other:      (Kidplug, Mailop( Envelope( Other_Mail   ))) -> Kidplug;

         # Sometimes a thread will eat messages
         # on one stream while forwarding those
         # on the others.  A new [plug] with
         # a dummy in the intercepted slot can
         # be made via the appropriate 'replace'
         # function from above with 'null_stream'.
         # This stream will never yield a message;
         # block_until_mailop_fires() on it will block forever:
         #
         null_stream:    Mailop(  Envelope(X) );

         # Menus and must wait until the mouse has reached
         # a stable state.  'while_mouse_state' eats mouse
         # mail until a given predicate such as
         #
         #     some_mousebutton_is_set
         #
         # is satisfied.  For example this fun will read
         # from_mouse' until mouse_button is released and
         # then call action(), after which it will wait
         # until all mouse buttons are up before returning:
         #
         #     fun do_mouseclick_action (from_mouse', mouse_button, action)
         #         =
         #         loop ()
         #         where
         #             while_some_set =  while_mouse_state  some_mousebutton_is_set;
         #
         #             fun loop ()
         #                 =
         #                 case (envelope_contents (block_until_mailop_fires from_mouse'))
         #                     #
         #                     MOUSE_UP { mouse_button => mouse_button', state, ... }
         #                         =>
         #                         if (mouse_button == mouse_button')
         #                             #
         #                             action ();
         #                             while_some_set (state, from_mouse');
         #                         else
         #                             loop ();
         #                         fi;
         #
         #                     MOUSE_LAST_UP _
         #                         =>
         #                         action ();
         #
         #                     _   => loop ();
         #             end;
         #         end;
         #
         # This idiom is useful for guaranteeing that the
         # mouse buttons are in a stable state before handling
         # more mouse button transitions.
         #
         # Credit: Comments and example adapted from p29 of
         #         http:://mythryl.org/pub/exene/1993-lib.ps
         #
         while_mouse_state
            :
            (Mousebuttons_State -> Bool)
            ->
            (Mousebuttons_State, Mailop(Mouse_Mail))
            ->
            Void;

        ################ end of input stuff #################



        ################ start of selection stuff #################
        #
        #
        #

        Selection_Handle;

        # Standard X atoms:
        #
        package atom: api {
            #
            primary:               Atom;
            secondary:             Atom;
            arc:                   Atom;
            atom:                  Atom;
            bitmap:                Atom;
            cardinal:              Atom;
            colormap:              Atom;
            cursor:                Atom;
            cut_buffer0:           Atom;
            cut_buffer1:           Atom;
            cut_buffer2:           Atom;
            cut_buffer3:           Atom;
            cut_buffer4:           Atom;
            cut_buffer5:           Atom;
            cut_buffer6:           Atom;
            cut_buffer7:           Atom;
            drawable:              Atom;
            font:                  Atom;
            integer:               Atom;
            pixmap:                Atom;
            point:                 Atom;
            rectangle:             Atom;
            resource_manager:      Atom;
            rgb_color_map:         Atom;
            rgb_best_map:          Atom;
            rgb_blue_map:          Atom;
            rgb_default_map:       Atom;
            rgb_gray_map:          Atom;
            rgb_green_map:         Atom;
            rgb_red_map:           Atom;
            string:                Atom;
            visualid:              Atom;
            window:                Atom;
            wm_command:            Atom;
            wm_hints:              Atom;
            wm_client_machine:     Atom;
            wm_icon_name:          Atom;
            wm_icon_size:          Atom;
            wm_name:               Atom;
            wm_normal_hints:       Atom;
            wm_size_hints:         Atom;
            wm_zoom_hints:         Atom;
            min_space:             Atom;
            norm_space:            Atom;
            max_space:             Atom;
            end_space:             Atom;
            superscript_x:         Atom;
            superscript_y:         Atom;
            subscript_x:           Atom;
            subscript_y:           Atom;
            underline_position:    Atom;
            underline_thickness:   Atom;
            strikeout_ascent:      Atom;
            strikeout_descent:     Atom;
            italic_angle:          Atom;
            x_height:              Atom;
            quad_width:            Atom;
            weight:                Atom;
            point_size:            Atom;
            resolution:            Atom;
            copyright:             Atom;
            notice:                Atom;
            font_name:             Atom;
            family_name:           Atom;
            full_name:             Atom;
            cap_height:            Atom;
            wm_ilk:                Atom;
            wm_transient_for:      Atom;
        };

        # Properties.

        # Raw data from server (in ClientMessage, property values, ...) 
        #
        Raw_Format = RAW8 | RAW16 | RAW32;
        #
        Raw_Data
            =
            RAW_DATA
              {
                format:  Raw_Format,
                data:    vector_of_one_byte_unts::Vector
              };

        # X property values.
        #
        # A property value has a type,
        # which is an atom, and a value.
        #
        # The value is a sequence of
        # 8, 16 or 32-bit items, represented
        # as a format and a string.
        #
        Property_Value
            =
            PROPERTY_VALUE
              {
                type:  Atom,
                value:  Raw_Data
              };

        exception PROPERTY_ALLOCATE;
            #
            # Raised, if there is not enough space to
            # store a property value on the server.


        # An abstract interface to a property on a window.
        #
        Property;

        property:  (Window, Atom) -> Property;
            #
            # Return the abstract representation of the
            # named property on the specified window.


        unused_property:  Window -> Property;
            #
            # Generate a property on the specified window
            # that is guaranteed to be unused.
            #
            # Note that once this property has
            # been "deleted" its name may be reused.
            #
            # NOTE: eventually, properties will be finalized,
            # but for the time being, programs should delete
            # any allocated properties they are not using.


        make_property:  (Window, Property_Value) -> Property;
            #
            #  Create a new property initialized to the given value 

        name_of_property:  Property -> Atom;
            #
            # Return the atom that names the given property.

        set_property:  ((Property, Property_Value)) -> Void;
            #
            # Set the value of the property.

        append_to_property:  ((Property, Property_Value)) -> Void;
            #
            # Append the property value to the property.
            # The types and formats must match.


        prepend_to_property:  ((Property, Property_Value)) -> Void;
            #
            # Prepend the property value to the property.
            # The types and formats must match.


        delete_property:  Property -> Void;
            #
            # Delete the named property.

        exception ROTATE_PROPERTIES;

        rotate_properties:  ((List( Property ), Int)) -> Void;
            #
            # Rotate the list of properties.
            #
            # Raise ROTATE_PROPERTIES if the
            # properties do not belong to
            # the same window.


        get_property:  Property -> Null_Or( Property_Value );
            #
            # Get the value of the property.
            # Return NULL if the property
            # has  not been set.


        # xrdb_of_screen: Return the list of strings contained in the
        # XA_RESOURCE_MANAGER property of the root screen of the
        # specified screen. 
        # This should properly belong some other place than in ICCC,
        # as it has nothing to do with ICCC, except that it accesses
        # data in the screen type, and uses the GetProperty functions
        # of ICCC.      XXX BUGGO FIXME
        #
        xrdb_of_screen:     Screen -> List( String );

        Property_Change
          = NEW_VALUE
          | DELETED
          ;

        watch_property:  Property -> Mailop( (Property_Change, xserver_timestamp::Xserver_Timestamp) );
            #
            # Return a mailop for monitoring changes
            # to a property's state.
            #
            # Note that once a property has been deleted
            # there will be no more mailops unless
            # watch_property is called again.



        # Hints about the window size: 
        #
        Window_Manager_Size_Hint
          = HINT_USPOSITION
          | HINT_PPOSITION
          | HINT_USSIZE
          | HINT_PSIZE
          | HINT_PMIN_SIZE     xg::Size
          | HINT_PMAX_SIZE     xg::Size
          | HINT_PRESIZE_INC   xg::Size
          | HINT_PBASE_SIZE    xg::Size
          | HINT_PWIN_GRAVITY  Gravity
          | HINT_PASPECT  { min:  (Int, Int),
                            max:  (Int, Int)
                          }
          ;

        # Window manager hints:
        #
        Window_Manager_Nonsize_Hint
          = HINT_INPUT  Bool                            # Does this application rely on the window 
                                                            # manager to get keyboard input? 

                                                            # Initial window state (choose one) 
          | HINT_WITHDRAWN_STATE                                #  o For windows that are not mapped.
          | HINT_NORMAL_STATE                           #  o Most want to start this way.
          | HINT_ICONIC_STATE                           #  o Application wants to start as an icon.
          | HINT_ICON_RO_PIXMAP         Ro_Pixmap               # Icon specified as ro_pixmap.
          | HINT_ICON_PIXMAP            Rw_Pixmap               # Icon specified as pixmap.
          | HINT_ICON_WINDOW            Window          # Icon specified as plain window.
          | HINT_ICON_MASK              Rw_Pixmap               # Icon mask bitmap.
          | HINT_ICON_POSITION          xg::Point               # Initial position of icon.
          | HINT_WINDOW_GROUP           Window          # The group leader.
          ;

        # Atom operations:
        #
        make_atom:      Xsession -> String -> Atom;
        find_atom:      Xsession -> String -> Null_Or( Atom );
        atom_to_string: Xsession -> Atom   -> String;

        # Selection owner operations:
        #
        acquire_selection
            :
            (Window, Atom, xserver_timestamp::Xserver_Timestamp)
            ->
            Null_Or( Selection_Handle );
            #
            # Acquire the named selection.

        selection_of:  Selection_Handle -> Atom;
        timestamp_of:  Selection_Handle -> xserver_timestamp::Xserver_Timestamp;

        selection_req_mailop
            :
            Selection_Handle
            ->
            Mailop
              {
                target:       Atom,
                timestamp:    Null_Or( xserver_timestamp::Xserver_Timestamp ),
                reply:        Null_Or( Property_Value ) -> Void
              };
            #
            # This mailop is enabled once for each request for the selection.
            #  The target field is the requested target type;
            #  the time field is the server-time of the gesture that caused the request, and
            #  the reply field is a function for sending the reply.
            # If the time field is NULL, this means a value of CURRENT_TIME was used.
            # Strictly speaking this violates the ICCC specification, but applications
            # may choose to accept it.


        selection_rel_mailop
            :
            Selection_Handle -> Mailop( Void );
            #
            # This mailop becomes enabled when
            # the selection is lost, either by
            # the owner releasing it, or by
            # some other client acquiring ownership.


        release_selection:  Selection_Handle -> Void;
            #
            # Release ownership of the selection.


        # Selection requestor operations.

        request_selection
            :
            { window:     Window,
              selection:  Atom,
              target:     Atom,
              property:   Atom,
              timestamp:  xserver_timestamp::Xserver_Timestamp
            }
            ->
            Mailop( Null_Or( Property_Value ) );
                #
                # Request the value of the selection.
                # the window field is the requesting window,
                # the selection field is the requested selection,
                # the target field is the requested target type, and
                # the time field is the server-time of the gesture causing the request.
                #
                # This returns a mailop that will become enabled
                # when the reply is received.

        ################ end of selection stuff #################



        ################ start of window stuff #################
        #
        #

        # User-level window attributes 
        #
        package a: api {
            Window_Attribute
              #
              = BACKGROUND_NONE
              | BACKGROUND_PARENT_RELATIVE
              | BACKGROUND_RO_PIXMAP          Ro_Pixmap
              | BACKGROUND_COLOR              Rgb
              | BACKGROUND_RW_PIXMAP      Rw_Pixmap
              #
              | BORDER_COPY_FROM_PARENT
              | BORDER_RW_PIXMAP          Rw_Pixmap
              | BORDER_RO_PIXMAP              Ro_Pixmap
              | BORDER_COLOR                  Rgb
              #
              | BIT_GRAVITY                   Gravity
              | WINDOW_GRAVITY                Gravity
              #
              | CURSOR                        Xcursor
              | CURSOR_NONE
              ;
        };

        # Window configuration values 
        #
        package c: api {

            Window_Config
              #
              = ORIGIN          xg::Point
              | SIZE            xg::Size
              #
              | BORDER_WID      Int
              | STACK_MODE      Stack_Mode
              #
              | REL_STACK_MODE  (Window, Stack_Mode)
              ;
        };

        # Window operations

        exception BAD_WINDOW_SITE;

        make_simple_top_window
            :
            Screen
            ->
            { site:              xg::Window_Site,
              border_color:      Rgb,
              background_color:  Rgb8
            }
            ->
            ( Window,
              Kidplug,
              Mailslot(Void)
            );

        make_simple_subwindow
            :
            Window
            ->
            { site:              xg::Window_Site,
              border_color:      Null_Or( Rgb ),
              background_color:  Null_Or( Rgb8  )
            }
            ->
            Window;

        make_transient_window
            :
            Window
            ->
            { site:              xg::Window_Site,
              border_color:      Rgb,
              background_color:  Rgb8
            }
            ->
            (Window, Kidplug);

        make_simple_popup_window
            :
            Screen
            ->
            { site:              xg::Window_Site,
              border_color:      Rgb,
              background_color:  Rgb8
            }
            ->
            (Window, Kidplug);

        make_input_only_window
            :
            Window -> xg::Box -> Window;

        # We raise this exception on operations
        # such as drawing that are illegal for
        # Input_Only windows.
        #
        exception OP_UNSUPPORTED_ON_INPUT_ONLY_WINDOWS;
                                                                                            # commandline               is from   src/lib/std/commandline.pkg
        # Set the properties of a top-level window.
        #
        # This should be done before showing (mapping)
        # the window:
        #
        set_window_manager_properties
            :
            Window
            ->
            {
              window_name:              Null_Or( String ),
              icon_name:                Null_Or( String ),
              #
              commandline_arguments:    List( String ),                                 # Typically from:   commandline::get_arguments ().
              size_hints:               List( Window_Manager_Size_Hint ),
              nonsize_hints:            List( Window_Manager_Nonsize_Hint ),
              #
              class_hints:              Null_Or { resource_class:   String,
                                                  resource_name:  String
                                                }
            }
            ->
            Void;

        # Set the window-manager protocols
        # for a window: 
        #
        set_window_manager_protocols:  Window -> List( Atom ) -> Bool;

        # Various routines to reconfigure window layout: 
        #
        configure_window:        Window -> List( c::Window_Config ) -> Void;
        move_window:             Window -> xg::Point -> Void;
        resize_window:           Window -> xg::Size  -> Void;
        move_and_resize_window:  Window -> xg::Box   -> Void;

        # Map a point in the window's coordinate
        # system to the screen's coordinate system:
        #
        window_point_to_screen_point
            :
            Window -> xg::Point -> xg::Point;

        set_cursor:  Window ->  Null_Or( Xcursor ) -> Void;

        set_background_color:  Window -> Null_Or( Rgb ) -> Void;
            #
            # Set the background color attribute of the window.
            #
            # This does not immediately affect the window's contents,
            # but if it is done before the window is mapped the window
            # will come up with the right color.


        change_window_attributes:  Window -> List( a::Window_Attribute ) -> Void;
            #
            # Set various window attributes.

        show_window:        Window -> Void;             # Show ("map") window.  Won't actually show unless all ancestors show.
        hide_window:        Window -> Void;             # Opposite of show.     
        withdraw_window:    Window -> Void;
        destroy_window:     Window -> Void;

        screen_of_window:   Window -> Screen;
        xsession_of_window: Window -> Xsession;

        grab_keyboard:      Window -> Int;
        ungrab_keyboard:    Window -> Int;

        get_window_site:    Window -> xg::Box;

        note_''seen_first_expose''_oneshot: Window -> Oneshot_Maildrop(Void) -> Void;
            #
            # Infrastructure -- see comments in src/lib/x-kit/xclient/src/window/window.pkg

        get_''seen_first_expose''_oneshot_of:     Window -> Null_Or(Oneshot_Maildrop(Void));
            #
            # This function makes the above oneshot
            # available to clients with access to
            # the Window but not the Widget.  Clients
            # with access to the Widget should use the
            #
            #     widget::seen_first_redraw_oneshot_of
            #
            # call because it is guaranteed to return
            # the required oneshot;  the above call may
            # return NULL, in which case the client thread
            # will have to sleep a bit and then retry.

        get_''gui_startup_complete''_oneshot_of                         # get_''gui_startup_complete''_oneshot_of       def in    src/lib/x-kit/xclient/src/window/xsession.pkg
            :
            Window -> Oneshot_Maildrop(Void);                           # See comments in   src/lib/x-kit/xclient/src/window/xsocket-to-topwindow-router.api


        # Make 'window' receive a (faked) keyboard keypress at 'point'.
        # 'window' should be the sub/window actually holding the widget to be activate.
        # 'point'  should be the click point in that window's coordinate system.
        #
        # NOTE! We send the event via the X server to provide full end-to-end testing;
        # the resulting network round trip will be quite slow, making this call
        # generally inappropriate for anything other than unit test code.
        #
        send_keyboard_key_press_xevent
            :
            { window:           Window,                         # Window handling the mouse-button click event.
              keycode:          Keycode,                        # Keyboard key just pressed down.
              point:            xg::Point
            }
            ->
            Void
            ;

        # Make 'window' receive a (faked) keyboard key release at 'point'.
        # 'window' should be the sub/window actually holding the widget to be activate.
        # 'point'  should be the click point in that window's coordinate system.
        #
        # NOTE! We send the event via the X server to provide full end-to-end testing;
        # the resulting network round trip will be quite slow, making this call
        # generally inappropriate for anything other than unit test code.
        #
        send_keyboard_key_release_xevent
            :
            { window:           Window,                         # Window handling the mouse-button click event.
              keycode:          Keycode,                        # Keyboard key just pressed down.
              point:            xg::Point
            }
            ->
            Void
            ;

        # Make 'window' receive a (faked) mousebutton click at 'point'.
        # 'window' should be the sub/window actually holding the widget to be activate.
        # 'point'  should be the click point in that window's coordinate system.
        #
        # NOTE! We send the event via the X server to provide full end-to-end testing;
        # the resulting network round trip will be quite slow, making this call
        # generally inappropriate for anything other than unit test code.
        #
        send_mousebutton_press_xevent
            :
            { window:           Window,                         # Window handling the mouse-button click event.
              button:           Mousebutton,                    # Mouse button just clicked down.
              point:            xg::Point
            }
            ->
            Void
            ;

        # Counterpart of previous:  make 'window' receive a (faked) mousebutton release at 'point'.
        # 'window' should be the sub/window actually holding the widget to be activate.
        # 'point'  should be the button-release point in that window's coordinate system.
        #
        # NOTE! We send the event via the X server to provide full end-to-end testing;
        # the resulting network round trip will be quite slow, making this call
        # generally inappropriate for anything other than unit test code.
        #
        send_mousebutton_release_xevent
            :
            { window:           Window,                         # Window handling the mouse-button release event.
              button:           Mousebutton,                    # Mouse button just released.
              point:            xg::Point
            }
            ->
            Void
            ;

        # This call may be used to simulate mouse "drag" operations in unit-test code.
        # 'window' should be the sub/window actually holding the widget to be activate.
        # 'point'  should be the supposed mouse-pointer location in that window's coordinate system.
        #
        # NOTE! We send the event via the X server to provide full end-to-end testing;
        # the resulting network round trip will be quite slow, making this call
        # generally inappropriate for anything other than unit test code.
        #
        send_mouse_motion_xevent
            :
            { window:           Window,                         # Window handling the mouse-motion event.
              buttons:          List(Mousebutton),              # Mouse button(s) being dragged.
              point:            xg::Point
            }
            ->
            Void
            ;

        # The xkit buttons react not just to mouse-up and mouse-down events but also
        # to mouse-enter and mouse-leave events, so to auto-test them propertly we
        # must synthesize those also:
        #
        send_''mouse_enter''_xevent
            :
            { window:           Window,                         # Window handling the event.
              point:            xg::Point                       # End-of-event coordinate, thus should be just inside window.
            }
            ->
            Void
            ;
        #
        send_''mouse_leave''_xevent
            :
            { window:           Window,                         # Window handling the event.
              point:            xg::Point                       # End-of-event coordinate, thus should be just outside window.
            }
            ->
            Void
            ;

        ################ end of window stuff #################

    };                                                          # api Xclient
end;



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext