Skip to content

Mouse motion events decoded with wrong button in X11 normal encoding (mode 1002) #126

Description

@RiderALT

When using X11 button-event mouse tracking (mode 1002, \e[?1002h), motion events while dragging are decoded with the wrong button. For example, dragging with Button1 held reports Button4 (scroll up) instead of Button1.

In lTerm_unix.ml, the [M mouse report parser reads the button byte as raw Char.code but doesn't subtract the X11 protocol offset of 32. The coordinate bytes (x, y) correctly subtract 33 (offset 32 + 1 for 1-based indexing), but the button/mask byte is used as-is.

(* Current code — lTerm_unix.ml line ~865 )
Lwt_stream.next stream >|= Char.code >>= fun mask ->
...
if mask = 0b00100011 then raise Exit; (
release check uses raw value )
...
match mask land 0b11000111 with (
button match uses raw value *)

For a Button1 press, the raw byte is 0x20 (32). 32 land 0b11000111 = 0 → Button1. This works by coincidence because the offset (32) maps to zero after masking.

For Button1 motion (drag), the raw byte is 0x40 (64 = 32 offset + 32 motion bit). 64 land 0b11000111 = 0b01000000 → Button4 (scroll up). This is wrong — it should be Button1.

Environment: Linux, Konsole terminal, mode 1002 (button-event tracking

simple test:

  let term = Lwt_main.run (Lazy.force LTerm.stdout) in
  (* Enable mode 1002 for button-event tracking (press + motion + release) *)
  Lwt_main.run (Lwt_io.write Lwt_io.stdout "\027[?1002h");
  Lwt_main.run (Lwt_io.flush Lwt_io.stdout);
  let mode = Lwt_main.run (LTerm.enter_raw_mode term) in
  Printf.eprintf "Mouse test: click, drag, scroll. Press 'q' to quit.\n%!";
  let running = ref true in
  while !running do
    let event = Lwt_main.run (LTerm.read_event term) in
    match event with
    | LTerm_event.Mouse m ->
      let btn =
        match m.LTerm_mouse.button with
        | Button1 -> "Button1"
        | Button2 -> "Button2"
        | Button3 -> "Button3"
        | Button4 -> "Button4"
        | Button5 -> "Button5"
        | Button6 -> "Button6"
        | Button7 -> "Button7"
        | Button8 -> "Button8"
        | Button9 -> "Button9"
      in
      Printf.eprintf "Mouse: %-8s row=%-3d col=%-3d ctrl=%b meta=%b shift=%b\n%!"
        btn m.row m.col m.control m.meta m.shift
    | LTerm_event.Key k ->
      (match k.LTerm_key.code with
       | Char uc when Uchar.to_int uc = Char.code 'q' ->
         running := false
       | _ ->
         Printf.eprintf "Key: %s\n%!" (LTerm_key.to_string k))
    | _ -> ()
  done;
  Lwt_main.run (LTerm.leave_raw_mode term mode);
  Lwt_main.run (Lwt_io.write Lwt_io.stdout "\027[?1002l");
  Lwt_main.run (Lwt_io.flush Lwt_io.stdout);
  Printf.eprintf "Done.\n%!"

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions