short y;
} XGlyphSpec;
-/* Key modifier masks */
-enum {
- ModNone = 0,
- ModShift = (1 << 0),
- ModCapsLock = (1 << 1),
- ModCtrl = (1 << 2),
- ModAlt = (1 << 3),
- ModNumLock = (1 << 4),
- ModScrollLock = (1 << 5),
- ModWindows = (1 << 6),
- ModOneOrMore = (ModCtrl|ModAlt),
- ModAny = -1
-};
-
enum {
MouseLeft = 1,
MouseMiddle = 2,
FOCUSED = 2
} WinRegion;
-typedef struct {
- int mods;
- Rune key;
- void (*fn)(char*);
- char* arg;
-} KeyBinding;
-
-void win_init(KeyBinding* bindings);
+void win_init(void);
void win_title(char* path);
void win_font(char* font);
void win_prop_set(char* xname, char* ename, char* value);
XIM xim;
GC gc;
void (*eventfns[LASTEvent])(struct XConf*, XEvent*);
+ Time now;
} XConf;
/* Selection identifiers */
KEY_CTRL_UNDERSCORE = 0x1F,
};
+/* Key modifier masks */
+enum {
+ ModNone = 0,
+ ModShift = (1 << 0),
+ ModCapsLock = (1 << 1),
+ ModCtrl = (1 << 2),
+ ModAlt = (1 << 3),
+ ModNumLock = (1 << 4),
+ ModScrollLock = (1 << 5),
+ ModWindows = (1 << 6),
+ ModOneOrMore = (ModCtrl|ModAlt),
+ ModAny = -1
+};
+
+typedef struct {
+ int mods;
+ uint32_t key;
+ void (*fn)(char*);
+ char* arg;
+} KeyBinding;
int x11_init(XConf* x);
void x11_error_clear(void);
void x11_event_loop(XConf* x, void (*redraw)(XConf* x));
int x11_getptr(XConf* x, int* ptrx, int* ptry);
uint32_t x11_getkey(XConf* x, XEvent* e);
+uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys);
void x11_centerwin(XConf* x);
void x11_init_gc(XConf* x);
XChangeProperty(x->display, x->self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
}
+static void update_time(XConf* x, XEvent* e) {
+ if (
+ (e->type == KeyPress) || (e->type == ButtonPress) ||
+ (e->type == ButtonRelease) || (e->type == MotionNotify)
+ ) {
+ x->now = e->xkey.time;
+ }
+}
+
int x11_process_events(XConf* x) {
int nqueued, nevents, dirty = false;
/* reap zombie background processes */
XGetMotionEvents(x->display, x->self, CurrentTime, CurrentTime, &nevents);
for (XEvent e; XPending(x->display);) {
XNextEvent(x->display, &e);
+ update_time(x, &e);
if (e.type == Expose) dirty = 1;
if (!XFilterEvent(&e, None) && x->eventfns[e.type])
(x->eventfns[e.type])(x, &e);
/* translate special key codes into unicode codepoints */
return special_keys(key);
}
+
+uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys) {
+ uint32_t key = x11_getkey(x, e);
+ if (key == RUNE_ERR) return key;
+ int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt);
+ int32_t mkey = tolower(key);
+ for (KeyBinding* bind = keys; bind && bind->key; bind++) {
+ bool match = (mkey == (int32_t)bind->key);
+ bool exact = (bind->mods == mods);
+ bool any = (bind->mods == ModAny);
+ bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore));
+ if (match && (exact || oneplus || any)) {
+ bind->fn(bind->arg);
+ return RUNE_ERR;
+ }
+ }
+ /* fallback to just inserting the rune if it doesn't fall in the private use area.
+ * the private use area is used to encode special keys */
+ return (key < 0xE000 || key > 0xF8FF ? key : RUNE_ERR);
+}
}
static void xkeypress(XConf* x, XEvent* e) {
- uint32_t key = x11_getkey(x, e);
- if (key == RUNE_ERR) return;
-// int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt);
-// int32_t mkey = tolower(key);
-// for (KeyBinding* bind = Keys; bind && bind->key; bind++) {
-// bool match = (mkey == bind->key);
-// bool exact = (bind->mods == mods);
-// bool any = (bind->mods == ModAny);
-// bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore));
-// if (match && (exact || oneplus || any)) {
-// bind->fn(bind->arg);
-// return;
-// }
-// }
- /* fallback to just inserting the rune if it doesn't fall in the private use area.
- * the private use area is used to encode special keys */
- if (key < 0xE000 || key > 0xF8FF)
+ uint32_t key = x11_process_key(x, e, NULL);
+ if (key != RUNE_ERR)
view_insert(&Tags, key);
}
XFlush(X.display);
}
-void win_init(KeyBinding* bindings) {
- (void)bindings;
+void win_init(void) {
signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
******************************************************************************/
int main(void) {
/* create the window */
- win_init(NULL);
+ win_init();
/* Initialize the views */
view_init(&Tags, NULL);
char* ARGV0;
static Tag Builtins[18];
-static Time Now;
+static KeyBinding Bindings[];
static struct XConf X;
static int KeyBtnState;
static WinRegion Focused = EDIT;
static View Regions[NREGIONS];
-static KeyBinding* Keys = NULL;
static int Divider;
static int FontSel;
static bool SyncMouse = false;
static int count = 0;
static Time before = 0;
if (!pressed) return;
- count = ((Now - before) <= (uint64_t)ClickTime ? count+1 : 1);
- before = Now;
+ count = ((X.now - before) <= (uint64_t)ClickTime ? count+1 : 1);
+ before = X.now;
if (PRESSED(MouseRight)) {
puts("fetch tag");
} else if (PRESSED(MouseMiddle)) {
}
static void xkeypress(XConf* x, XEvent* e) {
- (void)x;
- Now = e->xkey.time;
+ uint32_t key = x11_process_key(x, e, Bindings);
Focused = (e->xkey.y <= Divider ? TAGS : EDIT);
- uint32_t key = x11_getkey(x, e);
- if (key == RUNE_ERR) return;
KeyBtnState = e->xkey.state;
- int mods = KeyBtnState & (ModCtrl|ModShift|ModAlt);
- int32_t mkey = tolower(key);
- for (KeyBinding* bind = Keys; bind && bind->key; bind++) {
- bool match = (mkey == bind->key);
- bool exact = (bind->mods == mods);
- bool any = (bind->mods == ModAny);
- bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore));
- if (match && (exact || oneplus || any)) {
- bind->fn(bind->arg);
- return;
- }
- }
- /* fallback to just inserting the rune if it doesn't fall in the private use area.
- * the private use area is used to encode special keys */
- if (key < 0xE000 || key > 0xF8FF)
+ if (key != RUNE_ERR)
view_insert(win_view(FOCUSED), key);
}
static void xbtnpress(XConf* x, XEvent* e) {
(void)x;
- Now = e->xbutton.time;
KeyBtnState = (e->xbutton.state | (1 << (e->xbutton.button + 7)));
mouse_click(e->xbutton.button, true, e->xbutton.x, e->xbutton.y);
}
static void xbtnrelease(XConf* x, XEvent* e) {
(void)x;
- Now = e->xbutton.time;
KeyBtnState = (KeyBtnState & ~(1 << (e->xbutton.button + 7)));
mouse_click(e->xbutton.button, false, e->xbutton.x, e->xbutton.y);
}
static void xbtnmotion(XConf* x, XEvent* e) {
while (XCheckTypedEvent(x->display, MotionNotify, e));
- Now = e->xbutton.time;
size_t row, col;
KeyBtnState = e->xbutton.state;
int xpos = e->xbutton.x, ypos = e->xbutton.y;
XFlush(X.display);
}
-void win_init(KeyBinding* bindings) {
- Keys = bindings;
+void win_init(void) {
signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
void win_quit(void) {
static uint64_t before = 0;
- if ((win_buf(EDIT)->status != MODIFIED) || (Now - before) <= (uint64_t)ClickTime) {
+ if ((win_buf(EDIT)->status != MODIFIED) || (X.now - before) <= (uint64_t)ClickTime) {
tide_send("DEL");
X.eventfns[SelectionClear] = x11_sel_quit;
XUnmapWindow(X.display, X.self);
if (fork()) exit(0); /* fork into background if we still have selection */
}
}
- before = Now;
+ before = X.now;
}
void win_togglefocus(void) {
if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
/* create the window */
- win_init(Bindings);
+ win_init();
/* Initialize the views */
view_init(&Regions[TAGS], NULL);