summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog38
-rw-r--r--src/actions.c53
-rw-r--r--src/actions.h2
-rw-r--r--src/bar.c54
-rw-r--r--src/bar.h1
-rw-r--r--src/conf.h7
-rw-r--r--src/events.c82
-rw-r--r--src/input.c127
-rw-r--r--src/input.h4
-rw-r--r--src/list.c5
-rw-r--r--src/list.h2
11 files changed, 281 insertions, 94 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e1477f4..2313b76 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,41 @@
+2000-12-09 shawn <sabetts@diggin.lamenet.tmp>
+
+ * input.c (cook_keycode): properly handle LockMask
+
+ * input.h: added prototype for keysym_to_string
+
+ * input.c (keysym_to_string): added
+
+ * bar.c (show_bar): update_window_names(s) is called whether the
+ bar is raised or not.
+
+ * conf.h: Added BAR_Y_PADDING BAR_X_PADDING
+
+ * list.c (goto_window_name): return success or failure
+
+ * list.h: updated prototype for goto_window_name
+
+ * events.c (handle_key): Added a message indicating an unbound
+ key.
+
+ * bar.c (display_msg_in_bar): added
+ (update_window_names): uses BAR_X_PADDING instead of `5'
+ (update_window_names): Updated BAR_PADDING to BAR_Y_PADDING
+
+ * input.c (cook_keycode): mod is now an usigned int
+ (read_key): Ignores modifier keys. Now returns keysym and
+ modifiers.
+ (get_input): Updated BAR_PADDING to BAR_Y_PADDING and
+ BAR_X_PADDING.
+
+ * events.c (handle_key): uses read_key instead of XMaskEvent to
+ read a key.
+
+ * actions.c (goto_window_number): window list is displayed on failure.
+ (bye): added
+ (switch_to): added
+ (execute_command): no longer seg faults when no windows exist.
+
2000-12-03 shawn <sabetts@diggin.lamenet.tmp>
* input.h (cook_keycode): added prototype
diff --git a/src/actions.c b/src/actions.c
index 323f519..095604b 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -67,8 +67,15 @@ next_window (void *data)
void
last_window (void *data)
{
+ rp_window *oldwin = rp_current_window;
+
rp_current_window = find_last_accessed_window ();
set_active_window (rp_current_window);
+
+ if (rp_current_window == oldwin)
+ {
+ display_msg_in_bar (&screens[0], "No other window.");
+ }
}
@@ -145,7 +152,17 @@ execute_command (void *data)
{
char cmd[100];
- get_input (rp_current_window->scr, "Command: ", cmd, 100);
+ if (rp_current_window)
+ {
+ get_input (rp_current_window->scr, "Command: ", cmd, 100);
+ }
+ else
+ {
+ /* FIXME: We can always assume there is 1 screen, but which one
+ is the active one? Need to test on multi-screen x-servers. */
+ get_input (&screens[0], "Command: ", cmd, 100);
+ }
+
PRINT_DEBUG ("user entered: %s\n", cmd);
spawn (cmd);
@@ -163,8 +180,10 @@ spawn(void *data)
if (fork() == 0) {
putenv(DisplayString(dpy));
execlp(prog, prog, 0);
- fprintf (stderr, "exec %s ", prog);
+
+ PRINT_ERROR ("exec %s ", prog);
perror(" failed");
+
exit(EXIT_FAILURE);
}
exit(0);
@@ -173,6 +192,32 @@ spawn(void *data)
PRINT_DEBUG ("spawned %s\n", prog);
}
+/* Switch to a different Window Manager. Thanks to
+"Chr. v. Stuckrad" <stucki@math.fu-berlin.de> for the patch. */
+void
+switch_to(void *which)
+{
+ char *prog=(char *)which;
+
+ PRINT_DEBUG ("Switching to %s\n", prog);
+
+ putenv(DisplayString(dpy));
+ execlp(prog, prog, 0);
+
+ PRINT_ERROR ("exec %s ", prog);
+ perror(" failed");
+}
+
+/* Quit ratpoison. Thanks to
+"Chr. v. Stuckrad" <stucki@math.fu-berlin.de> for the patch. */
+void
+bye(void *dummy)
+{
+ PRINT_DEBUG ("Exiting\n");
+ clean_up ();
+ exit (EXIT_SUCCESS);
+}
+
void
goto_window_number (int n)
{
@@ -180,6 +225,10 @@ goto_window_number (int n)
if ((win = find_window_by_number (n)) == NULL)
{
+ /* Display window list to indicate failure. */
+ /* FIXME: We can always assume there is 1 screen, but which one
+ is the active one? Need to test on multi-screen x-servers. */
+ show_bar (&screens[0]);
return;
}
diff --git a/src/actions.h b/src/actions.h
index 793064d..54317c3 100644
--- a/src/actions.h
+++ b/src/actions.h
@@ -1,6 +1,8 @@
/* actions.h -- prototypes of all actions that can be performed with
keystrokes */
+void switch_to(void *which);
+void bye(void *dummy);
void generate_prefix (void *data);
void abort_keypress (void *data);
void goto_window_9 (void *data);
diff --git a/src/bar.c b/src/bar.c
index e61c9cd..c69e0d9 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -29,6 +29,11 @@
#include "ratpoison.h"
+/* Possible values for bar_is_raised status. */
+#define BAR_IS_WINDOW_LIST 1
+#define BAR_IS_MESSAGE 2
+
+/* Hide the bar from sight. */
int
hide_bar (screen_info *s)
{
@@ -42,12 +47,13 @@ hide_bar (screen_info *s)
return 0;
}
+/* Show window listing in bar. */
int
show_bar (screen_info *s)
{
if (!s->bar_is_raised)
{
- s->bar_is_raised = 1;
+ s->bar_is_raised = BAR_IS_WINDOW_LIST;
XMapWindow (dpy, s->bar_window);
update_window_names (s);
@@ -56,9 +62,14 @@ show_bar (screen_info *s)
return 1;
}
+ /* If the bar is raised we still need to display the window
+ names. */
+ update_window_names (s);
return 0;
}
+/* Calculate the width required for the bar to display the window
+ list. */
static int
calc_bar_width (XFontStruct *font)
{
@@ -88,7 +99,7 @@ int
bar_y (screen_info *s)
{
if (BAR_LOCATION % 2) return 0;
- else return s->root_attr.height - (FONT_HEIGHT (s->font) + BAR_PADDING * 2) - 2;
+ else return s->root_attr.height - (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2) - 2;
}
void
@@ -97,14 +108,14 @@ update_window_names (screen_info *s)
char str[100]; /* window names are capped at 99 chars */
int width = calc_bar_width (s->font);
rp_window *cur;
- int cur_x = 5;
+ int cur_x = BAR_X_PADDING;
if (!s->bar_is_raised) return;
XMoveResizeWindow (dpy, s->bar_window,
bar_x (s, width), bar_y (s),
width,
- (FONT_HEIGHT (s->font) + BAR_PADDING * 2));
+ (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2));
XClearWindow (dpy, s->bar_window);
XRaiseWindow (dpy, s->bar_window);
@@ -112,7 +123,7 @@ update_window_names (screen_info *s)
/* Draw them in reverse order they were added in, so the oldest
windows appear on the left and the newest on the right end of the
- program bar. */
+ bar. */
for (cur = rp_window_head; cur; cur = cur->next)
{
if (cur->state == STATE_UNMAPPED) continue;
@@ -121,14 +132,43 @@ update_window_names (screen_info *s)
if ( rp_current_window == cur)
{
XDrawString (dpy, s->bar_window, s->bold_gc, cur_x,
- BAR_PADDING + s->font->max_bounds.ascent, str, strlen (str));
+ BAR_Y_PADDING + s->font->max_bounds.ascent, str,
+ strlen (str));
}
else
{
XDrawString (dpy, s->bar_window, s->normal_gc, cur_x,
- BAR_PADDING + s->font->max_bounds.ascent, str, strlen (str));
+ BAR_Y_PADDING + s->font->max_bounds.ascent, str,
+ strlen (str));
}
cur_x += 10 + XTextWidth (s->font, str, strlen (str));
}
}
+
+void
+display_msg_in_bar (screen_info *s, char *msg)
+{
+ int width = BAR_X_PADDING * 2 + XTextWidth (s->font, msg, strlen (msg));
+
+ /* Map the bar if needed */
+ if (!s->bar_is_raised)
+ {
+ s->bar_is_raised = BAR_IS_MESSAGE;
+ XMapWindow (dpy, s->bar_window);
+ }
+
+ /* Reset the alarm to auto-hide the bar in BAR_TIMEOUT seconds. */
+ alarm (BAR_TIMEOUT);
+
+ XMoveResizeWindow (dpy, s->bar_window,
+ bar_x (s, width), bar_y (s),
+ width,
+ (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2));
+ XClearWindow (dpy, s->bar_window);
+ XRaiseWindow (dpy, s->bar_window);
+
+ XDrawString (dpy, s->bar_window, s->bold_gc, BAR_X_PADDING,
+ BAR_Y_PADDING + s->font->max_bounds.ascent, msg,
+ strlen (msg));
+}
diff --git a/src/bar.h b/src/bar.h
index 383bcdf..49c0ff4 100644
--- a/src/bar.h
+++ b/src/bar.h
@@ -25,4 +25,5 @@ int show_bar (screen_info *s);
int hide_bar (screen_info *s);
int bar_y (screen_info *s);
int bar_x (screen_info *s, int width);
+void display_msg_in_bar (screen_info *s, char *msg);
#endif _BAR_H
diff --git a/src/conf.h b/src/conf.h
index 3092bc6..9b705dd 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -27,10 +27,13 @@
#define BAR_FG_COLOR "Gray60"
#define BAR_BG_COLOR "Lightgreen"
-#define BAR_BOLD_COLOR "Black" /* To indicate the current window */
+#define BAR_BOLD_COLOR "Black" /* To indicate the current window */
#define FONT_NAME "fixed" /* The font you wish to use */
-#define BAR_PADDING 3 /* The amount of padding on the top and bottom of the program bar */
+#define BAR_Y_PADDING 3 /* The amount of padding on the top
+ and bottom of the message bar */
+#define BAR_X_PADDING 5 /* The amount of padding on the left
+ and right of the message bar */
#define BAR_LOCATION 3 /* 0=bottom-left 1=top-left 2=bottom-right 3=top-right */
#define BAR_TIMEOUT 5 /* Number of seconds before the progam bar autohides 0=don't autohide */
diff --git a/src/events.c b/src/events.c
index bf9c78b..d859965 100644
--- a/src/events.c
+++ b/src/events.c
@@ -239,59 +239,49 @@ client_msg (XClientMessageEvent *ev)
static void
handle_key (screen_info *s)
{
+ char *keysym_name;
+ char msg[100];
const rp_action *i;
- int revert;
- Window fwin;
- XEvent ev;
- KeySym keysym;
- int mod;
+ int revert;
+ Window fwin; /* Window currently in focus */
+ KeySym keysym; /* Key pressed */
+ unsigned int mod; /* Modifiers */
- PRINT_DEBUG ("handling key.\n");
+ PRINT_DEBUG ("handling key...\n");
- /* All functions hide the program bar. */
+ /* All functions hide the program bar. Unless the bar doesn't time
+ out. */
if (BAR_TIMEOUT > 0) hide_bar (s);
XGetInputFocus (dpy, &fwin, &revert);
XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime);
- do
- {
- XMaskEvent (dpy, KeyPressMask, &ev);
- mod = ev.xkey.state;
-
- cook_keycode (ev.xkey.keycode, &keysym, &mod);
+ read_key (&keysym, &mod);
- for (i = key_actions; i->key != 0; i++)
+ for (i = key_actions; i->key != 0; i++)
+ {
+ if (keysym == i->key)
{
- if (keysym == i->key)
- if (i->state == -1 || mod == i->state)
- {
- /* Revert focus back to the current window before
- executing the command. */
- XSetInputFocus (dpy, fwin, revert, CurrentTime);
- (*i->func)(i->data);
- goto handled_key;
- }
+ if (i->state == -1 || mod == i->state)
+ {
+ /* Revert focus back to the current window before
+ executing the command. */
+ XSetInputFocus (dpy, fwin, revert, CurrentTime);
+ (*i->func)(i->data);
+ return;
+ }
}
}
- while (1);
-
- handled_key:
-
-/* } while (keysym == XK_Shift_L */
-/* || keysym == XK_Shift_R */
-/* || keysym == XK_Control_L */
-/* || keysym == XK_Control_R */
-/* || keysym == XK_Caps_Lock */
-/* || keysym == XK_Shift_Lock */
-/* || keysym == XK_Meta_L */
-/* || keysym == XK_Meta_R */
-/* || keysym == XK_Alt_L */
-/* || keysym == XK_Alt_R */
-/* || keysym == XK_Super_L */
-/* || keysym == XK_Super_R */
-/* || keysym == XK_Hyper_L */
-/* || keysym == XK_Hyper_R); /\* ignore modifier keypresses. *\/ */
+
+ keysym_name = keysym_to_string (keysym, mod);
+ snprintf (msg, 100, "%s unbound key!", keysym_name);
+ free (keysym_name);
+
+ PRINT_DEBUG ("%s\n", msg)
+
+ /* No key match, notify user. */
+ XSetInputFocus (dpy, fwin, revert, CurrentTime);
+ display_msg_in_bar (s, msg);
}
void
@@ -404,14 +394,12 @@ delegate_event (XEvent *ev)
case KeyPress:
PRINT_DEBUG ("KeyPress %d %d\n", ev->xkey.keycode, ev->xkey.state);
- {
- KeySym thesym;
- char buf[512];
- XLookupString (&ev->xkey, buf, 512, &thesym, NULL);
- PRINT_DEBUG ("key string: '%s' %ld\n", buf, thesym);
- }
key_press (ev);
break;
+
+ case KeyRelease:
+ PRINT_DEBUG ("KeyRelease %d %d\n", ev->xkey.keycode, ev->xkey.state);
+ break;
case UnmapNotify:
PRINT_DEBUG ("UnmapNotify\n");
diff --git a/src/input.c b/src/input.c
index 60e3932..c9a276a 100644
--- a/src/input.c
+++ b/src/input.c
@@ -9,51 +9,102 @@
#include "ratpoison.h"
+/* Return the name of the keysym. caller must free returned pointer */
+char *
+keysym_to_string (KeySym keysym, unsigned int modifier)
+{
+ const unsigned int mod_table[] = {ControlMask,
+ Mod1Mask,
+ Mod2Mask,
+ Mod3Mask,
+ Mod4Mask,
+ Mod5Mask};
+ const unsigned char str_table[] = "CM2345";
+
+ unsigned char *name;
+ int pos, i;
+
+ name = malloc (15);
+ if (name == NULL)
+ {
+ PRINT_ERROR ("Out of memory!\n");
+ exit (EXIT_FAILURE);
+ }
+
+ for (pos = 0, i = 0; i < 6; i++)
+ {
+ if (modifier & mod_table[i])
+ {
+ name[pos] = str_table[i];
+ name[pos+1] = '-';
+ pos += 2;
+ }
+ }
+
+ name[pos] = keysym;
+ name[pos+1] = '\0';
+
+ return name;
+}
+
/* Cooks a keycode + modifier into a keysym + modifier. This should be
used anytime meaningful key information is to be extracted from a
KeyPress or KeyRelease event. */
void
-cook_keycode (KeyCode keycode, KeySym *keysym, int *mod)
+cook_keycode (KeyCode keycode, KeySym *keysym, unsigned int *mod)
{
KeySym normal, shifted;
- if (*mod & ShiftMask)
- {
- normal = XKeycodeToKeysym(dpy, keycode, 0);
- shifted = XKeycodeToKeysym(dpy, keycode, 1);
+ normal = XKeycodeToKeysym(dpy, keycode, 0);
+ shifted = XKeycodeToKeysym(dpy, keycode, 1);
- /* if the shifted code is not defined, then we use the normal keysym and keep the shift mask */
+ /* FIXME: eew, this looks gross. */
+ if (*mod & (ShiftMask | LockMask))
+ {
+ /* if the shifted code is not defined, then we use the normal
+ keysym and keep the shift mask */
if (shifted == NoSymbol)
{
*keysym = normal;
}
- /* But if the shifted code is defined, we use it and remove the shift mask */
- else
+ else if (*mod & ShiftMask)
+ {
+ *keysym = shifted;
+ *mod &= ~(ShiftMask | LockMask);
+ }
+ else if (normal >= XK_a
+ && normal <= XK_z
+ && *mod & LockMask)
{
*keysym = shifted;
- *mod &= ~ShiftMask;
+ }
+ /* But if the shifted code is defined, we use it and remove the
+ shift mask */
+ else
+ {
+ *keysym = normal;
}
}
else
{
- *keysym = XKeycodeToKeysym(dpy, keycode, 0);
+ *keysym = normal;
}
- PRINT_DEBUG ("cooked keysym: %ld '%c' mask: %d\n", *keysym, *keysym, *mod);
+ PRINT_DEBUG ("cooked keysym: %ld '%c' mask: %d\n",
+ *keysym, (char)*keysym, *mod);
}
-static KeySym
-read_key ()
+void
+read_key (KeySym *keysym, unsigned int *modifiers)
{
- KeySym keysym;
- int mod;
XEvent ev;
- XMaskEvent (dpy, KeyPressMask, &ev);
- mod = ev.xkey.state;
- cook_keycode (ev.xkey.keycode, &keysym, &mod);
-
- return keysym;
+ do
+ {
+ XMaskEvent (dpy, KeyPressMask, &ev);
+ *modifiers = ev.xkey.state;
+ cook_keycode (ev.xkey.keycode, keysym, modifiers);
+ } while (IsModifierKey (*keysym));
}
/* pass in a pointer a string and how much room we have, and fill it
@@ -63,6 +114,7 @@ get_input (screen_info *s, char *prompt, char *str, int len)
{
int cur_len; /* Current length of the string. */
KeySym ch;
+ unsigned int modifier;
int revert;
Window fwin;
int prompt_width = XTextWidth (s->font, prompt, strlen (prompt));
@@ -73,38 +125,49 @@ get_input (screen_info *s, char *prompt, char *str, int len)
XMapWindow (dpy, s->input_window);
XMoveResizeWindow (dpy, s->input_window,
- bar_x (s, width), bar_y (s), width, (FONT_HEIGHT (s->font) + BAR_PADDING * 2));
+ bar_x (s, width), bar_y (s), width,
+ (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2));
XClearWindow (dpy, s->input_window);
XRaiseWindow (dpy, s->input_window);
/* draw the window prompt. */
- XDrawString (dpy, s->input_window, s->bold_gc, 5,
- BAR_PADDING + s->font->max_bounds.ascent, prompt, strlen (prompt));
+ XDrawString (dpy, s->input_window, s->bold_gc, BAR_X_PADDING,
+ BAR_Y_PADDING + s->font->max_bounds.ascent, prompt,
+ strlen (prompt));
XGetInputFocus (dpy, &fwin, &revert);
XSetInputFocus (dpy, s->input_window, RevertToPointerRoot, CurrentTime);
+ /* XSync (dpy, False); */
cur_len = 0;
- while ((ch = read_key ()) != XK_Return)
+
+ read_key (&ch, &modifier);
+ while (ch != XK_Return)
{
- PRINT_DEBUG ("key %d\n", ch);
+ PRINT_DEBUG ("key %ld\n", ch);
if (ch == XK_BackSpace)
{
if (cur_len > 0) cur_len--;
XClearWindow (dpy, s->input_window);
- XDrawString (dpy, s->input_window, s->bold_gc, 5,
- BAR_PADDING + s->font->max_bounds.ascent, prompt, strlen (prompt));
- XDrawString (dpy, s->input_window, s->bold_gc, 5 + prompt_width,
- BAR_PADDING + s->font->max_bounds.ascent, str, cur_len);
+ XDrawString (dpy, s->input_window, s->bold_gc, BAR_X_PADDING,
+ BAR_Y_PADDING + s->font->max_bounds.ascent, prompt,
+ strlen (prompt));
+ XDrawString (dpy, s->input_window, s->bold_gc,
+ BAR_X_PADDING + prompt_width,
+ BAR_Y_PADDING + s->font->max_bounds.ascent, str,
+ cur_len);
}
- else if (!IsModifierKey (ch))
+ else
{
str[cur_len] = ch;
if (cur_len < len - 1) cur_len++;
- XDrawString (dpy, s->input_window, s->bold_gc, 5 + prompt_width,
- BAR_PADDING + s->font->max_bounds.ascent, str, cur_len);
+ XDrawString (dpy, s->input_window, s->bold_gc,
+ BAR_X_PADDING + prompt_width,
+ BAR_Y_PADDING + s->font->max_bounds.ascent, str, cur_len);
}
+
+ read_key (&ch, &modifier);
}
str[cur_len] = 0;
diff --git a/src/input.h b/src/input.h
index b00414d..ef2b4d3 100644
--- a/src/input.h
+++ b/src/input.h
@@ -1,2 +1,4 @@
-void cook_keycode (KeyCode keycode, KeySym *keysym, int *mod);
+char *keysym_to_string (KeySym keysym, unsigned int modifier);
+void cook_keycode (KeyCode keycode, KeySym *keysym, unsigned int *mod);
void get_input (screen_info *s, char *prompt, char *str, int len);
+void read_key (KeySym *keysym, unsigned int *mode);
diff --git a/src/list.c b/src/list.c
index fa06f69..8cdb38a 100644
--- a/src/list.c
+++ b/src/list.c
@@ -154,18 +154,19 @@ find_window_by_name (char *name)
return NULL;
}
-void
+int
goto_window_name (char *name)
{
rp_window *win;
if ((win = find_window_by_name (name)) == NULL)
{
- return;
+ return 0;
}
rp_current_window = win;
set_active_window (rp_current_window);
+ return 1;
}
rp_window *
diff --git a/src/list.h b/src/list.h
index 15b1d98..9004ed7 100644
--- a/src/list.h
+++ b/src/list.h
@@ -31,7 +31,7 @@ void maximize_current_window ();
void set_active_window (rp_window *rp_w);
void set_current_window (rp_window *win);
void goto_window_number (int n);
-void goto_window_name (char *name);
+int goto_window_name (char *name);
rp_window *find_last_accessed_window ();
rp_window *find_window_by_number (int n);
#endif /* _LIST_H */