| 1 | ;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
|
|---|
| 2 | ;;;
|
|---|
| 3 | ;;; **********************************************************************
|
|---|
| 4 | ;;; This code was written as part of the CMU Common Lisp project at
|
|---|
| 5 | ;;; Carnegie Mellon University, and has been placed in the public domain.
|
|---|
| 6 | ;;;
|
|---|
| 7 | #+CMU (ext:file-comment
|
|---|
| 8 | "$Header$")
|
|---|
| 9 | ;;;
|
|---|
| 10 | ;;; **********************************************************************
|
|---|
| 11 | ;;;
|
|---|
| 12 | ;;; Screen allocation functions.
|
|---|
| 13 | ;;;
|
|---|
| 14 | ;;; This is the screen management and event handlers for Hemlock under X.
|
|---|
| 15 | ;;;
|
|---|
| 16 | ;;; Written by Bill Chiles, Rob MacLachlan, and Blaine Burks.
|
|---|
| 17 | ;;;
|
|---|
| 18 |
|
|---|
| 19 | (in-package :hemlock-internals)
|
|---|
| 20 |
|
|---|
| 21 | (declaim (special *echo-area-window*))
|
|---|
| 22 |
|
|---|
| 23 | ;;; We have an internal notion of window groups on bitmap devices. Every
|
|---|
| 24 | ;;; Hemlock window has a hunk slot which holds a structure with information
|
|---|
| 25 | ;;; about physical real-estate on some device. Bitmap-hunks have an X window
|
|---|
| 26 | ;;; and a window-group. The X window is a child of the window-group's window.
|
|---|
| 27 | ;;; The echo area, pop-up display window, and the initial window are all in
|
|---|
| 28 | ;;; their own group.
|
|---|
| 29 | ;;;
|
|---|
| 30 | ;;; MAKE-WINDOW splits the current window which is some child window in a group.
|
|---|
| 31 | ;;; If the user supplied an X window, it becomes the parent window of some new
|
|---|
| 32 | ;;; group, and we make a child for the Hemlock window. If the user supplies
|
|---|
| 33 | ;;; ask-user, we prompt for a group/parent window. We link the hunks for
|
|---|
| 34 | ;;; NEXT-WINDOW and PREVIOUS-WINDOW only within a group, so the group maintains
|
|---|
| 35 | ;;; a stack of windows that always fill the entire group window.
|
|---|
| 36 | ;;;
|
|---|
| 37 |
|
|---|
| 38 | ;;; This is the object set for Hemlock windows. All types of incoming
|
|---|
| 39 | ;;; X events on standard editing windows have the same handlers via this set.
|
|---|
| 40 | ;;; We also include the group/parent windows in here, but they only handle
|
|---|
| 41 | ;;; :configure-notify events.
|
|---|
| 42 | ;;;
|
|---|
| 43 | (defvar *hemlock-windows*
|
|---|
| 44 | #+clx
|
|---|
| 45 | (hemlock-ext:make-object-set "Hemlock Windows" #'hemlock-ext:default-clx-event-handler))
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 | |
|---|
| 49 |
|
|---|
| 50 | ;;;; Some window making parameters.
|
|---|
| 51 |
|
|---|
| 52 | ;;; These could be parameters, but they have to be set after the display is
|
|---|
| 53 | ;;; opened. These are set in INIT-BITMAP-SCREEN-MANAGER.
|
|---|
| 54 |
|
|---|
| 55 | (defvar *default-background-pixel* nil
|
|---|
| 56 | "Default background color. It defaults to white.")
|
|---|
| 57 |
|
|---|
| 58 | (defvar *default-foreground-pixel* nil
|
|---|
| 59 | "Default foreground color. It defaults to black.")
|
|---|
| 60 |
|
|---|
| 61 | (defvar *foreground-background-xor* nil
|
|---|
| 62 | "The LOGXOR of *default-background-pixel* and *default-foreground-pixel*.")
|
|---|
| 63 |
|
|---|
| 64 | (defvar *default-border-pixmap* nil
|
|---|
| 65 | "This is the default color of X window borders. It defaults to a
|
|---|
| 66 | grey pattern.")
|
|---|
| 67 |
|
|---|
| 68 | (defvar *highlight-border-pixmap* nil
|
|---|
| 69 | "This is the color of the border of the current window when the mouse
|
|---|
| 70 | cursor is over any Hemlock window.")
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 | |
|---|
| 74 |
|
|---|
| 75 | ;;;; Exposed region handling.
|
|---|
| 76 |
|
|---|
| 77 | ;;; :exposure events are sent because we selected them. :graphics-exposure
|
|---|
| 78 | ;;; events are generated because of a slot in our graphics contexts. These are
|
|---|
| 79 | ;;; generated from using XLIB:COPY-AREA when the source could not be generated.
|
|---|
| 80 | ;;; Also, :no-exposure events are sent when a :graphics-exposure event could
|
|---|
| 81 | ;;; have been sent but wasn't.
|
|---|
| 82 | ;;;
|
|---|
| 83 | #|
|
|---|
| 84 | ;;; This is an old handler that doesn't do anything clever about multiple
|
|---|
| 85 | ;;; exposures.
|
|---|
| 86 | (defun hunk-exposed-region (hunk &key y height &allow-other-keys)
|
|---|
| 87 | (if (bitmap-hunk-lock hunk)
|
|---|
| 88 | (setf (bitmap-hunk-trashed hunk) t)
|
|---|
| 89 | (let ((liftp (and (eq *cursor-hunk* hunk) *cursor-dropped*)))
|
|---|
| 90 | (when liftp (lift-cursor))
|
|---|
| 91 | ;; (hunk-draw-top-border hunk)
|
|---|
| 92 | (let* ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 93 | (font-height (font-family-height font-family))
|
|---|
| 94 | (co (font-family-cursor-y-offset font-family))
|
|---|
| 95 | (start (truncate (- y hunk-top-border) font-height))
|
|---|
| 96 | (end (ceiling (- (+ y height) hunk-top-border) font-height))
|
|---|
| 97 | (start-bit (+ (* start font-height) co hunk-top-border))
|
|---|
| 98 | (nheight (- (* (- end start) font-height) co))
|
|---|
| 99 | (end-line (bitmap-hunk-end hunk)))
|
|---|
| 100 | (declare (fixnum font-height co start end start-bit nheight))
|
|---|
| 101 | (xlib:clear-area (bitmap-hunk-xwindow hunk) :x 0 :y start-bit
|
|---|
| 102 | :width (bitmap-hunk-width hunk) :height nheight)
|
|---|
| 103 | (do ((dl (bitmap-hunk-start hunk) (cdr dl))
|
|---|
| 104 | (i 0 (1+ i)))
|
|---|
| 105 | ((or (eq dl end-line) (= i start))
|
|---|
| 106 | (do ((i i (1+ i))
|
|---|
| 107 | (dl dl (cdr dl)))
|
|---|
| 108 | ((or (eq dl end-line) (= i end)))
|
|---|
| 109 | (declare (fixnum i))
|
|---|
| 110 | (hunk-write-line hunk (car dl) i)))
|
|---|
| 111 | (declare (fixnum i)))
|
|---|
| 112 | (when (and (bitmap-hunk-modeline-pos hunk)
|
|---|
| 113 | (>= (the fixnum (+ nheight start-bit))
|
|---|
| 114 | (the fixnum (bitmap-hunk-modeline-pos hunk))))
|
|---|
| 115 | (hunk-replace-modeline hunk)))
|
|---|
| 116 | (when liftp (drop-cursor)))))
|
|---|
| 117 | |#
|
|---|
| 118 |
|
|---|
| 119 | ;;; HUNK-EXPOSED-REGION redisplays the appropriate rectangle from the hunk
|
|---|
| 120 | ;;; dis-lines. Don't do anything if the hunk is trashed since redisplay is
|
|---|
| 121 | ;;; probably about to fix everything; specifically, this keeps new windows
|
|---|
| 122 | ;;; from getting drawn twice (once for the exposure and once for being trashed).
|
|---|
| 123 | ;;;
|
|---|
| 124 | ;;; Exposure and graphics-exposure events pass in a different number of
|
|---|
| 125 | ;;; arguments, with some the same but in a different order, so we just bind
|
|---|
| 126 | ;;; and ignore foo, bar, baz, and quux.
|
|---|
| 127 | ;;;
|
|---|
| 128 | #+clx
|
|---|
| 129 | (defun hunk-exposed-region (hunk event-key event-window x y width height
|
|---|
| 130 | foo bar &optional baz quux)
|
|---|
| 131 | (declare (ignore event-key event-window x width foo bar baz quux))
|
|---|
| 132 | (unless (bitmap-hunk-trashed hunk)
|
|---|
| 133 | (let ((liftp (and (eq *cursor-hunk* hunk) *cursor-dropped*))
|
|---|
| 134 | (display (bitmap-device-display (device-hunk-device hunk))))
|
|---|
| 135 | (when liftp (lift-cursor))
|
|---|
| 136 | (multiple-value-bind (y-peek height-peek)
|
|---|
| 137 | (exposed-region-peek-event display
|
|---|
| 138 | (bitmap-hunk-xwindow hunk))
|
|---|
| 139 | (if y-peek
|
|---|
| 140 | (let ((n (coelesce-exposed-regions hunk display
|
|---|
| 141 | y height y-peek height-peek)))
|
|---|
| 142 | (write-n-exposed-regions hunk n))
|
|---|
| 143 | (write-one-exposed-region hunk y height)))
|
|---|
| 144 | (xlib:display-force-output display)
|
|---|
| 145 | (when liftp (drop-cursor)))))
|
|---|
| 146 | ;;;
|
|---|
| 147 | #+clx (hemlock-ext:serve-exposure *hemlock-windows* #'hunk-exposed-region)
|
|---|
| 148 | #+clx (hemlock-ext:serve-graphics-exposure *hemlock-windows* #'hunk-exposed-region)
|
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 | ;;; HUNK-NO-EXPOSURE handles this bullshit event that gets sent without its
|
|---|
| 152 | ;;; being requested.
|
|---|
| 153 | ;;;
|
|---|
| 154 | (defun hunk-no-exposure (hunk event-key event-window major minor send-event-p)
|
|---|
| 155 | (declare (ignore hunk event-key event-window major minor send-event-p))
|
|---|
| 156 | t)
|
|---|
| 157 | ;;;
|
|---|
| 158 | #+clx (hemlock-ext:serve-no-exposure *hemlock-windows* #'hunk-no-exposure)
|
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 | ;;; EXPOSED-REGION-PEEK-EVENT returns the position and height of an :exposure
|
|---|
| 162 | ;;; or :graphics-exposure event on win if one exists. If there are none, then
|
|---|
| 163 | ;;; nil and nil are returned.
|
|---|
| 164 | ;;;
|
|---|
| 165 | #+clx
|
|---|
| 166 | (defun exposed-region-peek-event (display win)
|
|---|
| 167 | (xlib:display-finish-output display)
|
|---|
| 168 | (let ((result-y nil)
|
|---|
| 169 | (result-height nil))
|
|---|
| 170 | (xlib:process-event
|
|---|
| 171 | display :timeout 0
|
|---|
| 172 | :handler #'(lambda (&key event-key event-window window y height
|
|---|
| 173 | &allow-other-keys)
|
|---|
| 174 | (cond ((and (or (eq event-key :exposure)
|
|---|
| 175 | (eq event-key :graphics-exposure))
|
|---|
| 176 | (or (eq event-window win) (eq window win)))
|
|---|
| 177 | (setf result-y y)
|
|---|
| 178 | (setf result-height height)
|
|---|
| 179 | t)
|
|---|
| 180 | (t nil))))
|
|---|
| 181 | (values result-y result-height)))
|
|---|
| 182 |
|
|---|
| 183 | ;;; COELESCE-EXPOSED-REGIONS insert sorts exposed region events from the X
|
|---|
| 184 | ;;; input queue into *coelesce-buffer*. Then the regions are merged into the
|
|---|
| 185 | ;;; same number or fewer regions that are vertically distinct
|
|---|
| 186 | ;;; (non-overlapping). When this function is called, one event has already
|
|---|
| 187 | ;;; been popped from the queue, the first event that caused HUNK-EXPOSED-REGION
|
|---|
| 188 | ;;; to be called. That information is passed in as y1 and height1. There is
|
|---|
| 189 | ;;; a second event that also has already been popped from the queue, the
|
|---|
| 190 | ;;; event resulting from peeking for multiple "exposure" events. That info
|
|---|
| 191 | ;;; is passed in as y2 and height2.
|
|---|
| 192 | ;;;
|
|---|
| 193 | (defun coelesce-exposed-regions (hunk display y1 height1 y2 height2)
|
|---|
| 194 | (let ((len 0))
|
|---|
| 195 | (declare (fixnum len))
|
|---|
| 196 | ;;
|
|---|
| 197 | ;; Insert sort the exposeevents as we pick them off the event queue.
|
|---|
| 198 | (let* ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 199 | (font-height (font-family-height font-family))
|
|---|
| 200 | (co (font-family-cursor-y-offset font-family))
|
|---|
| 201 | (xwindow (bitmap-hunk-xwindow hunk)))
|
|---|
| 202 | ;;
|
|---|
| 203 | ;; Insert the region the exposedregion handler was called on.
|
|---|
| 204 | (multiple-value-bind (start-line start-bit end-line expanded-height)
|
|---|
| 205 | (exposed-region-bounds y1 height1 co font-height)
|
|---|
| 206 | (setf len
|
|---|
| 207 | (coelesce-buffer-insert start-bit start-line
|
|---|
| 208 | expanded-height end-line len)))
|
|---|
| 209 | ;;
|
|---|
| 210 | ;; Peek for exposedregion events on xwindow, inserting them into
|
|---|
| 211 | ;; the buffer.
|
|---|
| 212 | (let ((y y2)
|
|---|
| 213 | (height height2))
|
|---|
| 214 | (loop
|
|---|
| 215 | (multiple-value-bind (start-line start-bit end-line expanded-height)
|
|---|
| 216 | (exposed-region-bounds y height co font-height)
|
|---|
| 217 | (setf len
|
|---|
| 218 | (coelesce-buffer-insert start-bit start-line
|
|---|
| 219 | expanded-height end-line len)))
|
|---|
| 220 | (multiple-value-setq (y height)
|
|---|
| 221 | (exposed-region-peek-event display xwindow))
|
|---|
| 222 | (unless y (return)))))
|
|---|
| 223 | (coelesce-exposed-regions-merge len)))
|
|---|
| 224 |
|
|---|
| 225 | ;;; *coelesce-buffer* is a vector of records used to sort exposure events on a
|
|---|
| 226 | ;;; single hunk, so we can merge them into fewer, larger regions of exposure.
|
|---|
| 227 | ;;; COELESCE-BUFFER-INSERT places elements in this buffer, and each element
|
|---|
| 228 | ;;; is referenced with COELESCE-BUFFER-ELT. Each element of the coelescing
|
|---|
| 229 | ;;; buffer has the following accessors defined:
|
|---|
| 230 | ;;; COELESCE-BUFFER-ELT-START in pixels.
|
|---|
| 231 | ;;; COELESCE-BUFFER-ELT-START-LINE in dis-lines.
|
|---|
| 232 | ;;; COELESCE-BUFFER-ELT-HEIGHT in pixels.
|
|---|
| 233 | ;;; COELESCE-BUFFER-ELT-END-LINE in dis-lines.
|
|---|
| 234 | ;;; These are used by COELESCE-BUFFER-INSERT, COELESCE-EXPOSED-REGIONS-MERGE,
|
|---|
| 235 | ;;; and WRITE-N-EXPOSED-REGIONS.
|
|---|
| 236 |
|
|---|
| 237 | (defvar *coelesce-buffer-fill-ptr* 25)
|
|---|
| 238 | (defvar *coelesce-buffer* (make-array *coelesce-buffer-fill-ptr*))
|
|---|
| 239 | (dotimes (i *coelesce-buffer-fill-ptr*)
|
|---|
| 240 | (setf (svref *coelesce-buffer* i) (make-array 4)))
|
|---|
| 241 |
|
|---|
| 242 | (defmacro coelesce-buffer-elt-start (elt)
|
|---|
| 243 | `(svref ,elt 0))
|
|---|
| 244 | (defmacro coelesce-buffer-elt-start-line (elt)
|
|---|
| 245 | `(svref ,elt 1))
|
|---|
| 246 | (defmacro coelesce-buffer-elt-height (elt)
|
|---|
| 247 | `(svref ,elt 2))
|
|---|
| 248 | (defmacro coelesce-buffer-elt-end-line (elt)
|
|---|
| 249 | `(svref ,elt 3))
|
|---|
| 250 | (defmacro coelesce-buffer-elt (i)
|
|---|
| 251 | `(svref *coelesce-buffer* ,i))
|
|---|
| 252 |
|
|---|
| 253 | ;;; COELESCE-BUFFER-INSERT inserts an exposed region record into
|
|---|
| 254 | ;;; *coelesce-buffer* such that start is less than all successive
|
|---|
| 255 | ;;; elements. Returns the new length of the buffer.
|
|---|
| 256 | ;;;
|
|---|
| 257 | (defun coelesce-buffer-insert (start start-line height end-line len)
|
|---|
| 258 | (declare (fixnum start start-line height end-line len))
|
|---|
| 259 | ;;
|
|---|
| 260 | ;; Add element if len is to fill pointer. If fill pointer is to buffer
|
|---|
| 261 | ;; length, then grow buffer.
|
|---|
| 262 | (when (= len (the fixnum *coelesce-buffer-fill-ptr*))
|
|---|
| 263 | (when (= (the fixnum *coelesce-buffer-fill-ptr*)
|
|---|
| 264 | (the fixnum (length (the simple-vector *coelesce-buffer*))))
|
|---|
| 265 | (let ((new (make-array (ash (length (the simple-vector *coelesce-buffer*))
|
|---|
| 266 | 1))))
|
|---|
| 267 | (replace (the simple-vector new) (the simple-vector *coelesce-buffer*)
|
|---|
| 268 | :end1 *coelesce-buffer-fill-ptr*
|
|---|
| 269 | :end2 *coelesce-buffer-fill-ptr*)
|
|---|
| 270 | (setf *coelesce-buffer* new)))
|
|---|
| 271 | (setf (coelesce-buffer-elt len) (make-array 4))
|
|---|
| 272 | (incf *coelesce-buffer-fill-ptr*))
|
|---|
| 273 | ;;
|
|---|
| 274 | ;; Find point to insert record: start, start-line, height, and end-line.
|
|---|
| 275 | (do ((i 0 (1+ i)))
|
|---|
| 276 | ((= i len)
|
|---|
| 277 | ;; Start is greater than all previous starts. Add it to the end.
|
|---|
| 278 | (let ((region (coelesce-buffer-elt len)))
|
|---|
| 279 | (setf (coelesce-buffer-elt-start region) start)
|
|---|
| 280 | (setf (coelesce-buffer-elt-start-line region) start-line)
|
|---|
| 281 | (setf (coelesce-buffer-elt-height region) height)
|
|---|
| 282 | (setf (coelesce-buffer-elt-end-line region) end-line)))
|
|---|
| 283 | (declare (fixnum i))
|
|---|
| 284 | (when (< start (the fixnum
|
|---|
| 285 | (coelesce-buffer-elt-start (coelesce-buffer-elt i))))
|
|---|
| 286 | ;;
|
|---|
| 287 | ;; Insert new element at i, using storage allocated at element len.
|
|---|
| 288 | (let ((last (coelesce-buffer-elt len)))
|
|---|
| 289 | (setf (coelesce-buffer-elt-start last) start)
|
|---|
| 290 | (setf (coelesce-buffer-elt-start-line last) start-line)
|
|---|
| 291 | (setf (coelesce-buffer-elt-height last) height)
|
|---|
| 292 | (setf (coelesce-buffer-elt-end-line last) end-line)
|
|---|
| 293 | ;;
|
|---|
| 294 | ;; Shift elements after i (inclusively) to the right.
|
|---|
| 295 | (do ((j (1- len) (1- j))
|
|---|
| 296 | (k len j)
|
|---|
| 297 | (terminus (1- i)))
|
|---|
| 298 | ((= j terminus))
|
|---|
| 299 | (declare (fixnum j k terminus))
|
|---|
| 300 | (setf (coelesce-buffer-elt k) (coelesce-buffer-elt j)))
|
|---|
| 301 | ;;
|
|---|
| 302 | ;; Stash element to insert at i.
|
|---|
| 303 | (setf (coelesce-buffer-elt i) last))
|
|---|
| 304 | (return)))
|
|---|
| 305 | (1+ len))
|
|---|
| 306 |
|
|---|
| 307 |
|
|---|
| 308 | ;;; COELESCE-EXPOSED-REGIONS-MERGE merges/coelesces the regions in
|
|---|
| 309 | ;;; *coelesce-buffer*. It takes the number of elements and returns the new
|
|---|
| 310 | ;;; number of elements. The regions are examined one at a time relative to
|
|---|
| 311 | ;;; the current one. The current region remains so, with next advancing
|
|---|
| 312 | ;;; through the buffer, until a next region is found that does not overlap
|
|---|
| 313 | ;;; and is not adjacent. When this happens, the current values are stored
|
|---|
| 314 | ;;; in the current region, and the buffer's element after the current element
|
|---|
| 315 | ;;; becomes current. The next element that was found not to be in contact
|
|---|
| 316 | ;;; the old current element is stored in the new current element by copying
|
|---|
| 317 | ;;; its values there. The buffer's elements always stay in place, and their
|
|---|
| 318 | ;;; storage is re-used. After this process which makes the next region be
|
|---|
| 319 | ;;; the current region, the next pointer is incremented.
|
|---|
| 320 | ;;;
|
|---|
| 321 | (defun coelesce-exposed-regions-merge (len)
|
|---|
| 322 | (let* ((current 0)
|
|---|
| 323 | (next 1)
|
|---|
| 324 | (current-region (coelesce-buffer-elt 0))
|
|---|
| 325 | (current-height (coelesce-buffer-elt-height current-region))
|
|---|
| 326 | (current-end-line (coelesce-buffer-elt-end-line current-region))
|
|---|
| 327 | (current-end-bit (+ (the fixnum
|
|---|
| 328 | (coelesce-buffer-elt-start current-region))
|
|---|
| 329 | current-height)))
|
|---|
| 330 | (declare (fixnum current next current-height
|
|---|
| 331 | current-end-line current-end-bit))
|
|---|
| 332 | (loop
|
|---|
| 333 | (let* ((next-region (coelesce-buffer-elt next))
|
|---|
| 334 | (next-start (coelesce-buffer-elt-start next-region))
|
|---|
| 335 | (next-height (coelesce-buffer-elt-height next-region))
|
|---|
| 336 | (next-end-bit (+ next-start next-height)))
|
|---|
| 337 | (declare (fixnum next-start next-height next-end-bit))
|
|---|
| 338 | (cond ((<= next-start current-end-bit)
|
|---|
| 339 | (let ((extra-height (- next-end-bit current-end-bit)))
|
|---|
| 340 | (declare (fixnum extra-height))
|
|---|
| 341 | ;; Maybe the next region is contained in the current.
|
|---|
| 342 | (when (plusp extra-height)
|
|---|
| 343 | (incf current-height extra-height)
|
|---|
| 344 | (setf current-end-bit next-end-bit)
|
|---|
| 345 | (setf current-end-line
|
|---|
| 346 | (coelesce-buffer-elt-end-line next-region)))))
|
|---|
| 347 | (t
|
|---|
| 348 | ;;
|
|---|
| 349 | ;; Update current record since next does not overlap
|
|---|
| 350 | ;; with current.
|
|---|
| 351 | (setf (coelesce-buffer-elt-height current-region)
|
|---|
| 352 | current-height)
|
|---|
| 353 | (setf (coelesce-buffer-elt-end-line current-region)
|
|---|
| 354 | current-end-line)
|
|---|
| 355 | ;;
|
|---|
| 356 | ;; Move to new distinct region, copying data from next region.
|
|---|
| 357 | (incf current)
|
|---|
| 358 | (setf current-region (coelesce-buffer-elt current))
|
|---|
| 359 | (setf (coelesce-buffer-elt-start current-region) next-start)
|
|---|
| 360 | (setf (coelesce-buffer-elt-start-line current-region)
|
|---|
| 361 | (coelesce-buffer-elt-start-line next-region))
|
|---|
| 362 | (setf current-height next-height)
|
|---|
| 363 | (setf current-end-bit next-end-bit)
|
|---|
| 364 | (setf current-end-line
|
|---|
| 365 | (coelesce-buffer-elt-end-line next-region)))))
|
|---|
| 366 | (incf next)
|
|---|
| 367 | (when (= next len)
|
|---|
| 368 | (setf (coelesce-buffer-elt-height current-region) current-height)
|
|---|
| 369 | (setf (coelesce-buffer-elt-end-line current-region) current-end-line)
|
|---|
| 370 | (return)))
|
|---|
| 371 | (1+ current)))
|
|---|
| 372 |
|
|---|
| 373 | ;;; EXPOSED-REGION-BOUNDS returns as multiple values the first line affected,
|
|---|
| 374 | ;;; the first possible bit affected (accounting for the cursor), the end line
|
|---|
| 375 | ;;; affected, and the height of the region.
|
|---|
| 376 | ;;;
|
|---|
| 377 | (defun exposed-region-bounds (y height cursor-offset font-height)
|
|---|
| 378 | (declare (fixnum y height cursor-offset font-height))
|
|---|
| 379 | (let* ((start (truncate (the fixnum (- y hunk-top-border))
|
|---|
| 380 | font-height))
|
|---|
| 381 | (end (ceiling (the fixnum (- (the fixnum (+ y height))
|
|---|
| 382 | hunk-top-border))
|
|---|
| 383 | font-height)))
|
|---|
| 384 | (values
|
|---|
| 385 | start
|
|---|
| 386 | (+ (the fixnum (* start font-height)) cursor-offset hunk-top-border)
|
|---|
| 387 | end
|
|---|
| 388 | (- (the fixnum (* (the fixnum (- end start)) font-height))
|
|---|
| 389 | cursor-offset))))
|
|---|
| 390 |
|
|---|
| 391 | #+clx
|
|---|
| 392 | (defun write-n-exposed-regions (hunk n)
|
|---|
| 393 | (declare (fixnum n))
|
|---|
| 394 | (let* (;; Loop constants.
|
|---|
| 395 | (end-dl (bitmap-hunk-end hunk))
|
|---|
| 396 | (xwindow (bitmap-hunk-xwindow hunk))
|
|---|
| 397 | (hunk-width (bitmap-hunk-width hunk))
|
|---|
| 398 | ;; Loop variables.
|
|---|
| 399 | (dl (bitmap-hunk-start hunk))
|
|---|
| 400 | (i 0)
|
|---|
| 401 | (region (coelesce-buffer-elt 0))
|
|---|
| 402 | (start-line (coelesce-buffer-elt-start-line region))
|
|---|
| 403 | (start (coelesce-buffer-elt-start region))
|
|---|
| 404 | (height (coelesce-buffer-elt-height region))
|
|---|
| 405 | (end-line (coelesce-buffer-elt-end-line region))
|
|---|
| 406 | (region-idx 0))
|
|---|
| 407 | (declare (fixnum i start start-line height end-line region-idx))
|
|---|
| 408 | (loop
|
|---|
| 409 | (xlib:clear-area xwindow :x 0 :y start :width hunk-width :height height)
|
|---|
| 410 | ;; Find this regions first line.
|
|---|
| 411 | (loop
|
|---|
| 412 | (when (or (eq dl end-dl) (= i start-line))
|
|---|
| 413 | (return))
|
|---|
| 414 | (incf i)
|
|---|
| 415 | (setf dl (cdr dl)))
|
|---|
| 416 | ;; Write this region's lines.
|
|---|
| 417 | (loop
|
|---|
| 418 | (when (or (eq dl end-dl) (= i end-line))
|
|---|
| 419 | (return))
|
|---|
| 420 | (hunk-write-line hunk (car dl) i)
|
|---|
| 421 | (incf i)
|
|---|
| 422 | (setf dl (cdr dl)))
|
|---|
| 423 | ;; Get next region unless we're done.
|
|---|
| 424 | (when (= (incf region-idx) n) (return))
|
|---|
| 425 | (setf region (coelesce-buffer-elt region-idx))
|
|---|
| 426 | (setf start (coelesce-buffer-elt-start region))
|
|---|
| 427 | (setf start-line (coelesce-buffer-elt-start-line region))
|
|---|
| 428 | (setf height (coelesce-buffer-elt-height region))
|
|---|
| 429 | (setf end-line (coelesce-buffer-elt-end-line region)))
|
|---|
| 430 | ;;
|
|---|
| 431 | ;; Check for modeline exposure.
|
|---|
| 432 | (setf region (coelesce-buffer-elt (1- n)))
|
|---|
| 433 | (setf start (coelesce-buffer-elt-start region))
|
|---|
| 434 | (setf height (coelesce-buffer-elt-height region))
|
|---|
| 435 | (when (and (bitmap-hunk-modeline-pos hunk)
|
|---|
| 436 | (> (+ start height)
|
|---|
| 437 | (- (bitmap-hunk-modeline-pos hunk)
|
|---|
| 438 | (bitmap-hunk-bottom-border hunk))))
|
|---|
| 439 | (hunk-replace-modeline hunk)
|
|---|
| 440 | (hunk-draw-bottom-border hunk))))
|
|---|
| 441 |
|
|---|
| 442 | #+clx
|
|---|
| 443 | (defun write-one-exposed-region (hunk y height)
|
|---|
| 444 | (let* ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 445 | (font-height (font-family-height font-family))
|
|---|
| 446 | (co (font-family-cursor-y-offset font-family))
|
|---|
| 447 | (start-line (truncate (- y hunk-top-border) font-height))
|
|---|
| 448 | (end-line (ceiling (- (+ y height) hunk-top-border) font-height))
|
|---|
| 449 | (start-bit (+ (* start-line font-height) co hunk-top-border))
|
|---|
| 450 | (nheight (- (* (- end-line start-line) font-height) co))
|
|---|
| 451 | (hunk-end-line (bitmap-hunk-end hunk)))
|
|---|
| 452 | (declare (fixnum font-height co start-line end-line start-bit nheight))
|
|---|
| 453 | (xlib:clear-area (bitmap-hunk-xwindow hunk) :x 0 :y start-bit
|
|---|
| 454 | :width (bitmap-hunk-width hunk) :height nheight)
|
|---|
| 455 | (do ((dl (bitmap-hunk-start hunk) (cdr dl))
|
|---|
| 456 | (i 0 (1+ i)))
|
|---|
| 457 | ((or (eq dl hunk-end-line) (= i start-line))
|
|---|
| 458 | (do ((i i (1+ i))
|
|---|
| 459 | (dl dl (cdr dl)))
|
|---|
| 460 | ((or (eq dl hunk-end-line) (= i end-line)))
|
|---|
| 461 | (declare (fixnum i))
|
|---|
| 462 | (hunk-write-line hunk (car dl) i)))
|
|---|
| 463 | (declare (fixnum i)))
|
|---|
| 464 | (when (and (bitmap-hunk-modeline-pos hunk)
|
|---|
| 465 | (> (+ start-bit nheight)
|
|---|
| 466 | (- (bitmap-hunk-modeline-pos hunk)
|
|---|
| 467 | (bitmap-hunk-bottom-border hunk))))
|
|---|
| 468 | (hunk-replace-modeline hunk)
|
|---|
| 469 | (hunk-draw-bottom-border hunk))))
|
|---|
| 470 |
|
|---|
| 471 |
|
|---|
| 472 | |
|---|
| 473 |
|
|---|
| 474 | ;;;; Resized window handling.
|
|---|
| 475 |
|
|---|
| 476 | ;;; :configure-notify events are sent because we select :structure-notify.
|
|---|
| 477 | ;;; This buys us a lot of events we have to write dummy handlers to ignore.
|
|---|
| 478 | ;;;
|
|---|
| 479 |
|
|---|
| 480 | ;;; HUNK-RECONFIGURED -- Internal.
|
|---|
| 481 | ;;;
|
|---|
| 482 | ;;; This must note that the hunk changed to prevent certain redisplay problems
|
|---|
| 483 | ;;; with recentering the window that caused bogus lines to be drawn after the
|
|---|
| 484 | ;;; actual visible text in the window. We must also indicate the hunk is
|
|---|
| 485 | ;;; trashed to eliminate exposure event handling that comes after resizing.
|
|---|
| 486 | ;;; This also causes a full redisplay on the window which is the easiest and
|
|---|
| 487 | ;;; generally best looking thing.
|
|---|
| 488 | ;;;
|
|---|
| 489 | (defun hunk-reconfigured (object event-key event-window window x y width
|
|---|
| 490 | height border-width above-sibling
|
|---|
| 491 | override-redirect-p send-event-p)
|
|---|
| 492 | (declare (ignore event-key event-window window x y border-width
|
|---|
| 493 | above-sibling override-redirect-p send-event-p))
|
|---|
| 494 | (typecase object
|
|---|
| 495 | (bitmap-hunk
|
|---|
| 496 | (when (or (/= width (bitmap-hunk-width object))
|
|---|
| 497 | (/= height (bitmap-hunk-height object)))
|
|---|
| 498 | (hunk-changed object width height nil)
|
|---|
| 499 | ;; Under X11, don't redisplay since an exposure event is coming next.
|
|---|
| 500 | (setf (bitmap-hunk-trashed object) t)))
|
|---|
| 501 | (window-group
|
|---|
| 502 | (let ((old-width (window-group-width object))
|
|---|
| 503 | (old-height (window-group-height object)))
|
|---|
| 504 | (when (or (/= width old-width) (/= height old-height))
|
|---|
| 505 | (window-group-changed object width height))))))
|
|---|
| 506 | ;;;
|
|---|
| 507 | #+clx (hemlock-ext:serve-configure-notify *hemlock-windows* #'hunk-reconfigured)
|
|---|
| 508 |
|
|---|
| 509 |
|
|---|
| 510 | ;;; HUNK-IGNORE-EVENT ignores the following unrequested events. They all take
|
|---|
| 511 | ;;; at least five arguments, but then there are up to four more optional.
|
|---|
| 512 | ;;;
|
|---|
| 513 | (defun hunk-ignore-event (hunk event-key event-window window one
|
|---|
| 514 | &optional two three four five)
|
|---|
| 515 | (declare (ignore hunk event-key event-window window one two three four five))
|
|---|
| 516 | t)
|
|---|
| 517 | ;;;
|
|---|
| 518 | #+clx (hemlock-ext:serve-destroy-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 519 | #+clx (hemlock-ext:serve-unmap-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 520 | #+clx (hemlock-ext:serve-map-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 521 | #+clx (hemlock-ext:serve-reparent-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 522 | #+clx (hemlock-ext:serve-gravity-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 523 | #+clx (hemlock-ext:serve-circulate-notify *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 524 | #+clx (hemlock-ext:serve-client-message *hemlock-windows* #'hunk-ignore-event)
|
|---|
| 525 |
|
|---|
| 526 | |
|---|
| 527 |
|
|---|
| 528 | ;;;; Interface to X input events.
|
|---|
| 529 |
|
|---|
| 530 | ;;; HUNK-KEY-INPUT and HUNK-MOUSE-INPUT.
|
|---|
| 531 | ;;; Each key and mouse event is turned into a character via
|
|---|
| 532 | ;;; HEMLOCK-EXT:TRANSLATE-CHARACTER or HEMLOCK-EXT:TRANSLATE-MOUSE-CHARACTER, either of which
|
|---|
| 533 | ;;; may return nil. Nil is returned for input that is considered uninteresting
|
|---|
| 534 | ;;; input; for example, shift and control.
|
|---|
| 535 | ;;;
|
|---|
| 536 |
|
|---|
| 537 | (defun hunk-key-input (hunk event-key event-window root child same-screen-p x y
|
|---|
| 538 | root-x root-y modifiers time key-code send-event-p)
|
|---|
| 539 | (declare (ignore event-key event-window root child same-screen-p root-x
|
|---|
| 540 | root-y time send-event-p))
|
|---|
| 541 | (hunk-process-input hunk
|
|---|
| 542 | (hemlock-ext:translate-key-event
|
|---|
| 543 | (bitmap-device-display (device-hunk-device hunk))
|
|---|
| 544 | key-code modifiers)
|
|---|
| 545 | x y))
|
|---|
| 546 | ;;;
|
|---|
| 547 | #+clx (hemlock-ext:serve-key-press *hemlock-windows* #'hunk-key-input)
|
|---|
| 548 |
|
|---|
| 549 | (defun hunk-mouse-input (hunk event-key event-window root child same-screen-p x y
|
|---|
| 550 | root-x root-y modifiers time key-code send-event-p)
|
|---|
| 551 | (declare (ignore event-window root child same-screen-p root-x root-y
|
|---|
| 552 | time send-event-p))
|
|---|
| 553 | (hunk-process-input hunk
|
|---|
| 554 | (hemlock-ext:translate-mouse-key-event key-code modifiers
|
|---|
| 555 | event-key)
|
|---|
| 556 | x y))
|
|---|
| 557 | ;;;
|
|---|
| 558 | #+clx (hemlock-ext:serve-button-press *hemlock-windows* #'hunk-mouse-input)
|
|---|
| 559 | #+clx (hemlock-ext:serve-button-release *hemlock-windows* #'hunk-mouse-input)
|
|---|
| 560 |
|
|---|
| 561 | (defun hunk-process-input (hunk char x y)
|
|---|
| 562 | (when char
|
|---|
| 563 | (let* ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 564 | (font-width (font-family-width font-family))
|
|---|
| 565 | (font-height (font-family-height font-family))
|
|---|
| 566 | (ml-pos (bitmap-hunk-modeline-pos hunk))
|
|---|
| 567 | (height (bitmap-hunk-height hunk))
|
|---|
| 568 | (width (bitmap-hunk-width hunk))
|
|---|
| 569 | (handler (bitmap-hunk-input-handler hunk))
|
|---|
| 570 | (char-width (bitmap-hunk-char-width hunk)))
|
|---|
| 571 | (cond ((not (and (< -1 x width) (< -1 y height)))
|
|---|
| 572 | (funcall handler hunk char nil nil))
|
|---|
| 573 | ((and ml-pos (> y (- ml-pos (bitmap-hunk-bottom-border hunk))))
|
|---|
| 574 | (funcall handler hunk char
|
|---|
| 575 | ;; (/ width x) doesn't handle ends of thumb bar
|
|---|
| 576 | ;; and eob right, so do a bunch of truncating.
|
|---|
| 577 | (min (truncate x (truncate width char-width))
|
|---|
| 578 | (1- char-width))
|
|---|
| 579 | nil))
|
|---|
| 580 | (t
|
|---|
| 581 | (let* ((cx (truncate (- x hunk-left-border) font-width))
|
|---|
| 582 | (temp (truncate (- y hunk-top-border) font-height))
|
|---|
| 583 | (char-height (bitmap-hunk-char-height hunk))
|
|---|
| 584 | ;; Extra bits below bottom line and above modeline and
|
|---|
| 585 | ;; thumb bar are considered part of the bottom line since
|
|---|
| 586 | ;; we have already picked off the y=nil case.
|
|---|
| 587 | (cy (if (< temp char-height) temp (1- char-height))))
|
|---|
| 588 | (if (and (< -1 cx char-width)
|
|---|
| 589 | (< -1 cy))
|
|---|
| 590 | (funcall handler hunk char cx cy)
|
|---|
| 591 | (funcall handler hunk char nil nil))))))))
|
|---|
| 592 |
|
|---|
| 593 |
|
|---|
| 594 | |
|---|
| 595 |
|
|---|
| 596 | ;;;; Handling boundary crossing events.
|
|---|
| 597 |
|
|---|
| 598 | ;;; Entering and leaving a window are handled basically the same except that it
|
|---|
| 599 | ;;; is possible to get an entering event under X without getting an exiting
|
|---|
| 600 | ;;; event; specifically, when the mouse is in a Hemlock window that is over
|
|---|
| 601 | ;;; another window, and someone buries the top window, Hemlock only gets an
|
|---|
| 602 | ;;; entering event on the lower window (no exiting event for the buried
|
|---|
| 603 | ;;; window).
|
|---|
| 604 | ;;;
|
|---|
| 605 | ;;; :enter-notify and :leave-notify events are sent because we select
|
|---|
| 606 | ;;; :enter-window and :leave-window events.
|
|---|
| 607 | ;;;
|
|---|
| 608 |
|
|---|
| 609 | #+clx
|
|---|
| 610 | (defun hunk-mouse-entered (hunk event-key event-window root child same-screen-p
|
|---|
| 611 | x y root-x root-y state time mode kind send-event-p)
|
|---|
| 612 | (declare (ignore event-key event-window child root same-screen-p
|
|---|
| 613 | x y root-x root-y state time mode kind send-event-p))
|
|---|
| 614 | (when (and *cursor-dropped* (not *hemlock-listener*))
|
|---|
| 615 | (cursor-invert-center))
|
|---|
| 616 | (setf *hemlock-listener* t)
|
|---|
| 617 | (let ((current-hunk (window-hunk (current-window))))
|
|---|
| 618 | (unless (and *current-highlighted-border*
|
|---|
| 619 | (eq *current-highlighted-border* current-hunk))
|
|---|
| 620 | (setf (xlib:window-border (window-group-xparent
|
|---|
| 621 | (bitmap-hunk-window-group current-hunk)))
|
|---|
| 622 | *highlight-border-pixmap*)
|
|---|
| 623 | (xlib:display-force-output
|
|---|
| 624 | (bitmap-device-display (device-hunk-device current-hunk)))
|
|---|
| 625 | (setf *current-highlighted-border* current-hunk)))
|
|---|
| 626 | (let ((window (bitmap-hunk-window hunk)))
|
|---|
| 627 | (when window (invoke-hook hemlock::enter-window-hook window))))
|
|---|
| 628 | ;;;
|
|---|
| 629 | #+clx (hemlock-ext:serve-enter-notify *hemlock-windows* #'hunk-mouse-entered)
|
|---|
| 630 |
|
|---|
| 631 | #+clx
|
|---|
| 632 | (defun hunk-mouse-left (hunk event-key event-window root child same-screen-p
|
|---|
| 633 | x y root-x root-y state time mode kind send-event-p)
|
|---|
| 634 | (declare (ignore event-key event-window child root same-screen-p
|
|---|
| 635 | x y root-x root-y state time mode kind send-event-p))
|
|---|
| 636 | (setf *hemlock-listener* nil)
|
|---|
| 637 | (when *cursor-dropped* (cursor-invert-center))
|
|---|
| 638 | (when *current-highlighted-border*
|
|---|
| 639 | (setf (xlib:window-border (window-group-xparent
|
|---|
| 640 | (bitmap-hunk-window-group
|
|---|
| 641 | *current-highlighted-border*)))
|
|---|
| 642 | *default-border-pixmap*)
|
|---|
| 643 | (xlib:display-force-output
|
|---|
| 644 | (bitmap-device-display (device-hunk-device *current-highlighted-border*)))
|
|---|
| 645 | (setf *current-highlighted-border* nil))
|
|---|
| 646 | (let ((window (bitmap-hunk-window hunk)))
|
|---|
| 647 | (when window (invoke-hook hemlock::exit-window-hook window))))
|
|---|
| 648 | ;;;
|
|---|
| 649 | #+clx (hemlock-ext:serve-leave-notify *hemlock-windows* #'hunk-mouse-left)
|
|---|
| 650 |
|
|---|
| 651 |
|
|---|
| 652 | |
|---|
| 653 |
|
|---|
| 654 | ;;;; Making a Window.
|
|---|
| 655 |
|
|---|
| 656 | (defparameter minimum-window-height 100
|
|---|
| 657 | "If the window created by splitting a window would be shorter than this,
|
|---|
| 658 | then we create an overlapped window the same size instead.")
|
|---|
| 659 |
|
|---|
| 660 | ;;; The width must be that of a tab for the screen image builder, and the
|
|---|
| 661 | ;;; height must be one line (two with a modeline).
|
|---|
| 662 | ;;;
|
|---|
| 663 | (defconstant minimum-window-lines 2
|
|---|
| 664 | "Windows must have at least this many lines.")
|
|---|
| 665 | (defconstant minimum-window-columns 10
|
|---|
| 666 | "Windows must be at least this many characters wide.")
|
|---|
| 667 |
|
|---|
| 668 | (eval-when (:compile-toplevel :execute :load-toplevel)
|
|---|
| 669 | (defconstant xwindow-border-width 2 "X border around X windows")
|
|---|
| 670 | (defconstant xwindow-border-width*2 (* xwindow-border-width 2))
|
|---|
| 671 | ); eval-when
|
|---|
| 672 |
|
|---|
| 673 | ;;; We must name windows (set the "name" property) to get around a bug in
|
|---|
| 674 | ;;; awm and twm. They will not handle menu clicks without a window having
|
|---|
| 675 | ;;; a name. We set the name to this silly thing.
|
|---|
| 676 | ;;;
|
|---|
| 677 | (defvar *hemlock-window-count* 0)
|
|---|
| 678 | ;;;
|
|---|
| 679 | (defun new-hemlock-window-name ()
|
|---|
| 680 | (let ((*print-base* 10))
|
|---|
| 681 | (format nil "Hemlock ~S" (incf *hemlock-window-count*))))
|
|---|
| 682 |
|
|---|
| 683 | (declaim (inline surplus-window-height surplus-window-height-w/-modeline))
|
|---|
| 684 | ;;;
|
|---|
| 685 | (defun surplus-window-height (thumb-bar-p)
|
|---|
| 686 | (+ hunk-top-border (if thumb-bar-p
|
|---|
| 687 | hunk-thumb-bar-bottom-border
|
|---|
| 688 | hunk-bottom-border)))
|
|---|
| 689 | ;;;
|
|---|
| 690 | (defun surplus-window-height-w/-modeline (thumb-bar-p)
|
|---|
| 691 | (+ (surplus-window-height thumb-bar-p)
|
|---|
| 692 | hunk-modeline-top
|
|---|
| 693 | hunk-modeline-bottom))
|
|---|
| 694 |
|
|---|
| 695 |
|
|---|
| 696 | ;;; DEFAULT-CREATE-WINDOW-HOOK -- Internal.
|
|---|
| 697 | ;;;
|
|---|
| 698 | ;;; This is the default value for *create-window-hook*. It makes an X window
|
|---|
| 699 | ;;; for a new group/parent on the given display possibly prompting the user.
|
|---|
| 700 | ;;;
|
|---|
| 701 | #+clx
|
|---|
| 702 | (defun default-create-window-hook (display x y width height name font-family
|
|---|
| 703 | &optional modelinep thumb-bar-p)
|
|---|
| 704 | (maybe-prompt-user-for-window
|
|---|
| 705 | (xlib:screen-root (xlib:display-default-screen display))
|
|---|
| 706 | x y width height font-family modelinep thumb-bar-p name))
|
|---|
| 707 |
|
|---|
| 708 | #-clx
|
|---|
| 709 | (defun default-create-window-hook (display x y width height name font-family
|
|---|
| 710 | &optional modelinep thumb-bar-p)
|
|---|
| 711 | (declare (ignore display x y width height name font-family
|
|---|
| 712 | modelinep thumb-bar-p)))
|
|---|
| 713 |
|
|---|
| 714 | ;;; MAYBE-PROMPT-USER-FOR-WINDOW -- Internal.
|
|---|
| 715 | ;;;
|
|---|
| 716 | ;;; This makes an X window and sets its standard properties according to
|
|---|
| 717 | ;;; supplied values. When some of these are nil, the window manager should
|
|---|
| 718 | ;;; prompt the user for those missing values when the window gets mapped. We
|
|---|
| 719 | ;;; use this when making new group/parent windows. Returns the window without
|
|---|
| 720 | ;;; mapping it.
|
|---|
| 721 | ;;;
|
|---|
| 722 | (defun maybe-prompt-user-for-window (root x y width height font-family
|
|---|
| 723 | modelinep thumb-bar-p icon-name)
|
|---|
| 724 | (let ((font-height (font-family-height font-family))
|
|---|
| 725 | (font-width (font-family-width font-family))
|
|---|
| 726 | (extra-y (surplus-window-height thumb-bar-p))
|
|---|
| 727 | (extra-y-w/-modeline (surplus-window-height-w/-modeline thumb-bar-p)))
|
|---|
| 728 | (create-window-with-properties
|
|---|
| 729 | root x y
|
|---|
| 730 | (if width (+ (* width font-width) hunk-left-border))
|
|---|
| 731 | (if height
|
|---|
| 732 | (if modelinep
|
|---|
| 733 | (+ (* (1+ height) font-height) extra-y-w/-modeline)
|
|---|
| 734 | (+ (* height font-height) extra-y)))
|
|---|
| 735 | font-width font-height icon-name
|
|---|
| 736 | (+ (* minimum-window-columns font-width) hunk-left-border)
|
|---|
| 737 | (if modelinep
|
|---|
| 738 | (+ (* (1+ minimum-window-lines) font-height) extra-y-w/-modeline)
|
|---|
| 739 | (+ (* minimum-window-lines font-height) extra-y))
|
|---|
| 740 | t)))
|
|---|
| 741 |
|
|---|
| 742 | (defvar *create-window-hook* #'default-create-window-hook
|
|---|
| 743 | "Hemlock calls this function when it makes a new X window for a new group.
|
|---|
| 744 | It passes as arguments the X display, x (from MAKE-WINDOW), y (from
|
|---|
| 745 | MAKE-WINDOW), width (from MAKE-WINDOW), height (from MAKE-WINDOW), a name
|
|---|
| 746 | for the window's icon-name, font-family (from MAKE-WINDOW), modelinep (from
|
|---|
| 747 | MAKE-WINDOW), and whether the window will have a thumb-bar meter. The
|
|---|
| 748 | function returns a window or nil.")
|
|---|
| 749 |
|
|---|
| 750 | ;;; BITMAP-MAKE-WINDOW -- Internal.
|
|---|
| 751 | ;;;
|
|---|
| 752 | #+clx
|
|---|
| 753 | (defun bitmap-make-window (device start modelinep window font-family
|
|---|
| 754 | ask-user x y width-arg height-arg proportion)
|
|---|
| 755 | (let* ((display (bitmap-device-display device))
|
|---|
| 756 | (thumb-bar-p (value hemlock::thumb-bar-meter))
|
|---|
| 757 | (hunk (make-bitmap-hunk
|
|---|
| 758 | :font-family font-family
|
|---|
| 759 | :end *the-sentinel* :trashed t
|
|---|
| 760 | :input-handler #'window-input-handler
|
|---|
| 761 | :device device
|
|---|
| 762 | :thumb-bar-p (and modelinep thumb-bar-p))))
|
|---|
| 763 | (multiple-value-bind
|
|---|
| 764 | (xparent xwindow)
|
|---|
| 765 | (maybe-make-x-window-and-parent window display start ask-user x y
|
|---|
| 766 | width-arg height-arg font-family
|
|---|
| 767 | modelinep thumb-bar-p proportion)
|
|---|
| 768 | (unless xwindow (return-from bitmap-make-window nil))
|
|---|
| 769 | (let ((window-group (make-window-group xparent
|
|---|
| 770 | (xlib:drawable-width xparent)
|
|---|
| 771 | (xlib:drawable-height xparent))))
|
|---|
| 772 | (setf (bitmap-hunk-xwindow hunk) xwindow)
|
|---|
| 773 | (setf (bitmap-hunk-window-group hunk) window-group)
|
|---|
| 774 | (setf (bitmap-hunk-gcontext hunk)
|
|---|
| 775 | (default-gcontext xwindow font-family))
|
|---|
| 776 | ;;
|
|---|
| 777 | ;; Select input and enable event service before showing the window.
|
|---|
| 778 | (setf (xlib:window-event-mask xwindow) child-interesting-xevents-mask)
|
|---|
| 779 | (setf (xlib:window-event-mask xparent) group-interesting-xevents-mask)
|
|---|
| 780 | (add-xwindow-object xwindow hunk *hemlock-windows*)
|
|---|
| 781 | (add-xwindow-object xparent window-group *hemlock-windows*))
|
|---|
| 782 | (when xparent (xlib:map-window xparent))
|
|---|
| 783 | (xlib:map-window xwindow)
|
|---|
| 784 | (xlib:display-finish-output display)
|
|---|
| 785 | ;; A window is not really mapped until it is viewable. It is said to be
|
|---|
| 786 | ;; mapped if a map request has been sent whether it is handled or not.
|
|---|
| 787 | (loop (when (and (eq (xlib:window-map-state xwindow) :viewable)
|
|---|
| 788 | (eq (xlib:window-map-state xparent) :viewable))
|
|---|
| 789 | (return)))
|
|---|
| 790 | ;;
|
|---|
| 791 | ;; Find out how big it is...
|
|---|
| 792 | (xlib:with-state (xwindow)
|
|---|
| 793 | (set-hunk-size hunk (xlib:drawable-width xwindow)
|
|---|
| 794 | (xlib:drawable-height xwindow) modelinep)))
|
|---|
| 795 | (setf (bitmap-hunk-window hunk)
|
|---|
| 796 | (window-for-hunk hunk start modelinep))
|
|---|
| 797 | ;; If window is non-nil, then it is a new group/parent window, so don't
|
|---|
| 798 | ;; link it into the current window's group. When ask-user is non-nil,
|
|---|
| 799 | ;; we make a new group too.
|
|---|
| 800 | (cond ((or window ask-user)
|
|---|
| 801 | ;; This occurs when we make the world's first Hemlock window.
|
|---|
| 802 | (unless *current-window*
|
|---|
| 803 | (setq *current-window* (bitmap-hunk-window hunk)))
|
|---|
| 804 | (setf (bitmap-hunk-previous hunk) hunk)
|
|---|
| 805 | (setf (bitmap-hunk-next hunk) hunk))
|
|---|
| 806 | (t
|
|---|
| 807 | (let ((h (window-hunk *current-window*)))
|
|---|
| 808 | (shiftf (bitmap-hunk-next hunk) (bitmap-hunk-next h) hunk)
|
|---|
| 809 | (setf (bitmap-hunk-previous (bitmap-hunk-next hunk)) hunk)
|
|---|
| 810 | (setf (bitmap-hunk-previous hunk) h))))
|
|---|
| 811 | (push hunk (device-hunks device))
|
|---|
| 812 | (bitmap-hunk-window hunk)))
|
|---|
| 813 |
|
|---|
| 814 | ;;; MAYBE-MAKE-X-WINDOW-AND-PARENT -- Internal.
|
|---|
| 815 | ;;;
|
|---|
| 816 | ;;; BITMAP-MAKE-WINDOW calls this. If xparent is non-nil, we clear it and
|
|---|
| 817 | ;;; return it with a child that fills it. If xparent is nil, and ask-user is
|
|---|
| 818 | ;;; non-nil, then we invoke *create-window-hook* to get a parent window and
|
|---|
| 819 | ;;; return it with a child that fills it. By default, we make a child in the
|
|---|
| 820 | ;;; CURRENT-WINDOW's parent.
|
|---|
| 821 | ;;;
|
|---|
| 822 | #+clx
|
|---|
| 823 | (defun maybe-make-x-window-and-parent (xparent display start ask-user x y width
|
|---|
| 824 | height font-family modelinep thumb-p
|
|---|
| 825 | proportion)
|
|---|
| 826 | (let ((icon-name (buffer-name (line-buffer (mark-line start)))))
|
|---|
| 827 | (cond (xparent
|
|---|
| 828 | (check-type xparent xlib:window)
|
|---|
| 829 | (let ((width (xlib:drawable-width xparent))
|
|---|
| 830 | (height (xlib:drawable-height xparent)))
|
|---|
| 831 | (xlib:clear-area xparent :width width :height height)
|
|---|
| 832 | (modify-parent-properties :set xparent modelinep thumb-p
|
|---|
| 833 | (font-family-width font-family)
|
|---|
| 834 | (font-family-height font-family))
|
|---|
| 835 | (values xparent (xwindow-for-xparent xparent icon-name))))
|
|---|
| 836 | (ask-user
|
|---|
| 837 | (let ((xparent (funcall *create-window-hook*
|
|---|
| 838 | display x y width height icon-name
|
|---|
| 839 | font-family modelinep thumb-p)))
|
|---|
| 840 | (values xparent (xwindow-for-xparent xparent icon-name))))
|
|---|
| 841 | (t
|
|---|
| 842 | (let ((xparent (window-group-xparent
|
|---|
| 843 | (bitmap-hunk-window-group
|
|---|
| 844 | (window-hunk (current-window))))))
|
|---|
| 845 | (values xparent
|
|---|
| 846 | (create-window-from-current
|
|---|
| 847 | proportion font-family modelinep thumb-p xparent
|
|---|
| 848 | icon-name)))))))
|
|---|
| 849 |
|
|---|
| 850 | ;;; XWINDOW-FOR-XPARENT -- Internal.
|
|---|
| 851 | ;;;
|
|---|
| 852 | ;;; This returns a child of xparent that completely fills that parent window.
|
|---|
| 853 | ;;; We supply the font-width and font-height as nil because these are useless
|
|---|
| 854 | ;;; for child windows.
|
|---|
| 855 | ;;;
|
|---|
| 856 | #+clx
|
|---|
| 857 | (defun xwindow-for-xparent (xparent icon-name)
|
|---|
| 858 | (xlib:with-state (xparent)
|
|---|
| 859 | (create-window-with-properties xparent 0 0
|
|---|
| 860 | (xlib:drawable-width xparent)
|
|---|
| 861 | (xlib:drawable-height xparent)
|
|---|
| 862 | nil nil icon-name)))
|
|---|
| 863 |
|
|---|
| 864 | ;;; CREATE-WINDOW-FROM-CURRENT -- Internal.
|
|---|
| 865 | ;;;
|
|---|
| 866 | ;;; This makes a child window on parent by splitting the current window. If
|
|---|
| 867 | ;;; the result will be too small, this returns nil. If the current window's
|
|---|
| 868 | ;;; height is odd, the extra pixel stays with it, and the new window is one
|
|---|
| 869 | ;;; pixel smaller.
|
|---|
| 870 | ;;;
|
|---|
| 871 | #+clx
|
|---|
| 872 | (defun create-window-from-current (proportion font-family modelinep thumb-p
|
|---|
| 873 | parent icon-name)
|
|---|
| 874 | (let* ((cur-hunk (window-hunk *current-window*))
|
|---|
| 875 | (cwin (bitmap-hunk-xwindow cur-hunk)))
|
|---|
| 876 | ;; Compute current window's height and take a proportion of it.
|
|---|
| 877 | (xlib:with-state (cwin)
|
|---|
| 878 | (let* ((cw (xlib:drawable-width cwin))
|
|---|
| 879 | (ch (xlib:drawable-height cwin))
|
|---|
| 880 | (cy (xlib:drawable-y cwin))
|
|---|
| 881 | (new-ch (truncate (* ch (- 1 proportion))))
|
|---|
| 882 | (font-height (font-family-height font-family))
|
|---|
| 883 | (font-width (font-family-width font-family))
|
|---|
| 884 | (cwin-min (minimum-window-height
|
|---|
| 885 | (font-family-height
|
|---|
| 886 | (bitmap-hunk-font-family cur-hunk))
|
|---|
| 887 | (bitmap-hunk-modeline-pos cur-hunk)
|
|---|
| 888 | (bitmap-hunk-thumb-bar-p cur-hunk)))
|
|---|
| 889 | (new-min (minimum-window-height font-height modelinep
|
|---|
| 890 | thumb-p)))
|
|---|
| 891 | (declare (fixnum cw cy ch new-ch))
|
|---|
| 892 | ;; See if we have room for a new window. This should really
|
|---|
| 893 | ;; check the current window and the new one against their
|
|---|
| 894 | ;; relative fonts and the minimal window columns and line
|
|---|
| 895 | ;; (including whether there is a modeline).
|
|---|
| 896 | (if (and (> new-ch cwin-min)
|
|---|
| 897 | (> (- ch new-ch) new-min))
|
|---|
| 898 | (let ((win (create-window-with-properties
|
|---|
| 899 | parent 0 (+ cy new-ch)
|
|---|
| 900 | cw (- ch new-ch) font-width font-height
|
|---|
| 901 | icon-name)))
|
|---|
| 902 | ;; No need to reshape current Hemlock window structure here
|
|---|
| 903 | ;; since this call will send an appropriate event.
|
|---|
| 904 | (setf (xlib:drawable-height cwin) new-ch)
|
|---|
| 905 | ;; Set hints on parent, so the user can't resize it to be
|
|---|
| 906 | ;; smaller than what will hold the current number of
|
|---|
| 907 | ;; children.
|
|---|
| 908 | (modify-parent-properties :add parent modelinep
|
|---|
| 909 | thumb-p
|
|---|
| 910 | (font-family-width font-family)
|
|---|
| 911 | font-height)
|
|---|
| 912 | win)
|
|---|
| 913 | nil)))))
|
|---|
| 914 |
|
|---|
| 915 |
|
|---|
| 916 | ;;; MAKE-XWINDOW-LIKE-HWINDOW -- Interface.
|
|---|
| 917 | ;;;
|
|---|
| 918 | ;;; The window name is set to get around an awm and twm bug that inhibits menu
|
|---|
| 919 | ;;; clicks unless the window has a name; this could be used better.
|
|---|
| 920 | ;;;
|
|---|
| 921 | #+clx
|
|---|
| 922 | (defun make-xwindow-like-hwindow (window)
|
|---|
| 923 | "This returns an group/parent xwindow with dimensions suitable for making a
|
|---|
| 924 | Hemlock window like the argument window. The new window's position should
|
|---|
| 925 | be the same as the argument window's position relative to the root. When
|
|---|
| 926 | setting standard properties, we set x, y, width, and height to tell window
|
|---|
| 927 | managers to put the window where we intend without querying the user."
|
|---|
| 928 | (let* ((hunk (window-hunk window))
|
|---|
| 929 | (font-family (bitmap-hunk-font-family hunk))
|
|---|
| 930 | (xwin (bitmap-hunk-xwindow hunk)))
|
|---|
| 931 | (multiple-value-bind (x y)
|
|---|
| 932 | (window-root-xy xwin)
|
|---|
| 933 | (create-window-with-properties
|
|---|
| 934 | (xlib:screen-root (xlib:display-default-screen
|
|---|
| 935 | (bitmap-device-display (device-hunk-device hunk))))
|
|---|
| 936 | x y (bitmap-hunk-width hunk) (bitmap-hunk-height hunk)
|
|---|
| 937 | (font-family-width font-family)
|
|---|
| 938 | (font-family-height font-family)
|
|---|
| 939 | (buffer-name (window-buffer window))
|
|---|
| 940 | ;; When the user hands this window to MAKE-WINDOW, it will set the
|
|---|
| 941 | ;; minimum width and height properties.
|
|---|
| 942 | nil nil
|
|---|
| 943 | t))))
|
|---|
| 944 |
|
|---|
| 945 |
|
|---|
| 946 | |
|---|
| 947 |
|
|---|
| 948 | ;;;; Deleting a window.
|
|---|
| 949 |
|
|---|
| 950 | ;;; DEFAULT-DELETE-WINDOW-HOOK -- Internal.
|
|---|
| 951 | ;;;
|
|---|
| 952 | #+clx
|
|---|
| 953 | (defun default-delete-window-hook (xparent)
|
|---|
| 954 | (xlib:destroy-window xparent))
|
|---|
| 955 | #-clx
|
|---|
| 956 | (defun default-delete-window-hook (xparent)
|
|---|
| 957 | (declare (ignore xparent)))
|
|---|
| 958 | ;;;
|
|---|
| 959 | (defvar *delete-window-hook* #'default-delete-window-hook
|
|---|
| 960 | "Hemlock calls this function to delete an X group/parent window. It passes
|
|---|
| 961 | the X window as an argument.")
|
|---|
| 962 |
|
|---|
| 963 |
|
|---|
| 964 | ;;; BITMAP-DELETE-WINDOW -- Internal
|
|---|
| 965 | ;;;
|
|---|
| 966 | ;;;
|
|---|
| 967 | #+clx
|
|---|
| 968 | (defun bitmap-delete-window (window)
|
|---|
| 969 | (let* ((hunk (window-hunk window))
|
|---|
| 970 | (xwindow (bitmap-hunk-xwindow hunk))
|
|---|
| 971 | (xparent (window-group-xparent (bitmap-hunk-window-group hunk)))
|
|---|
| 972 | (display (bitmap-device-display (device-hunk-device hunk))))
|
|---|
| 973 | (remove-xwindow-object xwindow)
|
|---|
| 974 | (setq *window-list* (delete window *window-list*))
|
|---|
| 975 | (when (eq *current-highlighted-border* hunk)
|
|---|
| 976 | (setf *current-highlighted-border* nil))
|
|---|
| 977 | (when (and (eq *cursor-hunk* hunk) *cursor-dropped*) (lift-cursor))
|
|---|
| 978 | (xlib:display-force-output display)
|
|---|
| 979 | (bitmap-delete-and-reclaim-window-space xwindow window)
|
|---|
| 980 | (loop (unless (deleting-window-drop-event display xwindow) (return)))
|
|---|
| 981 | (let ((device (device-hunk-device hunk)))
|
|---|
| 982 | (setf (device-hunks device) (delete hunk (device-hunks device))))
|
|---|
| 983 | (cond ((eq hunk (bitmap-hunk-next hunk))
|
|---|
| 984 | ;; Is this the last window in the group?
|
|---|
| 985 | (remove-xwindow-object xparent)
|
|---|
| 986 | (xlib:display-force-output display)
|
|---|
| 987 | (funcall *delete-window-hook* xparent)
|
|---|
| 988 | (loop (unless (deleting-window-drop-event display xparent)
|
|---|
| 989 | (return)))
|
|---|
| 990 | (let ((window (find-if-not #'(lambda (window)
|
|---|
| 991 | (eq window *echo-area-window*))
|
|---|
| 992 | *window-list*)))
|
|---|
| 993 | (setf (current-buffer) (window-buffer window)
|
|---|
| 994 | (current-window) window)))
|
|---|
| 995 | (t
|
|---|
| 996 | (modify-parent-properties :delete xparent
|
|---|
| 997 | (bitmap-hunk-modeline-pos hunk)
|
|---|
| 998 | (bitmap-hunk-thumb-bar-p hunk)
|
|---|
| 999 | (font-family-width
|
|---|
| 1000 | (bitmap-hunk-font-family hunk))
|
|---|
| 1001 | (font-family-height
|
|---|
| 1002 | (bitmap-hunk-font-family hunk)))
|
|---|
| 1003 | (let ((next (bitmap-hunk-next hunk))
|
|---|
| 1004 | (prev (bitmap-hunk-previous hunk)))
|
|---|
| 1005 | (setf (bitmap-hunk-next prev) next)
|
|---|
| 1006 | (setf (bitmap-hunk-previous next) prev))))
|
|---|
| 1007 | (let ((buffer (window-buffer window)))
|
|---|
| 1008 | (setf (buffer-windows buffer) (delete window (buffer-windows buffer)))))
|
|---|
| 1009 | nil)
|
|---|
| 1010 |
|
|---|
| 1011 | ;;; BITMAP-DELETE-AND-RECLAIM-WINDOW-SPACE -- Internal.
|
|---|
| 1012 | ;;;
|
|---|
| 1013 | ;;; This destroys the X window after obtaining its necessary state information.
|
|---|
| 1014 | ;;; If the previous or next window (in that order) is "stacked" over or under
|
|---|
| 1015 | ;;; the target window, then it is grown to fill in the newly opened space. We
|
|---|
| 1016 | ;;; fetch all the necessary configuration data up front, so we don't have to
|
|---|
| 1017 | ;;; call XLIB:DESTROY-WINDOW while in the XLIB:WITH-STATE.
|
|---|
| 1018 | ;;;
|
|---|
| 1019 | #+clx
|
|---|
| 1020 | (defun bitmap-delete-and-reclaim-window-space (xwindow hwindow)
|
|---|
| 1021 | (multiple-value-bind (y height)
|
|---|
| 1022 | (xlib:with-state (xwindow)
|
|---|
| 1023 | (values (xlib:drawable-y xwindow)
|
|---|
| 1024 | (xlib:drawable-height xwindow)))
|
|---|
| 1025 | (xlib:destroy-window xwindow)
|
|---|
| 1026 | (let ((hunk (window-hunk hwindow)))
|
|---|
| 1027 | (xlib:free-gcontext (bitmap-hunk-gcontext hunk))
|
|---|
| 1028 | (unless (eq hunk (bitmap-hunk-next hunk))
|
|---|
| 1029 | (unless (maybe-merge-with-previous-window hunk y height)
|
|---|
| 1030 | (merge-with-next-window hunk y height))))))
|
|---|
| 1031 |
|
|---|
| 1032 | ;;; MAYBE-MERGE-WITH-PREVIOUS-WINDOW -- Internal.
|
|---|
| 1033 | ;;;
|
|---|
| 1034 | ;;; This returns non-nil when it grows the previous hunk to include the
|
|---|
| 1035 | ;;; argument hunk's screen space.
|
|---|
| 1036 | ;;;
|
|---|
| 1037 | #+clx
|
|---|
| 1038 | (defun maybe-merge-with-previous-window (hunk y h)
|
|---|
| 1039 | (declare (fixnum y h))
|
|---|
| 1040 | (let* ((prev (bitmap-hunk-previous hunk))
|
|---|
| 1041 | (prev-xwin (bitmap-hunk-xwindow prev)))
|
|---|
| 1042 | (xlib:with-state (prev-xwin)
|
|---|
| 1043 | (if (< (xlib:drawable-y prev-xwin) y)
|
|---|
| 1044 | (incf (xlib:drawable-height prev-xwin) h)))))
|
|---|
| 1045 |
|
|---|
| 1046 | ;;; MERGE-WITH-NEXT-WINDOW -- Internal.
|
|---|
| 1047 | ;;;
|
|---|
| 1048 | ;;; This trys to grow the next hunk's window to make use of the space created
|
|---|
| 1049 | ;;; by deleting hunk's window. If this is possible, then we must also move the
|
|---|
| 1050 | ;;; next window up to where hunk's window was.
|
|---|
| 1051 | ;;;
|
|---|
| 1052 | ;;; When we reconfigure the window, we must set the hunk trashed. This is a
|
|---|
| 1053 | ;;; hack since twm is broken again and is sending exposure events before
|
|---|
| 1054 | ;;; reconfigure notifications. Hemlock relies on the protocol's statement that
|
|---|
| 1055 | ;;; reconfigures come before exposures to set the hunk trashed before getting
|
|---|
| 1056 | ;;; the exposure. For now, we'll do it here too.
|
|---|
| 1057 | ;;;
|
|---|
| 1058 | #+clx
|
|---|
| 1059 | (defun merge-with-next-window (hunk y h)
|
|---|
| 1060 | (declare (fixnum y h))
|
|---|
| 1061 | (let* ((next (bitmap-hunk-next hunk))
|
|---|
| 1062 | (next-xwin (bitmap-hunk-xwindow next)))
|
|---|
| 1063 | ;; Fetch height before setting y to save an extra round trip to the X
|
|---|
| 1064 | ;; server.
|
|---|
| 1065 | (let ((next-h (xlib:drawable-height next-xwin)))
|
|---|
| 1066 | (setf (xlib:drawable-y next-xwin) y)
|
|---|
| 1067 | (setf (xlib:drawable-height next-xwin) (+ next-h h)))
|
|---|
| 1068 | (setf (bitmap-hunk-trashed next) t)
|
|---|
| 1069 | (let ((hints (xlib:wm-normal-hints next-xwin)))
|
|---|
| 1070 | (setf (xlib:wm-size-hints-y hints) y)
|
|---|
| 1071 | (setf (xlib:wm-normal-hints next-xwin) hints))))
|
|---|
| 1072 |
|
|---|
| 1073 |
|
|---|
| 1074 | ;;; DELETING-WINDOW-DROP-EVENT -- Internal.
|
|---|
| 1075 | ;;;
|
|---|
| 1076 | ;;; This checks for any events on win. If there is one, remove it from the
|
|---|
| 1077 | ;;; queue and return t. Otherwise, return nil.
|
|---|
| 1078 | ;;;
|
|---|
| 1079 | #+clx
|
|---|
| 1080 | (defun deleting-window-drop-event (display win)
|
|---|
| 1081 | (xlib:display-finish-output display)
|
|---|
| 1082 | (let ((result nil))
|
|---|
| 1083 | (xlib:process-event
|
|---|
| 1084 | display :timeout 0
|
|---|
| 1085 | :handler #'(lambda (&key event-window window &allow-other-keys)
|
|---|
| 1086 | (if (or (eq event-window win) (eq window win))
|
|---|
| 1087 | (setf result t)
|
|---|
| 1088 | nil)))
|
|---|
| 1089 | result))
|
|---|
| 1090 |
|
|---|
| 1091 |
|
|---|
| 1092 | ;;; MODIFY-PARENT-PROPERTIES -- Internal.
|
|---|
| 1093 | ;;;
|
|---|
| 1094 | ;;; This adds or deletes from xparent's min-height and min-width hints, so the
|
|---|
| 1095 | ;;; window manager will hopefully prevent users from making a window group too
|
|---|
| 1096 | ;;; small to hold all the windows in it. We add to the height when we split
|
|---|
| 1097 | ;;; windows making additional ones, and we delete from it when we delete a
|
|---|
| 1098 | ;;; window.
|
|---|
| 1099 | ;;;
|
|---|
| 1100 | ;;; NOTE, THIS FAILS TO MAINTAIN THE WIDTH CORRECTLY. We need to maintain the
|
|---|
| 1101 | ;;; width as the MAX of all the windows' minimal widths. A window's minimal
|
|---|
| 1102 | ;;; width is its font's width multiplied by minimum-window-columns.
|
|---|
| 1103 | ;;;
|
|---|
| 1104 | #+clx
|
|---|
| 1105 | (defun modify-parent-properties (type xparent modelinep thumb-p
|
|---|
| 1106 | font-width font-height)
|
|---|
| 1107 | (let ((hints (xlib:wm-normal-hints xparent)))
|
|---|
| 1108 | (xlib:set-wm-properties
|
|---|
| 1109 | xparent
|
|---|
| 1110 | :resource-name "Hemlock"
|
|---|
| 1111 | :x (xlib:wm-size-hints-x hints)
|
|---|
| 1112 | :y (xlib:wm-size-hints-y hints)
|
|---|
| 1113 | :width (xlib:drawable-width xparent)
|
|---|
| 1114 | :height (xlib:drawable-height xparent)
|
|---|
| 1115 | :user-specified-position-p t
|
|---|
| 1116 | :user-specified-size-p t
|
|---|
| 1117 | :width-inc (xlib:wm-size-hints-width-inc hints)
|
|---|
| 1118 | :height-inc (xlib:wm-size-hints-height-inc hints)
|
|---|
| 1119 | :min-width (or (xlib:wm-size-hints-min-width hints)
|
|---|
| 1120 | (+ (* minimum-window-columns font-width) hunk-left-border))
|
|---|
| 1121 | :min-height
|
|---|
| 1122 | (let ((delta (minimum-window-height font-height modelinep thumb-p)))
|
|---|
| 1123 | (ecase type
|
|---|
| 1124 | (:delete (- (xlib:wm-size-hints-min-height hints) delta))
|
|---|
| 1125 | (:add (+ (or (xlib:wm-size-hints-min-height hints) 0)
|
|---|
| 1126 | delta))
|
|---|
| 1127 | (:set delta))))))
|
|---|
| 1128 |
|
|---|
| 1129 | ;;; MINIMUM-WINDOW-HEIGHT -- Internal.
|
|---|
| 1130 | ;;;
|
|---|
| 1131 | ;;; This returns the minimum height necessary for a window given some of its
|
|---|
| 1132 | ;;; parameters. This is the number of lines times font-height plus any extra
|
|---|
| 1133 | ;;; pixels for aesthetics.
|
|---|
| 1134 | ;;;
|
|---|
| 1135 | (defun minimum-window-height (font-height modelinep thumb-p)
|
|---|
| 1136 | (if modelinep
|
|---|
| 1137 | (+ (* (1+ minimum-window-lines) font-height)
|
|---|
| 1138 | (surplus-window-height-w/-modeline thumb-p))
|
|---|
| 1139 | (+ (* minimum-window-lines font-height)
|
|---|
| 1140 | (surplus-window-height thumb-p))))
|
|---|
| 1141 |
|
|---|
| 1142 |
|
|---|
| 1143 | |
|---|
| 1144 |
|
|---|
| 1145 | ;;;; Next and Previous windows.
|
|---|
| 1146 |
|
|---|
| 1147 | (defun bitmap-next-window (window)
|
|---|
| 1148 | "Return the next window after Window, wrapping around if Window is the
|
|---|
| 1149 | bottom window."
|
|---|
| 1150 | (check-type window window)
|
|---|
| 1151 | (bitmap-hunk-window (bitmap-hunk-next (window-hunk window))))
|
|---|
| 1152 |
|
|---|
| 1153 | (defun bitmap-previous-window (window)
|
|---|
| 1154 | "Return the previous window after Window, wrapping around if Window is the
|
|---|
| 1155 | top window."
|
|---|
| 1156 | (check-type window window)
|
|---|
| 1157 | (bitmap-hunk-window (bitmap-hunk-previous (window-hunk window))))
|
|---|
| 1158 |
|
|---|
| 1159 |
|
|---|
| 1160 | |
|---|
| 1161 |
|
|---|
| 1162 | ;;;; Setting window width and height.
|
|---|
| 1163 |
|
|---|
| 1164 | ;;; %SET-WINDOW-WIDTH -- Internal
|
|---|
| 1165 | ;;;
|
|---|
| 1166 | ;;; Since we don't support non-full-width windows, this does nothing.
|
|---|
| 1167 | ;;;
|
|---|
| 1168 | (defun %set-window-width (window new-value)
|
|---|
| 1169 | (declare (ignore window))
|
|---|
| 1170 | new-value)
|
|---|
| 1171 |
|
|---|
| 1172 | ;;; %SET-WINDOW-HEIGHT -- Internal
|
|---|
| 1173 | ;;;
|
|---|
| 1174 | ;;; Can't change window height either.
|
|---|
| 1175 | ;;;
|
|---|
| 1176 | (defun %set-window-height (window new-value)
|
|---|
| 1177 | (declare (ignore window))
|
|---|
| 1178 | new-value)
|
|---|
| 1179 |
|
|---|
| 1180 |
|
|---|
| 1181 | |
|---|
| 1182 |
|
|---|
| 1183 | ;;;; Random Typeout
|
|---|
| 1184 |
|
|---|
| 1185 | ;;; Random typeout is done to a bitmap-hunk-output-stream
|
|---|
| 1186 | ;;; (Bitmap-Hunk-Stream.Lisp). These streams have an associated hunk
|
|---|
| 1187 | ;;; that is used for its font-family, foreground and background color,
|
|---|
| 1188 | ;;; and X window pointer. The hunk is not associated with any Hemlock
|
|---|
| 1189 | ;;; window, and the low level painting routines that use hunk dimensions
|
|---|
| 1190 | ;;; are not used for output. The X window is resized as necessary with
|
|---|
| 1191 | ;;; each use, but the hunk is only registered for input and boundary
|
|---|
| 1192 | ;;; crossing event service; therefore, it never gets exposure or changed
|
|---|
| 1193 | ;;; notifications.
|
|---|
| 1194 |
|
|---|
| 1195 | ;;; These are set in INIT-BITMAP-SCREEN-MANAGER.
|
|---|
| 1196 | ;;;
|
|---|
| 1197 | (defvar *random-typeout-start-x* 0
|
|---|
| 1198 | "Where we put the the random typeout window.")
|
|---|
| 1199 | (defvar *random-typeout-start-y* 0
|
|---|
| 1200 | "Where we put the the random typeout window.")
|
|---|
| 1201 | (defvar *random-typeout-start-width* 0
|
|---|
| 1202 | "How wide the random typeout window is.")
|
|---|
| 1203 |
|
|---|
| 1204 |
|
|---|
| 1205 | ;;; DEFAULT-RANDOM-TYPEOUT-HOOK -- Internal
|
|---|
| 1206 | ;;;
|
|---|
| 1207 | ;;; The default hook-function for random typeout. Nothing very fancy
|
|---|
| 1208 | ;;; for now. If not given a window, makes one on top of the initial
|
|---|
| 1209 | ;;; Hemlock window using specials set in INIT-BITMAP-SCREEN-MANAGER. If
|
|---|
| 1210 | ;;; given a window, we will change the height subject to the constraint
|
|---|
| 1211 | ;;; that the bottom won't be off the screen. Any resulting window has
|
|---|
| 1212 | ;;; input and boundary crossing events selected, a hemlock cursor defined,
|
|---|
| 1213 | ;;; and is mapped.
|
|---|
| 1214 | ;;;
|
|---|
| 1215 | #+clx
|
|---|
| 1216 | (defun default-random-typeout-hook (device window height)
|
|---|
| 1217 | (declare (fixnum height))
|
|---|
| 1218 | (let* ((display (bitmap-device-display device))
|
|---|
| 1219 | (root (xlib:screen-root (xlib:display-default-screen display)))
|
|---|
| 1220 | (full-height (xlib:drawable-height root))
|
|---|
| 1221 | (actual-height (if window
|
|---|
| 1222 | (multiple-value-bind (x y) (window-root-xy window)
|
|---|
| 1223 | (declare (ignore x) (fixnum y))
|
|---|
| 1224 | (min (- full-height y xwindow-border-width*2)
|
|---|
| 1225 | height))
|
|---|
| 1226 | (min (- full-height *random-typeout-start-y*
|
|---|
| 1227 | xwindow-border-width*2)
|
|---|
| 1228 | height)))
|
|---|
| 1229 | (win (cond (window
|
|---|
| 1230 | (setf (xlib:drawable-height window) actual-height)
|
|---|
| 1231 | window)
|
|---|
| 1232 | (t
|
|---|
| 1233 | (let ((win (xlib:create-window
|
|---|
| 1234 | :parent root
|
|---|
| 1235 | :x *random-typeout-start-x*
|
|---|
| 1236 | :y *random-typeout-start-y*
|
|---|
| 1237 | :width *random-typeout-start-width*
|
|---|
| 1238 | :height actual-height
|
|---|
| 1239 | :background *default-background-pixel*
|
|---|
| 1240 | :border-width xwindow-border-width
|
|---|
| 1241 | :border *default-border-pixmap*
|
|---|
| 1242 | :event-mask random-typeout-xevents-mask
|
|---|
| 1243 | :override-redirect :on :class :input-output
|
|---|
| 1244 | :cursor *hemlock-cursor*)))
|
|---|
| 1245 | (xlib:set-wm-properties
|
|---|
| 1246 | win :name "Pop-up Display" :icon-name "Pop-up Display"
|
|---|
| 1247 | :resource-name "Hemlock"
|
|---|
| 1248 | :x *random-typeout-start-x*
|
|---|
| 1249 | :y *random-typeout-start-y*
|
|---|
| 1250 | :width *random-typeout-start-width*
|
|---|
| 1251 | :height actual-height
|
|---|
| 1252 | :user-specified-position-p t :user-specified-size-p t
|
|---|
| 1253 | ;; Tell OpenLook pseudo-X11 server we want input.
|
|---|
| 1254 | :input :on)
|
|---|
| 1255 | win))))
|
|---|
| 1256 | (gcontext (if (not window) (default-gcontext win))))
|
|---|
| 1257 | (values win gcontext)))
|
|---|
| 1258 |
|
|---|
| 1259 | #-clx
|
|---|
| 1260 | (defun default-random-typeout-hook (device window height)
|
|---|
| 1261 | (declare (ignore device window height)))
|
|---|
| 1262 |
|
|---|
| 1263 | (defvar *random-typeout-hook* #'default-random-typeout-hook
|
|---|
| 1264 | "This function is called when a window is needed to display random typeout.
|
|---|
| 1265 | It is called with the Hemlock device, a pre-existing window or NIL, and the
|
|---|
| 1266 | number of pixels needed to display the number of lines requested in
|
|---|
| 1267 | WITH-RANDOM-TYPEOUT. It should return a window, and if a new window was
|
|---|
| 1268 | created, then a gcontext must be returned as the second value.")
|
|---|
| 1269 |
|
|---|
| 1270 | ;;; BITMAP-RANDOM-TYPEOUT-SETUP -- Internal
|
|---|
| 1271 | ;;;
|
|---|
| 1272 | ;;; This function is called by the with-random-typeout macro to
|
|---|
| 1273 | ;;; to set things up. It calls the *Random-Typeout-Hook* to get a window
|
|---|
| 1274 | ;;; to work with, and then adjusts the random typeout stream's data-structures
|
|---|
| 1275 | ;;; to match.
|
|---|
| 1276 | ;;;
|
|---|
| 1277 | #+clx
|
|---|
| 1278 | (defun bitmap-random-typeout-setup (device stream height)
|
|---|
| 1279 | (let* ((*more-prompt-action* :empty)
|
|---|
| 1280 | (hwin-exists-p (random-typeout-stream-window stream))
|
|---|
| 1281 | (hwindow (if hwin-exists-p
|
|---|
| 1282 | (change-bitmap-random-typeout-window hwin-exists-p height)
|
|---|
| 1283 | (setf (random-typeout-stream-window stream)
|
|---|
| 1284 | (make-bitmap-random-typeout-window
|
|---|
| 1285 | device
|
|---|
| 1286 | (buffer-start-mark
|
|---|
| 1287 | (line-buffer
|
|---|
| 1288 | (mark-line (random-typeout-stream-mark stream))))
|
|---|
| 1289 | height)))))
|
|---|
| 1290 | (let ((xwindow (bitmap-hunk-xwindow (window-hunk hwindow)))
|
|---|
| 1291 | (display (bitmap-device-display device)))
|
|---|
| 1292 | (xlib:display-finish-output display)
|
|---|
| 1293 | (loop
|
|---|
| 1294 | (unless (xlib:event-case (display :timeout 0)
|
|---|
| 1295 | (:exposure (event-window)
|
|---|
| 1296 | (eq event-window xwindow))
|
|---|
| 1297 | (t () nil))
|
|---|
| 1298 | (return))))))
|
|---|
| 1299 |
|
|---|
| 1300 | #+clx
|
|---|
| 1301 | (defun change-bitmap-random-typeout-window (hwindow height)
|
|---|
| 1302 | (update-modeline-field (window-buffer hwindow) hwindow :more-prompt)
|
|---|
| 1303 | (let* ((hunk (window-hunk hwindow))
|
|---|
| 1304 | (xwin (bitmap-hunk-xwindow hunk)))
|
|---|
| 1305 | ;;
|
|---|
| 1306 | ;; *random-typeout-hook* sets the window's height to the right value.
|
|---|
| 1307 | (funcall *random-typeout-hook* (device-hunk-device hunk) xwin
|
|---|
| 1308 | (+ (* height (font-family-height (bitmap-hunk-font-family hunk)))
|
|---|
| 1309 | hunk-top-border (bitmap-hunk-bottom-border hunk)
|
|---|
| 1310 | hunk-modeline-top hunk-modeline-bottom))
|
|---|
| 1311 | (xlib:with-state (xwin)
|
|---|
| 1312 | (hunk-changed hunk (xlib:drawable-width xwin) (xlib:drawable-height xwin)
|
|---|
| 1313 | nil))
|
|---|
| 1314 | ;;
|
|---|
| 1315 | ;; We push this on here because we took it out the last time we cleaned up.
|
|---|
| 1316 | (push hwindow (buffer-windows (window-buffer hwindow)))
|
|---|
| 1317 | (setf (bitmap-hunk-trashed hunk) t)
|
|---|
| 1318 | (xlib:map-window xwin)
|
|---|
| 1319 | (setf (xlib:window-priority xwin) :above))
|
|---|
| 1320 | hwindow)
|
|---|
| 1321 |
|
|---|
| 1322 | #+clx
|
|---|
| 1323 | (defun make-bitmap-random-typeout-window (device mark height)
|
|---|
| 1324 | (let* ((display (bitmap-device-display device))
|
|---|
| 1325 | (hunk (make-bitmap-hunk
|
|---|
| 1326 | :font-family *default-font-family*
|
|---|
| 1327 | :end *the-sentinel* :trashed t
|
|---|
| 1328 | :input-handler #'window-input-handler
|
|---|
| 1329 | :device device :thumb-bar-p nil)))
|
|---|
| 1330 | (multiple-value-bind
|
|---|
| 1331 | (xwindow gcontext)
|
|---|
| 1332 | (funcall *random-typeout-hook*
|
|---|
| 1333 | device (bitmap-hunk-xwindow hunk)
|
|---|
| 1334 | (+ (* height (font-family-height *default-font-family*))
|
|---|
| 1335 | hunk-top-border (bitmap-hunk-bottom-border hunk)
|
|---|
| 1336 | hunk-modeline-top hunk-modeline-bottom))
|
|---|
| 1337 | ;;
|
|---|
| 1338 | ;; When gcontext, we just made the window, so tie some stuff together.
|
|---|
| 1339 | (when gcontext
|
|---|
| 1340 | (setf (xlib:gcontext-font gcontext)
|
|---|
| 1341 | (svref (font-family-map *default-font-family*) 0))
|
|---|
| 1342 | (setf (bitmap-hunk-xwindow hunk) xwindow)
|
|---|
| 1343 | (setf (bitmap-hunk-gcontext hunk) gcontext)
|
|---|
| 1344 | ;;
|
|---|
| 1345 | ;; Select input and enable event service before showing the window.
|
|---|
| 1346 | (setf (xlib:window-event-mask xwindow) random-typeout-xevents-mask)
|
|---|
| 1347 | (add-xwindow-object xwindow hunk *hemlock-windows*))
|
|---|
| 1348 | ;;
|
|---|
| 1349 | ;; Put the window on the screen so it's visible and we can know the size.
|
|---|
| 1350 | (xlib:map-window xwindow)
|
|---|
| 1351 | (xlib:display-finish-output display)
|
|---|
| 1352 | ;; A window is not really mapped until it is viewable (not visible).
|
|---|
| 1353 | ;; It is said to be mapped if a map request has been sent whether it
|
|---|
| 1354 | ;; is handled or not.
|
|---|
| 1355 | (loop (when (eq (xlib:window-map-state xwindow) :viewable)
|
|---|
| 1356 | (return)))
|
|---|
| 1357 | (xlib:with-state (xwindow)
|
|---|
| 1358 | (set-hunk-size hunk (xlib:drawable-width xwindow)
|
|---|
| 1359 | (xlib:drawable-height xwindow) t))
|
|---|
| 1360 | ;;
|
|---|
| 1361 | ;; Get a Hemlock window and hide it from the rest of Hemlock.
|
|---|
| 1362 | (let ((hwin (window-for-hunk hunk mark *random-typeout-ml-fields*)))
|
|---|
| 1363 | (update-modeline-field (window-buffer hwin) hwin :more-prompt)
|
|---|
| 1364 | (setf (bitmap-hunk-window hunk) hwin)
|
|---|
| 1365 | (setf *window-list* (delete hwin *window-list*))
|
|---|
| 1366 | hwin))))
|
|---|
| 1367 |
|
|---|
| 1368 |
|
|---|
| 1369 | ;;; RANDOM-TYPEOUT-CLEANUP -- Internal
|
|---|
| 1370 | ;;;
|
|---|
| 1371 | ;;; Clean up after random typeout. This just removes the window from
|
|---|
| 1372 | ;;; the screen and sets the more-prompt action back to normal.
|
|---|
| 1373 | ;;;
|
|---|
| 1374 | #+clx
|
|---|
| 1375 | (defun bitmap-random-typeout-cleanup (stream degree)
|
|---|
| 1376 | (when degree
|
|---|
| 1377 | (xlib:unmap-window (bitmap-hunk-xwindow
|
|---|
| 1378 | (window-hunk (random-typeout-stream-window stream))))))
|
|---|
| 1379 |
|
|---|
| 1380 |
|
|---|
| 1381 | |
|---|
| 1382 |
|
|---|
| 1383 | ;;;; Initialization.
|
|---|
| 1384 |
|
|---|
| 1385 | ;;; DEFAULT-CREATE-INITIAL-WINDOWS-HOOK makes the initial windows, main and
|
|---|
| 1386 | ;;; echo. The main window is made according to "Default Initial Window X",
|
|---|
| 1387 | ;;; "Default Initial Window Y", "Default Initial Window Width", and "Default
|
|---|
| 1388 | ;;; Initial Window Height", prompting the user for any unspecified components.
|
|---|
| 1389 | ;;; DEFAULT-CREATE-INITIAL-WINDOWS-ECHO is called to return the location and
|
|---|
| 1390 | ;;; size of the echo area including how big its font is, and the main xwindow
|
|---|
| 1391 | ;;; is potentially modified by this function. The window name is set to get
|
|---|
| 1392 | ;;; around an awm and twm bug that inhibits menu clicks unless the window has a
|
|---|
| 1393 | ;;; name; this could be used better.
|
|---|
| 1394 | ;;;
|
|---|
| 1395 | #+clx
|
|---|
| 1396 | (defun default-create-initial-windows-hook (device)
|
|---|
| 1397 | (let ((root (xlib:screen-root (xlib:display-default-screen
|
|---|
| 1398 | (bitmap-device-display device)))))
|
|---|
| 1399 | (let* ((xwindow (maybe-prompt-user-for-window
|
|---|
| 1400 | root
|
|---|
| 1401 | (value hemlock::default-initial-window-x)
|
|---|
| 1402 | (value hemlock::default-initial-window-y)
|
|---|
| 1403 | (value hemlock::default-initial-window-width)
|
|---|
| 1404 | (value hemlock::default-initial-window-height)
|
|---|
| 1405 | *default-font-family*
|
|---|
| 1406 | t ;modelinep
|
|---|
| 1407 | (value hemlock::thumb-bar-meter)
|
|---|
| 1408 | "Hemlock")))
|
|---|
| 1409 | (setf (xlib:window-border xwindow) *highlight-border-pixmap*)
|
|---|
| 1410 | (let ((main-win (make-window (buffer-start-mark *current-buffer*)
|
|---|
| 1411 | :device device
|
|---|
| 1412 | :window xwindow)))
|
|---|
| 1413 | (multiple-value-bind
|
|---|
| 1414 | (echo-x echo-y echo-width echo-height)
|
|---|
| 1415 | (default-create-initial-windows-echo
|
|---|
| 1416 | (xlib:drawable-height root)
|
|---|
| 1417 | (window-hunk main-win))
|
|---|
| 1418 | (let ((echo-xwin (make-echo-xwindow root echo-x echo-y echo-width
|
|---|
| 1419 | echo-height)))
|
|---|
| 1420 | (setf *echo-area-window*
|
|---|
| 1421 | (hlet ((hemlock::thumb-bar-meter nil))
|
|---|
| 1422 | (make-window
|
|---|
| 1423 | (buffer-start-mark *echo-area-buffer*)
|
|---|
| 1424 | :device device :modelinep t
|
|---|
| 1425 | :window echo-xwin)))))
|
|---|
| 1426 | (setf *current-window* main-win)))))
|
|---|
| 1427 |
|
|---|
| 1428 | #-clx
|
|---|
| 1429 | (defun default-create-initial-windows-hook (device)
|
|---|
| 1430 | (declare (ignore device)))
|
|---|
| 1431 |
|
|---|
| 1432 | ;;; DEFAULT-CREATE-INITIAL-WINDOWS-ECHO makes the echo area window as wide as
|
|---|
| 1433 | ;;; the main window and places it directly under it. If the echo area does not
|
|---|
| 1434 | ;;; fit on the screen, we change the main window to make it fit. There is
|
|---|
| 1435 | ;;; a problem in computing main-xwin's x and y relative to the root window
|
|---|
| 1436 | ;;; which is where we line up the echo and main windows. Some losing window
|
|---|
| 1437 | ;;; managers (awm and twm) reparent the window, so we have to make sure
|
|---|
| 1438 | ;;; main-xwin's x and y are relative to the root and not some false parent.
|
|---|
| 1439 | ;;;
|
|---|
| 1440 | #+clx
|
|---|
| 1441 | (defun default-create-initial-windows-echo (full-height hunk)
|
|---|
| 1442 | (declare (fixnum full-height))
|
|---|
| 1443 | (let ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 1444 | (xwindow (bitmap-hunk-xwindow hunk))
|
|---|
| 1445 | (xparent (window-group-xparent (bitmap-hunk-window-group hunk))))
|
|---|
| 1446 | (xlib:with-state (xwindow)
|
|---|
| 1447 | (let ((w (xlib:drawable-width xwindow))
|
|---|
| 1448 | (h (xlib:drawable-height xwindow)))
|
|---|
| 1449 | (declare (fixnum w h))
|
|---|
| 1450 | (multiple-value-bind (x y)
|
|---|
| 1451 | (window-root-xy xwindow
|
|---|
| 1452 | (xlib:drawable-x xwindow)
|
|---|
| 1453 | (xlib:drawable-y xwindow))
|
|---|
| 1454 | (declare (fixnum x y))
|
|---|
| 1455 | (let* ((ff-height (font-family-height font-family))
|
|---|
| 1456 | (ff-width (font-family-width font-family))
|
|---|
| 1457 | (echo-height (+ (* ff-height 4)
|
|---|
| 1458 | hunk-top-border hunk-bottom-border
|
|---|
| 1459 | hunk-modeline-top hunk-modeline-bottom)))
|
|---|
| 1460 | (declare (fixnum echo-height))
|
|---|
| 1461 | (if (<= (+ y h echo-height xwindow-border-width*2) full-height)
|
|---|
| 1462 | (values x (+ y h xwindow-border-width*2)
|
|---|
| 1463 | w echo-height ff-width ff-height)
|
|---|
| 1464 | (let* ((newh (- full-height y echo-height xwindow-border-width*2
|
|---|
| 1465 | ;; Since y is really the outside y, subtract
|
|---|
| 1466 | ;; two more borders, so the echo area's borders
|
|---|
| 1467 | ;; both appear on the screen.
|
|---|
| 1468 | xwindow-border-width*2)))
|
|---|
| 1469 | (setf (xlib:drawable-height xparent) newh)
|
|---|
| 1470 | (values x (+ y newh xwindow-border-width*2)
|
|---|
| 1471 | w echo-height ff-width ff-height)))))))))
|
|---|
| 1472 |
|
|---|
| 1473 | (defvar *create-initial-windows-hook* #'default-create-initial-windows-hook
|
|---|
| 1474 | "Hemlock uses this function when it initializes the screen manager to make
|
|---|
| 1475 | the first windows, typically the main and echo area windows. It takes a
|
|---|
| 1476 | Hemlock device as a required argument. It sets *current-window* and
|
|---|
| 1477 | *echo-area-window*.")
|
|---|
| 1478 |
|
|---|
| 1479 | (defun make-echo-xwindow (root x y width height)
|
|---|
| 1480 | (let* ((font-width (font-family-width *default-font-family*))
|
|---|
| 1481 | (font-height (font-family-height *default-font-family*)))
|
|---|
| 1482 | (create-window-with-properties root x y width height
|
|---|
| 1483 | font-width font-height
|
|---|
| 1484 | "Echo Area" nil nil t)))
|
|---|
| 1485 |
|
|---|
| 1486 | #+clx
|
|---|
| 1487 | (defun init-bitmap-screen-manager (display)
|
|---|
| 1488 | ;;
|
|---|
| 1489 | ;; Setup stuff for X interaction.
|
|---|
| 1490 | (cond ((value hemlock::reverse-video)
|
|---|
| 1491 | (setf *default-background-pixel*
|
|---|
| 1492 | (xlib:screen-black-pixel (xlib:display-default-screen display)))
|
|---|
| 1493 | (setf *default-foreground-pixel*
|
|---|
| 1494 | (xlib:screen-white-pixel (xlib:display-default-screen display)))
|
|---|
| 1495 | (setf *cursor-background-color* (make-black-color))
|
|---|
| 1496 | (setf *cursor-foreground-color* (make-white-color))
|
|---|
| 1497 | (setf *hack-hunk-replace-line* nil))
|
|---|
| 1498 | (t (setf *default-background-pixel*
|
|---|
| 1499 | (xlib:screen-white-pixel (xlib:display-default-screen display)))
|
|---|
| 1500 | (setf *default-foreground-pixel*
|
|---|
| 1501 | (xlib:screen-black-pixel (xlib:display-default-screen display)))
|
|---|
| 1502 | (setf *cursor-background-color* (make-white-color))
|
|---|
| 1503 | (setf *cursor-foreground-color* (make-black-color))))
|
|---|
| 1504 | (setf *foreground-background-xor*
|
|---|
| 1505 | (logxor *default-foreground-pixel* *default-background-pixel*))
|
|---|
| 1506 | (setf *highlight-border-pixmap* *default-foreground-pixel*)
|
|---|
| 1507 | (setf *default-border-pixmap* (get-hemlock-grey-pixmap display))
|
|---|
| 1508 | (get-hemlock-cursor display)
|
|---|
| 1509 | (add-hook hemlock::make-window-hook 'define-window-cursor)
|
|---|
| 1510 | ;;
|
|---|
| 1511 | ;; Make the device for the rest of initialization.
|
|---|
| 1512 | (let ((device (make-default-bitmap-device display)))
|
|---|
| 1513 | ;;
|
|---|
| 1514 | ;; Create initial windows.
|
|---|
| 1515 | (funcall *create-initial-windows-hook* device)
|
|---|
| 1516 | ;;
|
|---|
| 1517 | ;; Setup random typeout over the user's main window.
|
|---|
| 1518 | (let ((xwindow (bitmap-hunk-xwindow (window-hunk *current-window*))))
|
|---|
| 1519 | (xlib:with-state (xwindow)
|
|---|
| 1520 | (multiple-value-bind (x y)
|
|---|
| 1521 | (window-root-xy xwindow (xlib:drawable-x xwindow)
|
|---|
| 1522 | (xlib:drawable-y xwindow))
|
|---|
| 1523 | (setf *random-typeout-start-x* x)
|
|---|
| 1524 | (setf *random-typeout-start-y* y))
|
|---|
| 1525 | (setf *random-typeout-start-width* (xlib:drawable-width xwindow)))))
|
|---|
| 1526 | (add-hook hemlock::window-buffer-hook 'set-window-name-for-window-buffer)
|
|---|
| 1527 | (add-hook hemlock::buffer-name-hook 'set-window-name-for-buffer-name)
|
|---|
| 1528 | (add-hook hemlock::set-window-hook 'set-window-hook-raise-fun)
|
|---|
| 1529 | (add-hook hemlock::buffer-modified-hook 'raise-echo-area-when-modified))
|
|---|
| 1530 |
|
|---|
| 1531 | (defun make-default-bitmap-device (display)
|
|---|
| 1532 | (make-bitmap-device
|
|---|
| 1533 | :name "Windowed Bitmap Device"
|
|---|
| 1534 | :init #'init-bitmap-device
|
|---|
| 1535 | :exit #'exit-bitmap-device
|
|---|
| 1536 | :smart-redisplay #'smart-window-redisplay
|
|---|
| 1537 | :dumb-redisplay #'dumb-window-redisplay
|
|---|
| 1538 | :after-redisplay #'bitmap-after-redisplay
|
|---|
| 1539 | :clear nil
|
|---|
| 1540 | :note-read-wait #'frob-cursor
|
|---|
| 1541 | :put-cursor #'hunk-show-cursor
|
|---|
| 1542 | :show-mark #'bitmap-show-mark
|
|---|
| 1543 | :next-window #'bitmap-next-window
|
|---|
| 1544 | :previous-window #'bitmap-previous-window
|
|---|
| 1545 | :make-window #'bitmap-make-window
|
|---|
| 1546 | :delete-window #'bitmap-delete-window
|
|---|
| 1547 | :force-output #'bitmap-force-output
|
|---|
| 1548 | :finish-output #'bitmap-finish-output
|
|---|
| 1549 | :random-typeout-setup #'bitmap-random-typeout-setup
|
|---|
| 1550 | :random-typeout-cleanup #'bitmap-random-typeout-cleanup
|
|---|
| 1551 | :random-typeout-full-more #'do-bitmap-full-more
|
|---|
| 1552 | :random-typeout-line-more #'update-bitmap-line-buffered-stream
|
|---|
| 1553 | :beep #'bitmap-beep
|
|---|
| 1554 | :display display))
|
|---|
| 1555 |
|
|---|
| 1556 | (defun init-bitmap-device (device)
|
|---|
| 1557 | (let ((display (bitmap-device-display device)))
|
|---|
| 1558 | (hemlock-ext:flush-display-events display)
|
|---|
| 1559 | (hemlock-window display t)))
|
|---|
| 1560 |
|
|---|
| 1561 | (defun exit-bitmap-device (device)
|
|---|
| 1562 | (hemlock-window (bitmap-device-display device) nil))
|
|---|
| 1563 |
|
|---|
| 1564 | #+clx
|
|---|
| 1565 | (defun bitmap-finish-output (device window)
|
|---|
| 1566 | (declare (ignore window))
|
|---|
| 1567 | (xlib:display-finish-output (bitmap-device-display device)))
|
|---|
| 1568 |
|
|---|
| 1569 | #+clx
|
|---|
| 1570 | (defun bitmap-force-output ()
|
|---|
| 1571 | (xlib:display-force-output
|
|---|
| 1572 | (bitmap-device-display (device-hunk-device (window-hunk (current-window))))))
|
|---|
| 1573 |
|
|---|
| 1574 | (defun bitmap-after-redisplay (device)
|
|---|
| 1575 | (let ((display (bitmap-device-display device)))
|
|---|
| 1576 | (loop (unless (hemlock-ext:object-set-event-handler display) (return)))))
|
|---|
| 1577 |
|
|---|
| 1578 |
|
|---|
| 1579 | |
|---|
| 1580 |
|
|---|
| 1581 | ;;;; Miscellaneous.
|
|---|
| 1582 |
|
|---|
| 1583 | ;;; HUNK-RESET is called in redisplay to make sure the hunk is up to date.
|
|---|
| 1584 | ;;; If the size is wrong, or it is trashed due to font changes, then we
|
|---|
| 1585 | ;;; call HUNK-CHANGED. We also clear the hunk.
|
|---|
| 1586 | ;;;
|
|---|
| 1587 | #+clx
|
|---|
| 1588 | (defun hunk-reset (hunk)
|
|---|
| 1589 | (let ((xwindow (bitmap-hunk-xwindow hunk))
|
|---|
| 1590 | (trashed (bitmap-hunk-trashed hunk)))
|
|---|
| 1591 | (when trashed
|
|---|
| 1592 | (setf (bitmap-hunk-trashed hunk) nil)
|
|---|
| 1593 | (xlib:with-state (xwindow)
|
|---|
| 1594 | (let ((w (xlib:drawable-width xwindow))
|
|---|
| 1595 | (h (xlib:drawable-height xwindow)))
|
|---|
| 1596 | (when (or (/= w (bitmap-hunk-width hunk))
|
|---|
| 1597 | (/= h (bitmap-hunk-height hunk))
|
|---|
| 1598 | (eq trashed :font-change))
|
|---|
| 1599 | (hunk-changed hunk w h nil)))))
|
|---|
| 1600 | (xlib:clear-area xwindow :width (bitmap-hunk-width hunk)
|
|---|
| 1601 | :height (bitmap-hunk-height hunk))
|
|---|
| 1602 | (hunk-draw-bottom-border hunk)))
|
|---|
| 1603 |
|
|---|
| 1604 | ;;; HUNK-CHANGED -- Internal.
|
|---|
| 1605 | ;;;
|
|---|
| 1606 | ;;; HUNK-RESET and the changed window handler call this. Don't go through
|
|---|
| 1607 | ;;; REDISPLAY-WINDOW-ALL since the window changed handler updates the window
|
|---|
| 1608 | ;;; image.
|
|---|
| 1609 | ;;;
|
|---|
| 1610 | (defun hunk-changed (hunk new-width new-height redisplay)
|
|---|
| 1611 | (set-hunk-size hunk new-width new-height)
|
|---|
| 1612 | (funcall (bitmap-hunk-changed-handler hunk) hunk)
|
|---|
| 1613 | (when redisplay (dumb-window-redisplay (bitmap-hunk-window hunk))))
|
|---|
| 1614 |
|
|---|
| 1615 | ;;; WINDOW-GROUP-CHANGED -- Internal.
|
|---|
| 1616 | ;;;
|
|---|
| 1617 | ;;; HUNK-RECONFIGURED calls this when the hunk was a window-group. This finds
|
|---|
| 1618 | ;;; the windows in the changed group, sorts them by their vertical stacking
|
|---|
| 1619 | ;;; order, and tries to resize the windows proportioned by their old sizes
|
|---|
| 1620 | ;;; relative to the old group size. If that fails, this tries to make all the
|
|---|
| 1621 | ;;; windows the same size, dividing up the new group's size.
|
|---|
| 1622 | ;;;
|
|---|
| 1623 | #+clx
|
|---|
| 1624 | (defun window-group-changed (window-group new-width new-height)
|
|---|
| 1625 | (let ((xparent (window-group-xparent window-group))
|
|---|
| 1626 | (affected-windows nil)
|
|---|
| 1627 | (count 0)
|
|---|
| 1628 | (old-xparent-height (window-group-height window-group)))
|
|---|
| 1629 | (setf (window-group-width window-group) new-width)
|
|---|
| 1630 | (setf (window-group-height window-group) new-height)
|
|---|
| 1631 | (dolist (window *window-list*)
|
|---|
| 1632 | (let ((test (window-group-xparent (bitmap-hunk-window-group
|
|---|
| 1633 | (window-hunk window)))))
|
|---|
| 1634 | (when (eq test xparent)
|
|---|
| 1635 | (push window affected-windows)
|
|---|
| 1636 | (incf count))))
|
|---|
| 1637 | ;; Probably shoulds insertion sort them, but I'm lame.
|
|---|
| 1638 | ;;
|
|---|
| 1639 | (xlib:with-state (xparent)
|
|---|
| 1640 | (sort affected-windows #'<
|
|---|
| 1641 | :key #'(lambda (window)
|
|---|
| 1642 | (xlib:drawable-y
|
|---|
| 1643 | (bitmap-hunk-xwindow (window-hunk window))))))
|
|---|
| 1644 | (let ((start 0))
|
|---|
| 1645 | (declare (fixnum start))
|
|---|
| 1646 | (do ((windows affected-windows (cdr windows)))
|
|---|
| 1647 | ((endp windows))
|
|---|
| 1648 | (let* ((xwindow (bitmap-hunk-xwindow (window-hunk (car windows))))
|
|---|
| 1649 | (new-child-height (round
|
|---|
| 1650 | (* new-height
|
|---|
| 1651 | (/ (xlib:drawable-height xwindow)
|
|---|
| 1652 | old-xparent-height))))
|
|---|
| 1653 | (hunk (window-hunk (car windows))))
|
|---|
| 1654 | ;; If there is not enough room for one of the windows, space them out
|
|---|
| 1655 | ;; evenly so there will be room.
|
|---|
| 1656 | ;;
|
|---|
| 1657 | (when (< new-child-height (minimum-window-height
|
|---|
| 1658 | (font-family-height
|
|---|
| 1659 | (bitmap-hunk-font-family hunk))
|
|---|
| 1660 | (bitmap-hunk-modeline-pos hunk)
|
|---|
| 1661 | (bitmap-hunk-thumb-bar-p hunk)))
|
|---|
| 1662 | (reconfigure-windows-evenly affected-windows new-width new-height)
|
|---|
| 1663 | (return))
|
|---|
| 1664 | (xlib:with-state (xwindow)
|
|---|
| 1665 | (setf (xlib:drawable-y xwindow) start
|
|---|
| 1666 | ;; Make the last window absorb or lose the number of pixels
|
|---|
| 1667 | ;; lost in rounding.
|
|---|
| 1668 | ;;
|
|---|
| 1669 | (xlib:drawable-height xwindow) (if (cdr windows)
|
|---|
| 1670 | new-child-height
|
|---|
| 1671 | (- new-height start))
|
|---|
| 1672 | (xlib:drawable-width xwindow) new-width
|
|---|
| 1673 | start (+ start new-child-height 1))))))))
|
|---|
| 1674 |
|
|---|
| 1675 | #+clx
|
|---|
| 1676 | (defun reconfigure-windows-evenly (affected-windows new-width new-height)
|
|---|
| 1677 | (let ((count (length affected-windows)))
|
|---|
| 1678 | (multiple-value-bind
|
|---|
| 1679 | (pixels-per-window remainder)
|
|---|
| 1680 | (truncate new-height count)
|
|---|
| 1681 | (let ((count-1 (1- count)))
|
|---|
| 1682 | (do ((windows affected-windows (cdr windows))
|
|---|
| 1683 | (i 0 (1+ i)))
|
|---|
| 1684 | ((endp windows))
|
|---|
| 1685 | (let ((xwindow (bitmap-hunk-xwindow (window-hunk (car windows)))))
|
|---|
| 1686 | (setf (xlib:drawable-y xwindow) (* i pixels-per-window))
|
|---|
| 1687 | (setf (xlib:drawable-width xwindow) new-width)
|
|---|
| 1688 | (if (= i count-1)
|
|---|
| 1689 | (return (setf (xlib:drawable-height
|
|---|
| 1690 | (bitmap-hunk-xwindow
|
|---|
| 1691 | (window-hunk (car windows))))
|
|---|
| 1692 | (+ pixels-per-window remainder)))
|
|---|
| 1693 | (setf (xlib:drawable-height xwindow) pixels-per-window))))))))
|
|---|
| 1694 |
|
|---|
| 1695 | ;;; SET-HUNK-SIZE -- Internal
|
|---|
| 1696 | ;;;
|
|---|
| 1697 | ;;; Given a pixel size for a bitmap hunk, set the char size. If the window
|
|---|
| 1698 | ;;; is too small, we refuse to admit it; if the user makes unreasonably small
|
|---|
| 1699 | ;;; windows, our only responsibity is to not blow up. X will clip any stuff
|
|---|
| 1700 | ;;; that doesn't fit.
|
|---|
| 1701 | ;;;
|
|---|
| 1702 | (defun set-hunk-size (hunk w h &optional modelinep)
|
|---|
| 1703 | (let* ((font-family (bitmap-hunk-font-family hunk))
|
|---|
| 1704 | (font-width (font-family-width font-family))
|
|---|
| 1705 | (font-height (font-family-height font-family)))
|
|---|
| 1706 | (setf (bitmap-hunk-height hunk) h)
|
|---|
| 1707 | (setf (bitmap-hunk-width hunk) w)
|
|---|
| 1708 | (setf (bitmap-hunk-char-width hunk)
|
|---|
| 1709 | (max (truncate (- w hunk-left-border) font-width)
|
|---|
| 1710 | minimum-window-columns))
|
|---|
| 1711 | (let* ((h-minus-borders (- h hunk-top-border
|
|---|
| 1712 | (bitmap-hunk-bottom-border hunk)))
|
|---|
| 1713 | (hwin (bitmap-hunk-window hunk))
|
|---|
| 1714 | (modelinep (or modelinep (and hwin (window-modeline-buffer hwin)))))
|
|---|
| 1715 | (setf (bitmap-hunk-char-height hunk)
|
|---|
| 1716 | (max (if modelinep
|
|---|
| 1717 | (1- (truncate (- h-minus-borders
|
|---|
| 1718 | hunk-modeline-top hunk-modeline-bottom)
|
|---|
| 1719 | font-height))
|
|---|
| 1720 | (truncate h-minus-borders font-height))
|
|---|
| 1721 | minimum-window-lines))
|
|---|
| 1722 | (setf (bitmap-hunk-modeline-pos hunk)
|
|---|
| 1723 | (if modelinep (- h font-height
|
|---|
| 1724 | hunk-modeline-top hunk-modeline-bottom))))))
|
|---|
| 1725 |
|
|---|
| 1726 | ;;; BITMAP-HUNK-BOTTOM-BORDER -- Internal.
|
|---|
| 1727 | ;;;
|
|---|
| 1728 | (defun bitmap-hunk-bottom-border (hunk)
|
|---|
| 1729 | (if (bitmap-hunk-thumb-bar-p hunk)
|
|---|
| 1730 | hunk-thumb-bar-bottom-border
|
|---|
| 1731 | hunk-bottom-border))
|
|---|
| 1732 |
|
|---|
| 1733 |
|
|---|
| 1734 | ;;; DEFAULT-GCONTEXT is used when making hunks.
|
|---|
| 1735 | ;;;
|
|---|
| 1736 | #+clx
|
|---|
| 1737 | (defun default-gcontext (drawable &optional font-family)
|
|---|
| 1738 | (xlib:create-gcontext
|
|---|
| 1739 | :drawable drawable
|
|---|
| 1740 | :foreground *default-foreground-pixel*
|
|---|
| 1741 | :background *default-background-pixel*
|
|---|
| 1742 | :font (if font-family (svref (font-family-map font-family) 0))))
|
|---|
| 1743 |
|
|---|
| 1744 |
|
|---|
| 1745 | ;;; WINDOW-ROOT-XY returns the x and y coordinates for a window relative to
|
|---|
| 1746 | ;;; its root. Some window managers reparent Hemlock's window, so we have
|
|---|
| 1747 | ;;; to mess around possibly to get this right. If x and y are supplied, they
|
|---|
| 1748 | ;;; are relative to xwin's parent.
|
|---|
| 1749 | ;;;
|
|---|
| 1750 | #+clx
|
|---|
| 1751 | (defun window-root-xy (xwin &optional x y)
|
|---|
| 1752 | (multiple-value-bind (children parent root)
|
|---|
| 1753 | (xlib:query-tree xwin)
|
|---|
| 1754 | (declare (ignore children))
|
|---|
| 1755 | (if (eq parent root)
|
|---|
| 1756 | (if (and x y)
|
|---|
| 1757 | (values x y)
|
|---|
| 1758 | (xlib:with-state (xwin)
|
|---|
| 1759 | (values (xlib:drawable-x xwin) (xlib:drawable-y xwin))))
|
|---|
| 1760 | (multiple-value-bind
|
|---|
| 1761 | (tx ty)
|
|---|
| 1762 | (if (and x y)
|
|---|
| 1763 | (xlib:translate-coordinates parent x y root)
|
|---|
| 1764 | (xlib:with-state (xwin)
|
|---|
| 1765 | (xlib:translate-coordinates
|
|---|
| 1766 | parent (xlib:drawable-x xwin) (xlib:drawable-y xwin) root)))
|
|---|
| 1767 | (values (- tx xwindow-border-width)
|
|---|
| 1768 | (- ty xwindow-border-width))))))
|
|---|
| 1769 |
|
|---|
| 1770 | ;;; CREATE-WINDOW-WITH-PROPERTIES makes an X window with parent. X, y, w, and
|
|---|
| 1771 | ;;; h are possibly nil, so we supply zero in this case. This would be used
|
|---|
| 1772 | ;;; for prompting the user. Some standard properties are set to keep window
|
|---|
| 1773 | ;;; managers in line. We name all windows because awm and twm window managers
|
|---|
| 1774 | ;;; refuse to honor menu clicks over windows without names. Min-width and
|
|---|
| 1775 | ;;; min-height are optional and only used for prompting the user for a window.
|
|---|
| 1776 | ;;;
|
|---|
| 1777 | #+clx
|
|---|
| 1778 | (defun create-window-with-properties (parent x y w h font-width font-height
|
|---|
| 1779 | icon-name
|
|---|
| 1780 | &optional min-width min-height
|
|---|
| 1781 | window-group-p)
|
|---|
| 1782 | (let* ((win (xlib:create-window
|
|---|
| 1783 | :parent parent :x (or x 0) :y (or y 0)
|
|---|
| 1784 | :width (or w 0) :height (or h 0)
|
|---|
| 1785 | :background (if window-group-p :none *default-background-pixel*)
|
|---|
| 1786 | :border-width (if window-group-p xwindow-border-width 0)
|
|---|
| 1787 | :border (if window-group-p *default-border-pixmap* nil)
|
|---|
| 1788 | :class :input-output)))
|
|---|
| 1789 | (xlib:set-wm-properties
|
|---|
| 1790 | win :name (new-hemlock-window-name) :icon-name icon-name
|
|---|
| 1791 | :resource-name "Hemlock"
|
|---|
| 1792 | :x x :y y :width w :height h
|
|---|
| 1793 | :user-specified-position-p t :user-specified-size-p t
|
|---|
| 1794 | :width-inc font-width :height-inc font-height
|
|---|
| 1795 | :min-width min-width :min-height min-height
|
|---|
| 1796 | ;; Tell OpenLook pseudo-X11 server we want input.
|
|---|
| 1797 | :input :on)
|
|---|
| 1798 | win))
|
|---|
| 1799 |
|
|---|
| 1800 |
|
|---|
| 1801 | ;;; SET-WINDOW-HOOK-RAISE-FUN is a "Set Window Hook" function controlled by
|
|---|
| 1802 | ;;; "Set Window Autoraise". When autoraising, check that it isn't only the
|
|---|
| 1803 | ;;; echo area window that we autoraise; if it is only the echo area window,
|
|---|
| 1804 | ;;; then see if window is the echo area window.
|
|---|
| 1805 | ;;;
|
|---|
| 1806 | #+clx
|
|---|
| 1807 | (defun set-window-hook-raise-fun (window)
|
|---|
| 1808 | (let ((auto (value hemlock::set-window-autoraise)))
|
|---|
| 1809 | (when (and auto
|
|---|
| 1810 | (or (not (eq auto :echo-only))
|
|---|
| 1811 | (eq window *echo-area-window*)))
|
|---|
| 1812 | (let* ((hunk (window-hunk window))
|
|---|
| 1813 | (win (window-group-xparent (bitmap-hunk-window-group hunk))))
|
|---|
| 1814 | (xlib:map-window win)
|
|---|
| 1815 | (setf (xlib:window-priority win) :above)
|
|---|
| 1816 | (xlib:display-force-output
|
|---|
| 1817 | (bitmap-device-display (device-hunk-device hunk)))))))
|
|---|
| 1818 |
|
|---|
| 1819 |
|
|---|
| 1820 | ;;; REVERSE-VIDEO-HOOK-FUN is called when the variable "Reverse Video" is set.
|
|---|
| 1821 | ;;; If we are running on a windowed bitmap, we first setup the default
|
|---|
| 1822 | ;;; foregrounds and backgrounds. Having done that, we get a new cursor. Then
|
|---|
| 1823 | ;;; we do over all the hunks, updating their graphics contexts, cursors, and
|
|---|
| 1824 | ;;; backgrounds. The current window's border is given the new highlight pixmap.
|
|---|
| 1825 | ;;; Lastly, we update the random typeout hunk and redisplay everything.
|
|---|
| 1826 | ;;;
|
|---|
| 1827 |
|
|---|
| 1828 | #+clx
|
|---|
| 1829 | (defun reverse-video-hook-fun (name kind where new-value)
|
|---|
| 1830 | (declare (ignore name kind where))
|
|---|
| 1831 | (when (windowed-monitor-p)
|
|---|
| 1832 | (let* ((current-window (current-window))
|
|---|
| 1833 | (current-hunk (window-hunk current-window))
|
|---|
| 1834 | (device (device-hunk-device current-hunk))
|
|---|
| 1835 | (display (bitmap-device-display device)))
|
|---|
| 1836 | (cond
|
|---|
| 1837 | (new-value
|
|---|
| 1838 | (setf *default-background-pixel*
|
|---|
| 1839 | (xlib:screen-black-pixel (xlib:display-default-screen display)))
|
|---|
| 1840 | (setf *default-foreground-pixel*
|
|---|
| 1841 | (xlib:screen-white-pixel (xlib:display-default-screen display)))
|
|---|
| 1842 | (setf *cursor-background-color* (make-black-color))
|
|---|
| 1843 | (setf *cursor-foreground-color* (make-white-color))
|
|---|
| 1844 | (setf *hack-hunk-replace-line* nil))
|
|---|
| 1845 | (t (setf *default-background-pixel*
|
|---|
| 1846 | (xlib:screen-white-pixel (xlib:display-default-screen display)))
|
|---|
| 1847 | (setf *default-foreground-pixel*
|
|---|
| 1848 | (xlib:screen-black-pixel (xlib:display-default-screen display)))
|
|---|
| 1849 | (setf *cursor-background-color* (make-white-color))
|
|---|
| 1850 | (setf *cursor-foreground-color* (make-black-color))))
|
|---|
| 1851 | (setf *highlight-border-pixmap* *default-foreground-pixel*)
|
|---|
| 1852 | (get-hemlock-cursor display)
|
|---|
| 1853 | (dolist (hunk (device-hunks device))
|
|---|
| 1854 | (reverse-video-frob-hunk hunk))
|
|---|
| 1855 | (dolist (rt-info *random-typeout-buffers*)
|
|---|
| 1856 | (reverse-video-frob-hunk
|
|---|
| 1857 | (window-hunk (random-typeout-stream-window (cdr rt-info)))))
|
|---|
| 1858 | (setf (xlib:window-border (bitmap-hunk-xwindow current-hunk))
|
|---|
| 1859 | *highlight-border-pixmap*))
|
|---|
| 1860 | (redisplay-all)))
|
|---|
| 1861 |
|
|---|
| 1862 | #-clx
|
|---|
| 1863 | (defun reverse-video-hook-fun (name kind where new-value)
|
|---|
| 1864 | (declare (ignore name kind where new-value)))
|
|---|
| 1865 |
|
|---|
| 1866 | #+clx
|
|---|
| 1867 | (defun reverse-video-frob-hunk (hunk)
|
|---|
| 1868 | (let ((gcontext (bitmap-hunk-gcontext hunk)))
|
|---|
| 1869 | (setf (xlib:gcontext-foreground gcontext) *default-foreground-pixel*)
|
|---|
| 1870 | (setf (xlib:gcontext-background gcontext) *default-background-pixel*))
|
|---|
| 1871 | (let ((xwin (bitmap-hunk-xwindow hunk)))
|
|---|
| 1872 | (setf (xlib:window-cursor xwin) *hemlock-cursor*)
|
|---|
| 1873 | (setf (xlib:window-background xwin) *default-background-pixel*)))
|
|---|