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

Finish tinywl. #5

Draft
wants to merge 109 commits into
base: master
Choose a base branch
from
Draft

Finish tinywl. #5

wants to merge 109 commits into from

Conversation

jsoo1
Copy link

@jsoo1 jsoo1 commented Jun 13, 2021

Hello,

@LambdaCalrissian and me have been working on finishing the tinywl implementation. We have something close to a working version here with a few bugs to fix.

We completed the rest of the failwiths in the file and completed the ffi required to accomplish it.

There are certainly things here that might need discussion and, as mentioned it still has bugs.

Thanks for the great start!

LambdaCalrissian and others added 30 commits December 13, 2020 12:55
* Get back pure ocaml type from Xdg_shell.Surface.role.
* Corresponds to wlr_xdg_surface_from_surface in xdg_shell.
Keycodes is not in Wlroots, but CTypes does not support abstract arrays. So
we're using this as a wrapper with a void*.
This is to finish focus_view in tinywl.
We need to mutate this value after it's held, so we need to make it into a ref.
Needed for move and resize events in tinywl.
Don't need to make the entire thing a ref. Just make the specific field we are
concerned with mutable.
Need to handle the interactive events (moving or resizing a winodw).

Need a new data type for the what the cursor is trying to do.
Might never be set to true. Do we need to handle this?
Edges are used in 32bit fashion. This could be changed since I do not
know if they can be coerced safely to 64 bits.
* Moves option elimination outside of process_cursor* functions.
* Changes grab to have an optional resize field, since resizing and
  moving are two disjoint states.
* Changes Resize cursor_mode paramter to Edges.t
@jsoo1 jsoo1 marked this pull request as draft June 13, 2021 18:34
@Armael
Copy link
Collaborator

Armael commented Jun 13, 2021

Wow, thanks a lot for this work, that looks great! I appreciate it especially given that it's useful work that is also quite tedious to do by oneself :). I'll certainly need to refresh my memory a bit as it's been a while since I haven't touched this project, but I'll definitely try to have a look soon.

Did you hit any particular issues that you'd like to report, when building the project or extending the existing bindings?

@jsoo1
Copy link
Author

jsoo1 commented Jun 19, 2021

Hey, thanks! It was a really great learning experience. I got from 0 to 1 with the ctypes library.

The only real problem came up about 2 weeks ago with the release of wlroots 0.13. A lot of the unstable features changed.

@Armael
Copy link
Collaborator

Armael commented Jun 19, 2021

Yeah, I noticed today that the repo doesn't build anymore with the latest git version of wlroots.
I'd like to try and look at whether wlroots could be vendored with the bindings, to make it easier to rely on a fixed version.

While I figure how to do that, could you tell me which git commit of wlroots you used when working on the bindings?

@jsoo1
Copy link
Author

jsoo1 commented Jun 19, 2021

We were using the 0.12.0 tag.

I personally try to avoid vendoring whenever possible. I am not sure how fast 0.13 is going to be adopted in distros, though.

@Armael
Copy link
Collaborator

Armael commented Jun 19, 2021

Thanks. I was thinking of vendoring only for developping the library, not for what would be a released version of the bindings.
Because otherwise I have to uninstall/downgrade my system installation of wlroots (and thus sway) to work on the bindings, which is not very convenient.

@jsoo1
Copy link
Author

jsoo1 commented Jun 19, 2021

Fair enough. I am using nix/guix to manage the wlroots installation so it's possible to have multiple versions installed. Totally understand if that does not help your process, though.

@Armael
Copy link
Collaborator

Armael commented Jun 20, 2021

Ah, that's a very good point. Relying on nix or guix for development does sound simpler than figuring out vendoring. Would you mind sharing which setup you use for that? (if you have a nix/guix profile file it could be part of the repo)
Does that mean that you don't use opam to setup your ocaml development environment?

@jsoo1
Copy link
Author

jsoo1 commented Jun 21, 2021

I used opam pretty extensively but I don't think it would be entirely necessary. I could setup a nix shell or guix environment if you wish. Right now my setup is a bit of a patchwork.

@Armael
Copy link
Collaborator

Armael commented Jul 7, 2021

Sorry for the delay, I just came back from holidays. I think if you could cook up a nix or guix environment that would be super useful (even more if it somehow works with opam, as that's what I know most). I tried to do that my self (with guix), but couldn't manage to make it work.

@Armael
Copy link
Collaborator

Armael commented Jul 8, 2021

I've been suggested another approach on #sway-devel: to build wlroots and install it locally (e.g. in ~/.local), then tweak environment variables to point to the local installation. I guess that's a form of poor-man's nix environment, but if it works it would be convenient enough for me. I'll try that tonight and report back.

@jsoo1
Copy link
Author

jsoo1 commented Jul 9, 2021 via email

@Armael
Copy link
Collaborator

Armael commented Jul 9, 2021

Alright, don't worry too much then, it turns out the solution of installing wlroots in ~/.local works well for me; I could compile your branch and I'm currently doing the review :-).

@jsoo1
Copy link
Author

jsoo1 commented Jul 9, 2021 via email

Copy link
Collaborator

@Armael Armael left a comment

Choose a reason for hiding this comment

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

Here's a first round of review (I haven't looked at tinywl itself yet). It's looking good, I only have a number of comments mostly regarding naming... Thanks for the hard work!

ffi/ffi.ml Outdated
let wlr_output_render_software_cursors = foreign "wlr_output_render_software_cursors"
(* FIXME: The void pointer is a pixman_region32_t for which no bindings exist (yet).
This is only ok because so far, no one uses it. *)
(wlr_output_p @-> ptr void @-> returning void)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would instead add a let pixman_region32_p = ptr void somewhere earlier in the file and use that here (maybe with a comment saying that it represents a pointer to a pixman_region32_t).

Copy link
Author

Choose a reason for hiding this comment

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

Fixed!

ffi/ffi.ml Outdated
@@ -104,6 +104,10 @@ struct

let wl_resource_p = ptr Wl_resource.t

(* wl_output_transform *)

let wl_output_transform = Wl_output_transform.t
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would drop the alias here (it's not adding anything) and directly use Wl_output_transform.t below.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed!


let signal_motion (cursor: t) : Pointer.Event_motion.t Wl.Signal.t = {
let signal_motion (cursor: t) : Event_pointer_motion.t Wl.Signal.t = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why move these to external modules? The naming convention I was trying to follow (and that also appears with Keyboard.Event_key for example) is that if there's a wlr_foo.h, then wlr_event_foo_bar gets mapped to Foo.Event_bar.
Did that naming scheme not work here? Otherwise I'd prefer to stick to it.

Copy link
Author

Choose a reason for hiding this comment

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

I think we did this because we were struggling to learn the module system. We can definitely use a different convention.

I was kind of hoping to move events to submodules as a convention, like Pointer.Event.motion for instance.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think in any case each event type needs to have its own module (so it can include its compare/hash function for example), so it would have to be Pointer.Event.Motion.t.
I think having an Event submodule would be useful if we had functions that worked on all events, so that we could put them there (Pointer.Event.foo). However I IIRC don't think we have such functions currently, so for now I would just stick with the Pointer.Event_foo naming scheme.

lib/edges.ml Outdated
module Bindings = Wlroots_ffi_f.Ffi.Make (Generated_ffi)
module Types = Wlroots_ffi_f.Ffi.Types

type edges = None | Top | Bottom | Left | Right
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be edge

Copy link
Author

Choose a reason for hiding this comment

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

I agree, but we wanted to stick to the names from wlroots. I think it is defined as wlr_edges in https://github.com/swaywm/wlroots/blob/475d9701e21e5047ee9d7e56909762c1eb961fcd/include/wlr/util/edges.h#L19:

enum wlr_edges {
	WLR_EDGE_NONE = 0,
	WLR_EDGE_TOP = 1 << 0,
	WLR_EDGE_BOTTOM = 1 << 1,
	WLR_EDGE_LEFT = 1 << 2,
	WLR_EDGE_RIGHT = 1 << 3,
};

Copy link
Collaborator

@Armael Armael Jul 25, 2021

Choose a reason for hiding this comment

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

Ah, I see. I still think that in ocaml it would be more natural to have the type named edge. In C it makes sense because an element of wlr_edges is going to be used as a bit-field and thus indeed corresponds to a set of edges ; but this is not the case for an inhabitant of the ocaml sum type.

common/utils.ml Outdated
) zero items
in
view ~read ~write uint32_t

Copy link
Collaborator

Choose a reason for hiding this comment

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

When should we use bitwise_enum32 instead of bitwise_enum?
After a quick google search it looks like it's not terribly well specified which size enums should have; that they fit in a uint32_t is probably a good conservative assumption. However enum from ctypes assumes int64 values so this is probably fine as well?

In any case I would make a choice and either get rid of bitwise_enum or of bitwise_enum32.

Copy link
Author

@jsoo1 jsoo1 Jul 20, 2021

Choose a reason for hiding this comment

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

Ah yeah, this was because the edges field of the wlr_xdg_toplevel_resize_event is a uint32_t here https://github.com/swaywm/wlroots/blob/84dea55b20b60c229a5e31ccd37b58c96cba611a/include/wlr/types/wlr_xdg_shell.h#L224:

struct wlr_xdg_toplevel_resize_event {
	struct wlr_xdg_surface *surface;
	struct wlr_seat_client *seat;
	uint32_t serial;
	uint32_t edges;
};

Which is used in begin_interactive in tinywl https://github.com/swaywm/wlroots/blob/475d9701e21e5047ee9d7e56909762c1eb961fcd/tinywl/tinywl.c#L723:

static void begin_interactive(struct tinywl_view *view,
		enum tinywl_cursor_mode mode, uint32_t edges) {
...
		double border_x = (view->x + geo_box.x) + ((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0);
		double border_y = (view->y + geo_box.y) + ((edges & WLR_EDGE_BOTTOM) ? geo_box.height : 0);
...
}

static void xdg_toplevel_request_move(
		struct wl_listener *listener, void *data) {
	/* This event is raised when a client would like to begin an interactive
	 * move, typically because the user clicked on their client-side
	 * decorations. Note that a more sophisticated compositor should check the
	 * provied serial against a list of button press serials sent to this
	 * client, to prevent the client from requesting this whenever they want. */
	struct tinywl_view *view = wl_container_of(listener, view, request_move);
	begin_interactive(view, TINYWL_CURSOR_MOVE, 0);
}

static void xdg_toplevel_request_resize(
		struct wl_listener *listener, void *data) {
	/* This event is raised when a client would like to begin an interactive
	 * resize, typically because the user clicked on their client-side
	 * decorations. Note that a more sophisticated compositor should check the
	 * provied serial against a list of button press serials sent to this
	 * client, to prevent the client from requesting this whenever they want. */
	struct wlr_xdg_toplevel_resize_event *event = data;
	struct tinywl_view *view = wl_container_of(listener, view, request_resize);
	begin_interactive(view, TINYWL_CURSOR_RESIZE, event->edges);
}

I wonder if this is an upstream issue.

Copy link
Author

@jsoo1 jsoo1 Jul 20, 2021

Choose a reason for hiding this comment

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

Another related question: Should bitwise_enum be defined in terms of int64 instead of uint64_t? (due to the underspecified nature of enum sizes)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for the details. Then I agree that sticking to the C api and avoiding any integer casts is best. In that case it makes sense to have both bitwise_enum and bitwise_enum32.

Copy link
Author

@jsoo1 jsoo1 Aug 1, 2021

Choose a reason for hiding this comment

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

Would it be possible to use a functor to parameterize the type of uint size of the enum members?

Copy link
Author

Choose a reason for hiding this comment

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

I just pushed a WIP commit with a functor for bitwise enums. It does change uint64 to int64 where the unsigned version was used.

(* Worth it? *)
if Bindings.wlr_surface_is_xdg_surface surface
then
(* assert is called so this might blow up *)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure I understand the comment there?

let surface = getfield Types.Xdg_surface.surface
let toplevel = getfield Types.Xdg_surface.toplevel

let from_surface (surface : Surface.t) : t option =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this function be called from_wlr_surface for consistency?

let seat = getfield Types.Xdg_toplevel_resize_event.seat
let serial = getfield Types.Xdg_toplevel_resize_event.serial
let edges ev = coerce uint32_t Edges.t
(getfield Types.Xdg_toplevel_resize_event.edges ev)
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of coerce, shouldn't this be using bitwise_enum?

types/types.ml Outdated
@@ -144,12 +190,47 @@ module Make (S : Cstubs_structs.TYPE) = struct
let state = field t "state" Key_state.t
end

module Keyboard_modifier = struct
type modifier =
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would name this t

types/types.ml Outdated
let _WLR_MODIFIER_LOGO = constant "WLR_MODIFIER_LOGO" int64_t
let _WLR_MODIFIER_MOD5 = constant "WLR_MODIFIER_MOD5" int64_t

let modifier : modifier typ =
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would also name this t

Note that pixman_region32_t is stubbed as a void pointer since no
bindings to pixman exist yet.
Just use Wl_output_transform.t, as wl_output_transform was just an alias.
@jsoo1
Copy link
Author

jsoo1 commented Jul 20, 2021

Thanks for the detailed review! I'll be going over it this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants