Define g-i's policy for discontinuous flags bits
Discussion started in gjs#507 (closed).
GdkModifierType
is a problem because it's defined like this:
typedef enum
{
GDK_SHIFT_MASK = 1 << 0,
GDK_LOCK_MASK = 1 << 1,
GDK_CONTROL_MASK = 1 << 2,
GDK_ALT_MASK = 1 << 3,
GDK_BUTTON1_MASK = 1 << 8,
GDK_BUTTON2_MASK = 1 << 9,
GDK_BUTTON3_MASK = 1 << 10,
GDK_BUTTON4_MASK = 1 << 11,
GDK_BUTTON5_MASK = 1 << 12,
GDK_SUPER_MASK = 1 << 26,
GDK_HYPER_MASK = 1 << 27,
GDK_META_MASK = 1 << 28,
} GdkModifierType;
The documentation says
Note that GDK may add internal values to events which include values outside of this enumeration. Your code should preserve and ignore them. You can use
GDK_MODIFIER_MASK
to remove all private values.
but of course this usage note is not able to be encoded in the GIR file.
The GJS bug was reported because 1<<4
was returned from C, which GJS chooses to interpret as an invalid value for this flags type. Clearly this is not the right choice for this particular situation, but I'm interested in coming up with a rule for language bindings that can be applied consistently in the case of flags with discontinuous bits. (This might apply to enum types with non-consecutive values, as well.)
I'm imagining we should define behaviour for six cases:
- (1) A value with a bit not covered by the mask is returned from C, but the uncovered bit is lower than the highest bit in the mask. (e.g. 0x10, 0x2000 in this case)
- (2) A value with a bit not covered by the mask is returned from C, and the uncovered bit is higher than the highest bit in the mask. (e.g. 0x2000_0000 in this case)
- (3) Same, but additionally the uncovered bit is bit 32 or higher. (I believe flags types are supposed to be limited to 32-bit in g-i)
- (4-6) Same as the above 3 cases, but sending a value from the language binding to C.
The GJS bug revealed that there is a use case for (1) to be "ignore, and mask out that bit". I wonder if there is any existing use case for the opposite behaviour for (1). I'm pretty sure that (3) and (6) should not be supported in any case.
Alternatively, we might choose to say that g-i does not support flags with discontinuous bits, and require that the C definition includes things like GDK_MODIFIER_TYPE_PRIVATE1 = 1 << 4
to cover the missing bits.
Or, we might choose to allow flags types to specify in their annotations a mask for values that can legally be marshalled from C. In the case of GdkModifierType it might be something like (allowed-bits 28)
to say that bits 0 through 28 are OK.