ultimatepp/uppsrc/CtrlCore/GtkX11Util.cpp
cxl e7c6a94955 OpenBSD support
git-svn-id: svn://ultimatepp.org/upp/trunk@14814 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-08-13 15:22:31 +00:00

176 lines
4.2 KiB
C++

#include "CtrlCore.h"
#ifdef GUI_GTK
#ifdef GDK_WINDOWING_X11
namespace Upp {
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#ifndef PLATFORM_OPENBSD // avoid warning
#define CurrentTime XCurrentTime
#endif
#include <gdk/gdkx.h>
#undef Picture
#undef Time
#undef Font
#undef Display
#ifndef PLATFORM_OPENBSD // avoid warning
#undef CurrentTime
#endif
XDisplay *Xdisplay()
{
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
}
Window Xroot()
{
return GDK_WINDOW_XID(gdk_screen_get_root_window(gdk_screen_get_default()));
}
String GetProperty(Window w, Atom property, Atom rtype)
{
GuiLock __;
String result;
int format;
unsigned long nitems, after = 1;
long offset = 0;
Atom type = None;
unsigned char *data;
long rsize = minmax((long)(XMaxRequestSize(Xdisplay()) - 100), (long)256, (long)65536);
while(after > 0) {
if(XGetWindowProperty(Xdisplay(), w, property, offset, rsize, 0,
rtype, &type, &format, &nitems, &after, &data) != Success)
break;
if(type == None)
break;
if(data) {
int len = format == 32 ? sizeof(unsigned long) * nitems : nitems * (format >> 3);
result.Cat(data, len);
XFree((char *)data);
offset += nitems / (32 / format);
}
else
break;
}
result.Shrink();
XFlush(Xdisplay());
return result;
}
Atom XAtomRaw(const char *name)
{
return XInternAtom(Xdisplay(), name, 0);
}
Atom XAtom(const char *name)
{
GuiLock __;
Atom x;
INTERLOCKED {
static VectorMap<String, int> atoms;
int q = atoms.Get(name, Null);
if(IsNull(q)) {
q = XAtomRaw(name);
atoms.Add(name, q);
}
x = q;
}
return x;
}
Vector<int> GetPropertyInts(GdkWindow *w, const char *property)
{
GuiLock __;
Vector<int> result;
String p = GetProperty(GDK_WINDOW_XID(w), XAtom(property), AnyPropertyType);
const long int *ptr = (const long int *)~p;
const long int *lim = ptr + p.GetLength() / sizeof(long int);
result.Reserve(p.GetLength() / sizeof(long int));
while(ptr < lim)
result.Add(*ptr++);
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, Function<void ()> cb)
{
GuiLock __;
ASSERT(key >= K_DELTA);
gdk_x11_display_error_trap_push(gdk_display_get_default());
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_x11_display_error_trap_pop_ignored(gdk_display_get_default());
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) = Event<> () << 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_x11_display_error_trap_push(gdk_display_get_default());
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_x11_display_error_trap_pop_ignored(gdk_display_get_default());
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;
}
}
#endif
#endif