summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c820
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;
-}