我想做什么
因此,我一直在尝试在Linux中访问键盘输入。具体来说,我需要能够在不按下其他键的情况下访问修饰键。此外,我希望能够在不运行X系统的的情况下执行。
简而言之,我的要求是:0 = not pressed,1 = currently pressed让我知道是否
选中键盘时按住该键
我的电脑设定
我的普通Linux机器正在卡车上驶向我的新公寓。因此,我现在只能使用Macbook Air。因此,我正在VM中运行Linux进行测试。
VirtualBox中的虚拟机
下面的所有操作都是在此环境中完成的。我已经尝试过在X和其他tty之一中运行。
我的想法
如果有人可以纠正我,我将更改此设置。
我已经读了很多书,以认识到高级库不提供这种功能。修饰键与其他键一起使用以提供备用键代码。通过Linux中的高级库本身访问修饰键并不容易。或者,相反,我还没有在Linux上找到用于此目的的高级API。
我以为libtermkey是答案,但是似乎不比普通的击键检索更好地支持Shift修饰键。我也不确定如果没有X,它是否可以工作。
在使用libtermkey时(在意识到Shift-Return之类的情况下没有发生移位之前),我打算编写一个守护程序来运行以收集键盘事件。运行守护程序的副本将仅通过管道传送对键盘数据的请求并作为响应接收键盘数据。我可以使用此设置使某些内容始终在后台运行,以防万一我无法在特定时间检查键码状态(必须及时接收键码状态)。
下面是我两次尝试编写可以从Linux键盘设备读取的程序的尝试。我还附了一张小支票,以确保我拥有正确的设备。
尝试#1
我试图直接访问键盘设备,但是遇到问题。我已经尝试了另一个堆栈溢出线程中的建议here。这给了我分割错误。因此,我将其从fopen更改为open:// ...
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
char key_map[KEY_MAX/8 + 1];
memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);
// ...
虽然没有分段错误,但没有任何按键指示(不仅仅是修饰键)。我使用以下方法进行了测试:./foo && echo "TRUE" || echo "FALSE"
我已经用它来测试命令是否成功返回了很多代码。所以,我知道那很好。我还输出了密钥(始终为0)和掩码(0100)进行检查。它似乎什么也没检测到。
尝试#2
从这里开始,我想我会尝试一种稍微不同的方法。我想弄清楚我做错了什么。在this页面提供了演示打印出关键代码的代码段之后,我将其 bundle 到程序中:#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char** argv) {
uint8_t keys[128];
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
for (;;) {
memset(keys, 0, 128);
ioctl (fd, EVIOCGKEY(sizeof keys), keys);
int i, j;
for (i = 0; i < sizeof keys; i++)
for (j = 0; j < 8; j++)
if (keys[i] & (1 << j))
printf ("key code %d\n", (i*8) + j);
}
return 0;
}
以前,我的大小为16个字节,而不是128个字节。老实说,我应该花更多的时间来了解ioctl和EVIOCGKEY。我只知道它应该将位映射到特定键以指示按下或类似操作(如果我输入错了,请纠正我,请!)。
我最初也没有循环,只是按住各种键以查看是否出现了键代码。我什么也没收到。因此,我认为循环可以使检查更容易进行,以防万一错过了一些东西。
我怎么知道输入设备是正确的
我通过在输入设备上运行cat对其进行了测试。特别:$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
当我使用cat开始输出时,在按下键并释放事件(从回车(回车)开始)时,垃圾ASCII被发送到我的终端。我也知道,这在运行Linux VM的Macbook上可以与诸如Shift,Control,Function甚至Apple的Command键之类的修饰键一起使用,似乎效果很好。按下按键时出现输出,从按住该按键发出的后续信号开始 swift 出现,并在释放按键时输出更多数据。
因此,尽管我的方法可能不正确(我愿意听到的任何替代方案),但该设备似乎满足了我的需求。
此外,我知道此设备只是从运行指向/dev/input/event2的链接:$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
我已经使用/dev/input/event2尝试了以上两个程序,但未收到任何数据。在/dev/input/event2上运行cat提供的输出与链接相同。
最佳答案
打开输入设备,
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
int main(void)
{
const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
while (1) {
n = read(fd, &ev, sizeof ev);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
break替换最后一个continue感到满意,从而忽略了部分事件结构。ev事件结构以查看发生了什么,并完成程序: if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
ev.time:事件的时间(struct timeval类型)ev.type:EV_KEY ev.code:KEY_*,密钥标识符;查看/usr/include/linux/input.h的完整列表ev.value:释放键时为0,按下键时为1,如果自动重复按键时为2 /usr/include/linux/input.h中的命名常量非常稳定,因为它是内核-用户空间接口(interface),内核开发人员非常努力地维护兼容性。 (也就是说,您可以期望偶尔会有新的代码,但是现有代码很少更改。)
关于c - 从Linux输入设备访问键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20943322/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内
我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token
Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation
是否有可能以某种方式访问Class.new范围内的a?a=5Class.new{defb;aend}.new.b#NameError:undefinedlocalvariableormethod`a'for#:0x007fa8b15e9af0>#:in`b' 最佳答案 即使@MarekLipka的回答是正确的——改变变量范围总是有风险的。这是可行的,因为每个block都带有创建它的上下文,因此您的局部变量a突然变得不那么局部了——它变成了一个“隐藏的”全局变量:a=5object=Class.new{define_method(