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)
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
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)
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
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 = []
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)
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
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()
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
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
def __init__(self, name, bases, dct): self._ptr = ffi.new("struct wl_interface *") self.events = [] self.requests = []
def __init__(self, name, bases, dct): self.events = [] self.requests = [] # Initialize the interface cdata self._ptr = ffi.new("struct wl_interface *")
def _post_error(self, code, msg=""): msg_ptr = ffi.new("char []", msg) lib.wl_resouce_post_error(self._ptr, code, msg_ptr)
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
def _post_error(self, code, msg=""): msg_ptr = ffi.new('char []', msg) lib.wl_resouce_post_error(self._ptr, code, msg_ptr)