;;; xwem-osd.el --- On Screen Display implementation for XWEM. ;; Copyright (C) 2004,2005 by XWEM Org. ;; Author: Zajcev Evgeny ;; Created: Mon Jan 12 13:14:32 MSK 2004 ;; Keywords: xwem ;; X-CVS: $Id: xwem-osd.el,v 1.7 2005-04-04 19:54:14 lg Exp $ ;; This file is part of XWEM. ;; XWEM 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. ;; XWEM 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 XEmacs; see the file COPYING. If not, write to the Free ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. ;;; Synched up with: Not in FSF ;;; Commentary: ;; Support for on screen display in XWEM. xwem-osd can display text, ;; processing bar, other stuff using shaped window. The main feature ;; of this OSD implementation that it uses OSD instances to display ;; stuff, so it does not need to handle expose events. ;; OSD supports system tray. It is very easy to write OSD dockapp. ;; Simple example in xwem-framei.el. You just create osd as usuall, ;; but using `xwem-osd-create-dock', where you can specify width, ;; height and keymap to use, for example: ;; ;; (setq myosd (xwem-osd-create-dock (xwem-dpy) 24 24 (list 'keymap myosd-keymap))) ;; (xwem-osd-text myosd "test") ;; ;; This will create dockapp in system tray, display "test" in it, and ;; will execute commands in `myosd-keymap' if you click on OSD. To ;; define commands in `myosd-keymap' do something like: ;; ;; (define-key myosd-keymap [button1] ;; (lambda () (interactive) (xwem-message 'info "Myosd Hello world!"))) ;; (define-key myosd-keymap [button3] 'myosd-popup-menu) ;; ;; New instance type added - dots. To poly dataset in OSD you can use ;; `xwem-osd-dots-add' function. TYPE is one of: ;; ;; 'points - Little circles. ;; 'lines - Lines ;; 'linespoints - Lines with points at ends. ;; 'impulses - Impulses from 0 to dot's Y. ;; 'dots - Tiny dots. ;; 'steps - Steps around points ;; 'fsteps - Another 'steps variant ;; 'histeps - Yet another 'steps variant (NI) ;; 'boxes - Boxes arount points (NI) ;; ;; For example if you have some dataset(CPU load f.i.) which ;; represented in as list of cons cells, which car is X and cdr is Y. ;; ;; ds ;; ==> ;; ((1 . 3) (3 . 6) (5 . 4) (7 . 10) (9 . 10) (11 . 3)) ;; ;; (xwem-osd-dots-add myosd ds 'impulses "red4") ;; ;; This will draw nice graph. ;; ;; For full drawing posibilities consider `xwem-diagram.el'. ;;; Code: (eval-when-compile (require 'cl)) (require 'xlib-xshape) (require 'xlib-tray) (require 'xlib-xpm) (require 'xwem-diagram) (defgroup xwem-osd nil "Group to customize OSD." :prefix "xwem-osd-" :group 'xwem-misc) (defcustom xwem-osd-default-font "fixed" "Default font for text drawed in osd." :type 'string :group 'xwem-osd) (defcustom xwem-osd-default-color "black" "Default color used to draw." :type 'color :group 'xwem-osd) (defcustom xwem-osd-default-stack-rank 100 "Default rank." :type 'number :group 'xwem-osd) ;;; Internal variables (defconst xwem-osd-instance-types '(text line dots arc rect icon) "List of valid types of osd instance.") (defstruct xwem-osd-instance type ; instance type, see `xwem-osd-instance-types' osd ; back reference to osd (depth 0) ; depth xwin xmask color ; instance background color plist) ; User defined plist (defsubst xwem-osd-instance-put-prop (osin prop val) "In OSD's instance OSIN properties list put property PROP with value VAL." (setf (xwem-osd-instance-plist osin) (plist-put (xwem-osd-instance-plist osin) prop val))) (put 'xwem-osd-instance-put-prop 'lisp-indent-function 2) (defsubst xwem-osd-instance-get-prop (osin prop) "Return OSD's instance OSIN property PROP." (plist-get (xwem-osd-instance-plist osin) prop)) (defsubst xwem-osd-instance-rem-prop (osin prop) "Remove OSD's instance OSIN property PROP." (setf (xwem-osd-instance-plist osin) (plist-remprop (xwem-osd-instance-plist osin) prop))) (defmacro xwem-osd-instance-xdpy (osin) "Return display of OSIN osd instance." `(xwem-osd-xdpy (xwem-osd-instance-osd osin))) (defstruct xwem-osd state ; 'destroyed, 'hided or 'shown x y width height xdpy xwin xmask gc ; GC used to draw mask-gc ; GC used to draw mask instances ; list of xwem-osd-instance structs sorted by depth plist) ; User defined plist (defsubst xwem-osd-put-prop (osd prop val) "In OSD's properties list put property PROP with value VAL." (setf (xwem-osd-plist osd) (plist-put (xwem-osd-plist osd) prop val))) (put 'xwem-osd-put-prop 'lisp-indent-function 2) (defsubst xwem-osd-get-prop (osd prop) "Return OSD's property PROP." (plist-get (xwem-osd-plist osd) prop)) (defsubst xwem-osd-rem-prop (osd prop) "Remove OSD's property PROP." (setf (xwem-osd-plist osd) (plist-remprop (xwem-osd-plist osd) prop))) (defmacro xwem-osd-xwin-copy (osd) `(xwem-osd-get-prop ,osd 'xwin-copy)) (defsetf xwem-osd-xwin-copy (osd) (xwin) `(xwem-osd-put-prop ,osd 'xwin-copy ,xwin)) ;;; Functions (defun xwem-osd-event-handler (xdpy xwin xev) "On X display XDPY and window XWIN handle X Event XEV." (let* ((osd (xwem-osd-get-osd xwin)) (keymap (xwem-osd-get-prop osd 'keymap))) (when (xwem-osd-p osd) (X-Event-CASE xev (:X-DestroyNotify (xwem-osd-destroy osd t)) ((:X-KeyPress :X-ButtonPress :X-ButtonRelease) (when (keymapp keymap) (xwem-overriding-local-map keymap (xwem-dispatch-command-xevent xev))))) ))) ;;; Instances operations (defun xwem-osd-instance-destroy (osin) "Destroy osd instance OSIN." (let ((xdpy (xwem-osd-instance-xdpy osin))) (XDestroyWindow xdpy (xwem-osd-instance-xwin osin)) (XFreeColors xdpy (XDefaultColormap xdpy) (list (xwem-osd-instance-color osin)) nil) (XFreePixmap xdpy (xwem-osd-instance-xmask osin)) (X-invalidate-cl-struct osin))) (defun xwem-osd-add-instance (osd depth &optional color) "In OSD add osd instance with background COLOR. Return newly created osd instance." (unless depth (setq depth 0)) (unless color (setq color (or (X-Color-name (X-Gc-foreground (xwem-osd-gc osd))) xwem-osd-default-color))) (let* ((xdpy (xwem-osd-xdpy osd)) (osin (make-xwem-osd-instance :osd osd :depth depth :color (XAllocNamedColor xdpy (XDefaultColormap xdpy) color)))) (setf (xwem-osd-instance-xwin osin) (XCreateWindow xdpy (xwem-osd-xwin osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd) 0 nil nil nil (make-X-Attr :override-redirect t :background-pixel (xwem-osd-instance-color osin)))) (setf (xwem-osd-instance-xmask osin) (XCreatePixmap xdpy (make-X-Pixmap :dpy xdpy :id (X-Dpy-get-id xdpy)) (xwem-osd-instance-xwin osin) 1 (xwem-osd-width osd) (xwem-osd-height osd))) (xwem-osd-instance-clear osin) (push osin (xwem-osd-instances osd)) ;; - Sort instances according to depth ;; - Install below sibling (setf (xwem-osd-instances osd) (sort (xwem-osd-instances osd) (lambda (s1 s2) (< (xwem-osd-instance-depth s1) (xwem-osd-instance-depth s2))))) (let ((siblings (xwem-osd-instances osd)) below-sibl) (while siblings (if (>= (xwem-osd-instance-depth (car siblings)) depth) (setq siblings nil) (setq below-sibl (car siblings))) (setq siblings (cdr siblings))) (when below-sibl (XConfigureWindow xdpy (xwem-osd-instance-xwin osin) (make-X-Conf :sibling (xwem-osd-instance-xwin below-sibl) :stackmode X-Below)))) osin)) (defun xwem-osd-instance-clear (osin) "Clear mask area of OSD instance." (let ((osd (xwem-osd-instance-osd osin))) (xwem-osd-mask-fgbg osd) (XFillRectangle (xwem-osd-xdpy osd) (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd)) (xwem-osd-mask-fgbg osd))) (defun xwem-osd-instance-show (osin) "Show osd instance OSIN." (XMapWindow (xwem-osd-instance-xdpy osin) (xwem-osd-instance-xwin osin))) (defun xwem-osd-instance-set-color (osin new-color) "Set new color." (let ((xdpy (xwem-osd-instance-xdpy osin))) (XFreeColors xdpy (XDefaultColormap xdpy) (list (xwem-osd-instance-color osin)) nil) (setf (xwem-osd-instance-color osin) (XAllocNamedColor xdpy (XDefaultColormap xdpy) new-color)) (XSetWindowBackground xdpy (xwem-osd-instance-xwin osin) (xwem-osd-instance-color osin)) (XClearArea xdpy (xwem-osd-instance-xwin osin) 0 0 (xwem-osd-width (xwem-osd-instance-osd osin)) (xwem-osd-height (xwem-osd-instance-osd osin)) nil))) ;;; OSD functions ;;;###autoload (defun xwem-osd-create (xdpy x y width height &optional x-parent properties) "On X display XDPY create new xwem osd context with +X+Y/WIDTHxHEIGHT geometry on X-PARENT. PROPERTIES is a plist for osd. Supported properties are: 'keymap - Keymap for OSD. 'stack-rank - Rank of OSD in windows stack." (let ((osd (make-xwem-osd :xdpy xdpy :x x :y y :width width :height height :plist properties)) (keymap (plist-get properties 'keymap)) (stack-rank (plist-get properties 'stack-rank))) (setf (xwem-osd-xwin osd) (XCreateWindow xdpy (or x-parent (XDefaultRootWindow xdpy)) x y width height 0 nil nil nil (make-X-Attr :override-redirect t :background-pixel (XBlackPixel xdpy) :event-mask (Xmask-or XM-StructureNotify (if keymap (Xmask-or XM-KeyPress XM-ButtonPress XM-ButtonRelease) 0))))) ;; Apply STACK-RANK (when stack-rank (xwem-misc-set-xwin-always-on-top (xwem-osd-xwin osd) stack-rank)) ;; Create gc (setf (xwem-osd-gc osd) (XCreateGC xdpy (xwem-osd-xwin osd) (make-X-Gc :dpy xdpy :id (X-Dpy-get-id xdpy) :foreground (XAllocNamedColor xdpy (XDefaultColormap xdpy) xwem-osd-default-color) :font (X-Font-get xdpy xwem-osd-default-font)))) (X-Win-put-prop (xwem-osd-xwin osd) 'osd-ctx osd) (X-Win-EventHandler-add-new (xwem-osd-xwin osd) 'xwem-osd-event-handler) (xwem-osd-create-mask osd) osd)) ;;;###autoload (defun xwem-osd-create-dock (xdpy width height &optional properties) "Create docked osd instance. XDPY - Display. X, Y, WIDTH, HEIGHT - OSD Geometry." (let ((osd (xwem-osd-create xdpy 0 0 width height nil properties))) (xwem-osd-clear osd) (xwem-XTrayInit xdpy (xwem-osd-xwin osd)) osd)) (defun xwem-osd-get-osd (xwin) "Get osd context associated with XWIN." (and (X-Win-p xwin) (X-Win-get-prop xwin 'osd-ctx))) (defun xwem-osd-mask-fgbg (osd) "Exchange foreground and background colors in OSD's mask gc." (let* ((mgc (xwem-osd-mask-gc osd)) (fg (X-Gc-foreground mgc)) (bg (X-Gc-background mgc))) (setf (X-Gc-foreground mgc) bg) (setf (X-Gc-background mgc) fg) (XChangeGC (xwem-osd-xdpy osd) mgc))) (defun xwem-osd-clear-mask (osd) "Clear mask area of OSD context." (xwem-osd-mask-fgbg osd) (XFillRectangle (xwem-osd-xdpy osd) (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd)) (xwem-osd-mask-fgbg osd)) (defun xwem-osd-create-mask (osd) "For xwem osd context OSD create mask pixmap." (let ((xdpy (xwem-osd-xdpy osd))) (setf (xwem-osd-xmask osd) (XCreatePixmap xdpy (make-X-Pixmap :dpy xdpy :id (X-Dpy-get-id xdpy)) (xwem-osd-xwin osd) 1 (xwem-osd-width osd) (xwem-osd-height osd))) (unless (xwem-osd-mask-gc osd) (setf (xwem-osd-mask-gc osd) (XCreateGC xdpy (xwem-osd-xmask osd) (make-X-Gc :dpy xdpy :id (X-Dpy-get-id xdpy) :foreground 1.0 :background 0.0 :font (X-Font-get xdpy xwem-osd-default-font))))) (xwem-osd-clear-mask osd))) (defun xwem-osd-set-height (osd new-height) "Set OSD's window height to NEW-HEIGHT." (setf (xwem-osd-height osd) new-height) (XResizeWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd) (xwem-osd-width osd) (xwem-osd-height osd)) (XFreePixmap (xwem-osd-xdpy osd) (xwem-osd-xmask osd)) (xwem-osd-create-mask osd)) (defun xwem-osd-set-width (osd new-width) "Set OSD's window width to NEW-WIDTH." (setf (xwem-osd-width osd) new-width) (XResizeWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd) (xwem-osd-width osd) (xwem-osd-height osd)) (XFreePixmap (xwem-osd-xdpy osd) (xwem-osd-xmask osd)) (xwem-osd-create-mask osd)) (defun xwem-osd-move (osd new-x new-y) "Change OSD's window position to NEW-X, NEW-Y." (XMoveWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd) new-x new-y)) (defun xwem-osd-set-xwin-color (osd color-name) "Set background for OSD's window to COLOR-NAME." (let ((xdpy (xwem-osd-xdpy osd))) (XSetWindowBackground xdpy (xwem-osd-xwin osd) (XAllocNamedColor xdpy (XDefaultColormap xdpy) color-name)))) (defun xwem-osd-set-gc-color (osd color-name) "Set OSD's gc foreground color to COLOR-NAME." (let ((xdpy (xwem-osd-xdpy osd))) (setf (X-Gc-foreground (xwem-osd-gc osd)) (XAllocNamedColor xdpy (XDefaultColormap xdpy) color-name)) (XChangeGC xdpy (xwem-osd-gc osd)))) (defun xwem-osd-set-color (osd color-name) "Set both OSD's background and OSD's gc foreground color to COLOR-NAME." (let* ((xdpy (xwem-osd-xdpy osd)) (col (XAllocNamedColor xdpy (XDefaultColormap xdpy) color-name))) (XSetWindowBackground xdpy (xwem-osd-xwin osd) col) (xwem-osd-clear-xwin osd) (setf (X-Gc-foreground (xwem-osd-gc osd)) col) (XChangeGC xdpy (xwem-osd-gc osd)))) (defun xwem-osd-show (osd) "Show OSD's window." (xwem-osd-apply-xmask-1 osd) (XMapWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd)) (xwem-misc-raise-xwin (xwem-osd-xwin osd)) (setf (xwem-osd-state osd) 'shown)) (defun xwem-osd-hide (osd) "Hide OSD's window." (XUnmapWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd)) (setf (xwem-osd-state osd) 'hidden)) (defun xwem-osd-destroy-instances (osd) "Destroy all instances in OSD." (mapc 'xwem-osd-instance-destroy (xwem-osd-instances osd)) (setf (xwem-osd-instances osd) nil)) (defun xwem-osd-destroy (osd &optional already-destroyed) "Destroy OSD context." (xwem-osd-destroy-instances osd) (X-Win-EventHandler-rem (xwem-osd-xwin osd) 'xwem-osd-event-handler) (X-Win-rem-prop (xwem-osd-xwin osd) 'osd-ctx) (unless already-destroyed (XDestroyWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd))) (XFreePixmap (xwem-osd-xdpy osd) (xwem-osd-xmask osd)) (XFreeGC (xwem-osd-xdpy osd) (xwem-osd-mask-gc osd)) (XFreeGC (xwem-osd-xdpy osd) (xwem-osd-gc osd)) (X-invalidate-cl-struct osd)) (defun xwem-osd-set-font (osd font-name) "In OSD's context set font to be FONT-NAME." (let* ((xdpy (xwem-osd-xdpy osd)) (gc (xwem-osd-gc osd)) (mgc (xwem-osd-mask-gc osd)) (font (X-Font-get xdpy font-name))) (setf (X-Gc-font mgc) font) (XChangeGC xdpy mgc) (setf (X-Gc-font gc) font) (XChangeGC xdpy gc))) (defun xwem-osd-char-width (osd) "Return width of OSD's window in characters." ;; XXX assumes that font is width fixed (/ (xwem-osd-width osd) (X-Text-width (xwem-osd-xdpy osd) (X-Gc-font (xwem-osd-mask-gc osd)) "_"))) (defun xwem-osd-clear-xwin (osd) "Clear contents of OSD's window." (XClearArea (xwem-osd-xdpy osd) (xwem-osd-xwin osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd) nil)) (defun xwem-osd-clear (osd) "Clear OSD window." (xwem-osd-destroy-instances osd) (xwem-osd-clear-mask osd) (xwem-osd-apply-xmask osd)) (define-xwem-deffered xwem-osd-apply-xmask (osd) "Apply OSD's mask to life." (X-XShapeMask (xwem-osd-xdpy osd) (xwem-osd-xwin osd) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-xmask osd))) (defun xwem-osd-text (osd string) "In OSD's context show STRING. If OSD has any instances, they will be destroyed." (let* ((xdpy (xwem-osd-xdpy osd)) (yoff (- (X-Text-height xdpy (X-Gc-font (xwem-osd-mask-gc osd)) string) (X-Text-descent xdpy (X-Gc-font (xwem-osd-mask-gc osd)) string)))) (xwem-osd-destroy-instances osd) ;; Update window shape (xwem-osd-clear-mask osd) (XDrawString xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) 0 yoff string) (xwem-osd-apply-xmask osd))) (defun xwem-osd-color-text (osd strspec-list) "In OSD's win draw colored text specified by STRSPEC-LIST." (xwem-osd-clear osd) (let ((curstr "")) (mapcar (lambda (strspec) (let* ((xdpy (xwem-osd-xdpy osd)) (str (concat curstr (car strspec))) (yoff (- (X-Text-height xdpy (X-Gc-font (xwem-osd-mask-gc osd)) str) (X-Text-descent xdpy (X-Gc-font (xwem-osd-mask-gc osd)) str)))) (xwem-osd-set-xwin-color osd (cdr strspec)) (XDrawString xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) 0 yoff str) (xwem-osd-apply-xmask osd) (setq curstr (concat curstr (car strspec))))) strspec-list))) (defun xwem-osd-text-add (osd x y string &optional depth color) "In OSD's context at X Y coordinates add STRING colored with COLOR." (let* ((xdpy (xwem-osd-xdpy osd)) (yoff (- (X-Text-height xdpy (X-Gc-font (xwem-osd-mask-gc osd)) string) (X-Text-descent xdpy (X-Gc-font (xwem-osd-mask-gc osd)) string))) osin) ;; Setup OSD instance (setq osin (xwem-osd-add-instance osd depth color)) (setf (xwem-osd-instance-type osin) 'text) (XDrawString xdpy (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) x (+ y yoff) string) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (xwem-osd-instance-show osin) ;; Update window shape (XDrawString xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) x (+ y yoff) string) (xwem-osd-apply-xmask osd) osin)) (defun xwem-osd-set-line-width (osd new-line-width) "Set OSD's gc line width to NEW-LINE-WIDTH." (setf (X-Gc-line-width (xwem-osd-gc osd)) new-line-width) (XChangeGC (xwem-osd-xdpy osd) (xwem-osd-gc osd)) (setf (X-Gc-line-width (xwem-osd-mask-gc osd)) new-line-width) (XChangeGC (xwem-osd-xdpy osd) (xwem-osd-mask-gc osd)) ) (defun xwem-osd-line-add (osd x0 y0 x1 y1 &optional depth color) "In OSD's window add line." (let ((xdpy (xwem-osd-xdpy osd)) osin) ;; Create OSD line instance (setq osin (xwem-osd-add-instance osd depth color)) (setf (xwem-osd-instance-type osin) 'line) (XDrawLine xdpy (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) x0 y0 x1 y1) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (xwem-osd-instance-show osin) ;; Update OSD window shape (XDrawLine xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) x0 y0 x1 y1) (xwem-osd-apply-xmask osd) osin)) (defun xwem-osd-dots-add (osd dots type &optional depth color) "In OSD's window add DOTS of TYPE." (let ((xdpy (xwem-osd-xdpy osd)) osin) ;; Create OSD dots instancne (setq osin (xwem-osd-add-instance osd depth color)) (setf (xwem-osd-instance-type osin) 'dots) (xwem-diag-plot-dots type (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) 0 (xwem-osd-height osd) dots) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (xwem-osd-instance-show osin) ;; Update OSD window shape (xwem-diag-plot-dots type (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) 0 (xwem-osd-height osd) dots) (xwem-osd-apply-xmask osd) osin)) (defun xwem-osd-arc-add (osd xarc &optional depth color) "In OSD's window draw arc specified by XARC." (let ((xdpy (xwem-osd-xdpy osd)) osin) ;; Create OSD arc instance (setq osin (xwem-osd-add-instance osd depth color)) (setf (xwem-osd-instance-type osin) 'arc) (XDrawArcs xdpy (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) (list xarc)) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (xwem-osd-instance-show osin) ;; Update OSD shape (XDrawArcs xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) (list xarc)) (xwem-osd-apply-xmask osd) osin)) (defun xwem-osd-rect-add (osd x y width height &optional depth color fill-p) "In OSD's window add rectangle specified by X Y WIDTH and HEIGHT. If FILL-P is non-nil, rectangle will be filled instead of outdrawing." (let ((xdpy (xwem-osd-xdpy osd)) osin) ;; Created OSD rect instance (setq osin (xwem-osd-add-instance osd depth color)) (setf (xwem-osd-instance-type osin) 'rect) (XDrawRectangles xdpy (xwem-osd-instance-xmask osin) (xwem-osd-mask-gc osd) (list (make-X-Rect :x x :y y :width width :height height)) fill-p) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (xwem-osd-instance-show osin) ;; Update OSD shape (XDrawRectangles xdpy (xwem-osd-xmask osd) (xwem-osd-mask-gc osd) (list (make-X-Rect :x x :y y :width width :height height)) fill-p) (xwem-osd-apply-xmask osd) osin)) (defun xwem-osd-icon-data-add (osd xpm-data &optional x y depth) "In OSD's window add icon. X and Y specifies osd instance location inside OSD(default is 0 0). DEPTH specifies osd instance depth(default is 0). XPM-DATA string of xpm image." (unless depth (setq depth 0)) (unless x (setq x 0)) (unless y (setq y 0)) (let ((xdpy (xwem-osd-xdpy osd)) osin xpix xpix-mask) ;; Created OSD icon instance (setq osin (xwem-osd-add-instance osd depth)) (setf (xwem-osd-instance-type osin) 'icon) (setq xpix (X:xpm-pixmap-from-data xdpy (xwem-osd-instance-xwin osin) xpm-data) xpix-mask (X:xpm-pixmap-from-data xdpy (xwem-osd-instance-xwin osin) xpm-data t)) (XCopyArea xdpy xpix-mask (xwem-osd-instance-xmask osin) xwem-misc-mask-bgc 0 0 (X-Pixmap-width xpix-mask) (X-Pixmap-height xpix-mask) x y) (X-XShapeMask xdpy (xwem-osd-instance-xwin osin) X-XShape-Bounding X-XShapeSet 0 0 (xwem-osd-instance-xmask osin)) (XCopyArea xdpy xpix-mask (xwem-osd-xmask osd) xwem-misc-mask-bgc 0 0 (X-Pixmap-width xpix-mask) (X-Pixmap-height xpix-mask) x y) (xwem-osd-apply-xmask osd) (XSetWindowBackgroundPixmap (xwem-dpy) (xwem-osd-instance-xwin osin) xpix) (xwem-osd-instance-show osin) osin)) (defun xwem-osd-icon-file-add (osd xpm-file &optional x y depth) "Same as `xwem-osd-icon-data-add', but takes xpm image from FILE." (let (xpm-data) (with-temp-buffer (insert-file-contents-literally xpm-file) (setq xpm-data (buffer-substring))) (xwem-osd-icon-data-add osd xpm-data x y depth))) (defun xwem-osd-offscreen (osd) "Put OSD off the screen, displaying OSD copy. Usefull to prevent flicking." (if (xwem-osd-xwin-copy osd) (XResizeWindow (xwem-osd-xdpy osd) (xwem-osd-xwin-copy osd) (xwem-osd-width osd) (xwem-osd-height osd)) (setf (xwem-osd-xwin-copy osd) (XCreateWindow (xwem-osd-xdpy osd) (xwem-osd-xwin osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd) 0 nil nil nil (make-X-Attr :override-redirect t)))) (XCopyArea (xwem-osd-xdpy osd) (xwem-osd-xwin osd) (xwem-osd-xwin-copy osd) (xwem-osd-gc osd) 0 0 (xwem-osd-width osd) (xwem-osd-height osd) 0 0) (XMapWindow (xwem-osd-xdpy osd) (xwem-osd-xwin-copy osd))) (defun xwem-osd-commit (osd) "Commit changes made while OSD was in off screen." (XUnmapWindow (xwem-osd-xdpy osd) (xwem-osd-xwin-copy osd))) ;;; You might consider more powerfull `working' package, which is part ;;; of CEDET. (defun xwem-osd-working-bar-display (tot-len percents) "Return a string with a bar-graph end percentile showing percentage. TOT-LEN is the total length of bar. PERCENTS is percentage state." (let* ((prstr (int-to-string percents)) (len (- tot-len (+ 10 (length prstr)))) (dcs (truncate (* len (/ percents 100.0)))) (tlen (- len dcs))) (concat ": [" (make-string (if (> dcs 0) dcs 0) ?#) (make-string (if (> tlen 0) tlen 0) ?.) "] ... " prstr "%"))) (defun xwem-osd-working-percent-bar (osd prompt percents) "Display percentage with PERCENTS done bar prompting PROMPT." (require 'working) (let ((osdcw (xwem-osd-char-width osd))) (xwem-osd-text osd (concat prompt (xwem-osd-working-bar-display (- osdcw (length prompt)) percents))))) ;;; Testing: ;; (setq mosd (xwem-osd-create (xwem-dpy) 10 20 400 200)) ;; (xwem-osd-set-color mosd "green4") ;; (xwem-osd-set-font mosd "10x20") ;; (xwem-osd-text mosd "test") ;; (xwem-osd-show mosd) ;; (progn ;; (setq i 0) ;; (xwem-osd-show mosd) ;; (xwem-osd-set-color mosd "red4") ;; (while (< i 100) ;; (cond ((= i 60) (xwem-osd-set-color mosd "green4")) ;; ((= i 30) (xwem-osd-set-color mosd "yellow4"))) ;; (xwem-osd-working-percent-bar mosd "Processing" i) ;; (sleep-for 0.01) ;; (incf i 1)) ;; (xwem-osd-set-color mosd "red4") ;; (xwem-osd-text mosd "Processing done.")) ;; (xwem-osd-destroy mosd) ;; Here is example from Steve Youngs to ;; display date using OSD: ;; (require 'xwem-osd) ;; (defvar sy-osd-date nil) ;; (copy-face 'default 'sy-osd-date-face) ;; (set-face-foreground 'sy-osd-date-face "blanchedalmond") ;; (defvar sy-osd-date-keymap ;; (let ((map (make-sparse-keymap 'sy-osd-date-keymap))) ;; (define-key map [button3] '(lambda () (interactive) (calendar))) ;; map) ;; "Keymap for date OSD.") ;; (defun sy-show-date-osd () ;; "*Display the current date using OSD." ;; (interactive) ;; (let* ((face `sy-osd-date-face) ;; (text (format-time-string "%a, %b %e")) ;; (width (+ 3 (X-Text-width ;; (xwem-dpy) ;; (X-Font-get (xwem-dpy) ;; (face-font-name face)) ;; text))) ;; (height (+ 3 (X-Text-height ;; (xwem-dpy) ;; (X-Font-get (xwem-dpy) ;; (face-font-name face)) ;; text)))) ;; (setq sy-osd-date (xwem-osd-create-dock ;; (xwem-dpy) ;; width ;; height ;; (list 'keymap sy-osd-date-keymap))) ;; (xwem-osd-set-color sy-osd-date (face-foreground-name face)) ;; (xwem-osd-set-font sy-osd-date (face-font-name face)) ;; (xwem-osd-text sy-osd-date text) ;; (xwem-osd-show sy-osd-date))) ;; (defun sy-update-osd-date-maybe (&optional force) ;; "Update the OSD date at midnight. ;; Optional Argument FORCE means to update the date now." ;; (let* ((now (decode-time)) ;; (cur-hour (nth 2 now)) ;; (cur-min (nth 1 now)) ;; (cur-comp-time (+ (* cur-hour 60) cur-min))) ;; (when (or force (= 0 cur-comp-time)) ;; (when (xwem-osd-p sy-osd-date) ;; (xwem-osd-text sy-osd-date (format-time-string "%a, %b %e")))))) ;; (defun sy-update-osd-date () ;; "*Force update of the OSD date." ;; (interactive) ;; (when (xwem-osd-p sy-osd-date) ;; (sy-update-osd-date-maybe t))) ;; (defun sy-delete-osd-date () ;; "*Delete the OSD date." ;; (interactive) ;; (when (xwem-osd-p sy-osd-date) ;; (when (itimerp "sy-osd-date-itimer") ;; (delete-itimer "sy-osd-date-itimer")) ;; (xwem-osd-destroy sy-osd-date))) ;; (add-hook 'xwem-after-init-hook (lambda () ;; (progn ;; (sy-show-date-osd) ;; (start-itimer "sy-osd-date-itimer" ;; 'sy-update-osd-date-maybe ;; 60 60)))) (provide 'xwem-osd) ;;; xwem-osd.el ends here