Mono 和 Gtk 中的全局热键#
我正在尝试使用 Mono 在 Linux 中使用全局热键。我找到了 XGrabKey
和 XUngrabKey
的签名,但我似乎无法让它们工作。每当我尝试调用 XGrabKey
时,应用程序都会崩溃并显示 SIGSEGV。
这就是我到目前为止所拥有的:
using System;
using Gtk;
using System.Runtime.InteropServices;
namespace GTKTest
{
class MainClass
{
const int GrabModeAsync = 1;
public static void Main(string[] args)
{
Application.Init();
MainWindow win = new MainWindow();
win.Show();
// Crashes here
XGrabKey(
win.Display.Handle,
(int)Gdk.Key.A,
(uint)KeyMasks.ShiftMask,
win.Handle,
true,
GrabModeAsync,
GrabModeAsync);
Application.Run();
XUngrabKey(
win.Display.Handle,
(int)Gdk.Key.A,
(uint)KeyMasks.ShiftMask,
win.Handle);
}
[DllImport("libX11")]
internal static extern int XGrabKey(
IntPtr display,
int keycode,
uint modifiers,
IntPtr grab_window,
bool owner_events,
int pointer_mode,
int keyboard_mode);
[DllImport("libX11")]
internal static extern int XUngrabKey(
IntPtr display,
int keycode,
uint modifiers,
IntPtr grab_window);
}
public enum KeyMasks
{
ShiftMask = (1 << 0),
LockMask = (1 << 1),
ControlMask = (1 << 2),
Mod1Mask = (1 << 3),
Mod2Mask = (1 << 4),
Mod3Mask = (1 << 5),
Mod4Mask = (1 << 6),
Mod5Mask = (1 << 7)
}
}
有人有 XGrabKey
的工作示例吗?
谢谢!
I'm trying to get a global hotkey working in Linux using Mono. I found the signatures of XGrabKey
and XUngrabKey
, but I can't seem to get them working. Whenever I try to invoke XGrabKey
, the application crashes with a SIGSEGV.
This is what I have so far:
using System;
using Gtk;
using System.Runtime.InteropServices;
namespace GTKTest
{
class MainClass
{
const int GrabModeAsync = 1;
public static void Main(string[] args)
{
Application.Init();
MainWindow win = new MainWindow();
win.Show();
// Crashes here
XGrabKey(
win.Display.Handle,
(int)Gdk.Key.A,
(uint)KeyMasks.ShiftMask,
win.Handle,
true,
GrabModeAsync,
GrabModeAsync);
Application.Run();
XUngrabKey(
win.Display.Handle,
(int)Gdk.Key.A,
(uint)KeyMasks.ShiftMask,
win.Handle);
}
[DllImport("libX11")]
internal static extern int XGrabKey(
IntPtr display,
int keycode,
uint modifiers,
IntPtr grab_window,
bool owner_events,
int pointer_mode,
int keyboard_mode);
[DllImport("libX11")]
internal static extern int XUngrabKey(
IntPtr display,
int keycode,
uint modifiers,
IntPtr grab_window);
}
public enum KeyMasks
{
ShiftMask = (1 << 0),
LockMask = (1 << 1),
ControlMask = (1 << 2),
Mod1Mask = (1 << 3),
Mod2Mask = (1 << 4),
Mod3Mask = (1 << 5),
Mod4Mask = (1 << 6),
Mod5Mask = (1 << 7)
}
}
Does anyone have a working example of XGrabKey
?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我终于在托管代码中找到了一个可行的解决方案。发生 SIGSEGV 是因为我混淆了非托管 Gdk 对象的句柄与其 X11 对应对象的句柄。感谢 Paul 的回答,我能够找到全局热键的非托管示例,并熟悉它的工作原理。然后我编写了自己的非托管测试程序来找出我需要做什么,而不必处理任何托管特性。成功后,我创建了一个托管解决方案。
这是托管解决方案:
这是测试程序:
我不确定
XKeyEvent
结构在具有不同大小的 Cint
和 < code>longs,所以这个解决方案是否适用于所有系统还有待观察。编辑:由于底层 C 类型大小的不同性质,看起来这个解决方案不会像我担心的那样独立于体系结构。 libgtkhotkey 看起来很有前途,可以避免使用托管程序集部署和编译自定义非托管库。
注意:现在您需要根据操作系统的字长明确定义
BUILD_FOR_32_BIT_X11
或BUILD_FOR_64_BIT_X11
。Well, I finally found a working solution in managed code. The SIGSEGV was happening because I was confusing the handles of the unmanaged Gdk objects with the handles of their X11 counterparts. Thanks to Paul's answer, I was able to find an unmanaged example of global hotkeys and familiarized myself with how it worked. Then I wrote my own unmanaged test program to find out what I needed to do without having to deal with any managed idiosyncrasies. After that was successful, I created a managed solution.
Here is the managed solution:
And here is the test program:
I'm not sure how the
XKeyEvent
structure will behave on other systems with different sizes for Cint
s andlong
s, so whether this solution will work on all systems remains to be seen.Edit: It looks like this solution is not going to be architecture-independent as I feared, due to the varying nature of the underlying C type sizes. libgtkhotkey looks promising as way to avoid deploying and compiling custom unmanaged libraries with your managed assemblies.
Note: Now you need to explicity define
BUILD_FOR_32_BIT_X11
orBUILD_FOR_64_BIT_X11
depending on the word-size of your OS.我是这个网站的新手,由于我的声誉不足,我似乎无法对之前的问题发表评论。 (抱歉,我什至不能给你投票!)
关于不同基础大小的问题,我认为这可以通过使用 IntPtr 来解决多头。这遵循 Mono 项目文档中的建议,请参阅 http://www.mono-project.com/ Interop_with_Native_Libraries#Longs。 C 类型 int 和 Bool 应映射到 C# int。
关于GAPI包装器,我尝试过,但无法让它工作。如果扎克可以发布任何有关他如何做到这一点的信息,我将不胜感激。
我也无法让示例程序运行。与 SDX2000 一样,我必须编辑库名称,并添加 using 语句。我在使用 Application.Init() 时遇到了问题,最终我将其换成了创建表单。但我的注册调用仍然因 BadRequest 而失败。如果任何已经完成此工作的人可以更新代码以使其更加完整,我将不胜感激。
I'm new to this site and it seems that I can't leave a comment on a previous question as I have insufficient reputation. (Sorry I can't even up-vote you!)
Relating to the issue of differing underlying sizes, I think this is solvable by using an IntPtr for the longs. This follows a suggestion in the Mono project documentation, see http://www.mono-project.com/Interop_with_Native_Libraries#Longs. The C types int and Bool should map to C# int.
Regarding the GAPI wrapper, I tried it, but couldn't get it working. If Zach could post any info on how he did it, I'd be grateful.
Also I couldn't get the sample program to work. Like SDX2000, I had to edit the library names, and I added using statements. I had a problem with Application.Init(), which in the end I swapped for creating a Form. But still my register call fails with BadRequest. If anyone who has got this working can update the code to make it more complete I'd be grateful.
Tomboy 有一些代码知道如何做到这一点,我会从那里获取代码。
Tomboy has some code that knows how to do this, I'd take the code from there.