Function: delete-window-internal

delete-window-internal is a function defined in window.c.

Signature

(delete-window-internal WINDOW)

Documentation

Remove WINDOW from its frame.

WINDOW defaults to the selected window. Return nil. Signal an error when WINDOW is the only window on its frame.

Source Code

// Defined in /usr/src/emacs/src/window.c
{
  Lisp_Object parent, sibling, frame, root;
  struct window *w, *p, *s, *r;
  struct frame *f;
  bool horflag, before_sibling = false;

  w = decode_any_window (window);
  XSETWINDOW (window, w);
  if (NILP (w->contents))
    /* It's a no-op to delete an already deleted window.  */
    return Qnil;

  parent = w->parent;
  if (NILP (parent))
    /* Never delete a minibuffer or frame root window.  */
    error ("Attempt to delete minibuffer or sole ordinary window");
  else if (NILP (w->prev) && NILP (w->next))
    /* Rather bow out here, this case should be handled on the Elisp
       level.  */
    error ("Attempt to delete sole window of parent");

  p = XWINDOW (parent);
  horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);

  frame = WINDOW_FRAME (w);
  f = XFRAME (frame);

  root = FRAME_ROOT_WINDOW (f);
  r = XWINDOW (root);

  /* Unlink WINDOW from window tree.  */
  if (NILP (w->prev))
    /* Get SIBLING below (on the right of) WINDOW.  */
    {
      /* before_sibling means WINDOW is the first child of its
	 parent and thus before the sibling.  */
      before_sibling = true;
      sibling = w->next;
      s = XWINDOW (sibling);
      wset_prev (s, Qnil);
      wset_combination (p, horflag, sibling);
    }
  else
    /* Get SIBLING above (on the left of) WINDOW.  */
    {
      sibling = w->prev;
      s = XWINDOW (sibling);
      wset_next (s, w->next);
      if (!NILP (s->next))
	wset_prev (XWINDOW (s->next), sibling);
    }

  if (window_resize_check (r, horflag)
      && (XFIXNUM (r->new_pixel)
	  == (horflag ? r->pixel_width : r->pixel_height)))
    /* We can delete WINDOW now.  */
    {

      /* Block input.  */
      block_input ();
      xwidget_view_delete_all_in_window (w);
      window_resize_apply (p, horflag);
      /* If this window is referred to by the dpyinfo's mouse
	 highlight, invalidate that slot to be safe (Bug#9904).  */
      if (!FRAME_INITIAL_P (f))
	{
	  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);

	  if (EQ (hlinfo->mouse_face_window, window))
	    hlinfo->mouse_face_window = Qnil;
	}

      fset_redisplay (f);
      Vwindow_list = Qnil;

      wset_next (w, Qnil);  /* Don't delete w->next too.  */
      free_window_matrices (w);

      if (WINDOWP (w->contents))
	{
	  delete_all_child_windows (w->contents);
	  wset_combination (w, false, Qnil);
	}
      else
	{
	  unshow_buffer (w);
	  unchain_marker (XMARKER (w->pointm));
	  unchain_marker (XMARKER (w->old_pointm));
	  unchain_marker (XMARKER (w->start));
	  wset_buffer (w, Qnil);
	}

      if (NILP (s->prev) && NILP (s->next))
	  /* A matrjoshka where SIBLING has become the only child of
	     PARENT.  */
	{
	  /* Put SIBLING into PARENT's place.  */
	  replace_window (parent, sibling, false);
	  /* Have SIBLING inherit the following three slot values from
	     PARENT (the combination_limit slot is not inherited).  */
	  wset_normal_cols (s, p->normal_cols);
	  wset_normal_lines (s, p->normal_lines);
	  /* Mark PARENT as deleted.  */
	  wset_combination (p, false, Qnil);
	  /* Try to merge SIBLING into its new parent.  */
	  recombine_windows (sibling);
	}

      adjust_frame_glyphs (f);

      if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
	/* We apparently deleted the frame's selected window; use the
	   frame's first window as substitute but don't record it yet.
	   `delete-window' may have something better up its sleeves.  */
	{
	  /* Use the frame's first window as fallback ...  */
	  Lisp_Object new_selected_window = Fframe_first_window (frame);

	  if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
	    Fselect_window (new_selected_window, Qt);
	  else
	    /* Do not clear f->select_mini_window_flag here.  If the
	       last selected window on F was an active minibuffer, we
	       want to return to it on a later Fselect_frame.  */
	    fset_selected_window (f, new_selected_window);
	}

      unblock_input ();
      FRAME_WINDOW_CHANGE (f) = true;
    }
  else
    /* We failed: Relink WINDOW into window tree.  */
    {
      if (before_sibling)
	{
	  wset_prev (s, window);
	  wset_combination (p, horflag, window);
	}
      else
	{
	  wset_next (s, window);
	  if (!NILP (w->next))
	    wset_prev (XWINDOW (w->next), window);
	}
      error ("Deletion failed");
    }

  return Qnil;
}