/*************************************************************************/ /* _____________ */ /* < yeahconsole > */ /* ------------- */ /* \ ^__^ */ /* \ (oo)\_______ */ /* (__)\ )\/\ */ /* ||----w | */ /* || || */ /* */ /* Copyright (C) knorke */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*************************************************************************/ #include #include #include #include #include #include #include #include #include "config.h" Display *dpy; Window root; Window win; Window termwin; Window last_focused; int revert_to; int screen; int opt_x, opt_width, opt_height, opt_delay, opt_bw, height; int opt_hideStep, opt_showStep; char *opt_color; KeySym opt_key; KeySym opt_key_smaller; KeySym opt_key_bigger; Cursor cursor; int resize_inc; void roll(int i); void get_defaults(void); KeySym grab_that_key(char *opt, unsigned int numlockmask); void init_win(void); void init_xterm(void); void resize(void); int handle_xerror(Display * display, XErrorEvent * e); int main(int argc, char *argv[]) { KeySym key; XEvent event; int hidden = 1; if (!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, " can not open dpy %s", XDisplayName(NULL)); } screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); XSetErrorHandler(handle_xerror); cursor = XCreateFontCursor(dpy, XC_double_arrow); get_defaults(); init_win(); init_xterm(); while (1) { XNextEvent(dpy, &event); switch (event.type) { case EnterNotify: XSetInputFocus(dpy, termwin, RevertToPointerRoot, CurrentTime); break; case LeaveNotify: if (last_focused && event.xcrossing.detail != NotifyInferior) XSetInputFocus(dpy, last_focused, RevertToPointerRoot, CurrentTime); break; case KeyPress: key = XKeycodeToKeysym(dpy, event.xkey.keycode, 0); if (key == opt_key) { if (!hidden) { if (last_focused) XSetInputFocus(dpy, last_focused, RevertToPointerRoot, CurrentTime); /* else XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); */ roll(0); hidden = 1; XSync(dpy, False); } else { XRaiseWindow(dpy, win); XGetInputFocus(dpy, &last_focused, &revert_to); XSetInputFocus(dpy, termwin, RevertToPointerRoot, CurrentTime); roll(-(height + opt_bw)); hidden = 0; } break; } if (!hidden) { if (key == opt_key_bigger) height += resize_inc; if (key == opt_key_smaller) height -= resize_inc; if (height < resize_inc) height = resize_inc; XResizeWindow(dpy, termwin, opt_width, height); XResizeWindow(dpy, win, opt_width, height + opt_bw); } break; case ButtonPress: resize(); break; case UnmapNotify: if (event.xunmap.window == termwin) { if (last_focused) XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XSync(dpy, False); exit(0); } break; } } return 0; } void roll(int i) { int x = opt_showStep; if (i == 0) x = -opt_hideStep; while (1) { i += x; if ( (x>0) && (i>0) ) i=0; if ( (x<0) && (i< -(height + opt_bw))) i=-(height + opt_bw); XMoveWindow(dpy, win, opt_x, i); XSync(dpy, False); usleep(opt_delay * 10); if (i == 0 || i == -(height + opt_bw)) break; } } void get_defaults() { char *opt; XModifierKeymap *modmap; unsigned int numlockmask = 0; int i, j; char def_key []="ControlAlt+y"; char def_key_bigger[] = "Control+KP_Add"; char def_key_smaller[] = "Control+KP_Subtract"; /* key grabbing stuff taken from evilwm */ modmap = XGetModifierMapping(dpy); for (i = 0; i < 8; i++) { for (j = 0; j < modmap->max_keypermod; j++) { if (modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) { numlockmask = (1 << i); } } } XFreeModifiermap(modmap); opt = XGetDefault(dpy, "yeahconsole", "showStep"); opt_showStep = opt ? atoi(opt) : 1; opt = XGetDefault(dpy, "yeahconsole", "hideStep"); opt_hideStep = opt ? atoi(opt) : 1; opt = XGetDefault(dpy, "yeahconsole", "screenWidth"); opt_width = opt ? atoi(opt) : DisplayWidth(dpy, screen); opt = XGetDefault(dpy, "yeahconsole", "handleColor"); opt_color = opt ? opt : "grey70"; opt = XGetDefault(dpy, "yeahconsole", "handleWidth"); opt_bw = opt ? atoi(opt) : 3; opt = XGetDefault(dpy, "yeahconsole", "consoleHeight"); opt_height = opt ? atoi(opt) : 10; opt = XGetDefault(dpy, "yeahconsole", "xOffset"); opt_x = opt ? atoi(opt) : 0; opt = XGetDefault(dpy, "yeahconsole", "aniDelay"); opt_delay = opt ? atoi(opt) : 40; opt = XGetDefault(dpy, "yeahconsole", "toggleKey"); opt_key = opt ? grab_that_key(opt, numlockmask) : grab_that_key(def_key, numlockmask); opt = XGetDefault(dpy, "yeahconsole", "keySmaller"); opt_key_smaller = opt ? grab_that_key(opt, numlockmask) : grab_that_key(def_key_smaller, numlockmask); opt = XGetDefault(dpy, "yeahconsole", "keyBigger"); opt_key_bigger = opt ? grab_that_key(opt, numlockmask) : grab_that_key(def_key_bigger, numlockmask); } KeySym grab_that_key(char *opt, unsigned int numlockmask) { unsigned int modmask = 0; KeySym keysym; if (strstr(opt, "Control")) modmask = modmask | ControlMask; if (strstr(opt, "Alt")) modmask = modmask | Mod1Mask; if (strstr(opt, "Win")) modmask = modmask | Mod4Mask; if (strstr(opt, "None")) modmask = 0; if (strtok(opt, "+")) keysym = XStringToKeysym(strtok(NULL, "+")); XGrabKey(dpy, XKeysymToKeycode(dpy, keysym), modmask, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, XKeysymToKeycode(dpy, keysym), LockMask | modmask, root, True, GrabModeAsync, GrabModeAsync); if (numlockmask) { XGrabKey(dpy, XKeysymToKeycode(dpy, keysym), numlockmask | modmask, root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, XKeysymToKeycode(dpy, keysym), numlockmask | LockMask | modmask, root, True, GrabModeAsync, GrabModeAsync); } return keysym; } void init_win() { XSetWindowAttributes attrib; XColor color; XColor dummy_color; attrib.override_redirect = True; attrib.background_pixel = BlackPixel(dpy, screen); win = XCreateWindow(dpy, root, opt_x, -opt_height, opt_width, opt_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWBackPixel, &attrib); XSelectInput(dpy, win, SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask); XAllocNamedColor(dpy, DefaultColormap(dpy, screen), opt_color, &color, &dummy_color); XSetWindowBackground(dpy, win, color.pixel); XMapWindow(dpy, win); /* printf("win:0x%x\n", win); */ } void init_xterm() { char cmd[20]; XEvent ev; long dummy; XSizeHints *size; sprintf(cmd, " %d ", (int) win); if (!fork()) { execlp("xterm", "xterm", "-name", "yeahconsole", "-b", "0", "-into", cmd, "-e", "~/.yeah/script.sh", NULL); fprintf(stderr, "Oops, no xterm found\n"); exit(1); } while (1) { XMaskEvent(dpy, SubstructureNotifyMask, &ev); if (ev.type == ReparentNotify && ev.xreparent.parent == win) { termwin = ev.xreparent.window; /* printf("termwin:0x%x\n", termwin); */ break; } } XSetWindowBorderWidth(dpy, termwin, 0); size = XAllocSizeHints(); XGetWMNormalHints(dpy, termwin, size, &dummy); resize_inc = size->height_inc; height = resize_inc * opt_height; XFree(size); XResizeWindow(dpy, termwin, opt_width, height); XMoveResizeWindow(dpy, win, opt_x, -(height + opt_bw), opt_width, height + opt_bw); } void resize() { XEvent ev; if (!XGrabPointer (dpy, root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime) == GrabSuccess) return; for (;;) { XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | PointerMotionHintMask, &ev); switch (ev.type) { case MotionNotify: if (!(ev.xmotion.y % resize_inc) && ev.xmotion.y >= resize_inc) { height = ev.xmotion.y; XResizeWindow(dpy, termwin, opt_width, height); XResizeWindow(dpy, win, opt_width, height + opt_bw); XSync(dpy, False); break; case ButtonRelease: XUngrabPointer(dpy, CurrentTime); return; } } } } int handle_xerror(Display * display, XErrorEvent * e) { /* this function does nothing, we receive xerrors when the last_focused window gets lost.. */ /* fprintf(stderr, "XError caught\n"); */ return 0; }