From bb36a84d39dc9d189e67874fff38c38a9812387a Mon Sep 17 00:00:00 2001 From: sabetts Date: Fri, 13 Apr 2001 08:22:11 +0000 Subject: * src/split.h (blank_frame): new prototype * src/split.c (split_frame): calls unhide_window after maximizing the new frame's window. (remove_all_splits): hide all windows but the current one (remove_all_splits): maximize the current window in its newly resized frame. (remove_frame): hide the frame's window after removing it from the list. (blank_frame): new function * src/manage.h (withdraw_window): new prototype (hide_window): likewise (unhide_window): likewise * src/manage.c (scanwins): glob ignored windows into 1 if statement. (scanwins): set the window's state to NormalState before calling map_window. (set_state): sets win->state (map_window): calls set_state (hide_window): new function (unhide_window): likewise (withdraw_window): new function * src/main.c (main): setup error handlers after --command, --restart, and --kill commands have been processed. (main): doesn't call set_active_window (init_screen): XSync's after selecting ewents on the root window. (clean_up): map iconized windows * src/list.h (give_window_focus): prototype updated * src/list.c (give_window_focus): takes a second argument, last_win. (give_window_focus): calls unhide_window (give_window_focus): uses last_win instead of current_window() (set_active_window): hides the last window and unhides the new window. (set_active_window): calls give_window_focus * src/events.c (cleanup_frame): maximizes the frame's new window (unmap_notify): do nothing if the window is in the iconic state. Withdraw the window if it is in the normal state. (map_request): calls unhide_window if the window is iconized. Do nothing if it is already mapped. (destroy_window): tightened up (client_msg): detects iconize requests from clients. * src/data.h (STATE_UNMAPPED): remove. Dependant code uses WithdawnState in its stead. (STATE_MAPPED): likewise. Dependant code uses NormalState in its stead * src/actions.c (initialize_default_keybindings): new keybinding - bound to "select -" (cmd_select): the string "-" selects a blank window --- ChangeLog | 60 ++++++++++++++++++++++++++++++++++++ NEWS | 4 +++ src/actions.c | 14 ++++++--- src/data.h | 4 --- src/events.c | 97 +++++++++++++++++++++++++++++++---------------------------- src/list.c | 45 +++++++++++++-------------- src/list.h | 2 +- src/main.c | 46 +++++++++++++++++++--------- src/manage.c | 85 +++++++++++++++++++++++++++++++++++++-------------- src/manage.h | 4 +++ src/split.c | 30 +++++++++++++----- src/split.h | 1 + 12 files changed, 270 insertions(+), 122 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6012b5..830f781 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,63 @@ +2001-04-13 shawn + + * src/split.h (blank_frame): new prototype + + * src/split.c (split_frame): calls unhide_window after maximizing + the new frame's window. + (remove_all_splits): hide all windows but the current one + (remove_all_splits): maximize the current window in its newly + resized frame. + (remove_frame): hide the frame's window after removing it from the + list. + (blank_frame): new function + + * src/manage.h (withdraw_window): new prototype + (hide_window): likewise + (unhide_window): likewise + + * src/manage.c (scanwins): glob ignored windows into 1 if + statement. + (scanwins): set the window's state to NormalState before calling + map_window. + (set_state): sets win->state + (map_window): calls set_state + (hide_window): new function + (unhide_window): likewise + (withdraw_window): new function + + * src/main.c (main): setup error handlers after --command, + --restart, and --kill commands have been processed. + (main): doesn't call set_active_window + (init_screen): XSync's after selecting ewents on the root window. + (clean_up): map iconized windows + + * src/list.h (give_window_focus): prototype updated + + * src/list.c (give_window_focus): takes a second argument, + last_win. + (give_window_focus): calls unhide_window + (give_window_focus): uses last_win instead of current_window() + (set_active_window): hides the last window and unhides the new + window. + (set_active_window): calls give_window_focus + + * src/events.c (cleanup_frame): maximizes the frame's new window + (unmap_notify): do nothing if the window is in the iconic + state. Withdraw the window if it is in the normal state. + (map_request): calls unhide_window if the window is iconized. Do + nothing if it is already mapped. + (destroy_window): tightened up + (client_msg): detects iconize requests from clients. + + * src/data.h (STATE_UNMAPPED): remove. Dependant code uses + WithdawnState in its stead. + (STATE_MAPPED): likewise. Dependant code uses NormalState in its + stead + + * src/actions.c (initialize_default_keybindings): new keybinding - + bound to "select -" + (cmd_select): the string "-" selects a blank window + 2001-04-12 shawn * src/main.c (main): calls XCloseDisplay before exitting after diff --git a/NEWS b/NEWS index f0cada9..207f9cb 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ ratpoison NEWS --- history of user-visible changes. -*- outline -*- * Changes since 0.1.1 +** windows not residing in a frame are hidden +This gets rid of annoying flickers around the edges of active windows +as windows in the back update. + ** rat cursor changes When you hit the prefix key the rat cursor changes to a square to tell diff --git a/src/actions.c b/src/actions.c index ab486bd..097991b 100644 --- a/src/actions.c +++ b/src/actions.c @@ -95,6 +95,7 @@ initialize_default_keybindings (void) add_keybinding (XK_7, 0, "select 7"); add_keybinding (XK_8, 0, "select 8"); add_keybinding (XK_9, 0, "select 9"); + add_keybinding (XK_minus, 0, "select -"); add_keybinding (XK_A, 0, "title"); add_keybinding (XK_A, ControlMask, "title"); add_keybinding (XK_K, 0, "kill"); @@ -468,11 +469,16 @@ cmd_select (void *data) /* Only search if the string contains something to search for. */ if (strlen (str) > 0) { - if ((w = find_window_name (str))) - goto_window (w); - + if (strlen (str) == 1 && str[0] == '-') + { + blank_frame (rp_current_frame); + } +/* else if ((w = find_window_name (str))) */ +/* { */ +/* goto_window (w); */ +/* } */ /* try by number */ - if ((n = string_to_window_number (str)) >= 0) + else if ((n = string_to_window_number (str)) >= 0) { if ((w = find_window_number (n))) goto_window (w); diff --git a/src/data.h b/src/data.h index 300059a..df29704 100644 --- a/src/data.h +++ b/src/data.h @@ -28,10 +28,6 @@ #define FONT_HEIGHT(f) ((f)->max_bounds.ascent + (f)->max_bounds.descent) -#define STATE_UNMAPPED 0 -#define STATE_MAPPED 1 - - typedef struct rp_window rp_window; typedef struct screen_info screen_info; typedef struct rp_action rp_action; diff --git a/src/events.c b/src/events.c index 6476f55..8d48fdb 100644 --- a/src/events.c +++ b/src/events.c @@ -59,6 +59,11 @@ static void cleanup_frame (rp_window_frame *frame) { frame->win = find_window_other (); + if (frame->win) + { + maximize (frame->win); + unhide_window (frame->win); + } } void @@ -75,37 +80,27 @@ unmap_notify (XEvent *ev) if (s && win) { rp_window_frame *frame; - long data[2] = { WithdrawnState, None }; - - /* 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; - - ignore_badwindow++; + /* If the window was inside a frame, fill the frame with another + window. */ frame = find_windows_frame (win); if (frame) cleanup_frame (frame); - remove_from_list (win); - append_to_list (win, rp_unmapped_window_sentinel); - - /* Update the state of the actual window */ - - XRemoveFromSaveSet (dpy, win->w); - XChangeProperty(dpy, win->w, wm_state, wm_state, 32, - PropModeReplace, (unsigned char *)data, 2); - - XSync(dpy, False); - - if (frame == rp_current_frame) + switch (win->state) { - set_active_frame (frame); + case IconicState: + /* This shouldn't actually happen, since the window is + already unmapped, so do nothing */ + PRINT_DEBUG ("Iconizing iconized window '%s'\n", win->name); + break; + case NormalState: + PRINT_DEBUG ("Withdrawing window '%s'\n", win->name); + withdraw_window (win); +/* hide_window (win); */ + if (frame == rp_current_frame) set_active_frame (frame); + break; } - ignore_badwindow--; - update_window_names (s); } } @@ -125,7 +120,7 @@ map_request (XEvent *ev) switch (win->state) { - case STATE_UNMAPPED: + case WithdrawnState: PRINT_DEBUG ("Unmapped window\n"); if (unmanaged_window (win->w)) { @@ -136,17 +131,21 @@ map_request (XEvent *ev) else { PRINT_DEBUG ("managed Window\n"); - map_window (win); break; } - case STATE_MAPPED: + case NormalState: PRINT_DEBUG ("Mapped Window\n"); + /* Its already mapped, so we don't have to do anything */ - maximize (win); - XMapRaised (dpy, win->w); - set_state (win, NormalState); - set_active_window (win); +/* maximize (win); */ +/* XMapRaised (dpy, win->w); */ +/* set_state (win, NormalState); */ +/* set_active_window (win); */ + break; + case IconicState: + PRINT_DEBUG ("Mapped iconic window\n"); + unhide_window (win); break; } } @@ -174,7 +173,6 @@ void destroy_window (XDestroyWindowEvent *ev) { rp_window *win; - ignore_badwindow++; win = find_window (ev->window); @@ -185,20 +183,9 @@ destroy_window (XDestroyWindowEvent *ev) frame = find_windows_frame (win); if (frame) cleanup_frame (frame); + if (frame == rp_current_frame) set_active_frame (frame); - if (frame == rp_current_frame) - { - PRINT_DEBUG ("Destroying the current window.\n"); - - set_active_frame (frame); - unmanage (win); - } - else - { - PRINT_DEBUG ("Destroying some other window.\n"); - - unmanage (win); - } + unmanage (win); } ignore_badwindow--; @@ -242,7 +229,7 @@ configure_request (XConfigureRequestEvent *e) PRINT_DEBUG("request CWY %d\n", e->y); } - if (e->value_mask & CWStackMode && win->state == STATE_MAPPED) + if (e->value_mask & CWStackMode && win->state == NormalState) { if (e->detail == Above) { @@ -310,6 +297,24 @@ client_msg (XClientMessageEvent *ev) clean_up (); exit (EXIT_SUCCESS); } + else if (ev->message_type == wm_change_state) + { + rp_window *win; + + win = find_window (ev->window); + if (win == NULL) return; + if (ev->format == 32 && ev->data.l[0] == IconicState) + { + if (win->state == NormalState) + { + /* TODO: Handle iconify events */ + } + } + else + { + PRINT_ERROR ("Non-standard WM_CHANGE_STATE format\n"); + } + } } static void diff --git a/src/list.c b/src/list.c index e4c7680..78359cd 100644 --- a/src/list.c +++ b/src/list.c @@ -64,7 +64,7 @@ add_to_window_list (screen_info *s, Window w) new_window->scr = s; new_window->last_access = 0; new_window->prev = NULL; - new_window->state = STATE_UNMAPPED; + new_window->state = WithdrawnState; new_window->number = -1; new_window->named = 0; new_window->hints = XAllocSizeHints (); @@ -370,51 +370,52 @@ save_mouse_position (rp_window *win) ignore_badwindow--; } +/* Takes focus away from last_win and gives focus to win */ void -give_window_focus (rp_window *win) +give_window_focus (rp_window *win, rp_window *last_win) { - static int counter = 1; /* increments every time this function - is called. This way we can track - which window was last accessed. */ + /* counter increments every time this function is called. This way + we can track which window was last accessed. */ + static int counter = 1; if (win == NULL) return; counter++; win->last_access = counter; -/* if (win->scr->bar_is_raised) update_window_names (win->scr); */ - - if (current_window() != NULL) - { - save_mouse_position (current_window()); - } + unhide_window (win); + /* Warp the cursor to the window's saved position. */ + if (last_win != NULL) save_mouse_position (last_win); XWarpPointer (dpy, None, win->scr->root, 0, 0, 0, 0, win->mouse_x, win->mouse_y); - XSync (dpy, False); - - XSetInputFocus (dpy, win->w, - RevertToPointerRoot, CurrentTime); /* Swap colormaps */ - if (current_window() != NULL) - { - XUninstallColormap (dpy, current_window()->colormap); - } + if (last_win != NULL) XUninstallColormap (dpy, last_win->colormap); XInstallColormap (dpy, win->colormap); + + /* Finally, give the window focus */ + XSetInputFocus (dpy, win->w, + RevertToPointerRoot, CurrentTime); + + XSync (dpy, False); } void set_active_window (rp_window *win) { + rp_window *last_win; + if (win == NULL) return; - give_window_focus (win); + last_win = rp_current_frame->win; rp_current_frame->win = win; /* Make sure the window comes up full screen */ - maximize (current_window()); - XRaiseWindow (dpy, win->w); + maximize (win); + unhide_window (win); + give_window_focus (win, last_win); + hide_window (last_win); /* Make sure the program bar is always on the top */ update_window_names (win->scr); diff --git a/src/list.h b/src/list.h index c69ff71..2ad0b47 100644 --- a/src/list.h +++ b/src/list.h @@ -31,7 +31,7 @@ void last_window (); rp_window *find_window_in_list (Window w, rp_window *sentinel); rp_window *find_window (Window w); void maximize_current_window (); -void give_window_focus (rp_window *rp_w); +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); diff --git a/src/main.c b/src/main.c index a41973b..ebe18c1 100644 --- a/src/main.c +++ b/src/main.c @@ -372,13 +372,6 @@ main (int argc, char *argv[]) return EXIT_FAILURE; } - /* Setup signal handlers. */ - XSetErrorHandler(handler); - set_sig_handler (SIGALRM, alrm_handler); - set_sig_handler (SIGTERM, sighandler); - set_sig_handler (SIGINT, sighandler); - set_sig_handler (SIGHUP, hup_handler); - /* Set ratpoison specific Atoms. */ rp_restart = XInternAtom (dpy, "RP_RESTART", False); rp_kill = XInternAtom (dpy, "RP_KILL", False); @@ -416,6 +409,14 @@ main (int argc, char *argv[]) wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); + /* Setup signal handlers. */ + XSetErrorHandler(handler); + set_sig_handler (SIGALRM, alrm_handler); + set_sig_handler (SIGTERM, sighandler); + set_sig_handler (SIGINT, sighandler); + set_sig_handler (SIGHUP, hup_handler); + + /* Setup ratpoison's internal structures */ init_numbers (); init_window_list (); init_frame_list (); @@ -441,9 +442,6 @@ main (int argc, char *argv[]) } read_startup_files (); - - /* Set an initial window as active. */ - set_active_window (find_window_other ()); handle_events (); @@ -479,6 +477,15 @@ 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. */ + XSelectInput(dpy, RootWindow (dpy, screen_num), + PropertyChangeMask | ColormapChangeMask + | SubstructureRedirectMask | KeyPressMask | KeyReleaseMask + | SubstructureNotifyMask ); + XSync (dpy, False); + s->screen_num = screen_num; s->root = RootWindow (dpy, screen_num); s->def_cmap = DefaultColormap (dpy, screen_num); @@ -520,11 +527,6 @@ init_screen (screen_info *s, int screen_num) /* | GCLineWidth | GCSubwindowMode | GCFont, */ /* &gv); */ - XSelectInput(dpy, s->root, - PropertyChangeMask | ColormapChangeMask - | SubstructureRedirectMask | KeyPressMask | KeyReleaseMask - | SubstructureNotifyMask ); - /* Create the program bar window. */ s->bar_is_raised = 0; s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, @@ -558,8 +560,22 @@ init_screen (screen_info *s, int screen_num) void clean_up () { + rp_window *cur; int i; + + /* Map any iconized windows. */ + for (cur = rp_mapped_window_sentinel->next; + cur != rp_mapped_window_sentinel; + cur = cur->next) + { + if (cur->state == IconicState) + { + unhide_window (cur); + } + } + XSync (dpy, False); + for (i=0; ibar_window || wins[i] == s->key_window || wins[i] == s->input_window - || wins[i] == s->frame_window) continue; + || wins[i] == s->frame_window + || attr.override_redirect == True + || unmanaged_window (wins[i])) continue; - if (attr.override_redirect != True && !unmanaged_window (wins[i])) + win = add_to_window_list (s, wins[i]); + + PRINT_DEBUG ("map_state: %d\n", attr.map_state); + if (attr.map_state == IsViewable) { - win = add_to_window_list (s, wins[i]); - - PRINT_DEBUG ("map_state: %d\n", attr.map_state); - if (attr.map_state == IsViewable) - { - map_window (win); - } - + win->state = NormalState; + map_window (win); } } - XFree((void *) wins); /* cast is to shut stoopid compiler up */ + + XFree(wins); } int @@ -271,17 +271,15 @@ unmanaged_window (Window w) return 0; } -/* Set the state of the window. - - FIXME: This is sort of broken. We should really record the state in - win->state and mimic the X states NormalState, WithdrawnState, - IconicState */ +/* Set the state of the window. */ void set_state (rp_window *win, int state) { long data[2]; - data[0] = (long)state; + win->state = state; + + data[0] = (long)win->state; data[1] = (long)None; XChangeProperty (dpy, win->w, wm_state, wm_state, 32, @@ -480,19 +478,60 @@ map_window (rp_window *win) { PRINT_DEBUG ("Mapping the unmapped window %s\n", win->name); + /* Fill in the necessary data about the window */ update_window_information (win); + win->number = get_unique_window_number (); grab_prefix_key (win->w); - maximize (win); + /* Put win in the mapped window list */ + remove_from_list (win); + insert_into_list (win, rp_mapped_window_sentinel); + + /* It is now considered iconic and set_active_window can handle the rest. */ + set_state (win, IconicState); + + /* FIXME: We may not want a window to pop up out of nowhere */ + set_active_window (win); +} + +void +hide_window (rp_window *win) +{ + if (win == NULL) return; + + set_state (win, IconicState); + XUnmapWindow (dpy, win->w); +} + +void +unhide_window (rp_window *win) +{ + if (win == NULL) return; + if (win->state != IconicState) return; XMapWindow (dpy, win->w); set_state (win, NormalState); - set_active_window (win); +} - win->state = STATE_MAPPED; - win->number = get_unique_window_number (); +void +withdraw_window (rp_window *win) +{ + if (win == NULL) return; + + PRINT_DEBUG ("withdawn_window on '%s'\n", win->name); + + /* Give back the window number. the window will get another one, + if it is remapped. */ + return_window_number (win->number); + win->number = -1; - /* Put win in the mapped window list */ remove_from_list (win); - insert_into_list (win, rp_mapped_window_sentinel); + append_to_list (win, rp_unmapped_window_sentinel); + + XRemoveFromSaveSet (dpy, win->w); + set_state (win, WithdrawnState); + + ignore_badwindow++; + XSync (dpy, False); + ignore_badwindow--; } diff --git a/src/manage.h b/src/manage.h index 22a6127..5607cda 100644 --- a/src/manage.h +++ b/src/manage.h @@ -43,4 +43,8 @@ void force_maximize (rp_window *win); void grab_prefix_key (Window w); void ungrab_prefix_key (Window w); +void hide_window (rp_window *win); +void unhide_window (rp_window *win); +void withdraw_window (rp_window *win); + #endif /* ! _RATPOISION_MANAGE_H */ diff --git a/src/split.c b/src/split.c index 0533de0..f8150f0 100644 --- a/src/split.c +++ b/src/split.c @@ -225,6 +225,7 @@ split_frame (rp_window_frame *frame, int way) new_frame->win = win; maximize (win); + unhide_window (win); XRaiseWindow (dpy, win->w); } else @@ -267,17 +268,13 @@ remove_all_splits () { cur = rp_window_frame_sentinel->next; delete_frame_from_list (cur); + if (cur != rp_current_frame) hide_window (cur->win); free (cur); } create_initial_frame (); rp_current_frame->win = cur_window; - - if (cur_window) - { - maximize (cur_window); - XRaiseWindow (dpy, cur_window->w); - } + maximize (cur_window); } static int @@ -384,6 +381,7 @@ remove_frame (rp_window_frame *frame) PRINT_DEBUG ("Total Area: %d\n", area); delete_frame_from_list (frame); + hide_window (frame->win); for (cur = rp_window_frame_sentinel->next; cur != rp_window_frame_sentinel; @@ -469,7 +467,7 @@ set_active_frame (rp_window_frame *frame) { rp_window_frame *old = rp_current_frame; - give_window_focus (frame->win); + give_window_focus (frame->win, rp_current_frame->win); rp_current_frame = frame; if (!frame->win || old != rp_current_frame) @@ -477,6 +475,8 @@ set_active_frame (rp_window_frame *frame) show_frame_indicator(); } + /* If the frame has no window to give focus to, give the frame + indicator focus. */ if( !frame->win ) { XSetInputFocus (dpy, current_screen()->frame_window, @@ -484,6 +484,22 @@ set_active_frame (rp_window_frame *frame) } } +void +blank_frame (rp_window_frame *frame) +{ + if (frame->win == NULL) return; + + hide_window (frame->win); + frame->win = NULL; + + if (frame == rp_current_frame) + { + show_frame_indicator(); + XSetInputFocus (dpy, current_screen()->frame_window, + RevertToPointerRoot, CurrentTime); + } +} + static void update_frame_indicator () { diff --git a/src/split.h b/src/split.h index 6ef0186..00139f3 100644 --- a/src/split.h +++ b/src/split.h @@ -33,6 +33,7 @@ rp_window_frame *find_frame_prev (rp_window_frame *frame); rp_window *current_window (); void init_frame_list (); void set_active_frame (rp_window_frame *frame); +void blank_frame (rp_window_frame *frame); void show_frame_indicator (); void hide_frame_indicator (); -- cgit v1.2.3