PreviousUpNext

15.4.1494  src/lib/x-kit/xclient/pkg/wire/sendevent-to-wire.pkg

## sendevent-to-wire.pkg
#
# Encode X SendEvent values in wire
# (network bytestring) format.
#
# Currently we implement:
#
#     fun encode_send_selectionnotify_xevent            # Respond to a selection request.
#     fun encode_send_unmapnotify_xevent                # Tell window manager to unmap a toplevel window.
#
# These get used in (respectively):
#
#     src/lib/x-kit/xclient/pkg/window/selection-imp.pkg
#     src/lib/x-kit/xclient/pkg/window/window.pkg
#
# See also:
#     src/lib/x-kit/xclient/pkg/wire/value-to-wire.pkg

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


stipulate
#    package xg  =  xgeometry;                          # xgeometry                     is from   src/lib/std/2d/xgeometry.pkg
    package xt  =  xtypes;                              # xtypes                        is from   src/lib/x-kit/xclient/pkg/wire/xtypes.pkg
    package ts  =  xserver_timestamp;                   # xserver_timestamp             is from   src/lib/x-kit/xclient/pkg/wire/xserver-timestamp.pkg
    #
    package w8a =  rw_vector_of_one_byte_unts;          # rw_vector_of_one_byte_unts    is from   src/lib/std/src/rw-vector-of-one-byte-unts.pkg
    package w8v =     vector_of_one_byte_unts;          # vector_of_one_byte_unts       is from   src/lib/std/src/vector-of-one-byte-unts.pkg
    package v2w =  value_to_wire;                       # value_to_wire                 is from   src/lib/x-kit/xclient/pkg/wire/value-to-wire.pkg
    package xtr =  xlogger;                             # xlogger                       is from   src/lib/x-kit/xclient/pkg/stuff/xlogger.pkg
    #
    sendevent_tracing = logger::make_logtree_leaf { parent => xlogger::lib_logging, name => "sendevent_tracing" };
    trace =  xtr::log_if  sendevent_tracing;            # Conditionally write strings to tracing.log or whatever.
herein


    package   sendevent_to_wire
    :         Sendevent_To_Wire                         # Sendevent_To_Wire     is from   src/lib/x-kit/xclient/pkg/wire/sendevent-to-wire.api
    {
        stipulate
            # We need to treat requests as modifiable
            # for initialization purposes, but we don't
            # want them to be modifiable afterwords:
            #
            my ro2rw:  vector_of_one_byte_unts::Vector -> rw_vector_of_one_byte_unts::Rw_Vector
                =
                unsafe::cast;

            encode_push_event
                =
                v2w::encode_push_event;

            event_offset = 12;

            fun put8        (buf, i, w) =  w8a::set (ro2rw buf, i+event_offset, w);
            fun put_signed8 (buf, i, x) =  put8 (buf, i, one_byte_unt::from_int x);

            fun put16 (buf, i, x)
                =
                pack_big_endian_unt16::set (ro2rw buf, i / 2 + event_offset / 2, x);

            fun put_signed16 (buf, i, x)
                =
                put16 (buf, i, large_unt::from_int x);


            fun put32 (buf, i, x)
                =
                pack_big_endian_unt1::set (ro2rw buf, i / 4 + event_offset / 4, x);

            fun put_word32   (buf, i, x) = put32 (buf, i, unt::to_large_unt x);
            fun put_signed32 (buf, i, x) = put32 (buf, i, large_unt::from_int x);

            fun put_bool (buf, i, FALSE) =>  put8 (buf, i, 0u0);
                put_bool (buf, i, TRUE ) =>  put8 (buf, i, 0u1);
            end;

            fun put_buttons (buf, i, xt::MOUSEBUTTON_STATE unt)
                =
                put16 (buf, i, one_word_unt::from_int (unt::to_int unt));               # There must be a better way to do this conversion...

            fun put_keycode (buf, i, xt::KEYCODE keycode)
                =
                put_signed8 (buf, i, keycode);

            fun put_button  (buf, i, xt::MOUSEBUTTON button)
                =
                put_signed8 (buf, i, button);

            fun put_xid (buf, i, xt::XID n)
                =
                put_word32 (buf, i, n);

            fun put_null_or_xid (buf, i, NULL)            =>  put_word32 (buf, i, 0u0);
                put_null_or_xid (buf, i, THE (xt::XID n)) =>  put_word32 (buf, i, n);
            end;

            fun put_atom (buf, i, xt::XATOM n)
                =
                put_word32 (buf, i, n);

            fun put_null_or_atom (buf, i, NULL)              =>  put_word32 (buf, i, 0u0);
                put_null_or_atom (buf, i, THE (xt::XATOM n)) =>  put_word32 (buf, i, n);
            end;

            fun put_timestamp (buf, i, xt::CURRENT_TIME)                         =>  put32 (buf, i, 0u0);
                put_timestamp (buf, i, xt::TIMESTAMP (ts::XSERVER_TIMESTAMP t)) =>  put32 (buf, i, t);
            end;

            # Event codes:
            #
            package event {
                key_press               = 0u2:  one_byte_unt::Unt;
                key_release             = 0u3:  one_byte_unt::Unt;
                button_press            = 0u4:  one_byte_unt::Unt;
                button_release          = 0u5:  one_byte_unt::Unt;
                motion_notify           = 0u6:  one_byte_unt::Unt;
                enter_notify            = 0u7:  one_byte_unt::Unt;
                leave_notify            = 0u8:  one_byte_unt::Unt;
                focus_in                = 0u9:  one_byte_unt::Unt;
                focus_out               = 0u10:  one_byte_unt::Unt;
                keymap_notify           = 0u11:  one_byte_unt::Unt;
                expose                  = 0u12:  one_byte_unt::Unt;
                graphics_expose         = 0u13:  one_byte_unt::Unt;
                no_expose               = 0u14:  one_byte_unt::Unt;
                visibility_notify       = 0u15:  one_byte_unt::Unt;
                create_notify           = 0u16:  one_byte_unt::Unt;
                destroy_notify          = 0u17:  one_byte_unt::Unt;
                unmap_notify            = 0u18:  one_byte_unt::Unt;
                map_notify              = 0u19:  one_byte_unt::Unt;
                map_request             = 0u20:  one_byte_unt::Unt;
                reparent_notify         = 0u21:  one_byte_unt::Unt;
                configure_notify        = 0u22:  one_byte_unt::Unt;
                configure_request       = 0u23:  one_byte_unt::Unt;
                gravity_notify          = 0u24:  one_byte_unt::Unt;
                resize_request          = 0u25:  one_byte_unt::Unt;
                circulate_notify        = 0u26:  one_byte_unt::Unt;
                circulate_request       = 0u27:  one_byte_unt::Unt;
                property_notify         = 0u28:  one_byte_unt::Unt;
                selection_clear         = 0u29:  one_byte_unt::Unt;
                selection_request       = 0u30:  one_byte_unt::Unt;
                selection_notify        = 0u31:  one_byte_unt::Unt;
                colormap_notify         = 0u32:  one_byte_unt::Unt;
                client_message          = 0u33:  one_byte_unt::Unt;
                mapping_notify          = 0u34:  one_byte_unt::Unt;
            };

            fun put_event_code (msg, code)
                =
                put8 (msg, 0, code);

            fun put_detail_code (msg, code)
                =
                put8 (msg, 1, code);

        herein

            # For SendEvent proper, see:
            #     p27   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #     p126  http://mythryl.org/pub/exene/X-protocol-R7.pdf


            # Event wire encodings are documented in
            #       p 150-157  http://mythryl.org/pub/exene/X-protocol-R7.pdf

            # See   p88 http://mythryl.org/pub/exene/X-protocol-R7.pdf  
            #
            fun encode_send_selectionnotify_xevent
                { send_event_to, propagate, event_mask,
                  requesting_window_id, selection, target, property, timestamp
                }
                =
                {   msg =  encode_push_event { send_event_to, propagate, event_mask };

                    put_event_code   (msg, event::selection_notify      );
                    put_timestamp    (msg,  4, timestamp                );
                    put_xid          (msg,  8, requesting_window_id     );
                    put_atom         (msg, 12, selection                );
                    put_atom         (msg, 16, target                   );
                    put_null_or_atom (msg, 20, property                 );

                    msg;
                };

            # See   p84 http://mythryl.org/pub/exene/X-protocol-R7.pdf  
            #
            fun encode_send_unmapnotify_xevent
                { send_event_to, propagate, event_mask,
                  event_window_id, unmapped_window_id, from_configure
                }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    put_event_code (msg, event::unmap_notify    );
                    put_xid        (msg,  4, event_window_id    );
                    put_xid        (msg,  8, unmapped_window_id );
                    put_bool       (msg, 12, from_configure     );

                    msg;
                };

            # Simulate press of a keyboard key.
            #
            # For semantics       see   p77  (81)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see  p151 (155)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            # Note that 'buttons' is the logical state BEFORE the event.
            #
            fun encode_send_keypress_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the keyboard-key press event.
                    child_window_id,    # Child of event window containing the press point. NULL if none such exists.
                    root_x,             # Mouse position on root window at time of keyboard keypress.
                    root_y,
                    event_x,            # Mouse position on recipient window at time of keypress.
                    event_y,
                    keycode,            # Keyboard key just "pressed".
                    buttons             # Mouse button state before keypress.
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    same_screen = TRUE;         # I'm pretending multiple-screen X servers do not exist.

                    put_event_code  (msg, event::key_press              );
                    put_keycode     (msg,  1, keycode                   );                      # Keyboard key being "pressed".
                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );                      # Supposed keys-and-buttons state before the keypress.
                    put_bool        (msg, 30, same_screen               );

                    msg;
                };

            # Simulate release of a keyboard key.
            #
            # For semantics       see   p77  (81)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see  p151 (155)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            # Note that 'buttons' is the logical state BEFORE the event.
            #
            fun encode_send_keyrelease_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the keyboard-key release event.
                    child_window_id,    # Child of event window containing the release point. NULL if none such exists.
                    root_x,             # Mouse position on root window at time of keyboard key release.
                    root_y,
                    event_x,            # Mouse position on recipient window at time of key release.
                    event_y,
                    keycode,            # Keyboard key just "released".
                    buttons             # Mouse button state before key release.
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    same_screen = TRUE;         # I'm pretending multiple-screen X servers do not exist.

                    put_event_code  (msg, event::key_release            );
                    put_keycode     (msg,  1, keycode                   );                      # Keyboard key being "released".
                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );                      # Supposed keys-and-buttons state before the key release.
                    put_bool        (msg, 30, same_screen               );

                    msg;
                };

            # Simulate down-click of a mousebutton.
            #
            # For semantics       see   p77  (81)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see  p151 (155)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            # Note that 'buttons' is the logical state BEFORE the event.
            #
            fun encode_send_buttonpress_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the mouse-button click event.
                    child_window_id,    # Child of event window containing the click point. NULL if none such exists.
                    root_x,             # Mouse position on root window at time of button click.
                    root_y,
                    event_x,            # Mouse position on recipient window at time of button click.
                    event_y,
                    button,             # Mouse button just clicked down.
                    buttons             # Mouse button state before buttonclick.
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    same_screen = TRUE;         # I'm pretending multiple-screen X servers do not exist.

                    put_event_code  (msg, event::button_press           );
                    put_button      (msg,  1, button                    );                      # Mouse button being clicked.
                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );                      # Supposed keys-and-buttons state before the click.
                    put_bool        (msg, 30, same_screen               );

                    msg;
                };

            # Simulate up-click of a mousebutton.
            #
            # For semantics       see   p77  (81)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see  p151 (155)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            # NOTE that the last three lines of the binary encoding are on page 152!
            # I missed this the first time around and wound up spending a day or two
            # tracking the problem down. :-(
            #
            # Note that 'buttons' is the logical state BEFORE the event.
            #
            fun encode_send_buttonrelease_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the mouse-button release event.
                    child_window_id,    # Child of event window containing the release point. NULL if none such exists.
                    root_x,             # Mouse position on root window at time of button release.
                    root_y,
                    event_x,            # Mouse position on recipient window at time of button release.
                    event_y,
                    button,             # Mouse button just released.
                    buttons             # Mouse button state before buttonrelease
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    same_screen = TRUE;         # I'm pretending multiple-screen X servers do not exist.

                    # Layout is identical to the button-press case:
                    #
                    put_event_code  (msg, event::button_release         );
                    put_button      (msg,  1, button                    );                      # Mouse button being released.
                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );                      # Supposed keys-and-buttons state before the click.
                    put_bool        (msg, 30, same_screen               );

                    msg;
                };

            # For semantics       see   p77  (81)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see  p152 (156)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            fun encode_send_motionnotify_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the mouse-button release event.
                    child_window_id,    # Child of event window containing the release point. NULL if none such exists.
                    root_x,             # Mouse position on root window at time of button release.
                    root_y,
                    event_x,            # Mouse position on recipient window at time of button release.
                    event_y,
                    buttons             # Mouse button state before buttonrelease
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    same_screen = TRUE;         # I'm pretending multiple-screen X servers do not exist.

                    # Layout is identical to the button-press case:
                    #
                    put_event_code  (msg, event::motion_notify          );
                    put8            (msg,  1, 0u0                       );                      # 0=Normal 1=Hint
                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );                      # Supposed keys-and-buttons state.
                    put_bool        (msg, 30, same_screen               );

                    msg;
                };

            # For semantics       see  p78  (82)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            # For binary encoding see p152 (156)   http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            fun encode_send_enternotify_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the EnterNotify event.
                    child_window_id,    # Child of event window containing the release point. NULL if none such exists.
                    root_x,             # Mouse position on root window at end of EnterNotify event.
                    root_y,
                    event_x,            # Mouse position on recipient window at end of EnterNotify event.
                    event_y,
                    buttons             # Mouse button state before buttonclick.
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    # Layout is identical to the button-press case
                    # except that it is missing the final two fields,
                    # 'buttons' and 'same_screen':
                    #
                    put_event_code  (msg, event::enter_notify           );
                    put8            (msg,  1, 0u0                       );      # entered from: 0=Ancestor 1=Virtual 2=Inferior 3=Nonlinear 4=NonlinearVirtual

                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );      # Supposed keys-and-buttons state on entry.
                    put8            (msg, 30, 0u0                       );      # Mode: 0=Normal 1=Grab 2=Ungrab
                    put8            (msg, 31, 0u2                       );      # 0x1=Focus 0x2=sameScreen

                    msg;
                };

            fun encode_send_leavenotify_xevent
                  { send_event_to, propagate, event_mask,
                    #
                    timestamp,
                    root_window_id,
                    event_window_id,    # Window handling the EnterNotify event.
                    child_window_id,    # Child of event window containing the release point. NULL if none such exists.
                    root_x,             # Mouse position on root window at end of EnterNotify event.
                    root_y,
                    event_x,            # Mouse position on recipient window at end of EnterNotify event.
                    event_y,
                    buttons             # Mouse button state before buttonclick.
                                        # We should support modifier keys as well as mouse keys here. XXX BUGGO FIXME.
                  }
                =
                {   msg = encode_push_event { send_event_to, propagate, event_mask };

                    # Layout is identical to the button-press case
                    # except that it is missing the final two fields,
                    # 'buttons' and 'same_screen':
                    #
                    put_event_code  (msg, event::leave_notify           );
                    put8            (msg,  1, 0u2                       );      # exited to: 0=Ancestor 1=Virtual 2=Inferior 3=Nonlinear 4=NonlinearVirtual

                    put_timestamp   (msg,  4, timestamp                 );
                    put_xid         (msg,  8, root_window_id            );
                    put_xid         (msg, 12, event_window_id           );
                    put_null_or_xid (msg, 16, child_window_id           );
                    put_signed16    (msg, 20, root_x                    );
                    put_signed16    (msg, 22, root_y                    );
                    put_signed16    (msg, 24, event_x                   );
                    put_signed16    (msg, 26, event_y                   );
                    put_buttons     (msg, 28, buttons                   );      # Supposed keys-and-buttons state on entry.
                    put8            (msg, 30, 0u0                       );      # Mode: 0=Normal 1=Grab 2=Ungrab
                    put8            (msg, 31, 0u2                       );      # 0x1=Focus 0x2=sameScreen

                    msg;
                };


        end;    # stipulate
    };          # package sendevent_to_wire
end;            # stipulate 


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext