Implement hide-on-modifier
This commit is contained in:
parent
84d7da0acf
commit
53ec74a4ab
@ -15,6 +15,7 @@ LDFLAGS += -lev
|
||||
LDFLAGS += -lyajl
|
||||
LDFLAGS += -lxcb
|
||||
LDFLAGS += -lxcb-atom
|
||||
LDFLAGS += -lX11
|
||||
LDFLAGS += -L/usr/local/lib
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
|
135
i3bar/src/xcb.c
135
i3bar/src/xcb.c
@ -13,10 +13,16 @@
|
||||
#include <xcb/xcb_event.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <i3/ipc.h>
|
||||
#include <ev.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKB.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* We save the Atoms in an easy to access array, indexed by an enum */
|
||||
@ -36,10 +42,15 @@ xcb_screen_t *xcb_screens;
|
||||
xcb_window_t xcb_root;
|
||||
xcb_font_t xcb_font;
|
||||
|
||||
Display *xkb_dpy;
|
||||
int xkb_event_base;
|
||||
int mod_pressed;
|
||||
|
||||
/* Event-Watchers, to interact with the user */
|
||||
ev_prepare *xcb_prep;
|
||||
ev_check *xcb_chk;
|
||||
ev_io *xcb_io;
|
||||
ev_io *xkb_io;
|
||||
|
||||
/*
|
||||
* Converts a colorstring to a colorpixel as expected from xcb_change_gc.
|
||||
@ -56,6 +67,54 @@ uint32_t get_colorpixel(const char *s) {
|
||||
return (r << 16 | g << 8 | b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hides all bars (unmaps them)
|
||||
*
|
||||
*/
|
||||
void hide_bars() {
|
||||
i3_output *walk;
|
||||
SLIST_FOREACH(walk, outputs, slist) {
|
||||
xcb_unmap_window(xcb_connection, walk->bar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unhides all bars (maps them)
|
||||
*
|
||||
*/
|
||||
void unhide_bars() {
|
||||
i3_output *walk;
|
||||
xcb_void_cookie_t cookie;
|
||||
xcb_generic_error_t *err;
|
||||
uint32_t mask;
|
||||
uint32_t values[4];
|
||||
|
||||
SLIST_FOREACH(walk, outputs, slist) {
|
||||
if (walk->bar == XCB_NONE) {
|
||||
continue;
|
||||
}
|
||||
mask = XCB_CONFIG_WINDOW_X |
|
||||
XCB_CONFIG_WINDOW_Y |
|
||||
XCB_CONFIG_WINDOW_WIDTH |
|
||||
XCB_CONFIG_WINDOW_HEIGHT;
|
||||
values[0] = walk->rect.x;
|
||||
values[1] = walk->rect.y + walk->rect.h - font_height - 6;
|
||||
values[2] = walk->rect.w;
|
||||
values[3] = font_height + 6;
|
||||
printf("Reconfiguring Window for output %s to %d,%d\n", walk->name, values[0], values[1]);
|
||||
cookie = xcb_configure_window_checked(xcb_connection,
|
||||
walk->bar,
|
||||
mask,
|
||||
values);
|
||||
|
||||
if ((err = xcb_request_check(xcb_connection, cookie)) != NULL) {
|
||||
printf("ERROR: Could not reconfigure window. XCB-errorcode: %d\n", err->error_code);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
xcb_map_window(xcb_connection, walk->bar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a button-press-event (i.c. a mouse click on one of our bars).
|
||||
* We determine, wether the click occured on a ws-button or if the scroll-
|
||||
@ -175,6 +234,45 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
|
||||
void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to bind to the modifier per XKB. Sadly, XCB does not implement this
|
||||
*
|
||||
*/
|
||||
void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
||||
XkbEvent ev;
|
||||
int modstate;
|
||||
|
||||
printf("Got XKB-Event!\n");
|
||||
|
||||
while (XPending(xkb_dpy)) {
|
||||
XNextEvent(xkb_dpy, (XEvent*)&ev);
|
||||
|
||||
if (ev.type != xkb_event_base) {
|
||||
printf("ERROR: No Xkb-Event!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.any.xkb_type != XkbStateNotify) {
|
||||
printf("ERROR: No State Notify!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int mods = ev.state.mods;
|
||||
modstate = mods & Mod4Mask;
|
||||
}
|
||||
|
||||
if (modstate != mod_pressed) {
|
||||
if (modstate == 0) {
|
||||
printf("Mod4 got released!\n");
|
||||
hide_bars();
|
||||
} else {
|
||||
printf("Mod4 got pressed!\n");
|
||||
unhide_bars();
|
||||
}
|
||||
mod_pressed = modstate;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the rendered width of a string with the configured font.
|
||||
* The string has to be encoded in ucs2 and glyph_len has to be the length
|
||||
@ -242,18 +340,55 @@ void init_xcb(char *fontname) {
|
||||
strlen(fontname),
|
||||
fontname);
|
||||
|
||||
int xkb_major, xkb_minor, xkb_errbase, xkb_err;
|
||||
xkb_major = XkbMajorVersion;
|
||||
xkb_minor = XkbMinorVersion;
|
||||
|
||||
xkb_dpy = XkbOpenDisplay(":0",
|
||||
&xkb_event_base,
|
||||
&xkb_errbase,
|
||||
&xkb_major,
|
||||
&xkb_minor,
|
||||
&xkb_err);
|
||||
|
||||
if (xkb_dpy == NULL) {
|
||||
printf("ERROR: No XKB!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fcntl(ConnectionNumber(xkb_dpy), F_SETFD, FD_CLOEXEC) == -1) {
|
||||
fprintf(stderr, "Could not set FD_CLOEXEC on xkbdpy\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int i1;
|
||||
if (!XkbQueryExtension(xkb_dpy, &i1, &xkb_event_base, &xkb_errbase, &xkb_major, &xkb_minor)) {
|
||||
printf("ERROR: XKB not supported by X-server!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!XkbSelectEvents(xkb_dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask)) {
|
||||
printf("Could not grab Key!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* The varios Watchers to communicate with xcb */
|
||||
xcb_io = malloc(sizeof(ev_io));
|
||||
xcb_prep = malloc(sizeof(ev_prepare));
|
||||
xcb_chk = malloc(sizeof(ev_check));
|
||||
xkb_io = malloc(sizeof(ev_io));
|
||||
|
||||
ev_io_init(xcb_io, &xcb_io_cb, xcb_get_file_descriptor(xcb_connection), EV_READ);
|
||||
ev_prepare_init(xcb_prep, &xcb_prep_cb);
|
||||
ev_check_init(xcb_chk, &xcb_chk_cb);
|
||||
ev_io_init(xkb_io, &xkb_io_cb, ConnectionNumber(xkb_dpy), EV_READ);
|
||||
|
||||
ev_io_start(main_loop, xcb_io);
|
||||
ev_prepare_start(main_loop, xcb_prep);
|
||||
ev_check_start(main_loop, xcb_chk);
|
||||
ev_io_start(main_loop, xkb_io);
|
||||
|
||||
XFlush(xkb_dpy);
|
||||
|
||||
/* Now we get the atoms and save them in a nice data-structure */
|
||||
get_atoms();
|
||||
|
Loading…
Reference in New Issue
Block a user