【问题标题】:Reading from mouse inputs in Ada从 Ada 中的鼠标输入读取
【发布时间】:2020-12-08 14:44:47
【问题描述】:

我在 Ada 中有一个从触摸屏输入读取的程序。代码很旧,我没有触摸屏了。我想用鼠标输入来代替触摸屏代码。用 C 语言编写函数并将其导入 Ada 代码会更简单吗?下面的代码是触摸屏代码。


   HIL_NAME : STRING (1.. 10) := "/dev/touch";

   procedure READ (X, Y : out INTEGER) is

      type BYTE is new INTEGER range 0 .. 255;
      for BYTE'SIZE use 8;
      package IN_IO is new SEQUENTIAL_IO (BYTE);
      use IN_IO;

      type DATA_TYPE is array (2 .. 9) of BYTE;

      HIL_FILE : IN_IO.FILE_TYPE;
      COUNT    : BYTE;
      DATA     : DATA_TYPE;

   begin
      IN_IO.OPEN (HIL_FILE, IN_FILE, HIL_NAME); -- open the touchscreen

      loop
         IN_IO.READ (HIL_FILE, COUNT); -- read the incoming record size
         -- read the incoming record
         for I in INTEGER range 2 .. BYTE'POS (COUNT) loop
            IN_IO.READ (HIL_FILE, DATA (I));
         end loop;
         -- is this a fingerdown?  overkill test.
         if ((COUNT = 9) and (DATA (6) = 2#01000010#) and (DATA (9) = 142)) then
            X := BYTE'POS (DATA (7)); -- pick out coordinates
            Y := BYTE'POS (DATA (8));
            IN_IO.CLOSE (HIL_FILE); -- close touchscreen to flush buffer
            return; -- return to caller
         end if;
      end loop;
   end READ;

【问题讨论】:

  • 我认为关键部分是了解如何将触摸屏数据编码到文件中(名称包含在 HIL_NAME 字符串中)——这是一种非常不寻常的方法!用 C 编写函数无济于事......
  • @Zerte 我认为您可以从分配到 X 和 Y(READ 的输出)进行逆向工程,并使用左键作为“手指向下”测试。
  • 我猜,下一个问题是要知道最终的"/dev/mouse"(而不是"/dev/touch")是如何工作的。

标签: c io ada


【解决方案1】:

了解操作系统、版本、编译器、窗口管理器工具包和版本会很有用。例如,我正在运行 Debian 10,并且使用 Gnome 3 作为我的 WM,我可以使用 GTKAda 工具包最轻松地访问鼠标。上次我编写直接访问鼠标的代码是在 DOS 上的 Modula-2 中。

不过,GTKAda 并不是特别好学...

如果您愿意将 Web 浏览器用作应用程序的 GUI(这也有助于跨系统移植……您甚至可以在 PC 上运行应用程序,但通过平板电脑或手机访问它,为您提供触摸屏!)我建议查看www.gnoga.com 提供的 Gnoga。看看它的一些教程,它们应该很容易构建并让您开始使用鼠标和简单的绘图。

编辑

在各种 cmets 中找到了神奇的词(Centos、ncurses)(如果有更好的答案,您可以有用地添加到问题中)您正在寻找的是绑定到 ncursessuch as this one 的 Ada。这个绑定是官方ncurses 源代码的一部分,从 5.8 版开始,所以应该已经可以在 Centos 上使用了。

然后编写一个调用ncurses mouse handling packageRead 过程应该很简单,返回鼠标位置(缩放为8 位整数或自然,并且可能从控制台窗口原点偏移)每当按下 LH 按钮时,否则可能会返回...无论 OUT 参数初始化为什么,(可能是 BYTE'FIRST)

工作完成。

现在我们可以看到触摸屏文件名 si 是 /dev/ 层次结构的一部分,如果像 @zerte 建议的那样在 /dev/mouse 上查找文档(或我的 /dev/input/mouse[0|1]笔记本电脑)...但我认为 ncurses 将减少对机器的依赖。

【讨论】:

  • 我正在使用带有 GNAT Studio Community 2020 的 CentOS 8。我可以打开设备,但是在读取数据时我得到一个非常大的数字。
  • 我应该补充一点,这是一个非常复杂的 Ada 控制台应用程序,它使用 ncurses 和 gui 命令来绘制屏幕。我不想在平板电脑或手机上运行该应用。
  • @JosephGabello 如果您仍然使用 GUI API,则应该使用该 API 提供的任何内容来读取鼠标输入。
  • 我的错误。该程序严格来说是一个控制台应用程序。它不使用任何 GUI 按钮。应用程序使用触摸屏,代码定义了每个按钮的区域,因此 X 和 Y 坐标必须在指定区域内才能正确响应。
【解决方案2】:

我已经使用 Ncurses 解决了这个问题。我下载了终端接口诅咒并使用这些文件创建了以下过程。

with Terminal_Interface.Curses;
use Terminal_Interface.Curses;

tmp2 : Event_Mask;
c    : Key_Code;
firsttime : Bollean;

procedure READ (X1 : out Column_Position;
                Y1 : Line_Position) is

begin
   tmp2 := Start_Mouse (All_Events);
   c:= Character'Pos ('?');
   Set_Raw_Mode (SwitchOn => True);
   Set_KeyPad_Mode (SwitchOn => True);
   firsttime := true;

   loop
      if not firsttime then
         if c = KeyMouse then
            declare
               event  : Mouse_Event;
               Y      : Line_Position;
               X      : Column_Position;
               Button : Mouse_Button;
               State  : Mouse_State;
            begin
               event := Get_Mouse;
               Get_Event (event, Y, X, Button, State);
               X1 := X;
               Y1 := Y;
               exit;
            end;
         end if;
      end if;

      firsttime := False;
      loop
         c := Get_Keystroke;
         exit when c /= Key_None;
      end loop;
   end loop;
   End_Mouse (tmp2);
end READ;

【讨论】:

    【解决方案3】:

    您可以使用 Linux 输入子系统读取鼠标(正如 @Zerte 所建议的那样)。另请参阅SO 上的这个问题以及一些内核文档herehere。读取鼠标的输入似乎并不难(至少在运行 Raspbian GNU/Linux 10 的 Raspberry Pi 3 上没有)。当然,您仍然需要应用适当的缩放,并且您需要找出暴露鼠标事件的设备(在我的情况下:/dev/input/event0

    注意:您可以通过检查 sudo dmesg | grep "input:" 的输出找到该数字。如果鼠标(或其他指针设备)连接到inputX,则此设备的事件将在eventX 上公开。

    ma​​in.adb

    with Ada.Text_IO;
    with Ada.Sequential_IO;
    with Interfaces.C;
    
    procedure Main is
    
       package C renames Interfaces.C;
       use type C.unsigned_short;
       use type C.int;
    
       --  Input event codes (linux/input-event-codes.h)
    
       EV_SYN      : constant := 16#00#;
       EV_KEY      : constant := 16#01#;
       EV_REL      : constant := 16#02#;
       EV_ABS      : constant := 16#03#;
       EV_MSC      : constant := 16#04#;
       
       BTN_MOUSE   : constant := 16#110#;
       BTN_LEFT    : constant := 16#110#;
       BTN_RIGHT   : constant := 16#111#;
       BTN_MIDDLE  : constant := 16#112#;
    
       REL_X       : constant := 16#00#;
       REL_Y       : constant := 16#01#;
       REL_WHEEL   : constant := 16#08#;
       
       -- Time value (sys/time.h)
    
       subtype suseconds_t is C.long;
       subtype time_t      is C.long;
    
       type timeval is record
          tv_sec  : time_t;
          tv_usec : suseconds_t;
       end record;
       pragma Convention (C, timeval);
    
       -- Input event struct (linux/input.h)
    
       type input_event is record
          time  : timeval;
          typ   : C.unsigned_short;
          code  : C.unsigned_short;
          value : C.int;
       end record;
       pragma Convention (C, input_event);
    
       --  ... and a package instantiation for sequential IO.
    
       package Input_Event_IO is new Ada.Sequential_IO (input_event);
       use Input_Event_IO;
    
    
       File  : File_Type;
       Event : input_event;
    
       --  Position of the mouse and wheel.
       X, Y, W : C.int := 0;
    
    begin
    
       Open (File, In_File, "/dev/input/event0");
    
       --  Infinite loop, use Ctrl-C to exit.
       loop
    
          --  Wait for a new event.
          Read (File, Event);
    
          --  Process the event.
          case Event.typ is
             
             when EV_SYN =>
                Ada.Text_IO.Put_Line 
                  (X'Image & "," & Y'Image & " [" & W'Image & "]");
    
             when EV_KEY =>            
                case Event.code is
                   when BTN_LEFT => 
                      Ada.Text_IO.Put_Line ("Left button.");
                   when BTN_MIDDLE => 
                      Ada.Text_IO.Put_Line ("Middle button.");
                   when BTN_RIGHT => 
                      Ada.Text_IO.Put_Line ("Right button.");
                   when others =>
                      null;
                end case;
    
             when EV_REL =>
                case Event.code is
                   when REL_X =>
                      X := X + Event.value;
                   when REL_Y =>
                      Y := Y + Event.value;
                   when REL_WHEEL =>
                      W := W + Event.value;
                   when others =>
                      null;
                end case;
    
             when EV_ABS =>
                case Event.code is
                   when REL_X =>
                      X := Event.value;
                   when REL_Y =>
                      Y := Event.value;
                   when REL_WHEEL =>
                      W := Event.value;
                   when others =>
                      null;
                end case;
             
             when others =>
                null;
             
          end case;
    
       end loop;
    
    end Main;
    

    输出(在无头 RPi 3 上运行)

    pi@raspberrypi:~/mouse $ sudo obj/main
    [...]
    -85, 9 [-5]
    -84, 9 [-5]
    -83, 9 [-5]
    Left button.
    -83, 9 [-5]
    Left button.
    -83, 9 [-5]
    Left button.
    -83, 9 [-5]
    Left button.
    -83, 9 [-5]
    Right button.
    -83, 9 [-5]
    Right button.
    -83, 9 [-5]
    Middle button.
    -83, 9 [-5]
    Middle button.
    -83, 9 [-5]
    -84, 9 [-5]
    ^C
    pi@raspberrypi:~/mouse $ 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 2018-02-05
      • 1970-01-01
      • 2013-03-30
      • 2012-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多