From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: joakim@verona.se Newsgroups: gmane.emacs.devel Subject: [PATCH] Window-groups Date: Sun, 22 Jun 2008 21:07:12 +0200 Message-ID: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1214161658 27155 80.91.229.12 (22 Jun 2008 19:07:38 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 22 Jun 2008 19:07:38 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Jun 22 21:08:22 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1KAUvG-0006PY-1Y for ged-emacs-devel@m.gmane.org; Sun, 22 Jun 2008 21:08:22 +0200 Original-Received: from localhost ([127.0.0.1]:51797 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KAUuQ-00056F-J3 for ged-emacs-devel@m.gmane.org; Sun, 22 Jun 2008 15:07:30 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KAUuM-000569-Ed for emacs-devel@gnu.org; Sun, 22 Jun 2008 15:07:26 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KAUuI-00055o-Rl for emacs-devel@gnu.org; Sun, 22 Jun 2008 15:07:25 -0400 Original-Received: from [199.232.76.173] (port=57972 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KAUuI-00055g-NF for emacs-devel@gnu.org; Sun, 22 Jun 2008 15:07:22 -0400 Original-Received: from iwfs.imcode.com ([82.115.149.64]:51558 helo=gate.verona.se) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KAUuI-0004wO-Bs for emacs-devel@gnu.org; Sun, 22 Jun 2008 15:07:22 -0400 Original-Received: from chopper (IDENT:1005@localhost [127.0.0.1]) by gate.verona.se (8.13.4/8.11.4) with ESMTP id m5MJ7B9a027620 for ; Sun, 22 Jun 2008 21:07:13 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-detected-kernel: by monty-python.gnu.org: Linux 2.4-2.6 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:99706 Archived-At: --=-=-= Heres a patch to implement Window-groups in Emacs, which I submit for review. Theres comments in the patch to explain what Window-groups are in practice. In brief, the aim is to create Emacs primitives useful to ECB like frameworks. The code builds on top of the already comitted window-properties code. The patch has C level changes and an elisp interface. To understand the design rationale, please read previous rather long-winded window group threads. The patch is a joint effort between me, Stefan Monnier, Chong Yidong, and Martin Rudalics. --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=emacs-winprop.diff === modified file 'lisp/window.el' --- lisp/window.el 2008-06-17 22:33:06 +0000 +++ lisp/window.el 2008-06-22 12:25:44 +0000 @@ -1625,5 +1625,77 @@ (define-key ctl-x-map "+" 'balance-windows) (define-key ctl-x-4-map "0" 'kill-buffer-and-window) + +;; Below are functions for managing window-groups. Window +;; groups allow windows in a frame a degree of separation from other +;; windows in the same frame, similar to the way windows in different +;; frames are separated from each other. + +;; Here's some examples. + +;; Make a new frame and split it vertically: +;; (split-window-horizontally) +;; Call the left side the "Context Area" and the left one the "Edit Area". +;; Now make the "Context Area" into a group: +;; (window-group-create (selected-window)) +;; Theres actually two groups now, the "Context Area" and the default "Edit Area". +;; Now try "c-x o". Notice that you dont go to the "Edit Area". +;; Now try splitting the "Context Area" with "c-x 2", and switch buffers a bit +;; Now try removing windows with "c-x 0". Notice that only windows in the +;; current group are affected. +;; To return the state as it was: +;; (window-group-dissolve (window-group (selected-window))) + + +(defun window-group (window) + "Return the window group object that WINDOW belongs to. +Return nil if WINDOW is not in a window group." + (window-parameter window 'group)) + +(defun window-group-member-p (window group) + "Non nil if WINDOW is a member of GROUP." + (eq group (window-group window))) + +(defun window-group-members (group) + "Return all windows in GROUP. +Must be in selected frame." + (let ((group-windows ())) + (walk-windows + (lambda (w) + (when (window-group-member-p w group ) + (push w group-windows)))) + group-windows)) + +(defvar window-group--counter 0 + "An internal variable to keep track of window groups.") + +(defun window-group-create (window) + "Return a window group object with WINDOW as its only member. +An error is signalled if WINDOW is not visible or already part of +a group." + (if (window-group window) + (error "Window %s is already part of group %s" + ;;TODO check that the resulting error is not nonsensical + window (window-group window))) + ;;TODO we should now test for window visibility + (setq window-group--counter (1+ window-group--counter)) + (let* ((name (concat "group-" (number-to-string window-group--counter))) + (group (make-symbol name))) + (set-window-parameter window 'group group) + group)) + +(defun window-group-dissolve (group) + "Dissolve the window group object GROUP. +The windows in the group are not deleted." + (let ((group-windows (window-group-members group))) + (if (null group-windows) + (error "No group %s on current frame" group) + ;;TODO I think the group id is not suitable for printing! + (dolist (win group-windows) + (set-window-parameter win 'group nil))))) + +(provide 'window-group) + + ;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9 ;;; window.el ends here === modified file 'src/window.c' --- src/window.c 2008-06-10 22:08:42 +0000 +++ src/window.c 2008-06-19 13:25:41 +0000 @@ -54,6 +54,7 @@ Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; Lisp_Object Qdisplay_buffer; Lisp_Object Qscroll_up, Qscroll_down; +Lisp_Object Qgroup; Lisp_Object Qwindow_size_fixed; extern Lisp_Object Qleft_margin, Qright_margin; @@ -82,7 +83,8 @@ Lisp_Object *)); static int foreach_window_1 P_ ((struct window *, int (* fn) (struct window *, void *), - void *)); + void *, + int)); static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); /* This is the window in which the terminal's cursor should @@ -1041,7 +1043,7 @@ window = Qnil; cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part; - foreach_window (f, check_window_containing, &cw); + foreach_window (f, check_window_containing, &cw, 1); /* If not found above, see if it's in the tool bar window, if a tool bar exists. */ @@ -1733,7 +1735,8 @@ static Lisp_Object window_list () { - if (!CONSP (Vwindow_list)) + //if(!CONSP (Vwindow_list)) + if (1) //never cache the window list for now FIXME { Lisp_Object tail; @@ -1746,7 +1749,7 @@ new windows at the front of args[1], which means we have to reverse this list at the end. */ args[1] = Qnil; - foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]); + foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1], 0); args[0] = Vwindow_list; args[1] = Fnreverse (args[1]); Vwindow_list = Fnconc (2, args); @@ -2213,7 +2216,7 @@ break; case DELETE_OTHER_WINDOWS: - if (!EQ (window, obj)) + if (!EQ (window, obj) ) Fdelete_window (window); break; @@ -3882,6 +3885,12 @@ adjust_glyphs (fo); Fset_window_buffer (new, o->buffer, Qt); + /* make the new window inherit group properties. We + inherit only those atm, because its not obvious that all + properties should be inherited + */ + if(!NILP(Fwindow_parameter(window, Qgroup))) + Fset_window_parameter(new, Qgroup, Fwindow_parameter(window, Qgroup)); return new; } @@ -6826,17 +6835,20 @@ /* Call FN for all leaf windows on frame F. FN is called with the first argument being a pointer to the leaf window, and with - additional argument USER_DATA. Stops when FN returns 0. */ + additional argument USER_DATA. Stops when FN returns 0. + ALLWINDOWS 1 means iterate every window, else only the group of the selected window +*/ void -foreach_window (f, fn, user_data) +foreach_window (f, fn, user_data, allwindows) struct frame *f; int (* fn) P_ ((struct window *, void *)); void *user_data; + int allwindows; { /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */ if (WINDOWP (FRAME_ROOT_WINDOW (f))) - foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data); + foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data,allwindows); } @@ -6846,22 +6858,31 @@ Stop when FN returns 0. Value is 0 if stopped by FN. */ static int -foreach_window_1 (w, fn, user_data) +foreach_window_1 (w, fn, user_data, allwindows) struct window *w; int (* fn) P_ ((struct window *, void *)); void *user_data; + int allwindows; { int cont; - + struct window *current_window=XWINDOW(selected_window); + register Lisp_Object group = Fcdr(Fassq(Qgroup, current_window->window_parameters)); + Lisp_Object group2; for (cont = 1; w && cont;) { if (!NILP (w->hchild)) - cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data); + cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data,allwindows); else if (!NILP (w->vchild)) - cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data); - else - cont = fn (w, user_data); - + cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data,allwindows); + else{ + //only call fn if the group of the frames selected window + //is the same as the group of the current window in the loop. + group2=Fcdr(Fassq(Qgroup,w->window_parameters)); + debug_print(group); + debug_print(group2); + if (allwindows || EQ(group , group2 )) + cont = fn (w, user_data); + } w = NILP (w->next) ? 0 : XWINDOW (w->next); } @@ -6900,7 +6921,7 @@ struct frame *f; int freeze_p; { - foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0)); + foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0),1); } @@ -7061,6 +7082,10 @@ void syms_of_window () { + + Qgroup = intern ("group"); + staticpro (&Qgroup); + Qscroll_up = intern ("scroll-up"); staticpro (&Qscroll_up); === modified file 'src/window.h' --- src/window.h 2008-06-06 00:00:29 +0000 +++ src/window.h 2008-06-07 22:28:47 +0000 @@ -784,7 +784,8 @@ extern void freeze_window_starts P_ ((struct frame *, int)); extern void foreach_window P_ ((struct frame *, int (* fn) (struct window *, void *), - void *)); + void *, + int allwindows)); extern void grow_mini_window P_ ((struct window *, int)); extern void shrink_mini_window P_ ((struct window *)); --=-=-= -- Joakim Verona --=-=-=--