From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ted Zlatanov Newsgroups: gmane.emacs.devel Subject: Re: Global bar to display global information Date: Sun, 25 Sep 2011 07:50:08 -0500 Organization: =?utf-8?B?0KLQtdC+0LTQvtGAINCX0LvQsNGC0LDQvdC+0LI=?= @ Cienfuegos Message-ID: <87d3eo7pmn.fsf@lifelogs.com> References: <87hb5he3dy.fsf@wanadoo.es> Reply-To: emacs-devel@gnu.org NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1316955037 4504 80.91.229.12 (25 Sep 2011 12:50:37 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sun, 25 Sep 2011 12:50:37 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Sep 25 14:50:33 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1R7oAC-00076H-LT for ged-emacs-devel@m.gmane.org; Sun, 25 Sep 2011 14:50:32 +0200 Original-Received: from localhost ([::1]:42513 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R7oAC-0000dr-6X for ged-emacs-devel@m.gmane.org; Sun, 25 Sep 2011 08:50:32 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:60401) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R7oA9-0000da-8m for emacs-devel@gnu.org; Sun, 25 Sep 2011 08:50:30 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R7oA7-00076Z-LU for emacs-devel@gnu.org; Sun, 25 Sep 2011 08:50:29 -0400 Original-Received: from lo.gmane.org ([80.91.229.12]:44839) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R7oA7-00076U-2J for emacs-devel@gnu.org; Sun, 25 Sep 2011 08:50:27 -0400 Original-Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1R7oA5-00074P-QN for emacs-devel@gnu.org; Sun, 25 Sep 2011 14:50:25 +0200 Original-Received: from 38.98.147.133 ([38.98.147.133]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 25 Sep 2011 14:50:25 +0200 Original-Received: from tzz by 38.98.147.133 with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 25 Sep 2011 14:50:25 +0200 X-Injected-Via-Gmane: http://gmane.org/ Mail-Followup-To: emacs-devel@gnu.org Original-Lines: 281 Original-X-Complaints-To: usenet@dough.gmane.org X-Gmane-NNTP-Posting-Host: 38.98.147.133 X-Face: bd.DQ~'29fIs`T_%O%C\g%6jW)yi[zuz6; d4V0`@y-~$#3P_Ng{@m+e4o<4P'#(_GJQ%TT= D}[Ep*b!\e,fBZ'j_+#"Ps?s2!4H2-Y"sx" Mail-Copies-To: never User-Agent: Gnus/5.110018 (No Gnus v0.18) Emacs/24.0.50 (gnu/linux) Cancel-Lock: sha1:rg1UoWT5pzYWL+GC5t9VRBgrNv0= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 80.91.229.12 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:144273 Archived-At: --=-=-= Content-Type: text/plain On Tue, 16 Aug 2011 13:31:13 -0400 Stefan Monnier wrote: SM> Overall, it sounds like it shouldn't be too hard to make up a little SM> package that fills a buffer with useful global info SM> (time/battery/mail/younameit) and then lets you choose where you want to SM> display it (separate frame, inactive minibuffer, ...). Don't forget the progress bar Michael Albinus and I were pushing, to indicate global "busy" status. That would fit nicely in such a global "status bar." Emacs should really support global progress indicators and I recall our discussion stalled. I am attaching an *early not really functional* version of my ideas in the global information direction, emacs-panel.el. I didn't get far with it this summer before other tasks took priority, but intend to keep working on it. It is specifically intended to function as an information panel, which I think is the goal of this thread. Note that it has some code to let the window manager treat the popups specially so they can be docked, which is essential IMHO. Any improvements, especially such that make it ELPA-ready, most welcome. As I said I intend to keep working on it as time allows. Thanks Ted --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=emacs-panel.el Content-Transfer-Encoding: quoted-printable ;;; emacs-panel.el --- gnome-panel-like functionality for Emacs ;; Copyright (C) 2011 Teodor Zlatanov ;; Author: Teodor Zlatanov ;; This program 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 3 of the License, or ;; (at your option) any later version. ;; This program 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 program. If not, see . ;;; Commentary: ;; example: ;; (require 'battery) ;; (require 'timeclock) ;; (emacs-panel-popup-add ;; "status" :function ;; (lambda () ;; (format "%s\n%s\n%s\n%s" ;; (format-time-string "%H:%M %Y-%m-%d" (current-time)) ;; (battery-format battery-echo-area-format (funcall ;; battery-status-func= tion)) ;; (timeclock-status-string) ;; (shell-command-to-string "nmcli -p dev")))) ;;; --OR-- ;; (emacs-panel-tile-add "myfeeds" :margin 3 :text ... :call ...) ;; (emacs-panel-tile-add 'mychat :padding 2 :update-function ... :call ...) ;; and then use it in a tiled 3x3 layout: ;; (emacs-panel-popup-add "status" :tiles '(nil "myfeeds" nil 'mychat) ;; :background "black" ;; :layout-manager '(tile :x 3 :y 3)) ;(emacs-panel-popup-remove "status") ;;; Code: (eval-when-compile (require 'cl)) (require 'timer) (require 'bindat) (defgroup emacs-panel nil "The Emacs panel." :version "24.1") (defvar emacs-panel-popup-frame) (defvar emacs-panel-popup-timer (run-at-time t 1 'emacs-panel-popup-runqueue)) (defcustom emacs-panel-popups nil "Alist of defined popup buffers format: (NAME :function F :frame-params P ...) The keys besides :function (called on a refresh) and :frame-params (used for new frames) are: ... TODO ..." :group 'emacs-panel) (defcustom emacs-panel-popup-interval 5 "How often to refresh the popups, in seconds." :group 'emacs-panel :type 'integer) (defvar emacs-panel-current-cycle 0) (defun emacs-panel-popup-add (name &rest params) (unless (emacs-panel-popup-entry name) (add-to-list 'emacs-panel-popups `(,name ,@params)))) (defun emacs-panel-popup-remove (name) (setq emacs-panel-popups (remove* name emacs-panel-popups :key 'car :test 'equal))) (defun emacs-panel-popup-entry (name) (cdr-safe (assoc name emacs-panel-popups))) (defun emacs-panel-popup-runqueue () (interactive) (incf emacs-panel-current-cycle) (when (zerop (mod emacs-panel-current-cycle emacs-panel-popup-interval)) (loop for p in emacs-panel-popups do (emacs-panel-popup (car-safe p))))) (defun emacs-panel-popup-strut-frame () (let* ((width 200) (height 500) (ff (make-frame `((visibility . nil) (width . 20))))) (x-change-window-property "_NET_WM_STRUT_PARTIAL" `(,width 0 0 0 0 ,height 0 0 0 0 0 0) ff "CARDINAL" 32 t) (x-change-window-property "_NET_WM_WINDOW_TYPE" '("_NET_WM_WINDOW_TYPE_DOCK") ff "ATOM" 32 t) (make-frame-visible ff))) (defconst emacs-panel-MWM `((hints (functions . ,(ash 1 0)) (decorations . ,(ash 1 1)) (input-mode . ,(ash 1 2)) (status . ,(ash 1 3))) (funcs (all . ,(ash 1 0)) (resize . ,(ash 1 1)) (move . ,(ash 1 2)) (minimize . ,(ash 1 3)) (maximize . ,(ash 1 4)) (close . ,(ash 1 5))) (decors (all . ,(ash 1 0)) (border . ,(ash 1 1)) (resizeh . ,(ash 1 2)) (title . ,(ash 1 3)) (menu . ,(ash 1 4)) (minimize . ,(ash 1 5)) (maximize . ,(ash 1 6)))) "WM hints for emacs-panel functions") (defun emacs-panel-popup-special-frame (hints funcs decors &rest frame-prop= s) (let ((ff (make-frame `((visibility . nil) ,@frame-props))) (special-data (make-list 5 0)) (todo '(hints funcs decors)) (pos 0)) (while todo (let* ((sym (pop todo)) (info (cdr (assq sym emacs-panel-MWM))) (v (symbol-value sym)) (v (if (consp v) v (list v))) (sum (apply '+ (mapcar (lambda (s) (or (cdr (assq s info)) 0)) v)= ))) (setf (nth pos special-data) sum) (incf pos))) (progn (message "Popping up frame with special properties %S" special-data) (x-change-window-property "_MOTIF_WM_HINTS" special-data ff "_MOTIF_WM_HINTS" 32 t) (make-frame-visible ff) ff))) ;; To make a frame without decoration (gtk_window_decorated): ;; (emacs-panel-popup-special-frame 'decorations nil nil) ;; To make a frame without delete (gtk_window_deletable): ;; (emacs-panel-popup-special-frame 'functions '(close all) nil) (defun emacs-panel-popup (name &optional hints funcs decors) (let* ((old-frame (selected-frame)) (entry (emacs-panel-popup-entry name)) (func (plist-get entry :function)) (frame-params (plist-get entry :frame-params)) (bufname (concat " *" name "*"))) (save-excursion (with-current-buffer (get-buffer-create bufname) (make-local-variable 'emacs-panel-popup-frame) (if (and (boundp 'emacs-panel-popup-frame) emacs-panel-popup-frame (member emacs-panel-popup-frame (frame-list))) (select-frame emacs-panel-popup-frame) (let ((default-frame-alist `((minibuffer . nil) (width . 20) (border-width . 0) (menu-bar-lines . 0) (tool-bar-lines . 0) (unsplittable . t) (left-fringe . 0) ,@frame-params)) (pop-up-frame-function (lambda nil (emacs-panel-popup-special-frame hints funcs decors pop-up-frame-alist)))) (switch-to-buffer-other-frame bufname) (setq emacs-panel-popup-frame (selected-frame)))) (when func (setq mode-line-format nil) (redraw-modeline) ;; TODO: optimize and improve (erase-buffer) (insert (funcall func))))) (select-frame old-frame))) (defmacro emacs-panel-x-property (prop window &optional type vec) `(x-window-property ,prop nil ,(or type "AnyPropertyType") ,window nil ,v= ec)) (defmacro emacs-panel-x-property-nullsepstringarray (prop window &optional = type) `(split-string (emacs-panel-x-property ,prop ,window ,type) "\0" t)) (defmacro emacs-panel-x-property-u32r (prop window &optional type n) `(let ((spec '((:v ,@(when n (list 'vec n)) u32r))) (bin (emacs-panel-x-property ,prop ,window ,type)) v) (cdr-safe (assq :v (bindat-unpack spec bin))))) (defun emacs-panel-wm-hints () ;; ask the root window what window to query for the WM name (let* ((nqid (emacs-panel-x-property-u32r "_NET_SUPPORTING_WM_CHECK" 0)) (name (emacs-panel-x-property "_NET_WM_NAME" nqid))) `((name ,name) (desktop-names ,@(emacs-panel-x-property-nullsepstringarray "_NET_DESKTOP_NAMES" 0)) (active-window ,(emacs-panel-x-property-u32r "_NET_ACTIVE_WINDOW" 0)) (desktop-count ,(emacs-panel-x-property-u32r "_NET_NUMBER_OF_DESKTOPS" 0)) (desktop-geometry ,@(let ((d (emacs-panel-x-property-u32r "_NET_DESKTOP_GEOMETRY" 0 nil 2))) (list (aref d 0) (aref d 1)))) (current-desktop ,(emacs-panel-x-property-u32r "_NET_CURRENT_DESKTOP" 0))))) (defmacro emacs-panel-wm-get-desktop (&optional frame) `(emacs-panel-x-property-u32r "_NET_WM_DESKTOP" (string-to-number (cdr (assq 'outer-window-id (frame-parameters ,frame)= ))))) (defmacro emacs-panel-wm-set-active-desktop (desktop) `(x-send-client-message nil 0 nil "_NET_CURRENT_DESKTOP" 32 '(,desktop 0)= )) (defun emacs-panel-unload-function () (cancel-timer emacs-panel-popup-timer)) (provide 'emacs-panel) ;;; emacs-panel.el ends here --=-=-=--