CtrlCore: GTK/X11 RegisterSystemHotKey #379

git-svn-id: svn://ultimatepp.org/upp/trunk@5724 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2013-01-19 18:56:11 +00:00
parent fb80a72de4
commit d676e2d8ec
5 changed files with 108 additions and 23 deletions

View file

@ -30,6 +30,7 @@ void InitGtkApp(int argc, char **argv, const char **envptr)
Ctrl::ReSkin();
g_timeout_add(20, (GSourceFunc) Ctrl::TimeHandler, NULL);
InstallPanicMessageBox(Ctrl::PanicMsgBox);
gdk_window_add_filter(NULL, Ctrl::RootKeyFilter, NULL);
}
END_UPP_NAMESPACE

View file

@ -156,7 +156,11 @@ public: // really private:
static Gclipboard& gclipboard();
static Gclipboard& gselection();
static String RenderPrimarySelection(const Value& fmt);
static Vector<Callback> hotkey;
static Vector<dword> keyhot;
static Vector<dword> modhot;
public:
static void EndSession() {}
static bool IsEndSession() { return false; }
@ -169,4 +173,7 @@ public:
GdkWindow *gdk() const { return top ? top->window->window : NULL; }
GtkWindow *gtk() const { return top ? (GtkWindow *)top->window : NULL; }
static GdkFilterReturn RootKeyFilter(GdkXEvent *xevent, GdkEvent *event, gpointer data);
//$ };

View file

@ -446,7 +446,20 @@ void Ctrl::Proc()
kv |= K_CTRL;
if(GetAlt() && kv != K_ALT_KEY)
kv |= K_ALT;
LLOG(GetKeyDesc(kv) << ", pressed: " << pressed << ", count: " << CurrentEvent.count);
DLOG(GetKeyDesc(kv) << ", pressed: " << pressed << ", count: " << CurrentEvent.count);
#ifdef GDK_WINDOWING_X11
DDUMP(FormatIntHex(kv));
if(pressed)
for(int i = 0; i < hotkey.GetCount(); i++) {
DDUMP(FormatIntHex(keyhot[i]));
DDUMP((bool)hotkey[i]);
if(hotkey[i] && keyhot[i] == kv) {
DLOG("CALL!");
hotkey[i]();
return;
}
}
#endif
DispatchKey(!pressed * K_KEYUP + kv, CurrentEvent.count);
}
break;

View file

@ -6,6 +6,10 @@ NAMESPACE_UPP
#define LLOG(x) // DLOG(rmsecs() << ' ' << x)
Vector<Callback> Ctrl::hotkey;
Vector<dword> Ctrl::keyhot;
Vector<dword> Ctrl::modhot;
Vector<Ctrl::Win> Ctrl::wins;
int Ctrl::WndCaretTime;
@ -110,36 +114,21 @@ Ctrl *Ctrl::GetActiveCtrl()
// Vector<Callback> Ctrl::hotkey;
#ifndef GDK_WINDOWING_X11
// There is no generic support in GTK for HotKey
int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
{
/* ASSERT(key >= K_DELTA);
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
dword mod = 0;
if(key & K_ALT)
mod |= MOD_ALT;
if(key & K_SHIFT)
mod |= MOD_SHIFT;
if(key & K_CTRL)
mod |= MOD_CONTROL;
return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
return -1;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
}
#endif
void Ctrl::AnimateCaret()
{
GuiLock __;

View file

@ -23,6 +23,11 @@ XDisplay *Xdisplay()
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
}
Window Xroot()
{
return GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gdk_screen_get_default()));
}
String GetProperty(Window w, Atom property, Atom rtype)
{
GuiLock __;
@ -88,6 +93,76 @@ Vector<int> GetPropertyInts(GdkWindow *w, const char *property)
return result;
}
dword X11mods(dword key)
{
dword mod = 0;
if(key & K_ALT)
mod |= Mod1Mask;
if(key & K_SHIFT)
mod |= ShiftMask;
if(key & K_CTRL)
mod |= ControlMask;
return mod;
}
int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
{
GuiLock __;
DDUMP(FormatIntHex(key));
ASSERT(key >= K_DELTA);
gdk_error_trap_push();
KeyCode k = XKeysymToKeycode(Xdisplay(), key & 0xffff);
dword mod = X11mods(key);
bool r = false;
for(dword nlock = 0; nlock < 2; nlock++)
for(dword clock = 0; clock < 2; clock++)
for(dword slock = 0; slock < 2; slock++)
r = XGrabKey(Xdisplay(), k,
mod | (nlock * Mod2Mask) | (clock * LockMask) | (slock * Mod3Mask),
Xroot(), true, GrabModeAsync, GrabModeAsync) || r;
gdk_error_trap_pop();
if(!r) return -1;
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
keyhot.At(q) = k;
modhot.At(q) = mod;
return q;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
GuiLock __;
if(id >= 0 && id < hotkey.GetCount() && hotkey[id]) {
gdk_error_trap_push();
for(dword nlock = 0; nlock < 2; nlock++)
for(dword clock = 0; clock < 2; clock++)
for(dword slock = 0; slock < 2; slock++)
XUngrabKey(Xdisplay(), keyhot[id],
modhot[id] | (nlock * Mod2Mask) | (clock * LockMask) | (slock * Mod3Mask),
Xroot());
gdk_error_trap_pop();
hotkey[id].Clear();
}
}
GdkFilterReturn Ctrl::RootKeyFilter(GdkXEvent *xevent, GdkEvent *Xevent, gpointer data)
{
XEvent *event = (XEvent *)xevent;
if(event->type == KeyPress)
for(int i = 0; i < hotkey.GetCount(); i++)
if(hotkey[i] && keyhot[i] == event->xkey.keycode &&
modhot[i] == (event->xkey.state & (Mod1Mask|ShiftMask|ControlMask))) {
hotkey[i]();
return GDK_FILTER_REMOVE;
}
return GDK_FILTER_CONTINUE;
}
END_UPP_NAMESPACE
#endif