Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle mod keys correctly #152

Closed
wants to merge 3 commits into from
Closed

Handle mod keys correctly #152

wants to merge 3 commits into from

Conversation

iacore
Copy link

@iacore iacore commented Mar 5, 2022

Need to first install QubesOS/qubes-gui-daemon#98, otherwise mod keys may not work.

To fix:

@iacore
Copy link
Author

iacore commented Mar 6, 2022

X's documentation is so bad that I did this with trail and error.

@marmarek
Copy link
Member

marmarek commented Mar 6, 2022

otherwise mod keys may not work.

This is unacceptable. If introducing incompatible protocol change (which, again, I'm not sure if is really necessary), it must be correctly handled. Generally, semantic of existing messages should not change; if really necessary, new messages can be introduced.

@iacore
Copy link
Author

iacore commented Mar 8, 2022

It's that keys like Ctrl and Alt are pressed and released twice without this patch. Most applications work fine.

@DemiMarie
Copy link
Contributor

otherwise mod keys may not work.

This is unacceptable. If introducing incompatible protocol change (which, again, I'm not sure if is really necessary), it must be correctly handled. Generally, semantic of existing messages should not change; if really necessary, new messages can be introduced.

One approach is for the daemon to send a “I support XYZ” message when it connects. The agent will then know that a new daemon is running and it can ignore the old events.

@DemiMarie
Copy link
Contributor

The GUI daemon can send a message that states, “XYZ is supported, use it if you know about it”.

@marmarek
Copy link
Member

marmarek commented Mar 8, 2022

It's called protocol version (minor part) in the handshake.

@DemiMarie
Copy link
Contributor

It's called protocol version (minor part) in the handshake.

I thought the agent told the daemon its version, but not the reverse. So the agent still needs some way to know whether to expect the new messages.

@marmarek
Copy link
Member

marmarek commented Mar 8, 2022

It's called protocol version (minor part) in the handshake.

I thought the agent told the daemon its version, but not the reverse. So the agent still needs some way to know whether to expect the new messages.

Ah, you're right, that's the other way around.

.gitignore Outdated
/xf86-input-mfndev/config.h.in
/xf86-input-mfndev/depcomp
/xf86-input-mfndev/ltmain.sh
/xf86-qubes-common/libxf86-qubes-common.so
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing newline at EOF

@iacore iacore changed the title Handle mod keys correctly & Treat all focus events equally Handle mod keys correctly Mar 14, 2022
@iacore
Copy link
Author

iacore commented Jun 20, 2022

Weird thing: sometimes, when starting up my arch linux AppVM, it says "sticky key enabled". Maybe this pressing shift a lot of times?

Not an issue in terms of usability, just a bit annoying to see the notification. It only happens at VM start up.

@DemiMarie
Copy link
Contributor

Weird thing: sometimes, when starting up my arch linux AppVM, it says "sticky key enabled". Maybe this pressing shift a lot of times?

Does this happen with a patched GUI daemon?

@iacore
Copy link
Author

iacore commented Jul 6, 2022

Weird thing: sometimes, when starting up my arch linux AppVM, it says "sticky key enabled". Maybe this pressing shift a lot of times?

Does this happen with a patched GUI daemon?

I do not remember it happening lately. Maybe it's fixed, maybe not. It only happened "sometimes" before the patch.

One way to fix it properly is to maybe disable sticky key in XFCE in AppVM. I don't know how to do that easily.

@DemiMarie
Copy link
Contributor

@locriacyber: I think this can be split into a cleanup patch (which does not change behavior) and a patch that changes behavior conditionally on the GUI daemon supporting a new protocol version.

@marmarek: I am inclined to make the changes in protocol 1.4 as minimal as possible, as everyone needs to have updated to a daemon that supports it before we can ship an agent that uses it. Therefore, I think this should be delayed until no earlier than protocol version 1.5.

@iacore
Copy link
Author

iacore commented Jul 18, 2022

I'll try if I can make this backwards compatible. Can I use Zig to write the patch? I'm already reaching my limit with C and 2 features. It's easier for me to rewrite the whole thing in C.

Also, it's better to negotiate protocol version.

QubesOS/qubes-gui-daemon#98 (comment)

@DemiMarie
Copy link
Contributor

I'll try if I can make this backwards compatible. Can I use Zig to write the patch? C is not as flexible.

I doubt @marmarek or myself know any Zig. The long term plan is to rewrite the entire daemon in Rust, but that will also involve switching from X11 to Wayland.

@iacore
Copy link
Author

iacore commented Jul 18, 2022

Interfacing Zig with C is easy. It's possible to replace a single C function with Zig. Rust and the borrow checker makes it harder (all the unsafe you have to write). zig translate-c is amazing to use if you want to translate a C function to Zig to patch it.

Still, if we have to rewrite the whole thing, why don't we use existing solution? (you mentioned one written in Rust before)

@DemiMarie
Copy link
Contributor

Interfacing Zig with C is easy. It's possible to replace a single C function with Zig. Rust and the borrow checker makes it harder (all the unsafe you have to write). zig translate-c is amazing to use if you want to translate a C function to Zig to patch it.

The problem is that neither @marmarek (to the best of my knowledge) nor myself know any Zig. We cannot accept patches we cannot review properly.

Still, if we have to rewrite the whole thing, why don't we use existing solution? (you mentioned one written in Rust before)

That one does not exist yet, and it will be quite a while before anyone gets around to implementing it.

@iacore
Copy link
Author

iacore commented Jul 20, 2022

Personally, I think Zig is a good choice at incrementally replacing C. It's
Zig documentation

The most important different of Zig from C is the pointer types are more fine grained and way harder to make mistakes

  • *T single pointer, no pointer arithmetic, no null. ?*T is nullable pointer.
  • ?T is either T (by-value) or nothing. Use val.? or if expression to get the wrapped value out.
  • []T is slice of T with length. In C this would be two arguments: char * s, int len.
  • [6]T is fixed sized array. No implicit coersion from this type to []T.
  • E!T or !T (inferred E) is either error E or T, where E is errorset.
  • Errorset is like enum in C and cannot cross ABI boundary. Better than using -1, -2 to denote error.
  • union(enum) is tagged enum

*T in C is ?[*]T in Zig (nullable pointer to array or a single item). You should never use this type unless you are dealing with C. Only [*]T allow you to do unchecked pointer arithmetic.

Otherwise, the memory model is the same as C. But apart from memory model, Zig's compiler is strict.

  • matching enum is exhaustive
  • enum and is its own type. It's still integer in memory though (you can choose the size too).
  • Few casts are implicit (only from literal to concrete type). All other casts look like @truncate.

As for memory allocation, there is no global malloc/free. Instead you pass std.mem.Allocator to any function that needs to allocate stuff.

Good of Zig than Rust is, I can control memory usage precisely, and it's easier to interface with C than C.
Bad of Zig than Rust: I still forget to release memory sometimes with Zig. There is no support for RAII.

@meithecatte
Copy link

What is Zig's story for temporal memory safety? If I understand correctly, Zig doesn't have any way of avoiding use-after-free other than "be careful".

@DemiMarie
Copy link
Contributor

What is Zig's story for temporal memory safety? If I understand correctly, Zig doesn't have any way of avoiding use-after-free other than "be careful".

Yup. It is not possible to prevent use-after-free without some form of lifetime analysis or a garbage collector. If one wants safe references into tagged unions and a guarantee of no iterator invalidation, then I believe one basically needs either the full Rust borrow checker or something even more complex, like full dependent types and hand-written (but machine-checked) proofs of correct API usage.

@marmarek
Copy link
Member

From the description above (which is my only knowledge of this language) Zig sounds appealing. But I don't want to introduce yet another language to the code base, especially one that isn't known to our team (and likely most contributors).

@iacore
Copy link
Author

iacore commented Jul 21, 2022

What is Zig's story for temporal memory safety? If I understand correctly, Zig doesn't have any way of avoiding use-after-free other than "be careful".

From https://ziglearn.org/chapter-2/:

The Zig standard library also has a general purpose allocator. This is a safe allocator which can prevent double-free, use-after-free and can detect leaks. Safety checks and thread safety can be turned off via its configuration struct (left empty below).

It still doesn't prevent race r/w cross thread.

Yup. It is not possible to prevent use-after-free without some form of lifetime analysis or a garbage collector. If one wants safe references into tagged unions and a guarantee of no iterator invalidation, then I believe one basically needs either the full Rust borrow checker or something even more complex, like full dependent types and hand-written (but machine-checked) proofs of correct API usage.

Check out compile-time use analysis in Koka. Data types that is proven to be acyclic do not invoke GC. You can write code with "weak" reference (lookup maybe fail) and not use GC at all. Dependent types has nothing to do with memory usage. You still need some kind of GC, or never use cyclic reference. There is also HVM which clones your function before calling it (it never shares anything).

@iacore
Copy link
Author

iacore commented Jul 21, 2022

@marmarek Can I try to patch gui-agent in Zig? This way you can see how well it integrates with existing code. Working with C programs that contains all definition in a single file has been difficult for me.

@DemiMarie
Copy link
Contributor

@marmarek Can I try to patch gui-agent in Zig? This way you can see how well it integrates with existing code. Working with C programs that contains all definition in a single file has been difficult for me.

Would splitting the C into multiple files help? I at least cannot review Zig as I do not know the language, and contributions that cannot be reviewed cannot be accepted.

@iacore
Copy link
Author

iacore commented Jul 22, 2022

I'll try

@iacore
Copy link
Author

iacore commented Aug 11, 2022

Superseded by #169

@iacore iacore closed this Aug 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants