lisp/desktop.el: Optionally force offscreen frames back onscreen.

(desktop-restoring-reuses-frames): New option.
(desktop--compute-pos, desktop--move-onscreen): New functions.
(desktop--make-frame): Use desktop--move-onscreen.
This commit is contained in:
Juanma Barranquero 2013-07-28 05:03:45 +02:00
parent 94fea300fd
commit ddeffb1731
2 changed files with 88 additions and 0 deletions

View file

@ -1,3 +1,10 @@
2013-07-28 Juanma Barranquero <lekktu@gmail.com>
* desktop.el: Optionally force offscreen frames back onscreen.
(desktop-restoring-reuses-frames): New option.
(desktop--compute-pos, desktop--move-onscreen): New functions.
(desktop--make-frame): Use desktop--move-onscreen.
2013-07-27 Alan Mackenzie <acm@muc.de>
Fontify a Java generic method as a function.

View file

@ -387,6 +387,18 @@ If `delete', frames on other displays are deleted instead of restored."
:group 'desktop
:version "24.4")
(defcustom desktop-restore-forces-onscreen t
"If t, offscreen frames are restored onscreen instead.
If `all', frames that are partially offscreen are also forced onscren.
NOTE: Checking of frame boundaries is only approximate and can fail
to reliably detect frames whose onscreen/offscreen state depends on a
few pixels, especially near the right / bottom borders of the screen."
:type '(choice (const :tag "Only fully offscreen frames" t)
(const :tag "Also partially offscreen frames" 'all)
(const :tag "Do not force frames onscreen" nil))
:group 'desktop
:version "24.4")
(defcustom desktop-restoring-reuses-frames t
"If t, restoring frames reuses existing frames.
If nil, existing frames are deleted.
@ -1201,6 +1213,68 @@ This function also sets `desktop-dirname' to nil."
(defvar desktop--reuse-list nil
"Internal use only.")
(defun desktop--compute-pos (value left/top right/bottom)
(pcase value
(`(+ ,val) (+ left/top val))
(`(- ,val) (+ right/bottom val))
(val val)))
(defun desktop--move-onscreen (frame)
"If FRAME is offscreen, move it back onscreen and, if necessary, resize it.
When forced onscreen, frames wider than the monitor's workarea are converted
to fullwidth, and frames taller than the workarea are converted to fullheight.
NOTE: This only works for non-iconified frames."
(pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr (frame-monitor-attributes frame)))
(right (+ left width -1))
(bottom (+ top height -1))
(fr-left (desktop--compute-pos (frame-parameter frame 'left) left right))
(fr-top (desktop--compute-pos (frame-parameter frame 'top) top bottom))
(ch-width (frame-char-width frame))
(ch-height (frame-char-height frame))
(fr-width (max (frame-pixel-width frame) (* ch-width (frame-width frame))))
(fr-height (max (frame-pixel-height frame) (* ch-height (frame-height frame))))
(fr-right (+ fr-left fr-width -1))
(fr-bottom (+ fr-top fr-height -1)))
(when (pcase desktop-restore-forces-onscreen
;; Any corner is outside the screen.
(`all (or (< fr-bottom top) (> fr-bottom bottom)
(< fr-left left) (> fr-left right)
(< fr-right left) (> fr-right right)
(< fr-top top) (> fr-top bottom)))
;; Displaced to the left, right, above or below the screen.
(`t (or (> fr-left right)
(< fr-right left)
(> fr-top bottom)
(< fr-bottom top)))
(_ nil))
(let ((fullwidth (> fr-width width))
(fullheight (> fr-height height))
(params nil))
;; Position frame horizontally.
(cond (fullwidth
(push `(left . ,left) params))
((> fr-right right)
(push `(left . ,(+ left (- width fr-width))) params))
((< fr-left left)
(push `(left . ,left) params)))
;; Position frame vertically.
(cond (fullheight
(push `(top . ,top) params))
((> fr-bottom bottom)
(push `(top . ,(+ top (- height fr-height))) params))
((< fr-top top)
(push `(top . ,top) params)))
;; Compute fullscreen state, if required.
(when (or fullwidth fullheight)
(push (cons 'fullscreen
(cond ((not fullwidth) 'fullheight)
((not fullheight) 'fullwidth)
(t 'maximized)))
params))
;; Finally, move the frame back onscreen.
(when params
(modify-frame-parameters frame params))))))
(defun desktop--find-frame (predicate display &rest args)
"Find a suitable frame in `desktop--reuse-list'.
Look through frames whose display property matches DISPLAY and
@ -1328,6 +1402,13 @@ its window state. Internal use only."
(assq-delete-all 'fullscreen filtered-cfg)
filtered-cfg))
;; If requested, force frames to be onscreen.
(when (and desktop-restore-forces-onscreen
;; FIXME: iconified frames should be checked too,
;; but it is impossible without deiconifying them.
(not (eq (frame-parameter frame 'visibility) 'icon)))
(desktop--move-onscreen frame))
;; Let's give the finishing touches (visibility, tool-bar, maximization).
(when lines (push lines alt-cfg))
(when alt-cfg (modify-frame-parameters frame alt-cfg))