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)
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)
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)
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)
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
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)
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
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 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