示例#1
0
def notify_func(listener_ptr, data):
    # basically a `container_of` macro, but using cffi, get the
    # wl_listener_container for the given listener
    container = ffi.cast(
        "struct wl_listener_container *",
        ffi.cast("char*", listener_ptr) -
        ffi.offsetof("struct wl_listener_container", "destroy_listener"))
    listener = ffi.from_handle(container.handle)

    if listener._signal is not None and listener._signal._data_wrapper is not None:
        data = listener._signal._data_wrapper(data)

    callback = listener._notify
    callback(listener, data)
示例#2
0
    def _post_event(self, opcode, *args):
        # Create wl_argument array
        args_ptr = self._interface.events[opcode].arguments_to_c(*args)
        # Make the cast to a wl_resource
        resource = ffi.cast("struct wl_resource *", self._ptr)

        lib.wl_resource_post_event_array(resource, opcode, args_ptr)
示例#3
0
    def _post_event(self, opcode, args):
        # Create wl_argument array
        args_ptr = self._interface.events[opcode].arguments_to_c(*args)
        # Make the cast to a wl_resource
        resource = ffi.cast('struct wl_resource *', self._ptr)

        lib.wl_resource_post_event_array(resource, opcode, args_ptr)
示例#4
0
    def _marshal(self, opcode, *args):
        """Marshal the given arguments into the Wayland wire format"""
        # Create a wl_argument array
        args_ptr = self.interface.requests[opcode].arguments_to_c(*args)

        # Write the event into the connection queue
        proxy = ffi.cast('struct wl_proxy *', self._ptr)
        lib.wl_proxy_marshal_array(proxy, opcode, args_ptr)
示例#5
0
    def c_to_arguments(self, args_ptr):
        """Create a list of arguments

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

        :param args_ptr: Input arguments
        :type args_ptr: cdata `union wl_argument []`
        :returns: list of args
        """
        args = []
        for i, argument in enumerate(self.arguments):
            arg_ptr = args_ptr[i]

            # Match numbers (int, unsigned, float, file descriptor)
            if argument.argument_type == ArgumentType.Int:
                args.append(arg_ptr.i)
            elif argument.argument_type == ArgumentType.Uint:
                args.append(arg_ptr.u)
            elif argument.argument_type == ArgumentType.Fixed:
                f = lib.wl_fixed_to_double(arg_ptr.f)
                args.append(f)
            elif argument.argument_type == ArgumentType.FileDescriptor:
                args.append(arg_ptr.h)
            elif argument.argument_type == ArgumentType.String:
                if arg_ptr == ffi.NULL:
                    if not argument.nullable:
                        raise Exception
                    args.append(None)
                else:
                    args.append(ffi.string(arg_ptr.s).decode())
            elif argument.argument_type == ArgumentType.Object:
                if arg_ptr.o == ffi.NULL:
                    if not argument.nullable:
                        message = "Got null object parsing arguments for '{}' message, may already be destroyed".format(
                            self.name)
                        raise RuntimeError(message)
                    args.append(None)
                else:
                    iface = self.types[i]
                    proxy_ptr = ffi.cast('struct wl_proxy *', arg_ptr.o)
                    obj = iface.proxy_class.registry.get(proxy_ptr)
                    if obj is None:
                        raise RuntimeError(
                            "Unable to get object for {}, was it garbage collected?"
                            .format(proxy_ptr))
                    args.append(obj)
            elif argument.argument_type == ArgumentType.NewId:
                # TODO
                raise NotImplementedError
            elif argument.argument_type == ArgumentType.Array:
                array_ptr = arg_ptr.a
                args.append(ffi.buffer(array_ptr.data, array_ptr.size)[:])
            else:
                raise Exception(f"Bad argument: {argument}")

        return args
示例#6
0
    def _marshal_constructor(self, opcode, interface, *args):
        """Marshal the given arguments into the Wayland wire format for a constructor"""
        # Create a wl_argument array
        args_ptr = self.interface.requests[opcode].arguments_to_c(*args)

        # Write the event into the connection queue and build a new proxy from the given args
        proxy = ffi.cast('struct wl_proxy *', self._ptr)
        proxy_ptr = lib.wl_proxy_marshal_array_constructor(
            proxy, opcode, args_ptr, interface._ptr)

        return interface.proxy_class(proxy_ptr, self._display)
示例#7
0
    def __init__(self, ptr, display=None):
        """Represents a protocol object on the client side.

        A :class:`Proxy` acts as a client side proxy to an object existing in
        the compositor.  Events coming from the compositor are also handled by
        the proxy, which will in turn call the handler set with
        :func:`Proxy.add_listener`.
        """
        self.user_data = None
        self.dispatcher = Dispatcher(self.interface.events)

        # This should only be true for wl_display proxies, as they will
        # initialize its pointer on a `.connect()` call
        if ptr is None:
            self._ptr = ptr
            self._display = self
            return

        self._display = display

        # parent display is the root-most client Display object, all proxies
        # should keep the display alive
        if display is None:
            raise ValueError(
                "Non-Display Proxy objects must be associated to a Display")
        display._children.add(self)

        if ptr == ffi.NULL:
            raise RuntimeError("Got a null pointer for the proxy")

        # note that even though we cast to a proxy here, the ptr may be a
        # wl_display, so the methods must still cast to 'struct wl_proxy *'
        ptr = ffi.cast('struct wl_proxy *', ptr)
        self._ptr = ffi.gc(ptr, lib.wl_proxy_destroy)

        self._handle = ffi.new_handle(self)
        lib.wl_proxy_add_dispatcher(self._ptr, lib.dispatcher_func,
                                    self._handle, ffi.NULL)

        self.interface.registry[self._ptr] = self
示例#8
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
示例#9
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