Ejemplo n.º 1
0
    def _gen_c(cls):
        """Creates the wl_interface C struct

        Generates the CFFI cdata for the wl_interface struct given by the
        interface.
        """
        # Initialize the interface cdata
        cls._ptr.name = name = ffi.new('char[]', cls.name.encode())
        cls._ptr.version = cls.version

        # Determine the number of methods to assign and assign them
        cls._ptr.method_count = len(cls.requests)
        cls._ptr.methods = methods_ptr = ffi.new("struct wl_message[]", len(cls.requests))
        # Iterate over the methods
        for i, message in enumerate(cls.requests):
            # First, generate the wl_message cdata
            msg_buf = ffi.buffer(message._ptr)
            methods_buf = ffi.buffer(methods_ptr + i)
            # Copy the contents of the cdata into the allocated cdata
            methods_buf[:] = msg_buf

        cls._ptr.event_count = len(cls.events)
        cls._ptr.events = events_ptr = ffi.new("struct wl_message[]", len(cls.events))
        # Iterate over the methods
        for i, message in enumerate(cls.events):
            # First, generate the wl_message cdata
            msg_buf = ffi.buffer(message._ptr)
            events_buf = ffi.buffer(events_ptr + i)
            # Copy the contents of the cdata into the allocated cdata
            events_buf[:] = msg_buf

        weakkeydict[cls._ptr] = (name, methods_ptr, events_ptr)
Ejemplo n.º 2
0
    def build_message_struct(self, wl_message_struct) -> Tuple:
        """Bulid the wl_message struct for this message

        :param wl_message_struct:
            The wl_message cdata struct to use to build the message struct.
        :return:
            A tuple of elements which must be kept alive for the message struct
            to remain valid.
        """
        signature = "".join(argument.signature for argument in self.arguments)
        if self.version is not None:
            signature = f"{self.version}{signature}"

        wl_message_struct.name = name = ffi.new('char[]', self.name.encode())
        wl_message_struct.signature = signature = ffi.new(
            'char[]', signature.encode())

        wl_message_struct.types = types = ffi.new(
            'struct wl_interface* []', len(list(self._marshaled_arguments)))

        for index, argument in enumerate(self._marshaled_arguments):
            if argument.interface is None:
                types[index] = ffi.NULL
            else:
                types[index] = argument.interface._ptr

        return name, signature, types
Ejemplo n.º 3
0
    def _gen_c(cls):
        """Creates the wl_interface C struct

        Generates the CFFI cdata for the wl_interface struct given by the
        interface.
        """
        cls.registry = WeakValueDictionary()

        cls._ptr.name = name = ffi.new('char[]', cls.name.encode())
        cls._ptr.version = cls.version

        keep_alive = []
        # Determine the number of methods to assign and assign them
        cls._ptr.method_count = len(cls.requests)
        cls._ptr.methods = methods_ptr = ffi.new("struct wl_message[]",
                                                 len(cls.requests))
        # Iterate over the methods
        for i, message in enumerate(cls.requests):
            keep_alive.extend(message.build_message_struct(methods_ptr[i]))

        cls._ptr.event_count = len(cls.events)
        cls._ptr.events = events_ptr = ffi.new("struct wl_message[]",
                                               len(cls.events))
        # Iterate over the methods
        for i, message in enumerate(cls.events):
            keep_alive.extend(message.build_message_struct(events_ptr[i]))

        weakkeydict[cls._ptr] = (name, methods_ptr,
                                 events_ptr) + tuple(keep_alive)
Ejemplo n.º 4
0
    def __init__(self, function):
        self._ptr = ffi.new("struct wl_listener *")
        self.notify = function
        self.link = None

        self._ptr.notify = callback_ffi = _wrap_listener_callback(function)

        weakkeydict[self] = callback_ffi
Ejemplo n.º 5
0
    def __init__(self, *, ptr=None, data_wrapper=None):
        if ptr is None:
            self._ptr = ffi.new("struct wl_listener *")
            lib.wl_signal_init(self._ptr)
        else:
            self._ptr = ptr

        self._data_wrapper = data_wrapper
        self._link = []
Ejemplo n.º 6
0
    def __init__(self, func, signature, types):
        self._func = func
        self.name = func.__name__.strip('_')
        self.signature = signature
        self.types = types

        self._ptr = ffi.new('struct wl_message *')
        self._ptr.name = name = ffi.new('char[]', self.name.encode())
        self._ptr.signature = signature = ffi.new('char[]', self.signature.encode())

        self._ptr.types = types = ffi.new('struct wl_interface* []', len(self.types))
        for i, _type in enumerate(self.types):
            if _type:
                self._ptr.types[i] = _type._ptr
            else:
                self._ptr.types[i] = ffi.NULL

        weakkeydict[self._ptr] = (name, signature, types)
Ejemplo n.º 7
0
    def __init__(self, function):
        self._handle = ffi.new_handle(self)

        # we need a way to get this Python object from the `struct
        # wl_listener*`, so we put the pointer in a container struct that
        # contains both the wl_listener and a pointer to our ffi handle
        self.container = ffi.new("struct wl_listener_container *")
        self.container.handle = self._handle

        self._ptr = ffi.addressof(self.container.destroy_listener)
        self._ptr.notify = lib.notify_func
        self._notify = function
        self._signal = None
Ejemplo n.º 8
0
    def add_socket(self, name=None):
        """Add a socket to Wayland display for the clients to connect.

        This adds a Unix socket to Wayland display which can be used by clients
        to connect to Wayland display.

        If `None` is passed as name, then it would look for `WAYLAND_DISPLAY`
        environment variable for the socket name. If `WAYLAND_DISPLAY` is not
        set, then default `wayland-0` is used.

        The Unix socket will be created in the directory pointed to by
        environment variable `XDG_RUNTIME_DIR`. If `XDG_RUNTIME_DIR` is not
        set, then this function throws an exception.

        The length of socket path, i.e., the path set in `XDG_RUNTIME_DIR` and
        the socket name, must not exceed the maxium length of a Unix socket
        path.  The function also fails if the user do not have write permission
        in the `XDG_RUNTIME_DIR` path or if the socket name is already in use.

        :param name: Name of the Unix socket.
        :type name: string or None
        """
        if name is None:
            name_ptr = lib.wl_display_add_socket_auto(self._ptr)
            name = ffi.string(name_ptr)

            if not name:
                # TODO: raise better
                raise Exception()

            return name
        else:
            name_ptr = ffi.new('char []', name.encode())
            ret = lib.wl_display_add_socket(self._ptr, name_ptr)

            if ret == -1:
                # TODO: raise better
                raise Exception()
Ejemplo n.º 9
0
    def add_socket(self, name: str = None) -> str:
        """Add a socket to Wayland display for the clients to connect.

        This adds a Unix socket to Wayland display which can be used by clients
        to connect to Wayland display.

        If `None` is passed as name, then it would look for `WAYLAND_DISPLAY`
        environment variable for the socket name. If `WAYLAND_DISPLAY` is not
        set, then default `wayland-0` is used.

        The Unix socket will be created in the directory pointed to by
        environment variable `XDG_RUNTIME_DIR`. If `XDG_RUNTIME_DIR` is not
        set, then this function throws an exception.

        The length of socket path, i.e., the path set in `XDG_RUNTIME_DIR` and
        the socket name, must not exceed the maxium length of a Unix socket
        path.  The function also fails if the user do not have write permission
        in the `XDG_RUNTIME_DIR` path or if the socket name is already in use.

        :param name: Name of the Unix socket.
        :type name: string or None
        """
        if name is None:
            name_ptr = lib.wl_display_add_socket_auto(self._ptr)
            if name_ptr == ffi.NULL:
                raise RuntimeError("Unable to create socket")
            name = ffi.string(name_ptr)
        else:
            name_ptr = ffi.new('char []', name.encode())
            ret = lib.wl_display_add_socket(self._ptr, name_ptr)

            if ret == -1:
                # TODO: raise better
                raise Exception()

        return name
Ejemplo n.º 10
0
    def arguments_to_c(self, *args):
        """Create an array of `wl_argument` C structs

        Generate the CFFI cdata array of `wl_argument` structs that correspond
        to the arguments of the method as specified by the method signature.

        :param args: Input arguments
        :type args: `list`
        :returns: cdata `union wl_argument []` of args
        """
        nargs = len(list(self._marshaled_arguments))
        args_ptr = ffi.new('union wl_argument []', nargs)

        arg_iter = iter(args)
        refs = []
        for i, argument in enumerate(self._marshaled_arguments):
            # New id (set to null for now, will be assigned on marshal)
            # Then, continue so we don't consume an arg
            if argument.argument_type == ArgumentType.NewId:
                args_ptr[i].o = ffi.NULL
                continue

            arg = next(arg_iter)
            # Match numbers (int, unsigned, float, file descriptor)
            if argument.argument_type == ArgumentType.Int:
                args_ptr[i].i = arg
            elif argument.argument_type == ArgumentType.Uint:
                args_ptr[i].u = arg
            elif argument.argument_type == ArgumentType.Fixed:
                if isinstance(arg, int):
                    f = lib.wl_fixed_from_int(arg)
                else:
                    f = lib.wl_fixed_from_double(arg)
                args_ptr[i].f = f
            elif argument.argument_type == ArgumentType.FileDescriptor:
                args_ptr[i].h = arg
            elif argument.argument_type == ArgumentType.String:
                if arg is None:
                    if not argument.nullable:
                        raise Exception
                    new_arg = ffi.NULL
                else:
                    new_arg = ffi.new('char []', arg.encode())
                    refs.append(new_arg)
                args_ptr[i].s = new_arg
            elif argument.argument_type == ArgumentType.Object:
                if arg is None:
                    if not argument.nullable:
                        raise Exception
                    new_arg = ffi.NULL
                else:
                    new_arg = ffi.cast('struct wl_object *', arg._ptr)
                    refs.append(new_arg)
                args_ptr[i].o = new_arg
            elif argument.argument_type == ArgumentType.Array:
                # TODO: this is a bit messy, we probably don't want to put everything in one buffer like this
                new_arg = ffi.new('struct wl_array *')
                new_data = ffi.new('void []', len(arg))
                new_arg.alloc = new_arg.size = len(arg)
                ffi.buffer(new_data)[:] = arg
                refs.append(new_arg)
                refs.append(new_data)

        if len(refs) > 0:
            weakkeydict[args_ptr] = tuple(refs)

        return args_ptr
Ejemplo n.º 11
0
 def __init__(self, name, bases, dct):
     self._ptr = ffi.new("struct wl_interface *")
     self.events = []
     self.requests = []
Ejemplo n.º 12
0
    def __init__(self, name, bases, dct):
        self.events = []
        self.requests = []

        # Initialize the interface cdata
        self._ptr = ffi.new("struct wl_interface *")
Ejemplo n.º 13
0
 def _post_error(self, code, msg=""):
     msg_ptr = ffi.new("char []", msg)
     lib.wl_resouce_post_error(self._ptr, code, msg_ptr)
Ejemplo n.º 14
0
    def arguments_to_c(self, *args):
        """Create an array of `wl_argument` C structs

        Generate the CFFI cdata array of `wl_argument` structs that correspond
        to the arguments of the method as specified by the method signature.

        :param args: Input arguments
        :type args: `list`
        :returns: cdata `union wl_argument []` of args
        """
        nargs = len(re_arg.findall(self.signature))
        args_ptr = ffi.new('union wl_argument []', nargs)

        arg_iter = iter(args)
        refs = []
        for i, sig_match in enumerate(re_arg.finditer(self.signature)):
            null, sig = sig_match.groups()

            # New id (set to null for now, will be assigned on marshal)
            # Then, continue so we don't consume an arg
            if sig == 'n':
                args_ptr[i].o = ffi.NULL
                continue
            arg = next(arg_iter)
            # Match numbers (int, unsigned, float, file descriptor)
            if sig == 'i':
                args_ptr[i].i = arg
            elif sig == 'u':
                args_ptr[i].u = arg
            elif sig == 'f':
                if isinstance(arg, int):
                    f = lib.wl_fixed_from_int(arg)
                else:
                    f = lib.wl_fixed_from_double(arg)
                args_ptr[i].f = f
            elif sig == 'h':
                args_ptr[i].h = arg
            # Match string
            elif sig == 's':
                if arg is None:
                    if not null:
                        raise Exception
                    new_arg = ffi.NULL
                else:
                    new_arg = ffi.new('char []', arg.encode())
                    refs.append(new_arg)
                args_ptr[i].s = new_arg
            # Object
            elif sig == 'o':
                if arg is None:
                    if not null:
                        raise Exception
                    new_arg = ffi.NULL
                else:
                    new_arg = ffi.cast('struct wl_object *', arg._ptr)
                    refs.append(new_arg)
                args_ptr[i].o = new_arg
            # Array (i.e. buffer of bytes)
            elif sig == 'a':
                new_arg = ffi.new('struct wl_array *')
                new_data = ffi.new('void []', len(arg))
                new_arg.alloc = new_arg.size = len(arg)
                ffi.buffer(new_data)[:] = arg
                refs.append(new_arg)
                refs.append(new_data)

        if refs:
            weakkeydict[args_ptr] = refs

        return args_ptr
Ejemplo n.º 15
0
 def _post_error(self, code, msg=""):
     msg_ptr = ffi.new('char []', msg)
     lib.wl_resouce_post_error(self._ptr, code, msg_ptr)