Logo Search packages:      
Sourcecode: sawfish version File versions  Download package

windows.c

/* windows.c -- window manipulation
   $Id: windows.c,v 1.132 2005/02/12 06:22:18 jsh Exp $

   Copyright (C) 1999 John Harper <john@dcs.warwick.ac.uk>

   This file is part of sawmill.

   sawmill 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.

   sawmill 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 sawmill; see the file COPYING.   If not, write to
   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */

#include "sawmill.h"
#include <assert.h>
#include <string.h>
#include <X11/extensions/shape.h>

Lisp_Window *window_list;
int window_type;

Lisp_Window *focus_window;

int pending_destroys;

static bool initialising;

DEFSYM(add_window_hook, "add-window-hook");
DEFSYM(before_add_window_hook, "before-add-window-hook");
DEFSYM(after_add_window_hook, "after-add-window-hook");
DEFSYM(place_window_hook, "place-window-hook");
DEFSYM(placed, "placed");
DEFSYM(after_framing_hook, "after-framing-hook");
DEFSYM(after_initialization_hook, "after-initialization-hook");
DEFSYM(remove_window_hook, "remove-window-hook");

/* for visibility-notify-hook */
DEFSYM(fully_obscured, "fully-obscured");
DEFSYM(partially_obscured, "partially-obscured");
DEFSYM(unobscured, "unobscured");

/* for window-size-hints */
DEFSYM(min_width, "min-width");
DEFSYM(min_height, "min-height");
DEFSYM(max_width, "max-width");
DEFSYM(max_height, "max-height");
DEFSYM(width_inc, "width-inc");
DEFSYM(height_inc, "height-inc");
DEFSYM(base_width, "base-width");
DEFSYM(base_height, "base-height");
DEFSYM(min_aspect, "min-aspect");
DEFSYM(max_aspect, "max-aspect");
DEFSYM(user_size, "user-size");
DEFSYM(program_size, "program-size");
DEFSYM(user_position, "user-position");
DEFSYM(program_position, "program-position");
DEFSYM(window_gravity, "window-gravity");

/* for window-gravity */
DEFSYM(forget, "forget");
DEFSYM(static, "static");
DEFSYM(north_west, "north-west");
DEFSYM(north, "north");
DEFSYM(north_east, "north-east");
DEFSYM(west, "west");
DEFSYM(center, "center");
DEFSYM(east, "east");
DEFSYM(south_west, "south-west");
DEFSYM(south, "south");
DEFSYM(south_east, "south-east");

static repv gravity_map[StaticGravity+1];

struct prop_handler {
    struct prop_handler *next;
    repv prop;
    void (*callback) (Lisp_Window *w, repv prop, repv old, repv new);
};

static struct prop_handler *prop_handlers;


/* utilities */

/* Returns true if we should manage window ID */
bool
mapped_not_override_p (Window id)
{
    XWindowAttributes wa;

    XGetWindowAttributes(dpy, id, &wa);
    return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
}

/* Returns true if the window's Input hint is set (or defaults to being set) */
static bool
window_input_hint_p (Lisp_Window *w)
{
    if (w->wmhints != 0 && (w->wmhints->flags & InputHint))
      return w->wmhints->input;
    else
      return TRUE;
}

static Window queued_focus_id;
static bool queued_take_focus;
static bool queued_set_focus;
static int queued_focus_revert;
static Time queued_focus_time;

/* We can lose the focus sometimes, notably after a was-focused
   window is closed while a keyboard grab exists.. (netscape) */
static void
check_for_lost_focus (void)
{
    Window focus;
    int revert_to;
    XGetInputFocus (dpy, &focus, &revert_to);
    if (focus == None || focus == PointerRoot)
    {
      DB (("lost focus (%ld)\n", focus));
      focus_on_window (focus_window);
    }
}

void
commit_queued_focus_change (void)
{
    if (0 && queued_focus_id == 0)
      check_for_lost_focus ();

    if (queued_focus_id != 0)
    {
      if (queued_take_focus)
      {
          DB(("  sending WM_TAKE_FOCUS %x %ld\n",
            (unsigned) queued_focus_id, queued_focus_time));
          send_client_message (queued_focus_id,
                         xa_wm_take_focus,
                         queued_focus_time);
      }
      if (queued_set_focus)
      {
          DB(("  focusing %x %ld\n",
            (unsigned) queued_focus_id, queued_focus_time));
          XSetInputFocus (dpy, queued_focus_id,
                      queued_focus_revert, queued_focus_time);
      }
      queued_focus_id = 0;
    }
}

/* Give the input focus to window W, or to no window if W is null */
void
focus_on_window (Lisp_Window *w)
{
    /* something's going to change, so */
    queued_focus_id = 0;
    queued_focus_time = last_event_time;
    queued_set_focus = FALSE;
    queued_take_focus = FALSE;

    if (w != 0 && !WINDOW_IS_GONE_P (w) && w->visible)
    {
      DB(("focus_on_window (%s)\n", rep_STR(w->name)));
      if (!w->client_unmapped)
      {
          queued_focus_id = w->id;

          if (w->does_wm_take_focus)
          {
            queued_take_focus = TRUE;

            if (window_input_hint_p (w))
                queued_set_focus = TRUE;
          }
          else
            queued_set_focus = TRUE;
      }
      else
      {
          queued_focus_id = w->frame;
          queued_set_focus = TRUE;
      }

      queued_focus_revert = RevertToParent;
    }

    if (queued_focus_id == 0 || (!queued_set_focus && !queued_take_focus))
    {
      DB(("focus_on_window (nil)\n"));
      queued_focus_id = no_focus_window;
      queued_set_focus = TRUE;
      queued_focus_revert = RevertToNone;
      queued_focus_time = last_event_time;
    }
}

/* Should be called when W is no longer focusable. */
void
focus_off_window (Lisp_Window *w)
{
    if (w == focus_window)
    {
      focus_window = 0;

      /* Do this immediately. Any real focus-change will be queued,
         so will happen after this. Doing this here just prevents us
         getting stuck with focus on nothing in some cases.. */

      XSetInputFocus (dpy, no_focus_window, RevertToNone, last_event_time);
    }
}

/* Set flags in W relating to which window manager protocols are recognised
   by window W. */
void
get_window_protocols (Lisp_Window *w)
{
    Atom *prot;
    u_int n;
    w->does_wm_take_focus = 0;
    w->does_wm_delete_window = 0;
    if (XGetWMProtocols (dpy, w->id, &prot, &n) != 0)
    {
      int i;
      for (i = 0; i < n; i++)
      {
          if (prot[i] == xa_wm_take_focus)
          {
            w->does_wm_take_focus = 1;
            DB(("  WM_TAKE_FOCUS is set\n"));
          }
          if (prot[i] == xa_wm_delete_window)
          {
            w->does_wm_delete_window = 1;
            DB(("  WM_DELETE_WINDOW is set\n"));
          }
      }
      XFree (prot);
    }
}

/* These two functions are used to bracket Xlib requests that would map,
   unmap, or reparent the client window. They ensure that any
   StructureNotifymask events generated between calling before_local_map ()
   and after_local_map () are discarded, but no others (so that we don't
   lose client-generated events) */

void
before_local_map (Lisp_Window *w)
{
    Fgrab_server ();
    XSelectInput (dpy, w->id, CLIENT_EVENTS & ~StructureNotifyMask);
}

void
after_local_map (Lisp_Window *w)
{
    XSelectInput (dpy, w->id, CLIENT_EVENTS);
    Fungrab_server ();
}


/* manipulating the Lisp window structures */

/* Return the window object containing ID, or a null pointer */
Lisp_Window *
find_window_by_id (Window id)
{
    Lisp_Window *w;
    w = window_list;
    while (w != 0 && w->id != id && w->frame != id)
      w = w->next;
    if (w != 0 && WINDOW_IS_GONE_P (w))
      w = 0;
    return w;
}

/* This is different to the above in that it could return a window
   that doesn't have a client window. */
Lisp_Window *
x_find_window_by_id (Window id)
{
    Lisp_Window *w;
    w = window_list;
    while (w != 0 && w->saved_id != id && w->frame != id)
      w = w->next;
    return w;
}

void
install_window_frame (Lisp_Window *w)
{
    DB(("install_window_frame (%s)\n", rep_STR(w->name)));
    if (!w->reparented && w->frame != 0 && !WINDOW_IS_GONE_P (w))
    {
      XSetWindowAttributes wa;

      XSelectInput (dpy, w->frame, FRAME_EVENTS);

      before_local_map (w);
      XReparentWindow (dpy, w->id, w->frame, -w->frame_x, -w->frame_y);
      w->reparented = TRUE;
      after_local_map (w);
      restack_window (w);

      if (queued_focus_id == w->id)
          queued_focus_id = w->frame;

      XAddToSaveSet (dpy, w->id);
      restack_frame_parts (w);
      reset_frame_parts (w);

      wa.win_gravity = StaticGravity;
      XChangeWindowAttributes (dpy, w->id, CWWinGravity, &wa);

      DB(("  reparented to %lx [%dx%d%+d%+d]\n",
          w->frame, w->frame_width, w->frame_height,
          w->frame_x, w->frame_y));
    }
}

void
remove_window_frame (Lisp_Window *w)
{
    DB(("remove_window_frame (%s)\n", rep_STR(w->name)));
    if (w->reparented && !WINDOW_IS_GONE_P (w))
    {
      XSetWindowAttributes wa;

      /* reparent the subwindow back to the root window */

      wa.win_gravity = w->attr.win_gravity;
      XChangeWindowAttributes (dpy, w->id, CWWinGravity, &wa);

      before_local_map (w);
      XReparentWindow (dpy, w->id, root_window, w->attr.x, w->attr.y);
      w->reparented = FALSE;
      after_local_map (w);
      restack_window (w);

      if (queued_focus_id == w->frame)
          queued_focus_id = w->id;

      if (!w->mapped)
          XRemoveFromSaveSet (dpy, w->id);
    }
}

/* Add the top-level window ID to the manager's data structures */
Lisp_Window *
add_window (Window id)
{
    char *tem;
    Lisp_Window *w = rep_ALLOC_CELL(sizeof (Lisp_Window));
    if (w != 0)
    {
      rep_GC_root gc_win;
      repv win = rep_VAL(w);
      XWindowChanges xwc;
      u_int xwcm;
      long supplied;
      XTextProperty prop;

      DB(("add_window (%lx)\n", id));

      if (id == root_window)
          DB(("  ** adding root window!?\n"));

      rep_data_after_gc += sizeof (Lisp_Window);
      memset (w, 0, sizeof (Lisp_Window));

      /* First initialise the Lisp stuff.. */
      w->next = window_list;
      window_list = w;
      w->car = window_type;
      w->id = id;
      w->saved_id = id;
      w->plist = Qnil;
      w->frame_style = Qnil;;
      w->icon_image = rep_NULL;
      w->name = rep_null_string ();

      /* have to put it somewhere until it finds the right place */
      insert_in_stacking_list_above_all (w);
      restack_window (w);

      /* ..now do the X11 stuff */

      XSelectInput (dpy, id, CLIENT_EVENTS);
      XGetWindowAttributes (dpy, id, &w->attr);
      DB(("  orig: width=%d height=%d x=%d y=%d\n",
          w->attr.width, w->attr.height, w->attr.x, w->attr.y));

      if (XGetWMName (dpy, id, &prop) && prop.value)
      {
          if (prop.nitems > 0)
          {
            char **list;
            int count;
            prop.nitems = strlen(prop.value);
            if (XmbTextPropertyToTextList (dpy, &prop, &list, &count)
                >= Success)
            {
                if (count > 0)
                  w->name = rep_string_dup (list[0]);
                XFreeStringList (list);
            }
          }
          XFree (prop.value);
      }
      w->full_name = w->name;
      if (XGetIconName (dpy, id, &tem))
      {
          w->icon_name = rep_string_dup (tem);
          XFree (tem);
      }
      else
          w->icon_name = w->name;

      w->wmhints = XGetWMHints (dpy, id);
      if (!XGetWMNormalHints (dpy, w->id, &w->hints, &supplied))
          w->hints.flags = 0;
      get_window_protocols (w);
      if (!XGetWMColormapWindows (dpy, w->id,
                            &w->cmap_windows, &w->n_cmap_windows))
      {
          w->n_cmap_windows = 0;
      }

      {
          /* Is the window shaped? */
          int xws, yws, xbs, ybs;
          u_int wws, hws, wbs, hbs;
          int bounding, clip;
          XShapeSelectInput (dpy, w->id, ShapeNotifyMask);
          XShapeQueryExtents (dpy, w->id, &bounding, &xws, &yws, &wws, &hws,
                        &clip, &xbs, &ybs, &wbs, &hbs);
          w->shaped = bounding ? 1 : 0;
      }

      DB(("  name=`%s' x=%d y=%d width=%d height=%d\n",
          rep_STR(w->name), w->attr.x, w->attr.y,
          w->attr.width, w->attr.height));

      xwcm = CWX | CWX | CWWidth | CWHeight | CWBorderWidth;
      xwc.x = w->attr.x;
      xwc.y = w->attr.y;
      xwc.width = w->attr.width;
      xwc.height = w->attr.height;
      xwc.border_width = 0;
      XConfigureWindow (dpy, id, xwcm, &xwc);

        w->visible = TRUE;
      w->mapped = TRUE;       /* only called from map request */

      if (initialising)
          Fwindow_put (rep_VAL (w), Qplaced, Qt);

      /* ..then call the add-window-hook's.. */
      rep_PUSHGC(gc_win, win);
      Fcall_window_hook (Qbefore_add_window_hook, rep_VAL(w), Qnil, Qnil);
      Fcall_window_hook (Qadd_window_hook, rep_VAL(w), Qnil, Qnil);
      rep_POPGC;

      /* In case the window disappeared during the hook call */
      if (!WINDOW_IS_GONE_P (w))
      {
          Fgrab_server ();

          /* this is where we create and reparent the window frame */
          create_window_frame (w);
          install_window_frame (w);

          /* this grabs bound events in the subwindow */
          grab_window_events (w, TRUE);

          Fungrab_server ();
      }
      else
          emit_pending_destroys ();

      if (!WINDOW_IS_GONE_P (w))
      {
          repv tem = Fwindow_get (rep_VAL(w), Qplaced);
          if (initialising || (tem && tem == Qnil))
          {
            /* ..then the place-window-hook.. */
            rep_PUSHGC(gc_win, win);
            Fcall_window_hook (Qplace_window_hook, rep_VAL(w), Qnil, Qor);
            rep_POPGC;
          }
      }
      Fwindow_put (rep_VAL(w), Qplaced, Qt);

      if (!WINDOW_IS_GONE_P (w))
          Fcall_window_hook (Qafter_add_window_hook, rep_VAL(w), Qnil, Qnil);

      if (!WINDOW_IS_GONE_P (w))
      {
          /* Tell the window where it ended up.. */
          send_synthetic_configure (w);
      }
    }
    return w;
}

/* Remove W from the managed windows. If DESTROYED is nil, then the
   window will be reparented back to the root window */
void
remove_window (Lisp_Window *w, bool destroyed, bool from_error)
{
    DB(("remove_window (%s, %s)\n",
      rep_STR(w->name), destroyed ? "destroyed" : "not-destroyed"));

    if (w->id != 0)
    {
      if (!destroyed && !from_error)
      {
          grab_window_events (w, FALSE);
          remove_window_frame (w);

          /* Restore original border width of the client */
          XSetWindowBorderWidth (dpy, w->id, w->attr.border_width);
      }

      if (!from_error)
          destroy_window_frame (w, FALSE);

      if (!WINDOW_IS_GONE_P (w))
          remove_from_stacking_list (w);

      if (!from_error)
          focus_off_window (w);

      w->id = 0;
      pending_destroys++;

      /* gc will do the rest... */
    }
    else if (w->frame != 0 && !from_error)
      destroy_window_frame (w, FALSE);
}

void
fix_window_size (Lisp_Window *w)
{
    Fgrab_server ();
    if (w->frame != 0 && w->rebuild_frame != 0)
      w->rebuild_frame (w);
    else
      XResizeWindow (dpy, w->id, w->attr.width, w->attr.height);
    Fungrab_server ();
}

/* Call destroy-notify-hook on any newly-dead windows */
void
emit_pending_destroys (void)
{
    if (pending_destroys > 0)
    {
      Lisp_Window *w;
    again:
      for (w = window_list; w != 0 && !rep_INTERRUPTP; w = w->next)
      {
          if (WINDOW_IS_GONE_P (w) && !w->destroyed)
          {
            w->destroyed = 1;
            Fcall_window_hook (Qdestroy_notify_hook,
                           rep_VAL(w), Qnil, Qnil);

            focus_off_window (w);

            /* gc may have reordered the list, so we have to start
               at the beginning again.. */
            goto again;
          }
      }
    }
    pending_destroys = 0;
}


/* Lisp functions */

DEFUN("window-get", Fwindow_get, Swindow_get,
      (repv win, repv prop), rep_Subr2) /*
::doc:sawfish.wm.windows.subrs#window-get::
window-get WINDOW PROPERTY

Return the value of the property named PROPERTY (a symbol) of WINDOW.

Note that these are Lisp properties not X properties.
::end:: */
{
    repv plist;
    rep_DECLARE1(win, XWINDOWP);
    plist = VWIN(win)->plist;
    while (rep_CONSP(plist) && rep_CONSP(rep_CDR(plist)))
    {
      if (rep_CAR(plist) == prop
          || (!rep_SYMBOLP(prop)
            && rep_value_cmp (rep_CAR(plist), prop) == 0))
      {
          return rep_CAR(rep_CDR(plist));
      }
      plist = rep_CDR(rep_CDR(plist));
    }
    return Qnil;
}

DEFUN("map-window-properties", Fmap_window_properties,
      Smap_window_properties, (repv fun, repv win), rep_Subr2) /*
::doc:sawfish.wm.windows.subrs#map-window-properties::
map-window-properties FUNCTION WINDOW

Call (FUNCTION PROPERTY VALUE) for all Lisp properties set on window
object WINDOW.
::end:: */
{
    repv ret = Qnil, plist;
    rep_GC_root gc_plist, gc_fun;
    rep_DECLARE2 (win, XWINDOWP);
    plist = VWIN(win)->plist;
    rep_PUSHGC (gc_plist, plist);
    rep_PUSHGC (gc_fun, fun);
    while (rep_CONSP(plist) && rep_CONSP(rep_CDR(plist)))
    {
      ret = rep_call_lisp2 (fun, rep_CAR (plist), rep_CADR (plist));
      if (ret == rep_NULL)
          break;
      plist = rep_CDDR (plist);
    }
    rep_POPGC; rep_POPGC;
    return ret;
}

void
register_property_monitor (repv prop,
                     void (*callback) (Lisp_Window *, repv, repv, repv))
{
    struct prop_handler *ph = rep_alloc (sizeof (struct prop_handler));
    ph->next = prop_handlers;
    prop_handlers = ph;
    ph->prop = prop;
    ph->callback = callback;
}    

DEFUN("window-put", Fwindow_put, Swindow_put,
      (repv win, repv prop, repv val), rep_Subr3) /*
::doc:sawfish.wm.windows.subrs#window-put::
window-put WINDOW PROPERTY VALUE

Set the value of the property named PROPERTY (a symbol) of WINDOW to VALUE.

Note that these are Lisp properties not X properties.
::end:: */
{
    repv plist;
    rep_DECLARE1(win, XWINDOWP);
    plist = VWIN(win)->plist;
    while (rep_CONSP(plist) && rep_CONSP(rep_CDR(plist)))
    {
      if (rep_CAR(plist) == prop
          || (!rep_SYMBOLP(prop)
            && rep_value_cmp (rep_CAR(plist), prop) == 0))
      {
          struct prop_handler *ph;
          for (ph = prop_handlers; ph != 0; ph = ph->next)
          {
            repv old = rep_CADR (plist);
            if (ph->prop == prop && old != val)
                ph->callback (VWIN (win), prop, old, val);
          }
          rep_CAR(rep_CDR(plist)) = val;
          return val;
      }
      plist = rep_CDR(rep_CDR(plist));
    }
    plist = Fcons(prop, Fcons(val, VWIN(win)->plist));
    if (plist != rep_NULL)
      VWIN(win)->plist = plist;
    return val;
}

DEFUN("window-name", Fwindow_name, Swindow_name, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-name::
window-name WINDOW

Return the name of window object WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->name;
}

DEFUN("window-full-name", Fwindow_full_name, Swindow_full_name,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-full-name::
window-full-name WINDOW

Return the full name of window object WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->full_name;
}

DEFUN("window-icon-name", Fwindow_icon_name, Swindow_icon_name,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-icon-name::
window-icon-name WINDOW

Return the name of window object WINDOW's icon.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->icon_name;
}

DEFUN("window-mapped-p", Fwindow_mapped_p, Swindow_mapped_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-mapped-p::
window-mapped-p WINDOW

Return t if the client window associated with object WINDOW is mapped.
(This doesn't necessarily mean that it is visible.)
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->mapped ? Qt : Qnil;
}

DEFUN("window-frame", Fwindow_frame, Swindow_frame, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-frame::
window-frame WINDOW

Return the frame object associated with WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->frame_style;
}

DEFUN("set-window-frame", Fset_window_frame, Sset_window_frame,
      (repv win, repv frame), rep_Subr2) /*
::doc:sawfish.wm.windows.subrs#set-window-frame::
set-window-frame WINDOW FRAME

Set the frame associated with the window object WINDOW to FRAME (a
list). If the window is mapped the old frame will be destroyed and a
new frame constructed as specified by FRAME.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    rep_DECLARE2(frame, rep_LISTP);
    Fgrab_server ();

    if (VWIN(win)->reparented)
      destroy_window_frame (VWIN(win), TRUE);

    VWIN(win)->frame_style = frame;

    if (VWIN(win)->reparented)
      create_window_frame (VWIN(win));

    Fungrab_server ();
    Fcall_window_hook (Qafter_framing_hook, win, Qnil, Qnil);
    return VWIN(win)->frame_style;
}

DEFUN("rebuild-frame", Frebuild_frame, Srebuild_frame, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#rebuild-frame::
rebuild-frame WINDOW

Reinitialises and recalibrates the window frame of WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (VWIN(win)->frame != 0 && VWIN(win)->rebuild_frame != 0)
    {
      VWIN(win)->rebuild_frame (VWIN(win));
      refresh_frame_parts (VWIN(win));
      Fcall_window_hook (Qafter_framing_hook, win, Qnil, Qnil);
    }
    return win;
}

DEFUN("window-position", Fwindow_position, Swindow_position,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-position::
window-position WINDOW

Return (X . Y) defining the current position of WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return Fcons (rep_MAKE_INT(VWIN(win)->attr.x),
              rep_MAKE_INT(VWIN(win)->attr.y));
}

DEFUN("window-dimensions", Fwindow_dimensions, Swindow_dimensions,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-dimensions::
window-dimensions WINDOW

Return (WIDTH . HEIGHT) defining the current dimensions of the client
window associated with WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return Fcons (rep_MAKE_INT(VWIN(win)->attr.width),
              rep_MAKE_INT(VWIN(win)->attr.height));
}

DEFUN("window-frame-dimensions", Fwindow_frame_dimensions,
      Swindow_frame_dimensions, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-frame-dimensions::
window-frame-dimensions WINDOW

Return (WIDTH . HEIGHT) defining the current dimensions of the frame
surrounding WINDOW.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (VWIN(win)->reparented)
    {
      return Fcons (rep_MAKE_INT(VWIN(win)->frame_width),
                  rep_MAKE_INT(VWIN(win)->frame_height));
    }
    else
      return Fwindow_dimensions (win);
}

DEFUN("window-frame-offset", Fwindow_frame_offset,
      Swindow_frame_offset, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-frame-offset::
window-frame-offset WINDOW

Return (X . Y) defining the offset from the origin of the client window
associated with WINDOW to its frame window.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return Fcons (rep_MAKE_INT(VWIN(win)->frame_x),
              rep_MAKE_INT(VWIN(win)->frame_y));
}

DEFUN("windowp", Fwindowp, Swindowp, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#windowp::
windowp ARG

Return t if ARG is a window object.
::end:: */
{
    return WINDOWP(win) ? Qt : Qnil;
}

DEFUN("set-input-focus", Fset_input_focus, Sset_input_focus,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#set-input-focus::
set-input-focus WINDOW

Set the input focus to WINDOW. If WINDOW is nil, then no window will
have the focus.
::end:: */
{
    if (win != Qnil && win != Qroot)
    {
      rep_DECLARE1(win, WINDOWP);
      focus_on_window (VWIN(win));
    }
    else
      focus_on_window (0);
    return win;
}

DEFUN("input-focus", Finput_focus, Sinput_focus, (void), rep_Subr0) /*
::doc:sawfish.wm.windows.subrs#input-focus::
input-focus

Return the window object that has the input focus, or nil if none does.
::end:: */
{
    return (focus_window == 0) ? Qnil : rep_VAL(focus_window);
}

DEFUN("window-wants-input-p", Fwindow_wants_input_p, Swindow_wants_input_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-wants-input-p::
window-wants-input-p WINDOW

Return t if the client window associated with object WINDOW has hinted
that it would like to be given the input focus when applicable.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (VWIN(win)->does_wm_take_focus)
      return Qt;
    else
      return window_input_hint_p (VWIN (win)) ? Qt : Qnil;
}

DEFUN("managed-windows", Fmanaged_windows, Smanaged_windows,
      (void), rep_Subr0) /*
::doc:sawfish.wm.windows.subrs#managed-windows::
managed-windows

Return a list of all known client window objects.
::end:: */
{
    repv list = Qnil;
    Lisp_Window *w = window_list;
    while (w != 0)
    {
      if (!WINDOW_IS_GONE_P (w))
          list = Fcons (rep_VAL(w), list);
      w = w->next;
    }
    return list;
}

DEFUN("get-window-by-id", Fget_window_by_id, Sget_window_by_id,
      (repv id), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#get-window-by-id::
get-window-by-id ID

Return the window object associated with xid ID, or nil.
::end:: */
{
    Lisp_Window *w;
    rep_DECLARE1(id, rep_INTEGERP);
    w = find_window_by_id (rep_get_long_uint (id));
    return w ? rep_VAL(w) : Qnil;
}

DEFUN("stacking-order", Fstacking_order, Sstacking_order, (void), rep_Subr0) /*
::doc:sawfish.wm.windows.subrs#stacking-order::
stacking-order

Return a list of windows defining the current stacking order of all
client windows.
::end:: */
{
    return make_stacking_list ();
}

DEFUN("window-visibility", Fwindow_visibility, Swindow_visibility,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-visibility::
window-visibility WINDOW

Return a symbol defining the visibility of WINDOW. Possible returned
symbols are `fully-obscured', `partially-obscured' or `unobscured'.
::end:: */
{
    repv sym = Qnil;
    rep_DECLARE1(win, WINDOWP);
    switch (VWIN(win)->frame_vis)
    {
    case VisibilityFullyObscured:
      sym = Qfully_obscured;
      break;

    case VisibilityPartiallyObscured:
      sym = Qpartially_obscured;
      break;

    case VisibilityUnobscured:
      sym = Qunobscured;
      break;
    }
    return sym;
}

DEFUN("window-urgent-p", Fwindow_urgent_p, Swindow_urgent_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-urgent-p::
window-urgent-p WINDOW

Return true if the `Urgency' hint of the window associated with WINDOW
is set.
::end:: */
{
    rep_DECLARE1 (win, WINDOWP);
    return ((VWIN (win)->wmhints
           && VWIN (win)->wmhints->flags & XUrgencyHint) ? Qt : Qnil);
}

DEFUN("window-shaped-p", Fwindow_shaped_p, Swindow_shaped_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-shaped-p::
window-shaped-p WINDOW

Return non-nil if WINDOW is shaped.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->shaped ? Qt : Qnil;
}

DEFUN("hide-window", Fhide_window, Shide_window, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#hide-window::
hide-window WINDOW

Prevent WINDOW from being displayed. See `show-window'.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (VWIN(win)->visible)
    {
      if (VWIN(win)->mapped)
      {
          if (VWIN(win)->frame)
            XUnmapWindow (dpy, VWIN(win)->frame);
          if (!VWIN(win)->client_unmapped)
          {
            before_local_map (VWIN(win));
            XUnmapWindow (dpy, VWIN(win)->id);
            VWIN(win)->client_unmapped = 1;
            after_local_map (VWIN(win));
          }
      }
      VWIN(win)->visible = 0;
      reset_frame_parts (VWIN(win));
    }
    return win;
}

DEFUN("show-window", Fshow_window, Sshow_window, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#show-window::
show-window WINDOW

Ensure that WINDOW (if it has been mapped) is visible. See `hide-window'.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (!VWIN(win)->visible)
    {
      if (VWIN(win)->mapped)
      {
          if (VWIN(win)->client_unmapped && !VWIN(win)->client_hidden)
          {
            before_local_map (VWIN(win));
            XMapWindow (dpy, VWIN(win)->id);
            VWIN(win)->client_unmapped = 0;
            after_local_map (VWIN(win));
          }
          if (VWIN(win)->frame)
            XMapWindow (dpy, VWIN(win)->frame);
      }
      VWIN(win)->visible = 1;
    }
    return win;
}

DEFUN("window-visible-p", Fwindow_visible_p, Swindow_visible_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-visible-p::
window-visible-p WINDOW

Return t if WINDOW is currently visible (i.e. not hidden, see `hide-window').
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->visible ? Qt : Qnil;
}

DEFUN("window-framed-p", Fwindow_framed_p, Swindow_framed_p,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-framed-p::
window-framed-p WINDOW

Return t if WINDOW has been reparented to a frame window.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->reparented ? Qt : Qnil;
}

DEFUN("window-frame-id", Fwindow_frame_id, Swindow_frame_id,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-frame-id::
window-frame-id WINDOW

Return the numeric id of the framing window associated with object
WINDOW. Returns nil if the client window has no frame.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->frame ? rep_MAKE_INT (VWIN(win)->frame) : Qnil;
}

DEFUN("window-id", Fwindow_id, Swindow_id, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-id::
window-id WINDOW

Return the numeric id of the client window associated with object
WINDOW. Returns nil if the client window has been deleted.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return VWIN(win)->id ? rep_MAKE_INT (VWIN(win)->id) : Qnil;
}

DEFUN("window-group-id", Fwindow_group_id, Swindow_group_id,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-group-id::
window-group-id WINDOW

Return the numeric id defining the leader of the group that WINDOW is a
member of, or nil if it is not a member of a group.
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    if (VWIN(win)->wmhints == 0)
      return Qnil;
    return ((VWIN(win)->wmhints->flags & WindowGroupHint)
          ? rep_MAKE_INT (VWIN(win)->wmhints->window_group)
          : Qnil);
}

DEFUN("window-border-width", Fwindow_border_width, Swindow_border_width,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-border-width::
window-border-width WINDOW
::end:: */
{
    rep_DECLARE1(win, WINDOWP);
    return rep_MAKE_INT(VWIN(win)->attr.border_width);
}

DEFUN("window-size-hints", Fwindow_size_hints, Swindow_size_hints,
      (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-size-hints::
window-size-hints WINDOW

Return an alist defining the size-hints specified by the client window
associated with WINDOW. Possible keys in the alist are `min-height',
`max-height', `min-width', `max-width', `height-inc', `width-inc',
`min-aspect', `max-aspect', `base-height', `base-width',
`user-position', `program-position', `user-size', `program-size',
`window-gravity', `border-size'.
::end:: */
{
    repv ret = Qnil;
    XSizeHints *hints;
    long flags;
    rep_DECLARE1(win, WINDOWP);

    hints = &VWIN(win)->hints;
    flags = hints->flags;

    /* Some sanity checking */
    if ((flags & PMinSize) 
      && (hints->min_width < 0 || hints->min_height < 0))
      flags &= ~PMinSize;
    if ((flags & PMaxSize)
      && (hints->max_width <= 0 || hints->max_height <= 0))
      flags &= ~PMaxSize;
    if ((flags & PResizeInc)
      && (hints->width_inc <= 0 || hints->width_inc <= 0))
      flags &= ~PResizeInc;
    if ((flags & PBaseSize)
      && (hints->base_width <= 0 || hints->base_height <= 0))
      flags &= ~PBaseSize;

    if (flags & PMinSize)
    {
      ret = Fcons (Fcons (Qmin_width, rep_MAKE_INT(MAX(hints->min_width,1))),
                 Fcons (Fcons (Qmin_height, rep_MAKE_INT(MAX(hints->min_height, 1))), ret));
    }
    if (flags & PMaxSize)
    {
      ret = Fcons (Fcons (Qmax_width, rep_MAKE_INT(hints->max_width)),
                 Fcons (Fcons (Qmax_height,
                           rep_MAKE_INT(hints->max_height)), ret));
    }
    if (flags & PResizeInc)
    {
      ret = Fcons (Fcons (Qwidth_inc, rep_MAKE_INT(hints->width_inc)),
                 Fcons (Fcons (Qheight_inc,
                           rep_MAKE_INT(hints->height_inc)), ret));
    }
    if (flags & PBaseSize)
    {
      ret = Fcons (Fcons (Qbase_width, rep_MAKE_INT(hints->base_width)),
                 Fcons (Fcons (Qbase_height,
                           rep_MAKE_INT(hints->base_height)), ret));
    }
    if (flags & PAspect)
    {
      ret = Fcons (Fcons (Qmin_aspect,
                      Fcons (rep_MAKE_INT(hints->min_aspect.x),
                           rep_MAKE_INT(hints->min_aspect.y))),
                 Fcons (Fcons (Qmax_aspect,
                           Fcons (rep_MAKE_INT(hints->max_aspect.x),
                                rep_MAKE_INT(hints->max_aspect.y))),
                      ret));
    }
    if (flags & USPosition)
      ret = Fcons (Fcons (Quser_position, Qt), ret);
    else if (flags & PPosition)
      ret = Fcons (Fcons (Qprogram_position, Qt), ret);
    if (flags & USSize)
      ret = Fcons (Fcons (Quser_size, Qt), ret);
    else if (flags & PSize)
      ret = Fcons (Fcons (Qprogram_size, Qt), ret);
    if ((flags & PWinGravity)
      && hints->win_gravity >= ForgetGravity
      && hints->win_gravity <= StaticGravity)
    {
      ret = Fcons (Fcons (Qwindow_gravity,
                      gravity_map[hints->win_gravity]), ret);
    }
    return ret;
}

DEFUN("call-window-hook", Fcall_window_hook, Scall_window_hook,
      (repv hook, repv win, repv args, repv type), rep_Subr4) /*
::doc:sawfish.wm.windows.subrs#call-window-hook::
call-window-hook HOOK WINDOW &optional ARGS HOOK-TYPE

Call HOOK for WINDOW with extra arguments ARGS. See `call-hook' for a
description of HOOK-TYPE.
::end:: */
{
    repv tem;
    rep_GC_root gc_hook, gc_args, gc_type;
    rep_DECLARE1(hook, rep_SYMBOLP);
    rep_DECLARE2(win, XWINDOWP);
    args = Fcons (win, args);
    rep_PUSHGC(gc_hook, hook);
    rep_PUSHGC(gc_args, args);
    rep_PUSHGC(gc_type, type);
    tem = Fwindow_get (win, hook);
    if (tem && tem != Qnil)
    {
      tem = Fcall_hook (tem, args, type);
      if (!tem || (type == Qand && tem == Qnil)
          || (type == Qor && tem != Qnil))
      {
          goto out;
      }
    }
    tem = Fcall_hook (hook, args, type);
out:
    rep_POPGC; rep_POPGC; rep_POPGC;
    return tem;
}

DEFUN("window-icon-image", Fwindow_icon_image,
      Swindow_icon_image, (repv win), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#window-icon-image::
window-icon-image WINDOW

Returns an image object representing the icon currently associated with
WINDOW. Returns the symbol `nil' if no such image.
::end:: */
{
   rep_DECLARE1 (win, WINDOWP);

   if (VWIN (win)->icon_image == rep_NULL)
   {
       Window pixmap_id = 0, mask_id = 0;

       if (VWIN (win)->wmhints != 0)
       {
         if (VWIN (win)->wmhints->flags & IconPixmapHint
             && VWIN (win)->wmhints->icon_pixmap != 0)
         {
             pixmap_id = VWIN (win)->wmhints->icon_pixmap;
         }

         if (VWIN (win)->wmhints->flags & IconMaskHint
             && VWIN (win)->wmhints->icon_mask != 0)
         {
             mask_id = VWIN (win)->wmhints->icon_mask;
         }
       }

       if (pixmap_id == 0 && !WINDOW_IS_GONE_P (VWIN (win)))
       {
         Atom actual_type;
         int actual_format;
         long nitems, bytes_after;
         union {
             u_long *l;
             u_char *c;
         } data;

         static Atom kwm_win_icon = 0;

         if (kwm_win_icon == 0)
             kwm_win_icon = XInternAtom (dpy, "KWM_WIN_ICON", False);

         data.l = 0;
         if (XGetWindowProperty (dpy, VWIN (win)->id, kwm_win_icon,
                           0, 2, False, kwm_win_icon,
                           &actual_type, &actual_format,
                           &nitems, &bytes_after,
                           &data.c) == Success
             && actual_type == kwm_win_icon
             && bytes_after == 0)
         {
             pixmap_id = data.l[0];
             mask_id = data.l[1];
         }
         if (data.l != 0)
             XFree (data.l);
       }

       VWIN (win)->icon_image = Qnil;

       if (pixmap_id != 0)
       {
         VWIN (win)->icon_image = (Fmake_image_from_x_drawable
                             (rep_MAKE_INT (pixmap_id),
                              mask_id ? rep_MAKE_INT (mask_id) : Qnil));
       }
   }

   return VWIN (win)->icon_image;
}

DEFUN ("map-windows", Fmap_windows, Smap_windows, (repv fun), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#map-windows::
map-windows FUN

Map the single-parameter function FUN over all existing windows.
::end:: */
{
    repv w;
    rep_GC_root gc_fun, gc_w;
    repv ret = Qnil;

    rep_PUSHGC (gc_fun, fun);
    rep_PUSHGC (gc_w, w);
    for (w = rep_VAL (window_list); w != rep_NULL; w = rep_VAL (VWIN(w)->next))
    {
      if (!WINDOW_IS_GONE_P (VWIN (w)))
      {
          ret = rep_call_lisp1 (fun, w);
          if (ret == rep_NULL)
            break;
      }
    }
    rep_POPGC; rep_POPGC;
    return ret;
}

DEFUN ("filter-windows", Ffilter_windows,
       Sfilter_windows, (repv pred), rep_Subr1) /*
::doc:sawfish.wm.windows.subrs#filter-windows::
filter-windows PRED

Return the list of windows that match the predicate function PRED.
::end:: */
{
    repv w, output = Qnil, *ptr = &output;
    rep_GC_root gc_pred, gc_w, gc_output;

    rep_PUSHGC(gc_pred, pred);
    rep_PUSHGC(gc_w, w);
    rep_PUSHGC(gc_output, output);
    for (w = rep_VAL (window_list); w != rep_NULL; w = rep_VAL (VWIN(w)->next))
    {
      if (!WINDOW_IS_GONE_P (VWIN (w)))
      {
          repv tem = rep_call_lisp1 (pred, w);
          if (tem == rep_NULL)
          {
            output = rep_NULL;
            break;
          }
          if (tem != Qnil)
          {
            *ptr = Fcons (w, Qnil);
            ptr = rep_CDRLOC (*ptr);
          }
      }
    }
    rep_POPGC; rep_POPGC; rep_POPGC;
    return output;
}


/* type hooks */

static int
window_cmp (repv w1, repv w2)
{
    return w1 != w2;
}

static void
window_prin (repv stream, repv win)
{
    char buf[128];
    sprintf (buf, "#<window %lx>", VWIN(win)->id);
    rep_stream_puts (stream, buf, -1, FALSE);
}

static void
window_mark (repv win)
{
    rep_MARKVAL(VWIN(win)->plist);
    rep_MARKVAL(VWIN(win)->frame_style);
    mark_frame_parts (VWIN(win));
    rep_MARKVAL(VWIN(win)->name);
    rep_MARKVAL(VWIN(win)->full_name);
    rep_MARKVAL(VWIN(win)->icon_name);
    rep_MARKVAL(VWIN(win)->icon_image);
}

static void
window_mark_type (void)
{
    Lisp_Window *w;
    struct prop_handler *ph;
    for (w = window_list; w != 0; w = w->next)
    {
      if (!WINDOW_IS_GONE_P (w) || !w->destroyed)
          rep_MARKVAL(rep_VAL(w));
    }
    for (ph = prop_handlers; ph != 0; ph = ph->next)
      rep_MARKVAL (ph->prop);
    rep_MARKVAL (rep_VAL (focus_window));
}

static void
window_sweep (void)
{
    Lisp_Window **ptr = &window_list;
    while (*ptr != 0)
    {
      Lisp_Window *w = *ptr;
      if (!rep_GC_CELL_MARKEDP(rep_VAL(w)))
      {
          assert (!window_in_stacking_list_p (w));
          destroy_window_frame (w, FALSE);
          if (w->wmhints != 0)
            XFree (w->wmhints);
          if (w->n_cmap_windows > 0)
            XFree (w->cmap_windows);
          *ptr = w->next;
          rep_FREE_CELL(w);
      }
      else
      {
          ptr = &(w->next);
          rep_GC_CLR_CELL(rep_VAL(w));
      }
    }
}


/* initialisation */

void
manage_windows (void)
{
    Window root, parent, *children, focus;
    unsigned int nchildren, i;
    int revert_to;

    Fgrab_server ();

    XGetInputFocus (dpy, &focus, &revert_to);
    if (focus == PointerRoot)
    {
      Window root, child;
      Bool found;
      int rx, ry, wx, wy;
      unsigned mask;

      found = XQueryPointer (dpy, DefaultRootWindow(dpy), &root,
                         &child, &rx, &ry, &wx, &wy, &mask);
      if (!found)
      {
          found = XQueryPointer (dpy, root, &root, &child,
                           &rx, &ry, &wx, &wy, &mask);
      }
      focus = child;
    }

    XQueryTree (dpy, root_window, &root, &parent, &children, &nchildren);
    initialising = TRUE;
    for (i = 0; i < nchildren; i++)
    {
      if (mapped_not_override_p (children[i]))
      {
          XEvent fake;
          Lisp_Window *w;
          fake.xmaprequest.window = children[i];
          /* Make sure the window is initially unmapped. We expect to
             get map-notify events when we later remap it.. #67601 */
          XUnmapWindow (dpy, children[i]);
          map_request (&fake);
          w = find_window_by_id (children[i]);
      }
    }
    initialising = FALSE;
    if (nchildren > 0)
      XFree (children);

    /* Try to keep the current focus state. */
    focus_on_window (0);
    if (focus != None)
    {
      Lisp_Window *w = find_window_by_id (focus);
      if (w != 0)
          focus_on_window (w);
    }

    Fungrab_server ();
    Fcall_hook (Qafter_initialization_hook, Qnil, Qnil);
}

void
windows_init (void)
{
    repv tem;
    window_type = rep_register_new_type ("window", window_cmp, window_prin,
                               window_prin, window_sweep,
                               window_mark, window_mark_type,
                               0, 0, 0, 0, 0, 0);

    tem = rep_push_structure ("sawfish.wm.windows.subrs");
    rep_ADD_SUBR(Swindow_get);
    rep_ADD_SUBR(Smap_window_properties);
    rep_ADD_SUBR(Swindow_put);
    rep_ADD_SUBR(Swindow_name);
    rep_ADD_SUBR(Swindow_full_name);
    rep_ADD_SUBR(Swindow_icon_name);
    rep_ADD_SUBR(Swindow_mapped_p);
    rep_ADD_SUBR(Swindow_frame);
    rep_ADD_SUBR(Sset_window_frame);
    rep_ADD_SUBR(Srebuild_frame);
    rep_ADD_SUBR(Swindow_position);
    rep_ADD_SUBR(Swindow_dimensions);
    rep_ADD_SUBR(Swindow_frame_dimensions);
    rep_ADD_SUBR(Swindow_frame_offset);
    rep_ADD_SUBR(Swindowp);
    rep_ADD_SUBR(Sset_input_focus);
    rep_ADD_SUBR(Sinput_focus);
    rep_ADD_SUBR(Swindow_wants_input_p);
    rep_ADD_SUBR(Smanaged_windows);
    rep_ADD_SUBR(Sget_window_by_id);
    rep_ADD_SUBR(Sstacking_order);
    rep_ADD_SUBR(Swindow_visibility);
    rep_ADD_SUBR(Swindow_urgent_p);
    rep_ADD_SUBR(Swindow_shaped_p);
    rep_ADD_SUBR(Shide_window);
    rep_ADD_SUBR(Sshow_window);
    rep_ADD_SUBR(Swindow_visible_p);
    rep_ADD_SUBR(Swindow_framed_p);
    rep_ADD_SUBR(Swindow_frame_id);
    rep_ADD_SUBR(Swindow_id);
    rep_ADD_SUBR(Swindow_group_id);
    rep_ADD_SUBR(Swindow_size_hints);
    rep_ADD_SUBR(Scall_window_hook);
    rep_ADD_SUBR(Swindow_border_width);
    rep_ADD_SUBR(Swindow_icon_image);
    rep_ADD_SUBR(Smap_windows);
    rep_ADD_SUBR(Sfilter_windows);
    rep_pop_structure (tem);

    rep_INTERN_SPECIAL(before_add_window_hook);
    rep_INTERN_SPECIAL(add_window_hook);
    rep_INTERN_SPECIAL(after_add_window_hook);
    rep_INTERN_SPECIAL(place_window_hook);
    rep_INTERN(placed);
    rep_INTERN_SPECIAL(after_framing_hook);
    rep_INTERN_SPECIAL(after_initialization_hook);
    rep_INTERN_SPECIAL(remove_window_hook);

    rep_INTERN(fully_obscured);
    rep_INTERN(partially_obscured);
    rep_INTERN(unobscured);

    rep_INTERN(min_width);
    rep_INTERN(min_height);
    rep_INTERN(max_width);
    rep_INTERN(max_height);
    rep_INTERN(width_inc);
    rep_INTERN(height_inc);
    rep_INTERN(base_width);
    rep_INTERN(base_height);
    rep_INTERN(min_aspect);
    rep_INTERN(max_aspect);
    rep_INTERN(user_size);
    rep_INTERN(user_position);
    rep_INTERN(program_size);
    rep_INTERN(program_position);
    rep_INTERN(window_gravity);
    rep_INTERN(forget);
    rep_INTERN(static);
    rep_INTERN(north_west);
    rep_INTERN(north);
    rep_INTERN(north_east);
    rep_INTERN(west);
    rep_INTERN(center);
    rep_INTERN(east);
    rep_INTERN(south_west);
    rep_INTERN(south);
    rep_INTERN(south_east);

    gravity_map[ForgetGravity] = Qforget;
    gravity_map[NorthWestGravity] = Qnorth_west;
    gravity_map[NorthGravity] = Qnorth;
    gravity_map[NorthEastGravity] = Qnorth_east;
    gravity_map[WestGravity] = Qwest;
    gravity_map[CenterGravity] = Qcenter;
    gravity_map[EastGravity] = Qeast;
    gravity_map[SouthWestGravity] = Qsouth_west;
    gravity_map[SouthGravity] = Qsouth;
    gravity_map[SouthEastGravity] = Qsouth_east;
    gravity_map[StaticGravity] = Qstatic;
}

void
windows_kill (void)
{
    Lisp_Window *w = window_list;
    repv next;
    rep_GC_root gc_next;
    rep_PUSHGC (gc_next, next);
    while (w != 0)
    {
      next = rep_VAL (w->next);
      Fcall_window_hook (Qremove_window_hook, rep_VAL (w), Qnil, Qnil);
      remove_window (w, FALSE, FALSE);
      w = VWIN (next);
    }
}

Generated by  Doxygen 1.6.0   Back to index