diff options
Diffstat (limited to 'src/window.c')
-rw-r--r-- | src/window.c | 820 |
1 files changed, 0 insertions, 820 deletions
diff --git a/src/window.c b/src/window.c deleted file mode 100644 index 15024f6..0000000 --- a/src/window.c +++ /dev/null @@ -1,820 +0,0 @@ -/* functions for handling the window list - * Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca> - * - * This file is part of ratpoison. - * - * ratpoison is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * ratpoison is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -/* Citing getsid(2) here: - To get the prototype under glibc, define both _XOPEN_SOURCE and - _XOPEN_SOURCE_EXTENDED, or use "#define _XOPEN_SOURCE n" for some - integer n larger than or equal to 500. */ -#define _XOPEN_SOURCE 500 -#include <unistd.h> /* for getsid */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ratpoison.h" - -LIST_HEAD(rp_unmapped_window); -LIST_HEAD(rp_mapped_window); - -struct numset *rp_window_numset; - -/* Get the mouse position relative to the the specified window */ -static void -get_mouse_position (rp_window *win, int *mouse_x, int *mouse_y) -{ - Window root_win, child_win; - int root_x, root_y; - unsigned int mask; - - XQueryPointer (dpy, win->scr->root, &root_win, &child_win, mouse_x, mouse_y, &root_x, &root_y, &mask); -} - -void -free_window (rp_window *w) -{ - if (w == NULL) return; - - free (w->user_name); - free (w->res_name); - free (w->res_class); - free (w->wm_name); - - XFree (w->hints); - - free (w); -} - -void -update_window_gravity (rp_window *win) -{ -/* if (win->hints->win_gravity == ForgetGravity) */ -/* { */ - if (win->transient) - win->gravity = defaults.trans_gravity; - else if (win->hints->flags & PMaxSize || win->hints->flags & PAspect) - win->gravity = defaults.maxsize_gravity; - else - win->gravity = defaults.win_gravity; -/* } */ -/* else */ -/* { */ -/* win->gravity = win->hints->win_gravity; */ -/* } */ -} - -char * -window_name (rp_window *win) -{ - if (win == NULL) return NULL; - - if (win->named) - return win->user_name; - - switch (defaults.win_name) - { - case WIN_NAME_RES_NAME: - if (win->res_name) - return win->res_name; - else return win->user_name; - - case WIN_NAME_RES_CLASS: - if (win->res_class) - return win->res_class; - else return win->user_name; - - /* if we're not looking for the res name or res class, then - we're looking for the window title. */ - default: - if (win->wm_name) - return win->wm_name; - else return win->user_name; - } - - return NULL; -} - -/* FIXME: we need to verify that the window is running on the same - host as something. otherwise there could be overlapping PIDs. */ -struct rp_child_info * -get_child_info (Window w) -{ - rp_child_info *cur; - int status; - int pid; - Atom type_ret; - int format_ret; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *req; - pid_t sid; - - status = XGetWindowProperty (dpy, w, _net_wm_pid, - 0, 0, False, XA_CARDINAL, - &type_ret, &format_ret, &nitems, &bytes_after, &req); - - if (status != Success || req == NULL) - { - PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); - return NULL; - } - - /* XGetWindowProperty always allocates one extra byte even if - the property is zero length. */ - XFree (req); - - status = XGetWindowProperty (dpy, w, _net_wm_pid, - 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), - False, XA_CARDINAL, &type_ret, &format_ret, &nitems, - &bytes_after, &req); - - if (status != Success || req == NULL) - { - PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); - return NULL; - } - - pid = *((int *)req); - XFree(req); - - PRINT_DEBUG(("pid: %d\n", pid)); - - /* The pids will hopefully be in the same session. */ - sid = getsid (pid); - list_for_each_entry (cur, &rp_children, node) - { - PRINT_DEBUG(("cur->pid=%d sid=%d\n", cur->pid, getsid (cur->pid))); - if (sid == getsid (cur->pid)) - return cur; - } - - return NULL; -} - -/* Allocate a new window and add it to the list of managed windows */ -rp_window * -add_to_window_list (rp_screen *s, Window w) -{ - struct rp_child_info *child_info; - rp_window *new_window; - rp_group *group = NULL; - int frame_num = -1; - - new_window = xmalloc (sizeof (rp_window)); - - new_window->w = w; - new_window->scr = s; - new_window->last_access = 0; - new_window->state = WithdrawnState; - new_window->number = -1; - new_window->frame_number = EMPTY; - new_window->intended_frame_number = -1; - new_window->named = 0; - new_window->hints = XAllocSizeHints (); - new_window->colormap = DefaultColormap (dpy, s->screen_num); - new_window->transient = XGetTransientForHint (dpy, new_window->w, &new_window->transient_for); - PRINT_DEBUG (("transient %d\n", new_window->transient)); - - update_window_gravity (new_window); - - get_mouse_position (new_window, &new_window->mouse_x, &new_window->mouse_y); - - XSelectInput (dpy, new_window->w, WIN_EVENTS); - - new_window->user_name = xstrdup ("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. */ - list_add_tail (&new_window->node, &rp_unmapped_window); - - child_info = get_child_info (w); - - if (child_info && !child_info->window_mapped) { - rp_frame *frame = screen_find_frame_by_frame (child_info->screen, child_info->frame); - - PRINT_DEBUG(("frame=%p\n", frame)); - group = groups_find_group_by_group (child_info->group); - if (frame) - frame_num = frame->number; - /* Only map the first window in the launch frame. */ - child_info->window_mapped = 1; - } - - /* Add the window to the group it's pid was launched in or the - current one. */ - if (group) - group_add_window (group, new_window); - else - group_add_window (rp_current_group, new_window); - - PRINT_DEBUG(("frame_num: %d\n", frame_num)); - if (frame_num >= 0) - new_window->intended_frame_number = frame_num; - - return new_window; -} - -/* Check to see if the window is in the list of windows. */ -rp_window * -find_window_in_list (Window w, struct list_head *list) -{ - rp_window *cur; - - list_for_each_entry (cur, list, node) - { - if (cur->w == w) return cur; - } - - return NULL; -} - -/* Check to see if the window is in any of the lists of windows. */ -rp_window * -find_window (Window w) -{ - rp_window *win = NULL; - - - win = find_window_in_list (w, &rp_mapped_window); - - if (!win) - { - win = find_window_in_list (w, &rp_unmapped_window); - if (win) - PRINT_DEBUG (("Window found in unmapped window list\n")); - else - PRINT_DEBUG (("Window not found.\n")); - } - else - { - PRINT_DEBUG (("Window found in mapped window list.\n")); - } - - return win; -} - -void -set_current_window (rp_window *win) -{ - set_frames_window (current_frame(), win); -} - -rp_window * -find_window_number (int n) -{ - rp_window *cur; - - list_for_each_entry (cur,&rp_mapped_window,node) - { -/* if (cur->state == STATE_UNMAPPED) continue; */ - - if (n == cur->number) return cur; - } - - return NULL; -} - -rp_window * -find_window_name (char *name) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, &rp_current_group->mapped_windows, node) - { - if (str_comp (name, window_name (cur->win), strlen (name))) - return cur->win; - } - - /* didn't find it */ - return NULL; -} - -/* Return the previous window in the list. Assumes window is in the - mapped window list. */ -rp_window* -find_window_prev (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = list_prev_entry (w, &rp_mapped_window, node); - cur != w; - cur = list_prev_entry (cur, &rp_mapped_window, node)) - { - if (!find_windows_frame (cur)) - { - return cur; - } - } - - return NULL; -} - -/* Return the next window in the list. Assumes window is in the mapped - window list. */ -rp_window* -find_window_next (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = list_next_entry (w, &rp_mapped_window, node); - cur != w; - cur = list_next_entry (cur, &rp_mapped_window, node)) - { - if (!find_windows_frame (cur)) - { - return cur; - } - } - - return NULL; -} - -rp_window * -find_window_other (rp_screen *screen) -{ - return group_last_window (rp_current_group, screen); -} - - - -/* Assumes the list is sorted by increasing number. Inserts win into - to Right place to keep the list sorted. */ -void -insert_into_list (rp_window *win, struct list_head *list) -{ - rp_window *cur; - - list_for_each_entry (cur, list, node) - { - if (cur->number > win->number) - { - list_add_tail (&win->node, &cur->node); - return; - } - } - - list_add_tail(&win->node, list); -} - -static void -save_mouse_position (rp_window *win) -{ - Window root_win, child_win; - int root_x, root_y; - unsigned int mask; - - /* In the case the XQueryPointer raises a BadWindow error, the - window is not mapped or has been destroyed so it doesn't matter - what we store in mouse_x and mouse_y since they will never be - used again. */ - - ignore_badwindow++; - - XQueryPointer (dpy, win->w, &root_win, &child_win, - &root_x, &root_y, &win->mouse_x, &win->mouse_y, &mask); - - ignore_badwindow--; -} - -/* Takes focus away from last_win and gives focus to win */ -void -give_window_focus (rp_window *win, rp_window *last_win) -{ - /* counter increments every time this function is called. This way - we can track which window was last accessed. */ - static int counter = 1; - - /* Warp the cursor to the window's saved position if last_win and - win are different windows. */ - if (last_win != NULL && win != last_win) - { - save_mouse_position (last_win); - XSetWindowBorder (dpy, last_win->w, last_win->scr->bw_color); - } - - if (win == NULL) return; - - counter++; - win->last_access = counter; - unhide_window (win); - - if (defaults.warp) - { - PRINT_DEBUG (("Warp pointer\n")); - XWarpPointer (dpy, None, win->w, - 0, 0, 0, 0, win->mouse_x, win->mouse_y); - } - - /* Swap colormaps */ - if (last_win != NULL) XUninstallColormap (dpy, last_win->colormap); - XInstallColormap (dpy, win->colormap); - - XSetWindowBorder (dpy, win->w, win->scr->fw_color); - - /* Finally, give the window focus */ - rp_current_screen = win->scr->xine_screen_num; - set_rp_window_focus (win); - - XSync (dpy, False); -} - -#if 0 -void -unhide_transient_for (rp_window *win) -{ - rp_frame *frame; - rp_window *transient_for; - - if (win == NULL) return; - if (!win->transient) return; - frame = find_windows_frame (win); - - transient_for = find_window (win->transient_for); - if (transient_for == NULL) - { - PRINT_DEBUG (("Can't find transient_for for '%s'\n", win->name )); - return; - } - - if (find_windows_frame (transient_for) == NULL) - { - set_frames_window (frame, transient_for); - maximize (transient_for); - - PRINT_DEBUG (("unhide transient window: %s\n", transient_for->name)); - - unhide_window_below (transient_for); - - if (transient_for->transient) - { - unhide_transient_for (transient_for); - } - - set_frames_window (frame, win); - } - else if (transient_for->transient) - { - unhide_transient_for (transient_for); - } -} -#endif - -#if 0 -/* Hide all transient windows for win until we get to last. */ -void -hide_transient_for_between (rp_window *win, rp_window *last) -{ - rp_window *transient_for; - - if (win == NULL) return; - if (!win->transient) return; - - transient_for = find_window (win->transient_for); - if (transient_for == last) - { - PRINT_DEBUG (("Can't find transient_for for '%s'\n", win->name )); - return; - } - - if (find_windows_frame (transient_for) == NULL) - { - PRINT_DEBUG (("hide transient window: %s\n", transient_for->name)); - hide_window (transient_for); - } - - if (transient_for->transient) - { - hide_transient_for (transient_for); - } -} -#endif - -#if 0 -void -hide_transient_for (rp_window *win) -{ - /* Hide ALL the transient windows for win. */ - hide_transient_for_between (win, NULL); -} -#endif - -#if 0 -/* return 1 if transient_for is a transient window for win or one of - win's transient_for ancestors. */ -int -is_transient_ancestor (rp_window *win, rp_window *transient_for) -{ - rp_window *tmp; - - if (win == NULL) return 0; - if (!win->transient) return 0; - if (transient_for == NULL) return 0; - - tmp = win; - - do - { - tmp = find_window (tmp->transient_for); - if (tmp == transient_for) - return 1; - } while (tmp && tmp->transient); - - return 0; -} -#endif - -/* Gets frame from window -- helper to set_active_window_body - * - * While this fct returns a value, it also modifies a param, last_frame, - * which is ugly... but since this is trying to fix ugly code I guess it - * can be a little ugly. - */ -static rp_frame* -get_frame(rp_window *win, rp_frame *last_frame) -{ - rp_frame* frame=NULL; - - /* use the intended frame if we can. */ - if (win->intended_frame_number >= 0) - { - /* With Xinerama, we can move a window over to the current screen; otherwise - * we have to switch to the screen that the window belongs to. - */ - if (rp_have_xinerama) - frame = screen_get_frame (current_screen(), win->intended_frame_number); - else - frame = screen_get_frame (win->scr, win->intended_frame_number); - - win->intended_frame_number = -1; - if (frame != current_frame()) - last_frame = current_frame(); - } - - if (!frame) - { - if (rp_have_xinerama) - frame = screen_get_frame (current_screen(), current_screen()->current_frame); - else - frame = screen_get_frame (win->scr, win->scr->current_frame); - } - - return frame; -} - -/* Finds a non-dedicated frame -- helper to set_active_window_body */ -static void -find_non_dedicated_frame(rp_window *win, rp_frame *frame, rp_frame *last_frame) -{ - /* Try to find a non-dedicated frame. */ - rp_frame *cur; - rp_screen *scr; - int done; - - scr = (rp_have_xinerama)?&screens[rp_current_screen]:win->scr; - done = 0; - - /* Try the only / current screen... */ - for (cur = list_next_entry (frame, &scr->frames, node); - cur != frame; - cur = list_next_entry (cur, &scr->frames, node)) - { - if (!cur->dedicated) - { - set_active_frame (cur, 0); - last_frame = frame; - frame = cur; - break; - } - } - - /* If we have Xinerama, we can check *all* screens... */ - /* TODO: could this be put into yet another function? */ - if (rp_have_xinerama && !done) - { - int i; - - for (i=0; i<num_screens && !done; i++) - { - if (scr == &screens[i]) continue; - list_for_each_entry (cur,&screens[i].frames,node) - { - if (!cur->dedicated) - { - set_active_frame (cur, 0); - last_frame = frame; - frame = cur; - - /* Good case for a goto here? */ - done = 1; /* Break outer loop. */ - break; /* Break inner loop. */ - } - } - } - } -} - -/* In the current frame, set the active window to win. win will have focus. */ -void set_active_window (rp_window *win) -{ - set_active_window_body(win, 0); -} - -void set_active_window_force (rp_window *win) -{ - set_active_window_body(win, 1); -} - -void -set_active_window_body (rp_window *win, int force) -{ - rp_window *last_win; - rp_frame *frame = NULL, *last_frame = NULL; - - if (win == NULL) return; - - PRINT_DEBUG (("intended_frame_number: %d\n", win->intended_frame_number)); - - frame = get_frame(win, last_frame); - - if (frame->dedicated && !force) - find_non_dedicated_frame(win, frame, last_frame); - - last_win = set_frames_window (frame, win); - - 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); - - /* Focus the window. */ - give_window_focus (win, last_win); - - /* The other windows in the frame will be hidden if this window - doesn't qualify as a transient window (ie dialog box. */ - if (!window_is_transient (win)) - hide_others(win); - - /* Make sure the program bar is always on the top */ - update_window_names (win->scr, defaults.window_fmt); - - XSync (dpy, False); - - /* If we switched frame, go back to the old one. */ - if (last_frame) - set_active_frame (last_frame, 0); - - /* Call the switch window hook */ - hook_run (&rp_switch_win_hook); -} - -/* Go to the window, switching frames if the window is already in a - frame. */ -void -goto_window (rp_window *win) -{ - rp_frame *frame; - - /* There is nothing to do if it is already the current window. */ - if (current_window() == win) - return; - - frame = find_windows_frame (win); - if (frame) - { - set_active_frame (frame, 0); - } - else - { - set_active_window (win); - } -} - -void -print_window_information (rp_group *group, rp_window *win) -{ - rp_window_elem *win_elem; - /* Display the window's number in group. This gives the possibility - of windows existing in multiple groups. */ - win_elem = group_find_window (&group->mapped_windows, win); - if (win_elem) - marked_message_printf (0, 0, MESSAGE_WINDOW_INFORMATION, - win_elem->number, window_name (win)); - else - marked_message_printf (0, 0, "%s doesn't exist in group %d\n", - window_name(win), group->number); -} - -/* 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 *fmt, char *delim, struct sbuf *buffer, - int *mark_start, int *mark_end) -{ - rp_window_elem *we; - - if (buffer == NULL) return; - - sbuf_clear (buffer); - find_window_other (current_screen()); - - /* We only loop through the current group to look for windows. */ - list_for_each_entry (we,&rp_current_group->mapped_windows,node) - { - PRINT_DEBUG (("%d-%s\n", we->number, window_name (we->win))); - - if (we->win == current_window()) - *mark_start = strlen (sbuf_get (buffer)); - - /* A hack, pad the window with a space at the beginning and end - if there is no delimiter. */ - if (!delim) - sbuf_concat (buffer, " "); - - format_string (fmt, we, buffer); - - /* A hack, pad the window with a space at the beginning and end - if there is no delimiter. */ - if (!delim) - sbuf_concat (buffer, " "); - - /* Only put the delimiter between the windows, and not after the the last - window. */ - if (delim && we->node.next != &rp_current_group->mapped_windows) - sbuf_concat (buffer, delim); - - if (we->win == current_window()) - { - *mark_end = strlen (sbuf_get (buffer)); - } - } - - if (!strcmp (sbuf_get (buffer), "")) - { - sbuf_copy (buffer, MESSAGE_NO_MANAGED_WINDOWS); - } -} - -void -init_window_stuff (void) -{ - rp_window_numset = numset_new (); -} - -void -free_window_stuff (void) -{ - rp_window *cur; - struct list_head *tmp, *iter; - - list_for_each_safe_entry (cur, iter, tmp, &rp_unmapped_window, node) - { - list_del (&cur->node); - groups_del_window (cur); - free_window (cur); - } - - list_for_each_safe_entry (cur, iter, tmp, &rp_mapped_window, node) - { - list_del (&cur->node); - groups_unmap_window (cur); - groups_del_window (cur); - free_window (cur); - } - - numset_free (rp_window_numset); -} - -rp_frame * -win_get_frame (rp_window *win) -{ - if (win->frame_number != EMPTY) - return screen_get_frame (win->scr, win->frame_number); - else - return NULL; -} |