diff options
author | sabetts <sabetts> | 2001-09-09 02:59:23 +0000 |
---|---|---|
committer | sabetts <sabetts> | 2001-09-09 02:59:23 +0000 |
commit | 1bd2211aa5c392d9873c74ffc998bea744007a29 (patch) | |
tree | b695cac6f169042430a4d7c1a9cc0ac9bda63304 | |
parent | 52cd2d7d10d543fe989e3cde617faf7453dcc494 (diff) | |
download | ratpoison-1bd2211aa5c392d9873c74ffc998bea744007a29.zip |
* src/list.h (update_window_position): new prototype
(window_name): new prototype
(get_window_list): update prototype
* src/events.c (grab_rat): Don't wrap in an #ifdef
(ungrab_rat): likewise
(handle_key): record if the rat is grabbed and only ungrab it at
the end if it was first grabbed.
* src/actions.h (cmd_pos): new prototype
(cmd_defwinpos): new prototype
(cmd_deftranspos): new prototype
(cmd_defmaxsizepos): new prototype
(cmd_defbartimeout): new prototype
(cmd_defbarloc): new prototype
(cmd_deffont): new prototype
(cmd_defpadding): new prototype
(cmd_defborder): new prototype
(cmd_definputwidth): new prototype
(cmd_defwaitcursor): new prototype
(cmd_defwinfmt): new prototype
(cmd_defwinname): new prototype
* src/messages.h (MESSAGE_FRAME_STRING): new message
* src/manage.c (get_wmname): renamed from get_window_name
(get_class_hints): new function
(get_res_name): likewise
(get_res_class): likewise
(update_window_name): update the window's wm_name, res_name, and
res_class fields.
(update_window_name): calls functions get_wmname, get_res_name,
get_res_class.
(update_window_name): Don't crop the window name.
(update_window_information): call update_window_position.
(move_window): new function
(maximize_transient): only set the window's width and height
fields.
(maximize_normal): likewise
(maximize): call move_window
(force_maximize): likewise
(force_maximize): if the window has resize hints, resize it 1
resize unit.
* src/main.c: new global variable, defaults. remove static
variable, font, and move to defaults. Dependant code updated.
(init_defaults): new function
(main): call init_defaults.
(init_screen): initialize the screen's fg_color to black and
bg_color to white.
* src/list.c (free_window): free the fields user_name, res_name,
res_class, and wm_name.
(update_window_position): new function
(window_name): new function. Code accessing a window's name uses
this function. All code updated.
(add_to_window_list): call update_window_position
(add_to_window_list): initialize wm_name, res_name, and res_class
for the new window.
(format_window_name): new function
(get_window_list): Add parameter fmt. All callers updated.
(get_window_list): call format_window_name.
* src/conf.h: move Configuration variables to the global variable,
defaults. Dependant code updated.
* src/data.h (TOP_LEFT): new define
(TOP_CENTER): likewise
(TOP_RIGHT): likewise
(CENTER_LEFT): likewise
(CENTER_CENTER): likewise
(CENTER_RIGHT): likewise
(BOTTOM_LEFT): likewise
(BOTTOM_CENTER): likewise
(BOTTOM_RIGHT): likewise
(struct rp_window): new fields user_name, wm_name, res_name,
res_class, position.
(struct rp_window): remove field name. Replaced with
user_name. Dependant code updated.
(struct screen_info): remove field font. dependant code updated.
(struct screen_info): new fields fg_color, bg_color.
(struct rp_defaults): new struct
(defaults): new global
* src/actions.c (parse_winpos): new function
(cmd_pos): likewise
(cmd_defwinpos): likewise
(cmd_deftranspos): likewise
(cmd_defmaxsizepos): likewise
(cmd_defbartimeout): likewise
(cmd_defbarloc): likewise
(cmd_deffont): likewise
(cmd_defpadding): likewise
(cmd_defborder): likewise
(cmd_definputwidth): likewise
(cmd_defwaitcursor): likewise
(cmd_defwinfmt): likewise
(cmd_defwinname): likewise
(user_commands): New commands defbarloc, defbartimeout, defborder,
deffont, defintputwidth, defmaxsizepos, defpadding, deftranspos,
defwaitcursor, defwinfmt, defwinname, defwinpos.
-rw-r--r-- | ChangeLog | 104 | ||||
-rw-r--r-- | NEWS | 23 | ||||
-rw-r--r-- | src/actions.c | 535 | ||||
-rw-r--r-- | src/actions.h | 13 | ||||
-rw-r--r-- | src/bar.c | 32 | ||||
-rw-r--r-- | src/conf.h | 51 | ||||
-rw-r--r-- | src/data.h | 61 | ||||
-rw-r--r-- | src/events.c | 36 | ||||
-rw-r--r-- | src/input.c | 20 | ||||
-rw-r--r-- | src/list.c | 137 | ||||
-rw-r--r-- | src/list.h | 5 | ||||
-rw-r--r-- | src/main.c | 85 | ||||
-rw-r--r-- | src/manage.c | 246 | ||||
-rw-r--r-- | src/messages.h | 29 | ||||
-rw-r--r-- | src/split.c | 20 |
15 files changed, 1076 insertions, 321 deletions
@@ -1,3 +1,107 @@ +2001-09-08 shawn <sabetts@diggin.lamenet.tmp> + + * src/list.h (update_window_position): new prototype + (window_name): new prototype + (get_window_list): update prototype + + * src/events.c (grab_rat): Don't wrap in an #ifdef + (ungrab_rat): likewise + (handle_key): record if the rat is grabbed and only ungrab it at + the end if it was first grabbed. + + * src/actions.h (cmd_pos): new prototype + (cmd_defwinpos): new prototype + (cmd_deftranspos): new prototype + (cmd_defmaxsizepos): new prototype + (cmd_defbartimeout): new prototype + (cmd_defbarloc): new prototype + (cmd_deffont): new prototype + (cmd_defpadding): new prototype + (cmd_defborder): new prototype + (cmd_definputwidth): new prototype + (cmd_defwaitcursor): new prototype + (cmd_defwinfmt): new prototype + (cmd_defwinname): new prototype + + * src/messages.h (MESSAGE_FRAME_STRING): new message + + * src/manage.c (get_wmname): renamed from get_window_name + (get_class_hints): new function + (get_res_name): likewise + (get_res_class): likewise + (update_window_name): update the window's wm_name, res_name, and + res_class fields. + (update_window_name): calls functions get_wmname, get_res_name, + get_res_class. + (update_window_name): Don't crop the window name. + (update_window_information): call update_window_position. + (move_window): new function + (maximize_transient): only set the window's width and height + fields. + (maximize_normal): likewise + (maximize): call move_window + (force_maximize): likewise + (force_maximize): if the window has resize hints, resize it 1 + resize unit. + + * src/main.c: new global variable, defaults. remove static + variable, font, and move to defaults. Dependant code updated. + (init_defaults): new function + (main): call init_defaults. + (init_screen): initialize the screen's fg_color to black and + bg_color to white. + + * src/list.c (free_window): free the fields user_name, res_name, + res_class, and wm_name. + (update_window_position): new function + (window_name): new function. Code accessing a window's name uses + this function. All code updated. + (add_to_window_list): call update_window_position + (add_to_window_list): initialize wm_name, res_name, and res_class + for the new window. + (format_window_name): new function + (get_window_list): Add parameter fmt. All callers updated. + (get_window_list): call format_window_name. + + * src/conf.h: move Configuration variables to the global variable, + defaults. Dependant code updated. + + * src/data.h (TOP_LEFT): new define + (TOP_CENTER): likewise + (TOP_RIGHT): likewise + (CENTER_LEFT): likewise + (CENTER_CENTER): likewise + (CENTER_RIGHT): likewise + (BOTTOM_LEFT): likewise + (BOTTOM_CENTER): likewise + (BOTTOM_RIGHT): likewise + (struct rp_window): new fields user_name, wm_name, res_name, + res_class, position. + (struct rp_window): remove field name. Replaced with + user_name. Dependant code updated. + (struct screen_info): remove field font. dependant code updated. + (struct screen_info): new fields fg_color, bg_color. + (struct rp_defaults): new struct + (defaults): new global + + * src/actions.c (parse_winpos): new function + (cmd_pos): likewise + (cmd_defwinpos): likewise + (cmd_deftranspos): likewise + (cmd_defmaxsizepos): likewise + (cmd_defbartimeout): likewise + (cmd_defbarloc): likewise + (cmd_deffont): likewise + (cmd_defpadding): likewise + (cmd_defborder): likewise + (cmd_definputwidth): likewise + (cmd_defwaitcursor): likewise + (cmd_defwinfmt): likewise + (cmd_defwinname): likewise + (user_commands): New commands defbarloc, defbartimeout, defborder, + deffont, defintputwidth, defmaxsizepos, defpadding, deftranspos, + defwaitcursor, defwinfmt, defwinname, defwinpos. + 2001-09-06 shawn <sabetts@diggin.lamenet.tmp> * configure.in: Use AC_CHECK_FUNCS to check for getopt and @@ -1,5 +1,28 @@ ratpoison NEWS --- history of user-visible changes. -*- outline -*- +* Changes since 1.0.0 +** conf.h compile-time customizations moved +They are now accessible through the def* suite of commands. + +** Window alignment +Windows can now be aligned so they stick to the top-left corner of the +screen, the center of the screen, the bottom-right, etc. Use the `pos' +command. There is a customizable default setting for each of the three +'kinds' of windows: `defwinpos' for normal windows, `deftranspos' for +transient windows, and `defmaxsizepos' for normal windows with +maximimum size hints. + +** Window format string +The format of the list of windows dumped by the `windows' command is +now customizable with `defwinfmt'. + +** Different Window naming schemes +Windows now have 3 resources that can be used as their default name: +the WMNAME hint which generally contains transient information such as +what file is currently open, the res_name from the WMCLASS hint, or +the res_class the WMCLASS hint. This affects commands like `select' +which search for a window by name. + * Changes since 0.1.1 ** new conf.h customization MAXSIZE_WINDOWS_ARE_TRANSIENTS diff --git a/src/actions.c b/src/actions.c index 74196d5..1d3509e 100644 --- a/src/actions.c +++ b/src/actions.c @@ -30,6 +30,84 @@ static rp_action *key_actions; static int key_actions_last; static int key_actions_table_size; +static user_command user_commands[] = + { {"abort", cmd_abort, arg_VOID}, + {"banish", cmd_banish, arg_VOID}, + {"bind", cmd_bind, arg_VOID}, + {"clock", cmd_clock, arg_VOID}, + {"colon", cmd_colon, arg_STRING}, + {"curframe", cmd_curframe, arg_VOID}, + {"delete", cmd_delete, arg_VOID}, + {"echo", cmd_echo, arg_STRING}, + {"escape", cmd_escape, arg_STRING}, + {"exec", cmd_exec, arg_STRING}, + {"focus", cmd_next_frame, arg_VOID}, + {"generate", cmd_generate, arg_STRING}, /* rename to stuff */ + {"help", cmd_help, arg_VOID}, + {"hsplit", cmd_h_split, arg_VOID}, + {"kill", cmd_kill, arg_VOID}, + {"maximize", cmd_maximize, arg_VOID}, + {"newwm", cmd_newwm, arg_STRING}, + {"next", cmd_next, arg_VOID}, + {"number", cmd_number, arg_STRING}, + {"only", cmd_only, arg_VOID}, + {"other", cmd_other, arg_VOID}, + {"pos", cmd_pos, arg_STRING}, + {"prev", cmd_prev, arg_VOID}, + {"quit", cmd_quit, arg_VOID}, + {"remove", cmd_remove, arg_VOID}, + {"rudeness", cmd_rudeness, arg_STRING}, + {"select", cmd_select, arg_STRING}, + {"source", cmd_source, arg_STRING}, + {"split", cmd_h_split, arg_VOID}, + {"title", cmd_rename, arg_STRING}, + {"unbind", cmd_unbind, arg_STRING}, + {"version", cmd_version, arg_VOID}, + {"vsplit", cmd_v_split, arg_VOID}, + {"windows", cmd_windows, arg_VOID}, + + /* Commands to set default behavior. */ + {"defbarloc", cmd_defbarloc, arg_STRING}, + {"defbartimeout", cmd_defbartimeout, arg_STRING}, + {"defborder", cmd_defborder, arg_STRING}, + {"deffont", cmd_deffont, arg_STRING}, + {"definputwidth", cmd_definputwidth, arg_STRING}, + {"defmaxsizepos", cmd_defmaxsizepos, arg_STRING}, + {"defpadding", cmd_defpadding, arg_STRING}, + {"deftranspos", cmd_deftranspos, arg_STRING}, + {"defwaitcursor", cmd_defwaitcursor, arg_STRING}, + {"defwinfmt", cmd_defwinfmt, arg_STRING}, + {"defwinname", cmd_defwinname, arg_STRING}, + {"defwinpos", cmd_defwinpos, arg_STRING}, + + /* Commands to help debug ratpoison. */ +#ifdef DEBUG +#endif + + /* the following screen commands may or may not be able to be + implemented. See the screen documentation for what should be + emulated with these commands */ +#if 0 + {"hardcopy", cmd_unimplemented, arg_VOID}, + {"lastmsg", cmd_unimplemented, arg_VOID}, + {"license", cmd_unimplemented, arg_VOID}, + {"lockscreen", cmd_unimplemented, arg_VOID}, + {"meta", cmd_unimplemented, arg_VOID}, + {"msgminwait", cmd_unimplemented, arg_VOID}, + {"msgwait", cmd_unimplemented, arg_VOID}, + {"nethack", cmd_unimplemented, arg_VOID}, + {"redisplay", cmd_unimplemented, arg_VOID}, + {"screen", cmd_unimplemented, arg_VOID}, + {"setenv", cmd_unimplemented, arg_VOID}, + {"shell", cmd_unimplemented, arg_VOID}, + {"shelltitle", cmd_unimplemented, arg_VOID}, + {"sleep", cmd_unimplemented, arg_VOID}, + {"sorendition", cmd_unimplemented, arg_VOID}, + {"startup_message", cmd_unimplemented, arg_VOID}, + {"stuff", cmd_unimplemented, arg_VOID}, +#endif + {0, 0, 0} }; + rp_action* find_keybinding_by_action (char *action) { @@ -184,65 +262,6 @@ initialize_default_keybindings (void) add_keybinding (XK_question, 0, "help"); } -user_command user_commands[] = - { {"abort", cmd_abort, arg_VOID}, - {"next", cmd_next, arg_VOID}, - {"prev", cmd_prev, arg_VOID}, - {"exec", cmd_exec, arg_STRING}, - {"select", cmd_select, arg_STRING}, - {"colon", cmd_colon, arg_STRING}, - {"kill", cmd_kill, arg_VOID}, - {"delete", cmd_delete, arg_VOID}, - {"other", cmd_other, arg_VOID}, - {"windows", cmd_windows, arg_VOID}, - {"title", cmd_rename, arg_STRING}, - {"clock", cmd_clock, arg_VOID}, - {"maximize", cmd_maximize, arg_VOID}, - {"newwm", cmd_newwm, arg_STRING}, - {"generate", cmd_generate, arg_STRING}, /* rename to stuff */ - {"version", cmd_version, arg_VOID}, - {"bind", cmd_bind, arg_VOID}, - {"unbind", cmd_unbind, arg_STRING}, - {"source", cmd_source, arg_STRING}, - {"escape", cmd_escape, arg_STRING}, - {"echo", cmd_echo, arg_STRING}, - {"split", cmd_h_split, arg_VOID}, - {"hsplit", cmd_h_split, arg_VOID}, - {"vsplit", cmd_v_split, arg_VOID}, - {"focus", cmd_next_frame, arg_VOID}, - {"only", cmd_only, arg_VOID}, - {"remove", cmd_remove, arg_VOID}, - {"banish", cmd_banish, arg_VOID}, - {"curframe", cmd_curframe, arg_VOID}, - {"help", cmd_help, arg_VOID}, - {"quit", cmd_quit, arg_VOID}, - {"number", cmd_number, arg_STRING}, - {"rudeness", cmd_rudeness, arg_STRING}, - - /* the following screen commands may or may not be able to be - implemented. See the screen documentation for what should be - emulated with these commands */ -#if 0 - {"stuff", cmd_unimplemented, arg_VOID}, - {"hardcopy", cmd_unimplemented, arg_VOID}, - {"lastmsg", cmd_unimplemented, arg_VOID}, - {"license", cmd_unimplemented, arg_VOID}, - {"lockscreen", cmd_unimplemented, arg_VOID}, - {"meta", cmd_unimplemented, arg_VOID}, - {"msgwait", cmd_unimplemented, arg_VOID}, - {"msgminwait", cmd_unimplemented, arg_VOID}, - {"nethack", cmd_unimplemented, arg_VOID}, - {"redisplay", cmd_unimplemented, arg_VOID}, - {"screen", cmd_unimplemented, arg_VOID}, - {"setenv", cmd_unimplemented, arg_VOID}, - {"shell", cmd_unimplemented, arg_VOID}, - {"shelltitle", cmd_unimplemented, arg_VOID}, - {"sleep", cmd_unimplemented, arg_VOID}, - {"sorendition", cmd_unimplemented, arg_VOID}, - {"startup_message", cmd_unimplemented, arg_VOID}, -#endif - {0, 0, 0} }; - /* return a KeySym from a string that contains either a hex value or an X keysym description */ static int string_to_keysym (char *str) @@ -680,10 +699,10 @@ cmd_rename (int interactive, void *data) if (*winname) { - free (current_window()->name); - current_window()->name = xmalloc (sizeof (char) * strlen (winname) + 1); + free (current_window()->user_name); + current_window()->user_name = xmalloc (sizeof (char) * strlen (winname) + 1); - strcpy (current_window()->name, winname); + strcpy (current_window()->user_name, winname); current_window()->named = 1; @@ -987,7 +1006,7 @@ cmd_windows (int interactive, void *data) else { window_list = sbuf_new (0); - get_window_list ("\n", window_list, &dummy, &dummy); + get_window_list (defaults.window_fmt, "\n", window_list, &dummy, &dummy); tmp = sbuf_get (window_list); free (window_list); @@ -1153,23 +1172,23 @@ cmd_help (int interactive, void *data) XSetInputFocus (dpy, s->help_window, RevertToPointerRoot, CurrentTime); XDrawString (dpy, s->help_window, s->normal_gc, - 10, y + s->font->max_bounds.ascent, + 10, y + defaults.font->max_bounds.ascent, "ratpoison key bindings", strlen ("ratpoison key bindings")); - y += FONT_HEIGHT (s->font) * 2; + y += FONT_HEIGHT (defaults.font) * 2; XDrawString (dpy, s->help_window, s->normal_gc, - 10, y + s->font->max_bounds.ascent, + 10, y + defaults.font->max_bounds.ascent, "Command key: ", strlen ("Command key: ")); keysym_name = keysym_to_string (prefix_key.sym, prefix_key.state); XDrawString (dpy, s->help_window, s->normal_gc, - 10 + XTextWidth (s->font, "Command key: ", strlen ("Command key: ")), - y + s->font->max_bounds.ascent, + 10 + XTextWidth (defaults.font, "Command key: ", strlen ("Command key: ")), + y + defaults.font->max_bounds.ascent, keysym_name, strlen (keysym_name)); free (keysym_name); - y += FONT_HEIGHT (s->font) * 2; + y += FONT_HEIGHT (defaults.font) * 2; i = 0; old_i = 0; @@ -1180,12 +1199,12 @@ cmd_help (int interactive, void *data) keysym_name = keysym_to_string (key_actions[i].key, key_actions[i].state); XDrawString (dpy, s->help_window, s->normal_gc, - x, y + s->font->max_bounds.ascent, + x, y + defaults.font->max_bounds.ascent, keysym_name, strlen (keysym_name)); - if (XTextWidth (s->font, keysym_name, strlen (keysym_name)) > max_width) + if (XTextWidth (defaults.font, keysym_name, strlen (keysym_name)) > max_width) { - max_width = XTextWidth (s->font, keysym_name, strlen (keysym_name)); + max_width = XTextWidth (defaults.font, keysym_name, strlen (keysym_name)); } free (keysym_name); @@ -1193,16 +1212,16 @@ cmd_help (int interactive, void *data) else { XDrawString (dpy, s->help_window, s->normal_gc, - x, y + s->font->max_bounds.ascent, + x, y + defaults.font->max_bounds.ascent, key_actions[i].data, strlen (key_actions[i].data)); - if (XTextWidth (s->font, key_actions[i].data, strlen (key_actions[i].data)) > max_width) + if (XTextWidth (defaults.font, key_actions[i].data, strlen (key_actions[i].data)) > max_width) { - max_width = XTextWidth (s->font, key_actions[i].data, strlen (key_actions[i].data)); + max_width = XTextWidth (defaults.font, key_actions[i].data, strlen (key_actions[i].data)); } } - y += FONT_HEIGHT (s->font); + y += FONT_HEIGHT (defaults.font); if (y > s->root_attr.height) { if (drawing_keys) @@ -1219,7 +1238,7 @@ cmd_help (int interactive, void *data) } max_width = 0; - y = FONT_HEIGHT (s->font) * 4; + y = FONT_HEIGHT (defaults.font) * 4; } else { @@ -1228,7 +1247,7 @@ cmd_help (int interactive, void *data) { x += max_width + 10; drawing_keys = 0; - y = FONT_HEIGHT (s->font) * 4; + y = FONT_HEIGHT (defaults.font) * 4; i = old_i; max_width = 0; } @@ -1266,3 +1285,363 @@ cmd_rudeness (int interactive, void *data) return NULL; } + +static int +parse_winpos (char *data) +{ + int ret = 0; + char *x, *y; + + x = xmalloc (strlen (data) + 1); + y = xmalloc (strlen (data) + 1); + + if (sscanf (data, "%s %s", x , y) < 2) + { + message (" pos: Two arguments needed "); + free (x); + free (y); + return -3; + } + + PRINT_DEBUG ("%s %s\n", x, y); + + switch (y[0]) + { + case 't': + case 'T': + ret = TOP_LEFT; + break; + + case 'c': + case 'C': + ret = CENTER_LEFT; + break; + + case 'b': + case 'B': + ret = BOTTOM_LEFT; + break; + + default: + ret = -1; + goto done; + break; + } + + switch (x[0]) + { + case 'l': + case 'L': + break; + + case 'c': + case 'C': + ret += TOP_CENTER; + break; + + case 'r': + case 'R': + ret += TOP_RIGHT; + break; + + default: + ret = -2; + goto done; + break; + } + + done: + free (x); + free (y); + + return ret; +} + +char * +cmd_pos (int interactive, void *data) +{ + int pos; + rp_window *win; + + if (current_window() == NULL) return NULL; + if (data == NULL) + { + message (" pos: Two arguments needed "); + return NULL; + } + + win = current_window(); + + if ((pos = parse_winpos (data)) < 0) + { + message (" pos: Unknown position "); + } + else + { + win->position = pos; + maximize (win); + } + + return NULL; +} + +char * +cmd_defwinpos (int interactive, void *data) +{ + int pos; + + if ((pos = parse_winpos (data)) < 0) + { + message (" pos: Unknown position "); + } + else + { + defaults.win_pos = pos; + } + + return NULL; +} + +char * +cmd_deftranspos (int interactive, void *data) +{ + int pos; + + if ((pos = parse_winpos (data)) < 0) + { + message (" pos: Unknown position "); + } + else + { + defaults.trans_pos = pos; + } + + return NULL; +} + +char * +cmd_defmaxsizepos (int interactive, void *data) +{ + int pos; + + if ((pos = parse_winpos (data)) < 0) + { + message (" pos: Unknown position "); + } + else + { + defaults.maxsize_pos = pos; + } + + return NULL; +} + +char * +cmd_defbartimeout (int interactive, void *data) +{ + if (data == NULL) return NULL; + + if (sscanf (data, "%d", &defaults.bar_timeout) < 1) + { + message (" defbartimeout: One argument required "); + } + + return NULL; +} + +char * +cmd_defbarloc (int interactive, void *data) +{ + int loc; + + if (data == NULL) return NULL; + + if (sscanf (data, "%d", &loc) < 1) + { + message (" defbarloc: One argument required "); + return NULL; + } + + switch (loc) + { + case 0: + defaults.bar_location = TOP_LEFT; + break; + case 1: + defaults.bar_location = TOP_RIGHT; + break; + case 2: + defaults.bar_location = BOTTOM_RIGHT; + break; + case 3: + defaults.bar_location = BOTTOM_LEFT; + break; + + default: + message (" defbarloc: Unknown location "); + break; + } + + return NULL; +} + +char * +cmd_deffont (int interactive, void *data) +{ + XFontStruct *font; + + if (data == NULL) return NULL; + + font = XLoadQueryFont (dpy, (char *)data); + if (font == NULL) + { + message (" deffont: Unknown font "); + return NULL; + } + + /* Save the font as the default. */ + XFreeFont (dpy, defaults.font); + defaults.font = font; + + return NULL; +} + +char * +cmd_defpadding (int interactive, void *data) +{ + rp_window_frame *frame; + int l, t, r, b; + + if (data == NULL) + { + message (" defpadding: Four arguments required "); + return NULL; + } + + if (sscanf (data, "%d %d %d %d", &l, &t, &r, &b) < 4) + { + message (" defpadding: Four arguments required "); + return NULL; + } + + /* Resize the frames to make sure they are not too big and not too + small. */ + for (frame = rp_window_frame_sentinel->next; + frame != rp_window_frame_sentinel; + frame = frame->next) + { + int bk_pos, bk_len; + + /* Resize horizontally. */ + bk_pos = frame->x; + bk_len = frame->width; + + if (frame->x == defaults.padding_left) + { + frame->x = l; + frame->width += bk_pos - l; + } + + if (bk_pos + bk_len == current_screen()->root_attr.width - defaults.padding_right) + frame->width = current_screen()->root_attr.width - r - frame->x; + + /* Resize vertically. */ + bk_pos = frame->y; + bk_len = frame->height; + + if (frame->y == defaults.padding_top) + { + frame->y = t; + frame->height += bk_pos - t; + } + + if (bk_pos + bk_len == current_screen()->root_attr.height - defaults.padding_bottom) + frame->height = current_screen()->root_attr.height - b - frame->y; + + maximize_all_windows_in_frame (frame); + } + + defaults.padding_left = l; + defaults.padding_right = r; + defaults.padding_top = t; + defaults.padding_bottom = b; + + return NULL; +} + +char * +cmd_defborder (int interactive, void *data) +{ + rp_window *win; + + if (data == NULL) return NULL; + + if (sscanf (data, "%d", &defaults.window_border_width) < 1) + { + message (" defborder: One argument required "); + } + + /* Update all the visible windows. */ + for (win = rp_mapped_window_sentinel->next; + win != rp_mapped_window_sentinel; + win = win->next) + { + if (win->frame) + maximize (win); + } + + return NULL; +} + +char * +cmd_definputwidth (int interactive, void *data) +{ + if (data == NULL + || sscanf (data, "%d", &defaults.input_window_size) < 1) + { + message (" definputwidth: One argument required "); + } + + return NULL; +} + +char * +cmd_defwaitcursor (int interactive, void *data) +{ + if (data == NULL + || sscanf (data, "%d", &defaults.wait_for_key_cursor) < 1) + { + message (" defwaitforkey: One argument required "); + } + + return NULL; +} + +char * +cmd_defwinfmt (int interactive, void *data) +{ + if (data == NULL) return NULL; + + free (defaults.window_fmt); + defaults.window_fmt = strdup (data); + + if (defaults.window_fmt == NULL) + { + PRINT_ERROR ("Not enough memory\n"); + exit (EXIT_FAILURE); + } + + return NULL; +} + +char * +cmd_defwinname (int interactive, void *data) +{ + if (data == NULL + || sscanf (data, "%d", &defaults.win_name) < 1) + { + message (" defwinname: One argument required "); + } + + return NULL; +} diff --git a/src/actions.h b/src/actions.h index 4c0f777..1834fc0 100644 --- a/src/actions.h +++ b/src/actions.h @@ -75,6 +75,19 @@ char * cmd_quit(int interactive, void *data); char * cmd_number (int interactive, void *data); char * cmd_rudeness (int interactive, void *data); char * cmd_unbind (int interactive, void *data); +char * cmd_pos (int interactive, void *data); +char * cmd_defwinpos (int interactive, void *data); +char * cmd_deftranspos (int interactive, void *data); +char * cmd_defmaxsizepos (int interactive, void *data); +char * cmd_defbartimeout (int interactive, void *data); +char * cmd_defbarloc (int interactive, void *data); +char * cmd_deffont (int interactive, void *data); +char * cmd_defpadding (int interactive, void *data); +char * cmd_defborder (int interactive, void *data); +char * cmd_definputwidth (int interactive, void *data); +char * cmd_defwaitcursor (int interactive, void *data); +char * cmd_defwinfmt (int interactive, void *data); +char * cmd_defwinname (int interactive, void *data); /* void cmd_xterm (void *data); */ @@ -64,7 +64,7 @@ show_bar (screen_info *s) update_window_names (s); /* Set an alarm to auto-hide the bar BAR_TIMEOUT seconds later */ - alarm (BAR_TIMEOUT); + alarm (defaults.bar_timeout); alarm_signalled = 0; return 1; } @@ -78,15 +78,21 @@ show_bar (screen_info *s) int bar_x (screen_info *s, int width) { - if (BAR_LOCATION >= 2) return s->root_attr.width - width - 2; - else return 0; + if (defaults.bar_location == BOTTOM_RIGHT + || defaults.bar_location == TOP_RIGHT) + return s->root_attr.width - width - 2; + else + return 0; } int bar_y (screen_info *s) { - if (BAR_LOCATION % 2) return 0; - else return s->root_attr.height - (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2) - 2; + if (defaults.bar_location == TOP_LEFT + || defaults.bar_location == TOP_RIGHT ) + return 0; + else + return s->root_attr.height - (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2) - 2; } void @@ -102,7 +108,7 @@ update_window_names (screen_info *s) if (bar_buffer == NULL) bar_buffer = sbuf_new (0); - get_window_list (NULL, bar_buffer, &mark_start, &mark_end); + get_window_list (defaults.window_fmt, NULL, bar_buffer, &mark_start, &mark_end); marked_message (sbuf_get (bar_buffer), mark_start, mark_end); } @@ -141,8 +147,8 @@ marked_message (char *msg, int mark_start, int mark_end) unsigned long mask; screen_info *s = current_screen (); - int width = BAR_X_PADDING * 2 + XTextWidth (s->font, msg, strlen (msg)); - int height = (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2); + int width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, msg, strlen (msg)); + int height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2); PRINT_DEBUG ("%s\n", msg); @@ -154,7 +160,7 @@ marked_message (char *msg, int mark_start, int mark_end) } /* Reset the alarm to auto-hide the bar in BAR_TIMEOUT seconds. */ - alarm (BAR_TIMEOUT); + alarm (defaults.bar_timeout); alarm_signalled = 0; XMoveResizeWindow (dpy, s->bar_window, @@ -166,8 +172,8 @@ marked_message (char *msg, int mark_start, int mark_end) XRaiseWindow (dpy, s->bar_window); XDrawString (dpy, s->bar_window, s->normal_gc, - BAR_X_PADDING, - BAR_Y_PADDING + s->font->max_bounds.ascent, + defaults.bar_x_padding, + defaults.bar_y_padding + defaults.font->max_bounds.ascent, msg, strlen (msg)); @@ -198,8 +204,8 @@ marked_message (char *msg, int mark_start, int mark_end) int start; int end; - start = XTextWidth (s->font, msg, mark_start) + BAR_X_PADDING; - end = XTextWidth (s->font, msg + mark_start, mark_end - mark_start) + BAR_X_PADDING; + start = XTextWidth (defaults.font, msg, mark_start) + defaults.bar_x_padding; + end = XTextWidth (defaults.font, msg + mark_start, mark_end - mark_start) + defaults.bar_x_padding; PRINT_DEBUG ("%d %d strlen(%d)==> %d %d\n", mark_start, mark_end, strlen(msg), start, end); @@ -32,56 +32,10 @@ #define INPUT_ABORT_KEY XK_g #define INPUT_ABORT_MODIFIER ControlMask -/* After hitting the prefix key ratpoison will change the mouse cursor - to a square to indicate that it is waiting for a second - keystroke. If do not wish this functionality, comment out the - following line. */ -#define USE_WAITFORKEY_CURSOR - -/* Quit ratpoison when there are no more managed windows. */ -/* #define AUTO_CLOSE */ - -/* Treat windows with maxsize hints as if they were a transient window - (don't hide the windows underneath, and center them) */ -#define MAXSIZE_WINDOWS_ARE_TRANSIENTS - -/* The minimum size of the input window */ -#define INPUT_WINDOW_SIZE 200 - -/* If you want the input window to take up the length of the screen, - use this: */ -/* #define INPUT_WINDOW_SIZE (s->root_attr.width - prompt_width) */ - - -/* The border width ratpoison configures all windows with */ -#define WINDOW_BORDER_WIDTH 1 - /* Pressing a key sends the mouse to the bottom right corner. This doesn't work very well yet. */ /* #define HIDE_MOUSE */ -#define FOREGROUND "black" -#define BACKGROUND "white" -#define FONT "9x15bold" - -#define BAR_Y_PADDING 0 /* The amount of padding on the top - and bottom of the message bar */ -#define BAR_X_PADDING 0 /* 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 */ - -/* Number of seconds before the frame indicator disappears */ -#define FRAME_INDICATOR_TIMEOUT 1 - -/* What to display in the frame indicator */ -#define FRAME_STRING "Current Frame" - -#define PADDING_LEFT 0 /* space not to be taken up around managed windows */ -#define PADDING_TOP 0 -#define PADDING_RIGHT 0 -#define PADDING_BOTTOM 0 - /* If for some sick reason you don't want ratpoison to manage a window, put its name in this list. These windows get drawn but ratpoison won't have any knowledge of them and you won't be able to @@ -89,9 +43,4 @@ mostly for use with hand-helds. */ #define UNMANAGED_WINDOW_LIST "xapm","xclock","xscribble" -#define RAT_WIDTH 16 -#define RAT_HEIGHT 16 -#define RAT_HOT_X 8 -#define RAT_HOT_Y 8 - #endif /* !_ _RATPOISON_CONF_H */ @@ -44,15 +44,33 @@ struct rp_window_frame }; +/* Possible positions for a window. */ +#define TOP_LEFT 0 +#define TOP_CENTER 1 +#define TOP_RIGHT 2 + +#define CENTER_LEFT 3 +#define CENTER_CENTER 4 +#define CENTER_RIGHT 5 + +#define BOTTOM_LEFT 6 +#define BOTTOM_CENTER 7 +#define BOTTOM_RIGHT 8 + struct rp_window { screen_info *scr; Window w; int number; - char *name; int state; int last_access; int named; + + /* Window name hints. */ + char *user_name; + char *wm_name; + char *res_name; + char *res_class; /* Dimensions */ int x, y, width, height, border; @@ -70,6 +88,10 @@ struct rp_window /* Saved mouse position */ int mouse_x, mouse_y; + /* The alignment of the window. To what side or corner should the + window stick to. */ + int position; + /* A window can be visible inside a frame but not the frame's current window. This keeps track of what frame the window was mapped into. */ @@ -81,13 +103,13 @@ struct rp_window struct screen_info { GC normal_gc; - XFontStruct *font; /* The font we want to use. */ XWindowAttributes root_attr; Window root, bar_window, key_window, input_window, frame_window, help_window; int bar_is_raised; int screen_num; /* Our screen number as dictated my X */ Colormap def_cmap; Cursor rat; + unsigned long fg_color, bg_color; /* The pixel color. */ }; struct rp_action @@ -104,6 +126,41 @@ struct rp_key unsigned int state; }; +struct rp_defaults +{ + /* Default positions for new normal windows, transient windows, and + normal windows with maxsize hints. */ + int win_pos; + int trans_pos; + int maxsize_pos; + + int input_window_size; + int window_border_width; + + int bar_x_padding; + int bar_y_padding; + int bar_location; + int bar_timeout; + + int frame_indicator_timeout; + + int padding_left; + int padding_right; + int padding_top; + int padding_bottom; + + XFontStruct *font; + + int wait_for_key_cursor; + + char *window_fmt; + + /* Which name to use: wm_name, res_name, res_class. */ + int win_name; +}; + +extern struct rp_defaults defaults; + /* The prefix key also known as the command character under screen. */ extern struct rp_key prefix_key; diff --git a/src/events.c b/src/events.c index 98ffa11..bcf1631 100644 --- a/src/events.c +++ b/src/events.c @@ -112,11 +112,11 @@ unmap_notify (XEvent *ev) switch (win->state) { case IconicState: - PRINT_DEBUG ("Withdrawing iconized window '%s'\n", win->name); + PRINT_DEBUG ("Withdrawing iconized window '%s'\n", window_name (win)); if (ev->xunmap.send_event) withdraw_window (win); break; case NormalState: - PRINT_DEBUG ("Withdrawing normal window '%s'\n", win->name); + PRINT_DEBUG ("Withdrawing normal window '%s'\n", window_name (win)); /* If the window was inside a frame, fill the frame with another window. */ frame = find_windows_frame (win); @@ -182,10 +182,10 @@ map_request (XEvent *ev) { if (win->transient) marked_message_printf (0, 0, MESSAGE_RAISE_TRANSIENT, - win->number, win->name); + win->number, window_name (win)); else marked_message_printf (0, 0, MESSAGE_RAISE_WINDOW, - win->number, win->name); + win->number, window_name (win)); } } break; @@ -223,7 +223,7 @@ configure_notify (XConfigureEvent *e) win = find_window (e->window); if (win) { - PRINT_DEBUG ("'%s' window notify: %d %d %d %d %d\n", win->name, + PRINT_DEBUG ("'%s' window notify: %d %d %d %d %d\n", window_name (win), e->x, e->y, e->width, e->height, e->border_width); } } @@ -269,10 +269,10 @@ configure_request (XConfigureRequestEvent *e) { if (win->transient) marked_message_printf (0, 0, MESSAGE_RAISE_TRANSIENT, - win->number, win->name); + win->number, window_name (win)); else marked_message_printf (0, 0, MESSAGE_RAISE_WINDOW, - win->number, win->name); + win->number, window_name (win)); } } else @@ -285,7 +285,7 @@ configure_request (XConfigureRequestEvent *e) PRINT_DEBUG("request CWStackMode %d\n", e->detail); } - PRINT_DEBUG ("'%s' window size: %d %d %d %d %d\n", win->name, + PRINT_DEBUG ("'%s' window size: %d %d %d %d %d\n", window_name (win), win->x, win->y, win->width, win->height, win->border); if (e->value_mask & CWBorderWidth) @@ -368,7 +368,6 @@ client_msg (XClientMessageEvent *ev) } } -#ifdef USE_WAITFORKEY_CURSOR static void grab_rat () { @@ -376,15 +375,12 @@ grab_rat () GrabModeAsync, GrabModeAsync, None, current_screen()->rat, CurrentTime); } -#endif -#ifdef USE_WAITFORKEY_CURSOR static void ungrab_rat () { XUngrabPointer (dpy, CurrentTime); } -#endif static void handle_key (screen_info *s) @@ -395,11 +391,12 @@ handle_key (screen_info *s) Window fwin; /* Window currently in focus */ KeySym keysym; /* Key pressed */ unsigned int mod; /* Modifiers */ + int rat_grabbed = 0; PRINT_DEBUG ("handling key...\n"); /* All functions hide the program bar and the frame indicator. */ - if (BAR_TIMEOUT > 0) hide_bar (s); + if (defaults.bar_timeout > 0) hide_bar (s); hide_frame_indicator(); /* Disable any alarm that was going to go off. */ @@ -411,9 +408,11 @@ handle_key (screen_info *s) /* Change the mouse icon to indicate to the user we are waiting for more keystrokes */ -#ifdef USE_WAITFORKEY_CURSOR - grab_rat(); -#endif + if (defaults.wait_for_key_cursor) + { + grab_rat(); + rat_grabbed = 1; + } read_key (&keysym, &mod, NULL, 0); @@ -437,9 +436,8 @@ handle_key (screen_info *s) free (keysym_name); } -#ifdef USE_WAITFORKEY_CURSOR - ungrab_rat(); -#endif + if (rat_grabbed) + ungrab_rat(); } static void diff --git a/src/input.c b/src/input.c index afb3c71..4e2ba4e 100644 --- a/src/input.c +++ b/src/input.c @@ -284,31 +284,31 @@ read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) static void update_input_window (screen_info *s, char *prompt, char *input, int input_len) { - int prompt_width = XTextWidth (s->font, prompt, strlen (prompt)); - int input_width = XTextWidth (s->font, input, input_len); + int prompt_width = XTextWidth (defaults.font, prompt, strlen (prompt)); + int input_width = XTextWidth (defaults.font, input, input_len); int width; - width = BAR_X_PADDING * 2 + prompt_width + input_width; + width = defaults.bar_x_padding * 2 + prompt_width + input_width; - if (width < INPUT_WINDOW_SIZE + prompt_width) + if (width < defaults.input_window_size + prompt_width) { - width = INPUT_WINDOW_SIZE + prompt_width; + width = defaults.input_window_size + prompt_width; } XMoveResizeWindow (dpy, s->input_window, bar_x (s, width), bar_y (s), width, - (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2)); + (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2)); XClearWindow (dpy, s->input_window); XDrawString (dpy, s->input_window, s->normal_gc, - BAR_X_PADDING, - BAR_Y_PADDING + s->font->max_bounds.ascent, prompt, + defaults.bar_x_padding, + defaults.bar_y_padding + defaults.font->max_bounds.ascent, prompt, strlen (prompt)); XDrawString (dpy, s->input_window, s->normal_gc, - BAR_X_PADDING + prompt_width, - BAR_Y_PADDING + s->font->max_bounds.ascent, input, + defaults.bar_x_padding + prompt_width, + defaults.bar_y_padding + defaults.font->max_bounds.ascent, input, input_len); } @@ -45,12 +45,52 @@ free_window (rp_window *w) { if (w == NULL) return; - free (w->name); + free (w->user_name); + free (w->res_name); + free (w->res_class); + free (w->wm_name); + XFree (w->hints); free (w); } +void +update_window_position (rp_window *win) +{ + if (win->transient) + win->position = defaults.trans_pos; + else if (win->hints->flags & PMaxSize) + win->position = defaults.maxsize_pos; + else + win->position = defaults.win_pos; +} + +char * +window_name (rp_window *win) +{ + if (win == NULL) return NULL; + + if (win->named) + return win->user_name; + + switch (defaults.win_name) + { + case 0: + return win->wm_name; + + case 1: + return win->res_name; + + case 2: + return win->res_class; + + default: + return win->wm_name; + } + + return NULL; +} /* Allocate a new window and add it to the list of managed windows */ rp_window * @@ -72,13 +112,18 @@ add_to_window_list (screen_info *s, Window w) new_window->transient = XGetTransientForHint (dpy, new_window->w, &new_window->transient_for); PRINT_DEBUG ("transient %d\n", new_window->transient); + update_window_position (new_window); + get_mouse_root_position (new_window, &new_window->mouse_x, &new_window->mouse_y); XSelectInput (dpy, new_window->w, WIN_EVENTS); - new_window->name = xmalloc (strlen ("Unnamed") + 1); + new_window->user_name = xmalloc (strlen ("Unnamed") + 1); - strcpy (new_window->name, "Unnamed"); + strcpy (new_window->user_name, "Unnamed"); + new_window->wm_name = NULL; + new_window->res_name = NULL; + new_window->res_class = NULL; /* Add the window to the end of the unmapped list. */ append_to_list (new_window, rp_unmapped_window_sentinel); @@ -177,7 +222,7 @@ find_window_name (char *name) /* if (w->state == STATE_UNMAPPED) */ /* continue; */ - if (str_comp (name, w->name, strlen (name))) + if (str_comp (name, window_name (w), strlen (name))) return w; } @@ -514,8 +559,8 @@ set_active_window (rp_window *win) last_win = set_frames_window (rp_current_frame, win); - if (last_win) PRINT_DEBUG ("last window: %s\n", last_win->name); - PRINT_DEBUG ("new window: %s\n", win->name); + if (last_win) PRINT_DEBUG ("last window: %s\n", window_name (last_win)); + PRINT_DEBUG ("new window: %s\n", window_name (win)); /* Make sure the window comes up full screen */ maximize (win); @@ -560,18 +605,78 @@ goto_window (rp_window *win) void print_window_information (rp_window *win) { - marked_message_printf (0, 0, MESSAGE_WINDOW_INFORMATION, win->number, win->name); + marked_message_printf (0, 0, MESSAGE_WINDOW_INFORMATION, + win->number, window_name (win)); +} + +/* format options + N - Window number + - - Window status (current window, last window, etc) + W - Window Name + w - Window res name + c - Window res class + n - X11 Window ID + + */ +static void +format_window_name (char *fmt, rp_window *win, rp_window *other_win, + struct sbuf *buffer) +{ + char dbuf[10]; + + for(; *fmt; fmt++) + { + switch (*fmt) + { + case 'N': + snprintf (dbuf, 10, "%d", win->number); + sbuf_concat (buffer, dbuf); + break; + + case '-': + if (win == current_window()) + sbuf_concat (buffer, "*"); + else if (win == other_win) + sbuf_concat (buffer, "+"); + else + sbuf_concat (buffer, "-"); + break; + + case 'W': + sbuf_concat (buffer, window_name (win)); + break; + + case 'w': + sbuf_concat (buffer, win->res_name); + break; + + case 'c': + sbuf_concat (buffer, win->res_class); + break; + + case 'n': + snprintf (dbuf, 9, "%ld", (unsigned long)win->w); + sbuf_concat (buffer, dbuf); + break; + + default: + dbuf[0] = *fmt; + dbuf[1] = 0; + sbuf_concat (buffer, dbuf); + break; + } + } } /* get the window list and store it in buffer delimiting each window with delim. mark_start and mark_end will be filled with the text positions for the start and end of the current window. */ void -get_window_list (char *delim, struct sbuf *buffer, int *mark_start, int *mark_end) +get_window_list (char *fmt, char *delim, struct sbuf *buffer, + int *mark_start, int *mark_end) { rp_window *w; rp_window *other_window; - char dbuf[10]; if (buffer == NULL) return; @@ -582,7 +687,7 @@ get_window_list (char *delim, struct sbuf *buffer, int *mark_start, int *mark_en w != rp_mapped_window_sentinel; w = w->next) { - PRINT_DEBUG ("%d-%s\n", w->number, w->name); + PRINT_DEBUG ("%d-%s\n", w->number, window_name (w)); if (w == current_window()) *mark_start = strlen (sbuf_get (buffer)); @@ -592,17 +697,7 @@ get_window_list (char *delim, struct sbuf *buffer, int *mark_start, int *mark_en if (!delim) sbuf_concat (buffer, " "); - sprintf (dbuf, "%d", w->number); - sbuf_concat (buffer, dbuf); - - if (w == current_window()) - sbuf_concat (buffer, "*"); - else if (w == other_window) - sbuf_concat (buffer, "+"); - else - sbuf_concat (buffer, "-"); - - sbuf_concat (buffer, w->name); + format_window_name (fmt, w, other_window, buffer); /* A hack, pad the window with a space at the beginning and end if there is no delimiter. */ @@ -37,6 +37,8 @@ void give_window_focus (rp_window *win, rp_window *last_win); void set_active_window (rp_window *win); void goto_window (rp_window *win); void set_current_window (rp_window *win); +void update_window_position (rp_window *win); +char *window_name (rp_window *win); #if 0 void unhide_transient_for (rp_window *win); @@ -61,6 +63,7 @@ void insert_into_list (rp_window *win, rp_window *sentinel); void remove_from_list (rp_window *win); void print_window_information (rp_window *win); -void get_window_list (char *delim, struct sbuf *buffer, int *mark_start, int *mark_end); +void get_window_list (char *fmt, char *delim, struct sbuf *buffer, + int *mark_start, int *mark_end); #endif /* ! _RATPOISON_LIST_H */ @@ -62,9 +62,9 @@ screen_info *screens; int num_screens; Display *dpy; -int ignore_badwindow = 0; +struct rp_defaults defaults; -static XFontStruct *font; +int ignore_badwindow = 0; char **myargv; @@ -345,6 +345,46 @@ show_welcome_message () free (prefix); } +static void +init_defaults () +{ + defaults.win_pos = TOP_LEFT; + defaults.trans_pos = CENTER_CENTER; + defaults.maxsize_pos = CENTER_CENTER; + + defaults.input_window_size = 200; + defaults.window_border_width = 1; + defaults.bar_x_padding = 0; + defaults.bar_y_padding = 0; + defaults.bar_location = TOP_RIGHT; + defaults.bar_timeout = 5; + + defaults.frame_indicator_timeout = 1; + + defaults.padding_left = 0; + defaults.padding_right = 0; + defaults.padding_top = 0; + defaults.padding_bottom = 0; + + defaults.font = XLoadQueryFont (dpy, "9x15bold"); + if (defaults.font == NULL) + { + fprintf (stderr, "ratpoison: Cannot load font %s.\n", "9x15bold"); + exit (EXIT_FAILURE); + } + + defaults.wait_for_key_cursor = 1; + + defaults.window_fmt = strdup ("N-W"); + if (defaults.window_fmt == NULL) + { + PRINT_ERROR ("Not enough memory\n"); + exit (EXIT_FAILURE); + } + + defaults.win_name = 0; +} + int main (int argc, char *argv[]) { @@ -440,19 +480,13 @@ main (int argc, char *argv[]) set_sig_handler (SIGHUP, hup_handler); /* Setup ratpoison's internal structures */ + init_defaults(); init_numbers (); init_window_list (); init_frame_list (); update_modifier_map (); initialize_default_keybindings (); - font = XLoadQueryFont (dpy, FONT); - if (font == NULL) - { - fprintf (stderr, "ratpoison: Cannot load font %s.\n", FONT); - exit (EXIT_FAILURE); - } - num_screens = ScreenCount (dpy); screens = (screen_info *)xmalloc (sizeof (screen_info) * num_screens); @@ -483,8 +517,6 @@ init_rat_cursor (screen_info *s) static void init_screen (screen_info *s, int screen_num) { - XColor fg_color, bg_color,/* bold_color, */ junk; - /* Select on some events on the root window, if this fails, then there is already a WM running and the X Error handler will catch it, terminating ratpoison. */ @@ -497,29 +529,20 @@ init_screen (screen_info *s, int screen_num) s->screen_num = screen_num; s->root = RootWindow (dpy, screen_num); s->def_cmap = DefaultColormap (dpy, screen_num); - s->font = font; XGetWindowAttributes (dpy, s->root, &s->root_attr); init_rat_cursor (s); - /* Get our program bar colors */ - if (!XAllocNamedColor (dpy, s->def_cmap, FOREGROUND, &fg_color, &junk)) - { - fprintf (stderr, "ratpoison: Unknown color '%s'\n", FOREGROUND); - } - - if (!XAllocNamedColor (dpy, s->def_cmap, BACKGROUND, &bg_color, &junk)) - { - fprintf (stderr, "ratpoison: Unknown color '%s'\n", BACKGROUND); - } + s->fg_color = BlackPixel (dpy, s->screen_num); + s->bg_color = WhitePixel (dpy, s->screen_num); /* Setup the GC for drawing the font. */ - gv.foreground = fg_color.pixel; - gv.background = bg_color.pixel; + gv.foreground = s->fg_color; + gv.background = s->bg_color; gv.function = GXcopy; gv.line_width = 1; gv.subwindow_mode = IncludeInferiors; - gv.font = font->fid; + gv.font = defaults.font->fid; s->normal_gc = XCreateGC(dpy, s->root, GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode | GCFont, @@ -528,28 +551,28 @@ init_screen (screen_info *s, int screen_num) /* Create the program bar window. */ s->bar_is_raised = 0; s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, - 1, 1, 1, fg_color.pixel, bg_color.pixel); + 1, 1, 1, s->fg_color, s->bg_color); XSelectInput (dpy, s->bar_window, StructureNotifyMask); /* Setup the window that will recieve all keystrokes once the prefix key has been pressed. */ - s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0, WhitePixel (dpy, 0), BlackPixel (dpy, 0)); + s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0, WhitePixel (dpy, s->screen_num), BlackPixel (dpy, s->screen_num)); XSelectInput (dpy, s->key_window, KeyPressMask ); XMapWindow (dpy, s->key_window); /* Create the input window. */ s->input_window = XCreateSimpleWindow (dpy, s->root, 0, 0, - 1, 1, 1, fg_color.pixel, bg_color.pixel); + 1, 1, 1, s->fg_color, s->bg_color); XSelectInput (dpy, s->input_window, KeyPressMask ); /* Create the frame indicator window */ s->frame_window = XCreateSimpleWindow (dpy, s->root, 1, 1, 1, 1, 1, - fg_color.pixel, bg_color.pixel); + s->fg_color, s->bg_color); XSelectInput (dpy, s->frame_window, KeyPressMask ); /* Create the help window */ s->help_window = XCreateSimpleWindow (dpy, s->root, 0, 0, s->root_attr.width, - s->root_attr.height, 1, fg_color.pixel, bg_color.pixel); + s->root_attr.height, 1, s->fg_color, s->bg_color); XSelectInput (dpy, s->help_window, KeyPressMask); XSync (dpy, 0); @@ -589,7 +612,7 @@ clean_up () XFreeGC (dpy, screens[i].normal_gc); } - XFreeFont (dpy, font); + XFreeFont (dpy, defaults.font); XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XCloseDisplay (dpy); diff --git a/src/manage.c b/src/manage.c index 47e5574..60f7971 100644 --- a/src/manage.c +++ b/src/manage.c @@ -84,8 +84,8 @@ update_normal_hints (rp_window *win) } -char * -get_window_name (Window w) +static char * +get_wmname (Window w) { char *name; XTextProperty text; @@ -107,19 +107,85 @@ get_window_name (Window w) if (list_len > 0) { name = xmalloc (strlen (name_list[0]) + 1); - strcpy (name, name_list[0]); - - /* Its our responsibility to free this. */ - XFreeStringList (name_list); - - return name; + } + else + { + name = NULL; } /* Its our responsibility to free this. */ XFreeStringList (name_list); - return NULL; + return name; +} + +static XClassHint * +get_class_hints (Window w) +{ + XClassHint *class; + + class = XAllocClassHint(); + + if (class == NULL) + { + PRINT_ERROR ("Not enough memory for WM_CLASS structure.\n"); + exit (EXIT_FAILURE); + } + + XGetClassHint (dpy, w, class); + + return class; +} + +static char * +get_res_name (Window w) +{ + XClassHint *class; + char *name; + + class = get_class_hints (w); + + if (class->res_name) + { + name = (char *)xmalloc (strlen (class->res_name) + 1); + strcpy (name, class->res_name); + } + else + { + name = NULL; + } + + XFree (class->res_name); + XFree (class->res_class); + XFree (class); + + return name; +} + +static char * +get_res_class (Window w) +{ + XClassHint *class; + char *name; + + class = get_class_hints (w); + + if (class->res_class) + { + name = (char *)xmalloc (strlen (class->res_class) + 1); + strcpy (name, class->res_class); + } + else + { + name = NULL; + } + + XFree (class->res_name); + XFree (class->res_class); + XFree (class); + + return name; } /* Reget the WM_NAME property for the window and update its name. */ @@ -127,24 +193,30 @@ int update_window_name (rp_window *win) { char *newstr; - char *loc; /* Don't overwrite the window name if the user specified one. */ - if (win->named) return 0; +/* if (win->named) return 0; */ + + newstr = get_wmname (win->w); + if (newstr != NULL) + { + free (win->wm_name); + win->wm_name = newstr; + } - newstr = get_window_name (win->w); + newstr = get_res_class (win->w); if (newstr != NULL) { - free (win->name); - win->name = newstr; + free (win->res_class); + win->res_class = newstr; } - /* A bit of a hack. If there's a : in the string, crop the - string off there. This is mostly brought on by netscape's - disgusting tendency to put its current URL in the WMName!! - arg! */ - loc = strchr (win->name, ':'); - if (loc) loc[0] = '\0'; + newstr = get_res_name (win->w); + if (newstr != NULL) + { + free (win->res_name); + win->res_name = newstr; + } return 1; } @@ -190,6 +262,8 @@ update_window_information (rp_window *win) /* Transient status */ win->transient = XGetTransientForHint (dpy, win->w, &win->transient_for); + + update_window_position (win); } void @@ -261,7 +335,7 @@ unmanaged_window (Window w) for (i = 0; unmanaged_window_list[i]; i++) { - wname = get_window_name (w); + wname = get_wmname (w); if (!wname) return 0; if (!strcmp (unmanaged_window_list[i], wname)) @@ -289,6 +363,53 @@ set_state (rp_window *win, int state) PropModeReplace, (unsigned char *)data, 2); } +static void +move_window (rp_window *win) +{ + if (win->frame == NULL) + return; + + /* X coord. */ + switch (win->position) + { + case TOP_LEFT: + case CENTER_LEFT: + case BOTTOM_LEFT: + win->x = win->frame->x; + break; + case TOP_CENTER: + case BOTTOM_CENTER: + case CENTER_CENTER: + win->x = win->frame->x + (win->frame->width - win->border * 2) / 2 - win->width / 2; + break; + case TOP_RIGHT: + case CENTER_RIGHT: + case BOTTOM_RIGHT: + win->x = win->frame->x + win->frame->width - win->width - win->border; + break; + } + + /* Y coord. */ + switch (win->position) + { + case TOP_LEFT: + case TOP_CENTER: + case TOP_RIGHT: + win->y = win->frame->y; + break; + case CENTER_LEFT: + case CENTER_CENTER: + case CENTER_RIGHT: + win->y = win->frame->y + (win->frame->height - win->border * 2) / 2 - win->height / 2; + break; + case BOTTOM_LEFT: + case BOTTOM_CENTER: + case BOTTOM_RIGHT: + win->y = win->frame->y + win->frame->height - win->height - win->border; + break; + } +} + /* Set a transient window's x,y,width,height fields to maximize the window. */ static void @@ -297,8 +418,12 @@ maximize_transient (rp_window *win) rp_window_frame *frame; int maxx, maxy; + /* We can't maximize a window if it has no frame. */ + if (win->frame == NULL) + return; + /* Set the window's border */ - win->border = WINDOW_BORDER_WIDTH; + win->border = defaults.window_border_width; frame = win->frame; @@ -336,22 +461,6 @@ maximize_transient (rp_window *win) PRINT_DEBUG ("maxsize: %d %d\n", maxx, maxy); - /* Fit the window inside its frame (if it has one) */ - if (frame) - { - win->x = frame->x - win->width / 2 - + (frame->width - win->border * 2) / 2; - win->y = frame->y - win->height / 2 - + (frame->height - win->border * 2) / 2; - } - else - { - win->x = PADDING_LEFT - win->width / 2 - + (win->scr->root_attr.width - PADDING_LEFT - PADDING_RIGHT - win->border * 2) / 2; - win->y = PADDING_TOP - win->height / 2 - + (win->scr->root_attr.height - PADDING_TOP - PADDING_BOTTOM - win->border * 2) / 2; - } - win->width = maxx; win->height = maxy; } @@ -363,11 +472,13 @@ maximize_normal (rp_window *win) { rp_window_frame *frame; int maxx, maxy; - int off_x = 0; - int off_y = 0; + + /* We can't maximize a window if it has no frame. */ + if (win->frame == NULL) + return; /* Set the window's border */ - win->border = WINDOW_BORDER_WIDTH; + win->border = defaults.window_border_width; frame = win->frame; @@ -379,10 +490,8 @@ maximize_normal (rp_window *win) } else { - maxx = win->scr->root_attr.width - - PADDING_LEFT - PADDING_RIGHT - win->border * 2; - maxy = win->scr->root_attr.height - - PADDING_TOP - PADDING_BOTTOM - win->border * 2; + maxx = frame->width - win->border * 2; + maxy = frame->height - win->border * 2; } /* Fit the window inside its frame (if it has one) */ @@ -416,26 +525,6 @@ maximize_normal (rp_window *win) } PRINT_DEBUG ("maxsize: %d %d\n", maxx, maxy); - -#ifdef MAXSIZE_WINDOWS_ARE_TRANSIENTS - if (win->hints->flags & PMaxSize && frame) - { - off_x = (frame->width - win->border * 2) / 2 - maxx / 2; - off_y = (frame->height - win->border * 2) / 2 - maxy / 2; - } -#endif - - /* Fit the window inside its frame (if it has one) */ - if (frame) - { - win->x = frame->x + off_x; - win->y = frame->y + off_y; - } - else - { - win->x = PADDING_LEFT + off_x; - win->y = PADDING_TOP + off_y; - } win->width = maxx; win->height = maxy; @@ -459,6 +548,9 @@ maximize (rp_window *win) maximize_normal (win); } + /* Reposition the window. */ + move_window (win); + /* Actually do the maximizing */ XMoveResizeWindow (dpy, win->w, win->x, win->y, win->width, win->height); XSetWindowBorderWidth (dpy, win->w, win->border); @@ -475,8 +567,20 @@ force_maximize (rp_window *win) maximize_normal(win); - /* Actually do the maximizing */ - XMoveResizeWindow (dpy, win->w, win->x, win->y, win->width+1, win->height+1); + /* Reposition the window. */ + move_window (win); + + if (win->hints->flags & PResizeInc) + { + XMoveResizeWindow (dpy, win->w, win->x, win->y, + win->width + win->hints->width_inc, + win->height + win->hints->height_inc); + } + else + { + XResizeWindow (dpy, win->w, win->width + 1, win->height + 1); + } + XMoveResizeWindow (dpy, win->w, win->x, win->y, win->width, win->height); XSetWindowBorderWidth (dpy, win->w, win->border); XSync (dpy, False); @@ -486,7 +590,7 @@ force_maximize (rp_window *win) void map_window (rp_window *win) { - PRINT_DEBUG ("Mapping the unmapped window %s\n", win->name); + PRINT_DEBUG ("Mapping the unmapped window %s\n", window_name (win)); /* Fill in the necessary data about the window */ update_window_information (win); @@ -512,10 +616,10 @@ map_window (rp_window *win) { if (win->transient) marked_message_printf (0, 0, MESSAGE_MAP_TRANSIENT, - win->number, win->name); + win->number, window_name (win)); else marked_message_printf (0, 0, MESSAGE_MAP_WINDOW, - win->number, win->name); + win->number, window_name (win)); } } @@ -570,7 +674,7 @@ withdraw_window (rp_window *win) { if (win == NULL) return; - PRINT_DEBUG ("withdraw_window on '%s'\n", win->name); + PRINT_DEBUG ("withdraw_window on '%s'\n", window_name (win)); /* Give back the window number. the window will get another one, if it is remapped. */ diff --git a/src/messages.h b/src/messages.h index 1d8a94b..fd56dc4 100644 --- a/src/messages.h +++ b/src/messages.h @@ -24,24 +24,25 @@ #include "config.h" -#define MESSAGE_NO_OTHER_WINDOW " No other window " -#define MESSAGE_NO_OTHER_FRAME " No other frame " -#define MESSAGE_NO_MANAGED_WINDOWS " No managed windows " -#define MESSAGE_UNKNOWN_COMMAND ": unknown command '%s' " -#define MESSAGE_WINDOW_INFORMATION " This is window %d (%s) " +#define MESSAGE_NO_OTHER_WINDOW " No other window " +#define MESSAGE_NO_OTHER_FRAME " No other frame " +#define MESSAGE_NO_MANAGED_WINDOWS " No managed windows " +#define MESSAGE_UNKNOWN_COMMAND ": unknown command '%s' " +#define MESSAGE_WINDOW_INFORMATION " This is window %d (%s) " #define MESSAGE_RAISE_TRANSIENT " Raise request from transient window %d (%s) " -#define MESSAGE_RAISE_WINDOW " Raise request from window %d (%s) " -#define MESSAGE_MAP_TRANSIENT " New transient window %d (%s) " -#define MESSAGE_MAP_WINDOW " New window %d (%s) " +#define MESSAGE_RAISE_WINDOW " Raise request from window %d (%s) " +#define MESSAGE_MAP_TRANSIENT " New transient window %d (%s) " +#define MESSAGE_MAP_WINDOW " New window %d (%s) " #define MESSAGE_PROMPT_SWITCH_TO_WINDOW " Switch to window: " -#define MESSAGE_PROMPT_NEW_WINDOW_NAME " Set window's title to: " -#define MESSAGE_PROMPT_SHELL_COMMAND "/bin/sh -c " -#define MESSAGE_PROMPT_COMMAND ":" -#define MESSAGE_PROMPT_SWITCH_WM " Switch to wm: " -#define MESSAGE_PROMPT_XTERM_COMMAND MESSAGE_PROMPT_SHELL_COMMAND TERM_PROG " -e " +#define MESSAGE_PROMPT_NEW_WINDOW_NAME " Set window's title to: " +#define MESSAGE_PROMPT_SHELL_COMMAND "/bin/sh -c " +#define MESSAGE_PROMPT_COMMAND ":" +#define MESSAGE_PROMPT_SWITCH_WM " Switch to wm: " +#define MESSAGE_PROMPT_XTERM_COMMAND MESSAGE_PROMPT_SHELL_COMMAND TERM_PROG " -e " -#define MESSAGE_WELCOME " Welcome to ratpoison! Hit `%s %s' for help. " +#define MESSAGE_WELCOME " Welcome to ratpoison! Hit `%s %s' for help. " +#define MESSAGE_FRAME_STRING "Current Frame" #endif /* ! _RATPOISON_MESSAGES_H */ diff --git a/src/split.c b/src/split.c index 7820a36..b915714 100644 --- a/src/split.c +++ b/src/split.c @@ -68,12 +68,12 @@ delete_frame_from_list (rp_window_frame *frame) static void maximize_frame (rp_window_frame *frame) { - frame->x = PADDING_LEFT; - frame->y = PADDING_TOP; + frame->x = defaults.padding_left; + frame->y = defaults.padding_top; /* FIXME: what about multiple screens? */ - frame->width = DisplayWidth (dpy, 0) - PADDING_RIGHT - PADDING_LEFT; - frame->height = DisplayHeight (dpy, 0) - PADDING_BOTTOM - PADDING_TOP; + frame->width = DisplayWidth (dpy, 0) - defaults.padding_right - defaults.padding_left; + frame->height = DisplayHeight (dpy, 0) - defaults.padding_bottom - defaults.padding_top; } /* Create a full screen frame */ @@ -560,8 +560,8 @@ show_frame_indicator () screen_info *s = current_screen (); int width, height; - width = BAR_X_PADDING * 2 + XTextWidth (s->font, FRAME_STRING, strlen (FRAME_STRING)); - height = (FONT_HEIGHT (s->font) + BAR_Y_PADDING * 2); + width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, MESSAGE_FRAME_STRING, strlen (MESSAGE_FRAME_STRING)); + height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2); XMoveResizeWindow (dpy, current_screen()->frame_window, rp_current_frame->x + rp_current_frame->width / 2 - width / 2, @@ -572,9 +572,9 @@ show_frame_indicator () XClearWindow (dpy, s->frame_window); XDrawString (dpy, s->frame_window, s->normal_gc, - BAR_X_PADDING, - BAR_Y_PADDING + s->font->max_bounds.ascent, - FRAME_STRING, strlen (FRAME_STRING)); + defaults.bar_x_padding, + defaults.bar_y_padding + defaults.font->max_bounds.ascent, + MESSAGE_FRAME_STRING, strlen (MESSAGE_FRAME_STRING)); - alarm (FRAME_INDICATOR_TIMEOUT); + alarm (defaults.frame_indicator_timeout); } |