PreviousUpNext

15.4.1598  src/lib/x-kit/xclient/src/iccc/window-property.pkg

## window-property.pkg
#
# This package is exported by
#
#     src/lib/x-kit/xclient/xclient.pkg
#
# as part of "Selection stuff".
# We have no other direct reference.
#
# Selection stuff clients include:
#
#     src/lib/x-kit/widget/old/basic/hostwindow.pkg
#     src/lib/x-kit/widget/old/basic/root-window-old.pkg
#     src/lib/x-kit/tut/bouncing-heads/bouncing-heads-app.pkg
#     src/lib/x-kit/tut/triangle/triangle-app.pkg

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




stipulate
    include package   threadkit;                        # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
    package xt  = xtypes;                               # xtypes                        is from   src/lib/x-kit/xclient/src/wire/xtypes.pkg
    package xe  = xerrors;                              # xerrors                       is from   src/lib/x-kit/xclient/src/wire/xerrors.pkg
    package v2w = value_to_wire;                        # value_to_wire                 is from   src/lib/x-kit/xclient/src/wire/value-to-wire.pkg
    package w2v = wire_to_value;                        # wire_to_value                 is from   src/lib/x-kit/xclient/src/wire/wire-to-value.pkg
    #
    package wpi = window_watcher_ximp;                  # window_watcher_ximp           is from   src/lib/x-kit/xclient/src/window/window-watcher-ximp.pkg
    package wpp = client_to_window_watcher;             # client_to_window_watcher      is from   src/lib/x-kit/xclient/src/window/client-to-window-watcher.pkg
    package sn  = xsession_junk;                        # xsession_junk                 is from   src/lib/x-kit/xclient/src/window/xsession-junk.pkg
#   package dt  = draw_types;                           # draw_types                    is from   src/lib/x-kit/xclient/src/window/draw-types.pkg
#   package xok = xsocket_old;                          # xsocket_old                   is from   src/lib/x-kit/xclient/src/wire/xsocket-old.pkg
herein


    package   window_property
    : (weak)  Window_Property                           # Window_Property               is from   src/lib/x-kit/xclient/src/iccc/window-property.api
    {
        exception PROPERTY_ALLOCATE;
            #
            # Raised if there is not enough space to
            # store a property value on the server.

        # Given message encode and reply decode
        # functions, send and receive a query 
        #
        fun query (encode, decode) (x: sn::Xsession)
            =
            {   send_xrequest_and_read_reply
                    =
                    x.windowsystem_to_xserver.xclient_to_sequencer.send_xrequest_and_read_reply;

                fun ask msg
                    =
                    decode (block_until_mailop_fires (send_xrequest_and_read_reply (encode msg)));
#                           ========================                                                 XXX SUCKO FIXME    
#                   except
#                       xok::LOST_REPLY
#                           =>
#                           raise exception (xgripe::XERROR "[reply lost]");
#
#                       xok::ERROR_REPLY err
#                           =>
#                           raise exception (xgripe::XERROR (xerror_to_string::xerror_to_string err));
#                   end ;

                ask;
            };


        ############################################
        # Various protocol requests which we need:

        req_get_property
            =
            query
              ( v2w::encode_get_property,
                w2v::decode_get_property_reply
              );


        fun rotate_props (x: sn::Xsession) arg
            =
            x.windowsystem_to_xserver.xclient_to_sequencer.send_xrequest
                (v2w::encode_rotate_properties arg);


        fun delete_prop (x: sn::Xsession) arg
            =
            x.windowsystem_to_xserver.xclient_to_sequencer.send_xrequest
                (v2w::encode_delete_property arg);


        fun change_property  (x: sn::Xsession)  arg
            =
            {   ack = x.windowsystem_to_xserver.xclient_to_sequencer.send_xrequest_and_return_completion_mailop
                          (v2w::encode_change_property arg);

                block_until_mailop_fires ack;
#               ========================                        XXX SUCKO FIXME
#               except
#                   xok::ERROR_REPLY (xe::XERROR { kind=>xe::BAD_ALLOC, ... } )
#                       =>
#                       raise exception PROPERTY_ALLOCATE;
#
#                   ex  =>
#                       raise exception ex;
#               end ;
            };


        stipulate
            package xt' : (weak) api {

                                 Atom;
                                #  raw data from server (in ClientMessage, property values, ...) 

                                 Raw_Format = RAW08 | RAW16 | RAW32;

                                 Raw_Data = RAW_DATA  {
                                    format:  Raw_Format,
                                    data:  vector_of_one_byte_unts::Vector
                                  };

                                # X property values.  A property value has a name and type, which are atoms,
                                # 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
                                  };

                           }
                =
                xt;
        herein
            include package   xt';
        end;


        # An abstract interface to a property on a window 
        #
        Property
            =
            PROPERTY
              { xsession:   sn::Xsession,
                name:       Atom,
                window:     xt::Window_Id,
                is_unique:  Bool
              };


        # Get the xsession and
        # window ID from a window:
        #
        fun info_of_window ({ window_id, screen=> { xsession, ... }: sn::Screen, ... }: sn::Window )
            =
            (xsession, window_id);


        fun prop_server ({ client_to_window_watcher, ... }: sn::Xsession )              # Get the property server of a display .
            =
            client_to_window_watcher;


        fun info_of_prop (PROPERTY { xsession, name, window, ... } )            # Get the xsession, window id and atom from a property.
            =
            (xsession, window, name);


        fun property (window, name)                                             # Return the abstract representation of the named property on the specified window.
            =
            {   (info_of_window  window) ->   (xsession, window_id);
                #
                PROPERTY { xsession, name, window=>window_id, is_unique=>FALSE };
            };


        # Generate a property on the
        # specified window that is
        # guaranteed to be unused:
        #
        fun unused_property window
            =
            {   (info_of_window  window) ->   (xsession, window_id);
                #
                client_to_window_watcher =  prop_server  xsession;

                prop_name =  client_to_window_watcher.unused_property  window_id;

                PROPERTY
                  { xsession,
                    name   => prop_name,
                    window => window_id,
                    is_unique => TRUE
                  };
            };


        # Return the atom that
        # names the given property: 
        #
        fun name_of_property (PROPERTY { name, ... } )
            =
            name;


        # Update a property: 
        #
        fun update_prop  mode  (prop, value)
            =
            {   my (display, window_id, name)
                    =
                    info_of_prop prop;

                change_property  display
                  { name,
                    mode,
                    window_id,
                    property => value
                  };
            };


        # Set the value of
        # the property: 
        #
        set_property
            =
            update_prop xt::REPLACE_PROPERTY;


        # Append the property value
        # to the property.
        # The types must match:
        #
        append_to_property
            =
            update_prop xt::APPEND_PROPERTY;


        # Prepend the property value
        # to the property.
        # The types must match.
        #
        prepend_to_property
            =
            update_prop xt::PREPEND_PROPERTY;


        # Delete the named property: 
        #
        fun delete_property prop
            =
            {   (info_of_prop prop)
                    ->
                    (display, wid, name);

                delete_prop display { window_id => wid, property => name };
            };


        # Create a new property initialized
        # to the given value: 
        #
        fun make_property (window, value)
            =
            {   prop =  unused_property  window;
                #
                set_property (prop, value); prop;
            };


        exception ROTATE_PROPERTIES;


        # Rotate the list of properties:
        #
        fun rotate_properties ([], _)
                =>
                ();

            rotate_properties (l as prop ! r, n)
                =>
                {   (info_of_prop  prop)
                        ->
                        (display, window_id, _);

                    fun check_prop prop
                        =
                        {   (info_of_prop prop) ->   (_, w, name);
                            #
                            if (w != window_id)   raise exception ROTATE_PROPERTIES;
                            else                  name;
                            fi;
                        };

                    rotate_props  display
                        {
                          window_id,
                          delta      =>  n,
                          properties =>  map  check_prop  l
                        };
              };
        end;


        # Get a property value, which
        # may require several requests:
        #
        fun get_property property
            =
            get_prop ()
            where
                (info_of_prop  property)
                    ->
                    (display, window_id, name);

                fun size_of (xt::RAW_DATA { data, ... } )
                    =
                    (vector_of_one_byte_unts::length data) / 4;

                fun get_chunk words_so_far
                    =
                    req_get_property  display
                      {
                        window_id,
                        property => name,
                        type     => NULL,                       #  AnyPropertyType 
                        offset   => words_so_far,
                        len      => 1024,
                        delete   => FALSE
                      };

                fun extend_data (data', xt::RAW_DATA { data, ... } )
                    =
                    data ! data';

                fun flatten_data (data', xt::RAW_DATA { format, data } )
                    =
                    xt::RAW_DATA {
                        format,
                        data=>vector_of_one_byte_unts::cat (reverse (data ! data'))
                    };

                fun get_prop ()
                    =
                    case (get_chunk 0)

                        NULL => NULL;

                        THE { type, bytes_after, value as xt::RAW_DATA { data, ... } }
                            =>
                            if (bytes_after == 0)    THE (PROPERTY_VALUE { type, value } );
                            else                     get_rest (size_of value, [data]);
                            fi;
                  esac

                also
                fun get_rest (words_so_far, data')
                    =
                    case (get_chunk words_so_far)

                         NULL => NULL;

                         THE { type, bytes_after, value }
                             =>
                             if (bytes_after == 0)

                                  THE (PROPERTY_VALUE { type, value=>flatten_data (data', value) } );
                             else
                                  get_rest(
                                      words_so_far + size_of value,
                                      extend_data (data', value));
                             fi;
                     esac;
              end;


        Property_Change ==  wpp::Property_Change;


        fun watch_property  (PROPERTY { xsession, name, window, is_unique },  watcher)
            =
            {   client_to_window_watcher =  prop_server  xsession;
                #
                client_to_window_watcher.watch_property (name, window, is_unique, watcher);
            };


        # 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 SUCKO FIXME
        #
        fun xrdb_of_screen (screen: sn::Screen)
            = 
            {   xsession    =  sn::xsession_of_screen     screen;
                root_window =  sn::root_window_of_screen  screen;

                case (get_property
                         (PROPERTY
                           { xsession,
                             name      =>  standard_x11_atoms::resource_manager,
                             window    =>  root_window,
                             is_unique =>  FALSE
                           }
                     )   )
                    #         
                    THE (PROPERTY_VALUE { type, value=>RAW_DATA { format, data } } )
                        => 
                        string::tokens
                            (\\ c
                                =
                                case (char::to_int c)
                                    #
                                    13 =>  TRUE;                # CR
                                    10 =>  TRUE;                # lF
                                    _  =>  FALSE;
                                esac
                            )
                            (byte::bytes_to_string  data);

                    _   => [];
                esac;
        };
    };                                                          # package window_property 

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext