diff options
author | sabetts <sabetts> | 2000-09-07 16:49:23 +0000 |
---|---|---|
committer | sabetts <sabetts> | 2000-09-07 16:49:23 +0000 |
commit | 60767d1215233461273d4d16df8ff52cf15b4010 (patch) | |
tree | d62f90a2f202366b829f274fc21458ab70df6730 /src/events.c | |
parent | 33fb61429337fc71292628e9dac1ddf599938304 (diff) | |
download | ratpoison-60767d1215233461273d4d16df8ff52cf15b4010.zip |
restructured tree, added automake and autoconf to the build process.
Diffstat (limited to 'src/events.c')
-rw-r--r-- | src/events.c | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..a835eb3 --- /dev/null +++ b/src/events.c @@ -0,0 +1,473 @@ +/* Copyright (C) 2000 Shawn Betts + * + * 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, 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/keysymdef.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> + +#include "ratpoison.h" + +extern Display *dpy; + +void +spawn(char *prog) +{ + /* + * ugly dance to avoid leaving zombies. Could use SIGCHLD, + * but it's not very portable. + */ + if (fork() == 0) { + if (fork() == 0) { + putenv(DisplayString(dpy)); + execlp(prog, prog, 0); + fprintf(stderr, "ratpoison: exec %s ", prog); + perror(" failed"); + exit(EXIT_FAILURE); + } + exit(0); + } + wait((int *) 0); +#ifdef DEBUG + printf ("spawned %s\n", prog); +#endif +} + +void +new_window (XCreateWindowEvent *e) +{ + rp_window *win; + screen_info *s; + + if (e->override_redirect) return; + + s = find_screen (e->parent); + win = find_window (e->window); + + if (s && !win && e->window != s->key_window && e->window != s->bar_window + && e->window != s->input_window) + { + win = add_to_window_list (s, e->window); + win->state = STATE_UNMAPPED; + } +} + +void +unmap_notify (XEvent *ev) +{ + screen_info *s; + rp_window *win; + + s = find_screen (ev->xunmap.event); + win = find_window (ev->xunmap.window); + + if (s && win) + { + /* Give back the window number. the window will get another one, + if it in remapped. */ + return_window_number (win->number); + win->number = -1; + win->state = STATE_UNMAPPED; + update_window_names (s); + } +} + +void +map_request (XEvent *ev) +{ + screen_info *s; + rp_window *win; + + s = find_screen (ev->xmap.event); + win = find_window (ev->xmap.window); + + if (s && win) + { + switch (win->state) + { + case STATE_UNMAPPED: + manage (win, s); + case STATE_MAPPED: + XMapRaised (dpy, win->w); + rp_current_window = win; + set_active_window (rp_current_window); + } + } + else + { + printf ("Not managed.\n"); + XMapWindow (dpy, ev->xmap.window); + } +} + +int +more_destroy_events () +{ + XEvent ev; + + if (XCheckTypedEvent (dpy, DestroyNotify, &ev)) + { + XPutBackEvent (dpy, &ev); + return 1; + } + return 0; +} + +void +destroy_window (XDestroyWindowEvent *ev) +{ + /* if there are multiple destroy events queued, and a mapped window + is deleted then switch_window_pending is set to 1 and the window + switch is done after all destroy events have been done. */ + static int switch_window_pending = 0; + int last_destroy_event; + rp_window *win; + + win = find_window (ev->window); + + last_destroy_event = !more_destroy_events(); + if (win) + { + /* Goto the last accessed window. */ + if (win == rp_current_window) + { + printf ("Destroying current window.\n"); + + /* tell ratpoison to switch to the last window when all the + destroy events have been delt with. */ + switch_window_pending = 1; + unmanage (win); + } + else + { + printf ("Destroying some other window.\n"); + unmanage (win); + } + } + + if (last_destroy_event && switch_window_pending) + { + last_window (); + switch_window_pending = 0; + } +} + +void +configure_request (XConfigureRequestEvent *e) +{ + XConfigureEvent ce; + rp_window *win; + + win = find_window (e->window); + + if (win) + { + ce.type = ConfigureNotify; + ce.event = e->window; + ce.window = e->window; + ce.x = 0; + ce.y = 0; + ce.width = win->scr->root_attr.width; + ce.height = win->scr->root_attr.height; + ce.border_width = 0; + ce.above = None; + ce.override_redirect = 0; + + if (e->value_mask & CWStackMode && win->state == STATE_MAPPED) + { + if (e->detail == Above) + { + rp_current_window = win; + set_active_window (rp_current_window); + } + else if (e->detail == Below && win == rp_current_window) + { + last_window (); + } + } + + XSendEvent(dpy, win->w, False, StructureNotifyMask, (XEvent*)&ce); + } +} + +void +delete_window () +{ + XEvent ev; + int status; + + if (rp_current_window == NULL) return; + + ev.xclient.type = ClientMessage; + ev.xclient.window = rp_current_window->w; + ev.xclient.message_type = wm_protocols; + ev.xclient.format = 32; + ev.xclient.data.l[0] = wm_delete; + ev.xclient.data.l[1] = CurrentTime; + + status = XSendEvent(dpy, rp_current_window->w, False, 0, &ev); + if (status == 0) fprintf(stderr, "ratpoison: XSendEvent failed\n"); +} + +void +kill_window () +{ + if (rp_current_window == NULL) return; + + XKillClient(dpy, rp_current_window->w); +} + +static void +client_msg (XClientMessageEvent *ev) +{ + printf ("Recieved client message.\n"); +} + +static void +goto_win_by_name (screen_info *s) +{ + char winname[100]; + + get_input (s, "Window: ", winname, 100); + printf ("user entered: %s\n", winname); + + goto_window_name (winname); +} + +static void +handle_key (screen_info *s) +{ + int revert; + Window fwin; + XEvent ev; + int keysym; + +#ifdef DEBUG + printf ("handling key.\n"); +#endif + + XGetInputFocus (dpy, &fwin, &revert); + XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime); + XMaskEvent (dpy, KeyPressMask, &ev); + XSetInputFocus (dpy, fwin, revert, CurrentTime); + + if (XLookupKeysym((XKeyEvent *) &ev, 0) == KEY_PREFIX && !ev.xkey.state) + { + /* Generate the prefix keystroke for the app */ + ev.xkey.window = fwin; + ev.xkey.state = MODIFIER_PREFIX; + XSendEvent (dpy, fwin, False, KeyPressMask, &ev); + XSync (dpy, False); + return; + } + + keysym = XLookupKeysym((XKeyEvent *) &ev, 0); + + if (keysym == KEY_TOGGLEBAR) + { + toggle_bar (s); + return; + } + + /* All functions tested for after this point hide the program bar. */ + hide_bar (s); + + if (keysym >= '0' && keysym <= '9') + { + goto_window_number (XLookupKeysym((XKeyEvent *) &ev, 0) - '0'); + hide_bar (s); + return; + } + + switch (keysym) + { + case KEY_XTERM: + spawn (TERM_PROG); + break; + case KEY_EMACS: + spawn (EMACS_PROG); + break; + case KEY_PREVWINDOW: + prev_window (); + break; + case KEY_NEXTWINDOW: + next_window (); + break; + case KEY_LASTWINDOW: + last_window (); + break; + case KEY_WINBYNAME: + goto_win_by_name (s); + break; + case KEY_RENAME: + rename_current_window (); + break; + case KEY_DELETE: + if (ev.xkey.state & ShiftMask) kill_window (); + else delete_window (); + break; + default: + fprintf (stderr, "Unknown key command '%c'\n", (char)keysym); + break; + } +} + +void +key_press (XEvent *ev) +{ + screen_info *s; + unsigned int modifier = ev->xkey.state; + int ks = XLookupKeysym((XKeyEvent *) ev, 0); + + s = find_screen (ev->xkey.root); + + if (s && ks == KEY_PREFIX && (modifier & MODIFIER_PREFIX)) + { + handle_key (s); + } +} + +void +property_notify (XEvent *ev) +{ + rp_window *win; + + printf ("atom: %ld\n", ev->xproperty.atom); + + win = find_window (ev->xproperty.window); + + if (win) + { + if (ev->xproperty.atom == XA_WM_NAME) + { + printf ("updating window name\n"); + if (update_window_name (win)) + { + update_window_names (win->scr); + } + } + } +} + +/* Given an event, call the correct function to handle it. */ +void +delegate_event (XEvent *ev) +{ + switch (ev->type) + { + case ConfigureRequest: + printf ("ConfigureRequest\n"); + configure_request (&ev->xconfigurerequest); + break; + case CirculateRequest: + printf ("CirculateRequest\n"); + break; + case CreateNotify: + printf ("CreateNotify\n"); + new_window (&ev->xcreatewindow); + break; + case DestroyNotify: + printf ("DestroyNotify\n"); + destroy_window (&ev->xdestroywindow); + break; + case ClientMessage: + client_msg (&ev->xclient); + printf ("ClientMessage\n"); + break; + case ColormapNotify: + printf ("ColormapNotify\n"); + break; + case PropertyNotify: + printf ("PropertyNotify\n"); + property_notify (ev); + break; + case SelectionClear: + printf ("SelectionClear\n"); + break; + case SelectionNotify: + printf ("SelectionNotify\n"); + break; + case SelectionRequest: + printf ("SelectionRequest\n"); + break; + case EnterNotify: + printf ("EnterNotify\n"); + break; + case ReparentNotify: + printf ("ReparentNotify\n"); + break; + case FocusIn: + printf ("FocusIn\n"); + break; + + case MapRequest: + printf ("MapRequest\n"); + map_request (ev); + break; + + case KeyPress: + printf ("KeyPress\n"); + key_press (ev); + break; + + case UnmapNotify: + printf ("UnmapNotify\n"); + unmap_notify (ev); + break; + + case MotionNotify: + printf ("MotionNotify\n"); + break; + case Expose: + printf ("Expose\n"); + break; + case FocusOut: + printf ("FocusOut\n"); + break; + case ConfigureNotify: + printf ("ConfigureNotify\n"); + break; + case MapNotify: + printf ("MapNotify\n"); + break; + case MappingNotify: + printf ("MappingNotify\n"); + break; + default: + printf ("Unhandled event %d\n", ev->type); + } +} + +void +handle_events () +{ + XEvent ev; + + for (;;) + { + XNextEvent (dpy, &ev); + delegate_event (&ev); + } +} + + |