unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
@ 2017-12-17 17:28 Robert Weiner
  2017-12-17 18:13 ` martin rudalics
  0 siblings, 1 reply; 18+ messages in thread
From: Robert Weiner @ 2017-12-17 17:28 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 2126 bytes --]

If you have followed the lengthy recent discussions here:

  https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00418.html

and

  https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00372.html

on temporarily displaying frames when multiple overlapping frames are
on screen, then you know this is a complex issue and hard to get
right.  I suggested a higher level programming model for this, so I
wrote a library to make this easy: display-until.el.  Please try it
out and send any improvement suggestions.

I would like to see this code added to core Emacs if it is acceptable
and someone will help me add the external documentation and commits
needed for it.

The library is attached and the commentary is included below.

-- Bob

-----

# display-until - Display a window or frame topmost in the frame stack
until a condition or timeout occurs.

This library temporarily displays an existing or new frame topmost in
the frame stack.  Then it restores the prior topmost frame as well
as any prior visibility status of the temporarily displayed frame,
e.g. if it was hidden or iconified.  See the end of the file for
sample usage expressions.


It includes the following:
  Variable:
    display-until-delay - time in seconds to display a temporary frame or
      window

  Display Functions:
    display-window-until - given a window and optional buffer, display the
      buffer in the window, make the window's frame topmost for
      `display-until-delay' seconds, then return the window's frame
      to its prior visibility

    display-frame-until - given a frame and optional buffer, display the
      buffer in the frame's selected window, make the frame topmost for
      `display-until-delay' seconds, then return the frame to its prior
      visibility

  Utility Functions:
    display-until-get-frame-by-name - given a name string, return the
      matching frame or nil

  Utility Macros:
    display-until-condition-or-timeout - wait for a boolean condition
      or timeout seconds
    display-until-thread-condition-or-timeout - run a thread until a boolean
      condition or timeout seconds

[-- Attachment #1.2: Type: text/html, Size: 3720 bytes --]

[-- Attachment #2: display-until.el --]
[-- Type: application/octet-stream, Size: 10074 bytes --]

;;; display-until.el --- temporarily display windows and frames  -*- lexical-binding: t -*-

;; Copyright (C) 2017 Free Software Foundation, Inc.

;; Author: Robert Weiner
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
;; Package: emacs
;; Version: 1.0
;; Orig-Date: 16-Dec-17
;; Last-Mod:  17-Dec-17

;; This file could become part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; (RSW would like this code to be added to core Emacs if it is
;;  acceptable.  Someone else who adds to Emacs regularly would have
;;  to add the NEWS entry, Elisp Manual entry and commit the code.
;;  In that case, the utilty macros and function names could be generalized).

;; This library temporarily displays an existing or new frame topmost in
;; the frame stack.  Then it restores the prior topmost frame as well
;; as any prior visibility status of the temporarily displayed frame,
;; e.g. if it was hidden or iconified.  See the end of the file for
;; sample usage expressions.

;; This library includes the following:
;;   Variable:
;;     display-until-delay - time in seconds to display a temporary frame or
;;       window
;;
;;   Display Functions:
;;     display-window-until - given a window and optional buffer, display the
;;       buffer in the window, make the window's frame topmost for
;;       `display-until-delay' seconds, then return the window's frame
;;       to its prior visibility
;;
;;     display-frame-until - given a frame and optional buffer, display the
;;       buffer in the frame's selected window, make the frame topmost for
;;       `display-until-delay' seconds, then return the frame to its prior
;;       visibility
;;
;;   Utility Functions:
;;     display-until-get-frame-by-name - given a name string, return the
;;       matching frame or nil
;;
;;   Utility Macros:
;;     display-until-condition-or-timeout - wait for a boolean condition
;;       or timeout seconds
;;     display-until-thread-condition-or-timeout - run a thread until a boolean
;;;      condition or timeout seconds

;;; Code:

(defvar display-until-delay 0.5
  "Delay time in seconds to display a temporary frame or window.")

(defvar display-until-frame-parameters nil
  "Alist of frame parameters to apply to any newly created temporarily displayed frame.")

(defun display-until-get-frame-by-name (name)
  "Return any frame named NAME, a string, else nil."
  (if (stringp name)
      (catch 'done
	(mapc (lambda (frame)
		(when (string-equal name (get-frame-name frame))
		  (throw 'done frame)))
	      (frame-list))
	nil)
    (error "(display-until-get-frame-by-name): Argument must be a name string, not `%s'" name)))

(defmacro display-until-condition-or-timeout (condition timeout)
  "Wait for the either CONDITION to become non-nil or for TIMEOUT seconds to expire.
CONDITION must be a boolean predicate form.  TIMEOUT must be > zero."
  `(let ((decrement 0.05))
     (setq timeout ,timeout)
     (while (not (or ,condition (<= timeout 0)))
       (sleep-for decrement)
       (setq timeout (- timeout decrement)))))

(defmacro display-until-thread-condition-or-timeout (condition timeout)
  "Wait in a separate thread for either CONDITION to become non-nil or for TIMEOUT seconds to expire.
CONDITION must be a boolean predicate form.  TIMEOUT must be > zero."
  `(make-thread (lambda ()
		  (display-until-condition-or-timeout ,condition ,timeout))))

(defun display-frame-until-condition (frame &optional buffer condition)
  "Display FRAME topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

FRAME may be an existing, even invisible frame, frame name or
nil.  If nil, the selected frame is used.  If FRAME is a string
and no live frame with that name is found, a new one with the
name and any `display-until-frame-parameters' is created.

BUFFER may be an existing buffer or buffer name.

After display, FRAME's prior visibility status is restored.
FRAME's depth in the frame stacking order is not restored."
  (unless frame
    (setq frame (selected-frame)))
  (when (stringp frame)
    (setq frame (or (display-until-get-frame-by-name frame)
		    (make-frame (cons `(name . ,frame)
				      display-until-frame-parameters)))))
  (cond ((not (framep frame))
	 (error "(display-frame-until): First argument must be a frame, not `%s'"
		frame))
	((not (frame-live-p frame))
	 (error "(display-frame-until): First argument must be a live frame, not `%s'"
		frame))
	((and buffer (not (or (bufferp buffer) (and (stringp buffer)
						    (get-buffer buffer)))))
	 (redisplay t)
	 (error "(display-frame-until): Second argument must be an existing buffer or buffer name, not `%s'"
		buffer))
	(t
	 (let ((frame-visible-flag (frame-visible-p frame)))
	   (select-frame frame)
	   (raise-frame frame)
	   (display-buffer (or buffer (window-buffer))
			   (cons 'display-buffer-same-window
				 display-until-frame-parameters) frame)
	   ;; Force redisplay or any changes to frame won't be displayed here.
	   (redisplay t)
	   (if condition
	       (display-until-condition-or-timeout condition display-until-delay)
	     ;; Don't use sit-for here because it can be interrupted early.
	     (sleep-for display-until-delay))
	   (pcase frame-visible-flag
	     ('icon (iconify-frame frame))
	     ('nil  (make-frame-invisible frame)))))))

(defun display-frame-until (frame &optional buffer condition)
  "Display FRAME topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

FRAME may be an existing, even invisible frame, frame name or
nil.  If nil, the selected frame is used.  If FRAME is a string
and no live frame with that name is found, a new one with the
name and any `display-until-frame-parameters' is created.

BUFFER may be an existing buffer or buffer name.

CONDITION must be an unquoted boolean predicate form.

After display, FRAME's prior visibility status is restored, as is
the prior frame that had input focus.  FRAME's depth in the frame
stacking order is not restored."
  (let ((prior-frame (or (frame-focus) (selected-frame))))
    (display-frame-until-condition frame buffer condition)
    (select-frame-set-input-focus prior-frame)))

(defun display-window-until (win-or-buf &optional buffer condition)
  "Display WIN-OR-BUF's frame topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

WIN-OR-BUF may be a window, existing buffer or buffer name, or nil.
If a buffer or buffer name, any window presently with that buffer
is used.  If nil or if no window is associated with the buffer, the
selected window is used.

The first matching item from this list is displayed in the chosen window:
BUFFER if it is non-nil; WIN-OR-BUF if it is a buffer or buffer name;
the window's current buffer.

CONDITION must be an unquoted boolean predicate form.

After display, WIN-OR-BUF frame's prior visibility status is
restored, as is the prior frame that had input focus.  WIN-OR-BUF
frame's depth in the frame stacking order is not restored."
  (unless win-or-buf
    (setq win-or-buf (selected-window)))
  (when (or (stringp win-or-buf) (bufferp win-or-buf))
    (setq win-or-buf (or (get-buffer-window win-or-buf t) win-or-buf))
    (when (and (stringp win-or-buf) (get-buffer win-or-buf))
      ;; Set to display the buffer given by win-or-buf.
      (unless buffer (setq buffer win-or-buf))
      ;; Use selected window since no other window to use was found.
      (setq win-or-buf (selected-window))))
  (unless (window-live-p win-or-buf)
    (error "(display-window-until): First argument must reference a live window, not `%s'"
	   win-or-buf))
  ;; Don't use with-selected-window here since it affects frame visibility.
  (let ((sel-window (selected-window)))
    (select-window win-or-buf)
    (display-frame-until-condition (window-frame win-or-buf) buffer condition)
    (select-window sel-window)
    (select-frame-set-input-focus (window-frame sel-window))))

;;; Sample Usage and Tests - Interactively evaluate these Lisp forms

;; The Lisp reader will ignore these samples when loading the library
(when nil

  ;; Display frames atop the window stack for 2 seconds
  (setq display-until-delay 2)

  ;; Create a new frame named 'My-Frame', make it display the *Messages*
  ;; buffer, temporarily display it, then hide it.
  (progn (when (display-until-get-frame-by-name "My-Frame")
	   (delete-frame (display-until-get-frame-by-name "My-Frame")))
	 (let ((display-until-frame-parameters '((visibility . nil))))
	   (display-frame-until "My-Frame" "*Messages*")))

  ;; Temporarily display My-Frame, then leave it displayed but move
  ;; prior topmost frame back to the top.
  (progn (set-frame-parameter (display-until-get-frame-by-name "My-Frame") 'visibility t)
	 (display-frame-until "My-Frame"))

  ;; Temporarily display the frame of a specific window (one currently
  ;; showing the *Messages* buffer) and make it display the *scratch* buffer.
  (display-window-until "*Messages*" "*scratch*")

  ;; Temporarily display an existing frame.
  (display-frame-until "My-Frame")

  ;; Temporarily display an existing window.
  (display-window-until "*scratch*")

  ;; Temporarily display a window currently showing "*scratch*" and
  ;; switch it to the buffer "*Messages*".
  (display-window-until "*scratch*" "*Messages*")

  ;; Likely display the buffer "*scratch*" in the selected window.
  (display-window-until "*scratch*")
  )

(provide 'display-until)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-17 17:28 display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs Robert Weiner
@ 2017-12-17 18:13 ` martin rudalics
  2017-12-17 18:46   ` Robert Weiner
  0 siblings, 1 reply; 18+ messages in thread
From: martin rudalics @ 2017-12-17 18:13 UTC (permalink / raw)
  To: rswgnu, emacs-devel

 > I suggested a higher level programming model for this, so I
 > wrote a library to make this easy: display-until.el.  Please try it
 > out and send any improvement suggestions.

I replaced the line

		(when (string-equal name (get-frame-name frame))

with

		(when (equal name (frame-parameter frame 'name))

and started the test but it got me some chaotically appearing frames.

 > I would like to see this code added to core Emacs if it is acceptable
 > and someone will help me add the external documentation and commits
 > needed for it.

We could add it to ELPA but it would have to compile cleanly first.

display-until.el:140:62:Warning: assignment to free variable ‘timeout’
display-until.el:140:52:Warning: reference to free variable ‘timeout’

In end of data:
display-until.el:241:1:Warning: the function ‘get-frame-name’ is not known to
     be defined.

Thanks, martin




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-17 18:13 ` martin rudalics
@ 2017-12-17 18:46   ` Robert Weiner
  2017-12-18  7:26     ` martin rudalics
  0 siblings, 1 reply; 18+ messages in thread
From: Robert Weiner @ 2017-12-17 18:46 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 804 bytes --]

On Sun, Dec 17, 2017 at 1:13 PM, martin rudalics <rudalics@gmx.at> wrote:

>
> and started the test but it got me some chaotically appearing frames.


​Please describe in detail what you see and what you think
is wrong but update to 1.1 attached first.​

​​
>
> ​​
> We could add it to ELPA but it would have to compile cleanly first.
>

​I think after these are vetted sufficiently and proven to
work well enought that they should ship with Emacs so
that any Elisp programmer can rely on them.


> ​​
>
> display-until.el:140:62:Warning: assignment to free variable ‘timeout’
> display-until.el:140:52:Warning: reference to free variable ‘timeout’
>
​​

​Thanks for the pointers; I have fixed these issues with V1.1.
Give it a try.​

Bob

[-- Attachment #1.2: Type: text/html, Size: 2838 bytes --]

[-- Attachment #2: display-until.el --]
[-- Type: application/octet-stream, Size: 10200 bytes --]

;;; display-until.el --- temporarily display windows and frames  -*- lexical-binding: t -*-

;; Copyright (C) 2017 Free Software Foundation, Inc.

;; Author: Robert Weiner
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
;; Package: emacs
;; Version: 1.1
;; Orig-Date: 16-Dec-17
;; Last-Mod:  17-Dec-17

;; This file could become part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; (RSW would like this code to be added to core Emacs if it is
;;  acceptable.  Someone else who adds to Emacs regularly would have
;;  to add the NEWS entry, Elisp Manual entry and commit the code.
;;  In that case, the utilty macros and function names could be generalized).

;; This library temporarily displays an existing or new frame topmost in
;; the frame stack.  Then it restores the prior topmost frame as well
;; as any prior visibility status of the temporarily displayed frame,
;; e.g. if it was hidden or iconified.  See the end of the file for
;; sample usage expressions.

;; This library includes the following:
;;   Variables:
;;     display-until-delay - time in seconds to display a temporary frame or
;;       window
;;     display-until-frame-parameters - alist of frame parameters to apply to
;;       any newly created temporarily displayed frame
;;
;;   Display Functions:
;;     display-window-until - given a window and optional buffer, display the
;;       buffer in the window, make the window's frame topmost for
;;       `display-until-delay' seconds, then return the window's frame
;;       to its prior visibility
;;
;;     display-frame-until - given a frame and optional buffer, display the
;;       buffer in the frame's selected window, make the frame topmost for
;;       `display-until-delay' seconds, then return the frame to its prior
;;       visibility
;;
;;   Utility Functions:
;;     display-until-get-frame-by-name - given a name string, return the
;;       matching frame or nil
;;
;;   Utility Macros:
;;     display-until-condition-or-timeout - wait for a boolean condition
;;       or timeout seconds
;;     display-until-thread-condition-or-timeout - run a thread until a boolean
;;;      condition or timeout seconds

;;; Code:

(defvar display-until-delay 0.5
  "Delay time in seconds to display a temporary frame or window.")

(defvar display-until-frame-parameters nil
  "Alist of frame parameters to apply to any newly created temporarily displayed frame.")

(defun display-until-get-frame-by-name (name)
  "Return any frame named NAME, a string, else nil."
  (if (stringp name)
      (catch 'done
	(mapc (lambda (frame)
		(when (equal name (frame-parameter frame 'name))
		  (throw 'done frame)))
	      (frame-list))
	nil)
    (error "(display-until-get-frame-by-name): Argument must be a name string, not `%s'" name)))

(defmacro display-until-condition-or-timeout (condition timeout)
  "Wait for the either CONDITION to become non-nil or for TIMEOUT seconds to expire.
CONDITION must be a boolean predicate form.  TIMEOUT must be > zero."
  `(let ((decrement 0.05)
	 (timeout ,timeout))
     (while (not (or ,condition (<= timeout 0)))
       (sleep-for decrement)
       (setq timeout (- timeout decrement)))))

(defmacro display-until-thread-condition-or-timeout (condition timeout)
  "Wait in a separate thread for either CONDITION to become non-nil or for TIMEOUT seconds to expire.
CONDITION must be a boolean predicate form.  TIMEOUT must be > zero."
  `(make-thread (lambda ()
		  (display-until-condition-or-timeout ,condition ,timeout))))

(defun display-frame-until-condition (frame &optional buffer condition)
  "Display FRAME topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

FRAME may be an existing, even invisible frame, frame name or
nil.  If nil, the selected frame is used.  If FRAME is a string
and no live frame with that name is found, a new one with the
name and any `display-until-frame-parameters' is created.

BUFFER may be an existing buffer or buffer name.

After display, FRAME's prior visibility status is restored.
FRAME's depth in the frame stacking order is not restored."
  (unless frame
    (setq frame (selected-frame)))
  (when (stringp frame)
    (setq frame (or (display-until-get-frame-by-name frame)
		    (make-frame (cons `(name . ,frame)
				      display-until-frame-parameters)))))
  (cond ((not (framep frame))
	 (error "(display-frame-until): First argument must be a frame, not `%s'"
		frame))
	((not (frame-live-p frame))
	 (error "(display-frame-until): First argument must be a live frame, not `%s'"
		frame))
	((and buffer (not (or (bufferp buffer) (and (stringp buffer)
						    (get-buffer buffer)))))
	 (redisplay t)
	 (error "(display-frame-until): Second argument must be an existing buffer or buffer name, not `%s'"
		buffer))
	(t
	 (let ((frame-visible-flag (frame-visible-p frame)))
	   (select-frame frame)
	   (raise-frame frame)
	   (display-buffer (or buffer (window-buffer))
			   (cons 'display-buffer-same-window
				 display-until-frame-parameters) frame)
	   ;; Force redisplay or any changes to frame won't be displayed here.
	   (redisplay t)
	   (if condition
	       (display-until-condition-or-timeout condition display-until-delay)
	     ;; Don't use sit-for here because it can be interrupted early.
	     (sleep-for display-until-delay))
	   (pcase frame-visible-flag
	     ('icon (iconify-frame frame))
	     ('nil  (make-frame-invisible frame)))))))

(defun display-frame-until (frame &optional buffer condition)
  "Display FRAME topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

FRAME may be an existing, even invisible frame, frame name or
nil.  If nil, the selected frame is used.  If FRAME is a string
and no live frame with that name is found, a new one with the
name and any `display-until-frame-parameters' is created.

BUFFER may be an existing buffer or buffer name.

CONDITION must be an unquoted boolean predicate form.

After display, FRAME's prior visibility status is restored, as is
the prior frame that had input focus.  FRAME's depth in the frame
stacking order is not restored."
  (let ((prior-frame (or (frame-focus) (selected-frame))))
    (display-frame-until-condition frame buffer condition)
    (select-frame-set-input-focus prior-frame)))

(defun display-window-until (win-or-buf &optional buffer condition)
  "Display WIN-OR-BUF's frame topmost with optional BUFFER in its selected window until CONDITION or `display-until-delay' seconds.

WIN-OR-BUF may be a window, existing buffer or buffer name, or nil.
If a buffer or buffer name, any window presently with that buffer
is used.  If nil or if no window is associated with the buffer, the
selected window is used.

The first matching item from this list is displayed in the chosen window:
BUFFER if it is non-nil; WIN-OR-BUF if it is a buffer or buffer name;
the window's current buffer.

CONDITION must be an unquoted boolean predicate form.

After display, WIN-OR-BUF frame's prior visibility status is
restored, as is the prior frame that had input focus.  WIN-OR-BUF
frame's depth in the frame stacking order is not restored."
  (unless win-or-buf
    (setq win-or-buf (selected-window)))
  (when (or (stringp win-or-buf) (bufferp win-or-buf))
    (setq win-or-buf (or (get-buffer-window win-or-buf t) win-or-buf))
    (when (and (stringp win-or-buf) (get-buffer win-or-buf))
      ;; Set to display the buffer given by win-or-buf.
      (unless buffer (setq buffer win-or-buf))
      ;; Use selected window since no other window to use was found.
      (setq win-or-buf (selected-window))))
  (unless (window-live-p win-or-buf)
    (error "(display-window-until): First argument must reference a live window, not `%s'"
	   win-or-buf))
  ;; Don't use with-selected-window here since it affects frame visibility.
  (let ((sel-window (selected-window)))
    (select-window win-or-buf)
    (display-frame-until-condition (window-frame win-or-buf) buffer condition)
    (select-window sel-window)
    (select-frame-set-input-focus (window-frame sel-window))))

;;; Sample Usage and Tests - Interactively evaluate these Lisp forms

;; The Lisp reader will ignore these samples when loading the library
(when nil

  ;; Display frames atop the window stack for 2 seconds
  (setq display-until-delay 2)

  ;; Create a new frame named 'My-Frame', make it display the *Messages*
  ;; buffer, temporarily display it, then hide it.
  (progn (when (display-until-get-frame-by-name "My-Frame")
	   (delete-frame (display-until-get-frame-by-name "My-Frame")))
	 (let ((display-until-frame-parameters '((visibility . nil))))
	   (display-frame-until "My-Frame" "*Messages*")))

  ;; Temporarily display My-Frame, then leave it displayed but move
  ;; prior topmost frame back to the top.
  (progn (set-frame-parameter (display-until-get-frame-by-name "My-Frame") 'visibility t)
	 (display-frame-until "My-Frame"))

  ;; Temporarily display the frame of a specific window (one currently
  ;; showing the *Messages* buffer) and make it display the *scratch* buffer.
  (display-window-until "*Messages*" "*scratch*")

  ;; Temporarily display an existing frame.
  (display-frame-until "My-Frame")

  ;; Temporarily display an existing window.
  (display-window-until "*scratch*")

  ;; Temporarily display a window currently showing "*scratch*" and
  ;; switch it to the buffer "*Messages*".
  (display-window-until "*scratch*" "*Messages*")

  ;; Likely display the buffer "*scratch*" in the selected window.
  (display-window-until "*scratch*")
  )

(provide 'display-until)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-17 18:46   ` Robert Weiner
@ 2017-12-18  7:26     ` martin rudalics
  2017-12-18 16:10       ` Eli Zaretskii
  2017-12-20  8:54       ` martin rudalics
  0 siblings, 2 replies; 18+ messages in thread
From: martin rudalics @ 2017-12-18  7:26 UTC (permalink / raw)
  To: rswgnu; +Cc: emacs-devel

 > ​Please describe in detail what you see and what you think
 > is wrong but update to 1.1 attached first.​

Here on Windows XP I mostly see an incompletely drawn frame with the
entire or parts of the toolbar missing, sometimes also a completely
blank frame.  More or less what you described earlier in another thread.

I will try on GNU/Linux as soon as I have that machine running again.

martin




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18  7:26     ` martin rudalics
@ 2017-12-18 16:10       ` Eli Zaretskii
  2017-12-18 18:17         ` Robert Weiner
  2017-12-20  8:54       ` martin rudalics
  1 sibling, 1 reply; 18+ messages in thread
From: Eli Zaretskii @ 2017-12-18 16:10 UTC (permalink / raw)
  To: martin rudalics; +Cc: rswgnu, emacs-devel

> Date: Mon, 18 Dec 2017 08:26:23 +0100
> From: martin rudalics <rudalics@gmx.at>
> Cc: emacs-devel <emacs-devel@gnu.org>
> 
>  > ​Please describe in detail what you see and what you think
>  > is wrong but update to 1.1 attached first.​
> 
> Here on Windows XP I mostly see an incompletely drawn frame with the
> entire or parts of the toolbar missing, sometimes also a completely
> blank frame.  More or less what you described earlier in another thread.

Which is quite expected, since the frame is created by a separate
thread, and the display-until library doesn't give Emacs a chance to
create it before it calls 'redisplay' (which has nothing to redisplay,
as the frame is not official yet), and then immediately goes into the
sleep-for loop (which doesn't redisplay).  I think.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18 16:10       ` Eli Zaretskii
@ 2017-12-18 18:17         ` Robert Weiner
  2017-12-18 19:05           ` Eli Zaretskii
  0 siblings, 1 reply; 18+ messages in thread
From: Robert Weiner @ 2017-12-18 18:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: martin rudalics, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1865 bytes --]

On Mon, Dec 18, 2017 at 11:10 AM, Eli Zaretskii <eliz@gnu.org> wrote:

> ​​
> > Date: Mon, 18 Dec 2017 08:26:23 +0100
> ​​
> > From: martin rudalics <rudalics@gmx.at>
> ​​
> > Cc: emacs-devel <emacs-devel@gnu.org>
> ​​
> >
> ​​
> >  > ​Please describe in detail what you see and what you think
> ​​
> >  > is wrong but update to 1.1 attached first.​
> ​​
> >
> ​​
> > Here on Windows XP I mostly see an incompletely drawn frame with the
> ​​
> > entire or parts of the toolbar missing, sometimes also a completely
> ​​
> > blank frame.  More or less what you described earlier in another thread.
>
​​
​

> ​​
>
> ​​
> Which is quite expected, since the frame is created by a separate
> ​​
> thread, and the display-until library doesn't give Emacs a chance to
> ​​
> create it before it calls 'redisplay' (which has nothing to redisplay,
> ​​
> as the frame is not official yet), and then immediately goes into the
> ​​
> sleep-for loop (which doesn't redisplay).  I think.
>

​If possible, shouldn't make-frame wait until the frame is
created and mapped to the display if the creation command
demands mapping?  I guess you could start editing properties
on ​an as yet unmapped frame but in the general case, wouldn't
a programmer want the frame and its constituent parts to
exist prior to moving on?

Since frame creation is done by a separate thread now,
are all following operations on the frame queued until the
whole frame is built or will they be lost if invoked during
this interim creation period.  For example, if I change an
item on the toolbar prior to full toolbar creation, what
happens?

How can an Elisp programmer be sure the frame creation has
finished without any reference to its creation thread?

Bob
​​

[-- Attachment #2: Type: text/html, Size: 5570 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18 18:17         ` Robert Weiner
@ 2017-12-18 19:05           ` Eli Zaretskii
  2017-12-18 19:19             ` Robert Weiner
  0 siblings, 1 reply; 18+ messages in thread
From: Eli Zaretskii @ 2017-12-18 19:05 UTC (permalink / raw)
  To: rswgnu; +Cc: rudalics, emacs-devel

> From: Robert Weiner <rsw@gnu.org>
> Date: Mon, 18 Dec 2017 13:17:04 -0500
> Cc: martin rudalics <rudalics@gmx.at>, emacs-devel <emacs-devel@gnu.org>
> 
> ​If possible, shouldn't make-frame wait until the frame is
> created and mapped to the display if the creation command
> demands mapping?  I guess you could start editing properties
> on ​an as yet unmapped frame but in the general case, wouldn't
> a programmer want the frame and its constituent parts to
> exist prior to moving on?
> 
> Since frame creation is done by a separate thread now,
> are all following operations on the frame queued until the
> whole frame is built or will they be lost if invoked during
> this interim creation period.  For example, if I change an
> item on the toolbar prior to full toolbar creation, what
> happens?

AFAIK, you can operate on the frame, as long as you don't expect it to
be displayed right away.

> How can an Elisp programmer be sure the frame creation has
> finished without any reference to its creation thread?

The usual way is to insert

  (sit-for 0 t)

before the code that needs the frame visible.  You can see this, e.g.,
in fancy-splash-frame and in some other places.




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18 19:05           ` Eli Zaretskii
@ 2017-12-18 19:19             ` Robert Weiner
  2017-12-19 17:05               ` Eli Zaretskii
  0 siblings, 1 reply; 18+ messages in thread
From: Robert Weiner @ 2017-12-18 19:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: martin rudalics, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2525 bytes --]

On Mon, Dec 18, 2017 at 2:05 PM, Eli Zaretskii <eliz@gnu.org> wrote:

> > How can an Elisp programmer be sure the frame creation has
> > finished without any reference to its creation thread?
>
> The usual way is to insert
>
>   (sit-for 0 t)
>
> before the code that needs the frame visible.  You can see this, e.g.,
> in fancy-splash-frame and in some other places.
>

​Ok, I'll add that.  Could you run the tests at the end
of the file and see if this version of that function resolves
your issues:

(defun display-frame-until-condition (frame &optional buffer condition)
  "Display FRAME topmost with optional BUFFER in its selected window until
CONDITION or `display-until-delay' seconds.

FRAME may be an existing, even invisible frame, frame name or
nil.  If nil, the selected frame is used.  If FRAME is a string
and no live frame with that name is found, a new one with the
name and any `display-until-frame-parameters' is created.

BUFFER may be an existing buffer or buffer name.

After display, FRAME's prior visibility status is restored.
FRAME's depth in the frame stacking order is not restored."
  (unless frame
    (setq frame (selected-frame)))
  (when (stringp frame)
    (setq frame (or (display-until-get-frame-by-name frame)
    (prog1 (make-frame (cons `(name . ,frame)
     display-until-frame-parameters))
      ;; Wait for frame creation to finish
      (sit-for 0 t)))))
  (cond ((not (framep frame))
(error "(display-frame-until): First argument must be a frame, not `%s'"
frame))
((not (frame-live-p frame))
(error "(display-frame-until): First argument must be a live frame, not
`%s'"
frame))
((and buffer (not (or (bufferp buffer) (and (stringp buffer)
    (get-buffer buffer)))))
(redisplay t)
(error "(display-frame-until): Second argument must be an existing buffer
or buffer name, not `%s'"
buffer))
(t
(let ((frame-visible-flag (frame-visible-p frame)))
   (select-frame frame)
   (raise-frame frame)
   (display-buffer (or buffer (window-buffer))
   (cons 'display-buffer-same-window
display-until-frame-parameters) frame)
   ;; Force redisplay or any changes to frame won't be displayed here.
   (redisplay t)
   (if condition
       (display-until-condition-or-timeout condition display-until-delay)
     ;; Don't use sit-for here because it can be interrupted early.
     (sleep-for display-until-delay))
   (pcase frame-visible-flag
     ('icon (iconify-frame frame))
     ('nil  (make-frame-invisible frame)))))))

[-- Attachment #2: Type: text/html, Size: 8133 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18 19:19             ` Robert Weiner
@ 2017-12-19 17:05               ` Eli Zaretskii
  2018-01-02 17:36                 ` Robert Weiner
  0 siblings, 1 reply; 18+ messages in thread
From: Eli Zaretskii @ 2017-12-19 17:05 UTC (permalink / raw)
  To: rswgnu; +Cc: rudalics, emacs-devel

> From: Robert Weiner <rsw@gnu.org>
> Date: Mon, 18 Dec 2017 14:19:23 -0500
> Cc: martin rudalics <rudalics@gmx.at>, emacs-devel <emacs-devel@gnu.org>
> 
> > The usual way is to insert
> >
> >   (sit-for 0 t)
> >
> > before the code that needs the frame visible.  You can see this, e.g.,
> > in fancy-splash-frame and in some other places.
> >
> 
> ​Ok, I'll add that.  Could you run the tests at the end
> of the file and see if this version of that function resolves
> your issues:

It still works erratically, at least on one system I tried it:
sometimes displays an incompletely rendered frame, sometimes triggers
an error with a backtrace, saying I attempted to delete a sole frame,
sometimes doesn't return to the original frame/window/buffer.  I will
take a closer look at what happens when I have time.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-18  7:26     ` martin rudalics
  2017-12-18 16:10       ` Eli Zaretskii
@ 2017-12-20  8:54       ` martin rudalics
  2017-12-20 13:44         ` Robert Weiner
                           ` (2 more replies)
  1 sibling, 3 replies; 18+ messages in thread
From: martin rudalics @ 2017-12-20  8:54 UTC (permalink / raw)
  To: rswgnu; +Cc: emacs-devel

 > I will try on GNU/Linux as soon as I have that machine running again.

I tried your functions on GNU/Linux now.  The GTK build seems to handle
them as expected.  The other builds (Motif, Lucid and no-toolkit) have
the frame lose its title bar after executing the

   (progn (set-frame-parameter (display-until-get-frame-by-name "My-Frame") 'visibility t)
	 (display-frame-until "My-Frame"))

form.  So far I have not been able to reproduce such behavior by just
making a frame invisible and visible again.

martin



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-20  8:54       ` martin rudalics
@ 2017-12-20 13:44         ` Robert Weiner
  2018-01-02 17:38         ` Robert Weiner
  2018-01-19 18:55         ` martin rudalics
  2 siblings, 0 replies; 18+ messages in thread
From: Robert Weiner @ 2017-12-20 13:44 UTC (permalink / raw)
  To: martin rudalics; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1179 bytes --]

On Wed, Dec 20, 2017 at 3:54 AM, martin rudalics <rudalics@gmx.at> wrote:

>
> I tried your functions on GNU/Linux now.  The GTK build seems to handle
> them as expected.  The other builds (Motif, Lucid and no-toolkit) have
> the frame lose its title bar after executing the
>
>   (progn (set-frame-parameter (display-until-get-frame-by-name
> "My-Frame") 'visibility t)
>          (display-frame-until "My-Frame"))
>
> form.


​Thanks for testing this.  It would be helpful with such reports if
you include your thoughts about where you think the misbehaving
code lives (display-until, the code shipped in Emacs itself, the
windowing system), so we have an idea of what to look at to hopefully
eliminate the problem.

Please also test with display-until-delay set to 3 seconds or so just
to see if a timing difference eliminates your problem.

display-until is small enough that you could strip down its functions
pretty quickly to just the part that generates the issue you are seeing
and even see if any small code change eliminates it.

Just FYI, I see none of the problems you and Eli have reported when
using the MacOS window manager.

Bob

[-- Attachment #2: Type: text/html, Size: 3043 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-19 17:05               ` Eli Zaretskii
@ 2018-01-02 17:36                 ` Robert Weiner
  0 siblings, 0 replies; 18+ messages in thread
From: Robert Weiner @ 2018-01-02 17:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: martin rudalics, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1110 bytes --]

On Tue, Dec 19, 2017 at 12:05 PM, Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Robert Weiner <rsw@gnu.org>
> > Date: Mon, 18 Dec 2017 14:19:23 -0500
> > Cc: martin rudalics <rudalics@gmx.at>, emacs-devel <emacs-devel@gnu.org>
> >
> > > The usual way is to insert
> > >
> > >   (sit-for 0 t)
> > >
> > > before the code that needs the frame visible.  You can see this, e.g.,
> > > in fancy-splash-frame and in some other places.
> > >
> >
> > ​Ok, I'll add that.  Could you run the tests at the end
> > of the file and see if this version of that function resolves
> > your issues:
>
> It still works erratically, at least on one system I tried it:
> sometimes displays an incompletely rendered frame, sometimes triggers
> an error with a backtrace, saying I attempted to delete a sole frame,
> sometimes doesn't return to the original frame/window/buffer.  I will
> take a closer look at what happens when I have time.
>

​Please lengthen the frame creation delay time and see if that changes the
behavior.
Since frame creation is asynchronous, this is important.

Bob
​

[-- Attachment #2: Type: text/html, Size: 2264 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-20  8:54       ` martin rudalics
  2017-12-20 13:44         ` Robert Weiner
@ 2018-01-02 17:38         ` Robert Weiner
  2018-01-07 16:08           ` martin rudalics
  2018-01-19 18:55         ` martin rudalics
  2 siblings, 1 reply; 18+ messages in thread
From: Robert Weiner @ 2018-01-02 17:38 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 773 bytes --]

On Wed, Dec 20, 2017 at 3:54 AM, martin rudalics <rudalics@gmx.at> wrote:

> ​​
> > I will try on GNU/Linux as soon as I have that machine running again.
>

​Any further thoughts?​

> ​​
>
> ​​
> I tried your functions on GNU/Linux now.  The GTK build seems to handle
> ​​
> t
> ​​
> h
> ​​
> e
> ​​
> m
> ​​
> ​​
> a
> ​​
> s
> ​​
> ​​
> e
> ​​
> x
> ​​
> pected.  The other builds (Motif, Lucid and no-toolkit) have
> the frame lose its title bar after executing the
>
>   (progn (set-frame-parameter (display-until-get-frame-by-name
> "My-Frame") 'visibility t)
>          (display-frame-until "My-Frame"))
>
> form.


​Does it just seem like a timing issue?

Bob

[-- Attachment #2: Type: text/html, Size: 3010 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2018-01-02 17:38         ` Robert Weiner
@ 2018-01-07 16:08           ` martin rudalics
  2018-01-16 17:06             ` Robert Weiner
  0 siblings, 1 reply; 18+ messages in thread
From: martin rudalics @ 2018-01-07 16:08 UTC (permalink / raw)
  To: rswgnu; +Cc: emacs-devel

 > ​Any further thoughts?​

Not really.  I've been struggling with such problems ever since.  The
mixture of making a frame invisible, raising it, giving it focus and
selecting it is hard to understand.

 >> The other builds (Motif, Lucid and no-toolkit) have
 >> the frame lose its title bar after executing the
 >>
 >>    (progn (set-frame-parameter (display-until-get-frame-by-name
 >> "My-Frame") 'visibility t)
 >>           (display-frame-until "My-Frame"))
 >>
 >> form.
 >
 >
 > ​Does it just seem like a timing issue?

IMHO the word "just" is inappropriate here.  Practically all issues I
fought with in this context were timing issues.

martin




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2018-01-07 16:08           ` martin rudalics
@ 2018-01-16 17:06             ` Robert Weiner
  0 siblings, 0 replies; 18+ messages in thread
From: Robert Weiner @ 2018-01-16 17:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

On Sun, Jan 7, 2018 at 11:08 AM, martin rudalics <rudalics@gmx.at> wrote:

> > ​Any further thoughts?​
>
> > ​Does it just seem like a timing issue?
>
> IMHO the word "just" is inappropriate here.  Practically all issues I
> fought with in this context were timing issues.


​I mean can you find a longer delay that resolves the problem.  If so, then
we could examine what reasonable defaults might be based on platform
differences.

Bob

[-- Attachment #2: Type: text/html, Size: 1302 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2017-12-20  8:54       ` martin rudalics
  2017-12-20 13:44         ` Robert Weiner
  2018-01-02 17:38         ` Robert Weiner
@ 2018-01-19 18:55         ` martin rudalics
  2018-01-20  5:12           ` Noam Postavsky
  2 siblings, 1 reply; 18+ messages in thread
From: martin rudalics @ 2018-01-19 18:55 UTC (permalink / raw)
  To: rswgnu; +Cc: emacs-devel

 > The other builds (Motif, Lucid and no-toolkit) have
 > the frame lose its title bar after executing the
 >
 >    (progn (set-frame-parameter (display-until-get-frame-by-name "My-Frame") 'visibility t)
 >       (display-frame-until "My-Frame"))
 >
 > form.  So far I have not been able to reproduce such behavior by just
 > making a frame invisible and visible again.

Meanwhile I have been able to do precisely that by evaluating the
forms below in sequence

(setq frame (make-frame))

(make-frame-invisible frame)

(make-frame-visible frame)

The Lucid build has FRAME lose its window manager decorations when it
becomes visible again.  Stepping through x_make_frame_visible under
the debugger does not exhibit the problem, so it seems to be a timinig
issue.

I will continue investigating this but would like to hear from others
whether they can see a similar behavior and, if that is the case,
whether they have an older (< 25) build which does not exhibit it.
Here Motif and builds without X toolkit support have the same problem.

With the GTK build, the frame is positioned at (0, 0) on my screeen
which is clearly another bug.  But at least the GTK frame retains its
decorations when it becomes visible again.

Thanks, martin



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2018-01-19 18:55         ` martin rudalics
@ 2018-01-20  5:12           ` Noam Postavsky
  2018-01-20 10:34             ` martin rudalics
  0 siblings, 1 reply; 18+ messages in thread
From: Noam Postavsky @ 2018-01-20  5:12 UTC (permalink / raw)
  To: martin rudalics; +Cc: Robert Weiner, emacs-devel

On Fri, Jan 19, 2018 at 1:55 PM, martin rudalics <rudalics@gmx.at> wrote:

> Meanwhile I have been able to do precisely that by evaluating the
> forms below in sequence
>
> (setq frame (make-frame))
>
> (make-frame-invisible frame)
>
> (make-frame-visible frame)
>
> The Lucid build has FRAME lose its window manager decorations when it
> becomes visible again.

Doesn't happen here with emacs-26 and master Lucid builds under the i3 wm.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs
  2018-01-20  5:12           ` Noam Postavsky
@ 2018-01-20 10:34             ` martin rudalics
  0 siblings, 0 replies; 18+ messages in thread
From: martin rudalics @ 2018-01-20 10:34 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: Robert Weiner, emacs-devel

 >> The Lucid build has FRAME lose its window manager decorations when it
 >> becomes visible again.
 >
 > Doesn't happen here with emacs-26 and master Lucid builds under the i3 wm.

Thanks.  Can someone out there please try with a non-tiling window
manager?

Thanks, martin



^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-01-20 10:34 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-17 17:28 display-until.el - Display a window or frame topmost in the frame stack until a condition or timeout occurs Robert Weiner
2017-12-17 18:13 ` martin rudalics
2017-12-17 18:46   ` Robert Weiner
2017-12-18  7:26     ` martin rudalics
2017-12-18 16:10       ` Eli Zaretskii
2017-12-18 18:17         ` Robert Weiner
2017-12-18 19:05           ` Eli Zaretskii
2017-12-18 19:19             ` Robert Weiner
2017-12-19 17:05               ` Eli Zaretskii
2018-01-02 17:36                 ` Robert Weiner
2017-12-20  8:54       ` martin rudalics
2017-12-20 13:44         ` Robert Weiner
2018-01-02 17:38         ` Robert Weiner
2018-01-07 16:08           ` martin rudalics
2018-01-16 17:06             ` Robert Weiner
2018-01-19 18:55         ` martin rudalics
2018-01-20  5:12           ` Noam Postavsky
2018-01-20 10:34             ` martin rudalics

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).