Emacs 透明窗口

(defun peek (arg)
  "Temporary set transparent to arg seconds."
  (interactive "p")
  (let ((time (1+ (log (+ 1 (abs arg)) 4))))
    (unless (spacemacs/toggle-transparent-frame-p)
      (spacemacs/toggle-transparency))
    (message "%d sec" time)
    (sleep-for (abs time) 500)
    (spacemacs/toggle-transparency)))

(defun perspective ()
  "Be transparent until a key stroke."
  (interactive)
  (spacemacs/toggle-transparency)
  (read-event)
  (when last-input-event
    (spacemacs/toggle-transparency)
    (setq unread-command-events (list last-input-event))))

差不多这样。

用compiz窗口管理器的我……路过一下

The conflict to the Spacemacs is fixed, now here is the improved version.

;;; Code:


(defvar frame-alpha-default '(100 . 70)
  "The default value for active and inactive windows,
should be a cons cell.")

(defconst frame-alpha-original-lower-limit 20)

(setq frame-alpha-lower-limit 10)
(defvar frame-alpha-max 100)
(defvar frame-alpha-min frame-alpha-lower-limit
  "The alpha value for \"invisible\" frames.")

(defun frame-alpha-initialize ()
  "Must call this function to initialize frame-alpha."
  (set-frame-parameter nil 'alpha (or (frame-parameter nil 'alpha) frame-alpha-default)))
;; important
(frame-alpha-initialize)

(defun frame-alpha-set (type arg)
  "Set the frame alpha, TYPE can be \"active\", \"inactive\",
or \"all\". If TYPE is \"all\", ARG needs to be a cons cell,
otherwise ARG should be a number."
  (let ((alpha (unless (eq type 'all)
                 (cond ((> arg frame-alpha-max)
                        frame-alpha-max)
                       ((< arg frame-alpha-min)
                        frame-alpha-min)
                       (t arg)))))
    (dolist (f (frame-list))
      (set-frame-parameter
       f 'alpha (if (eq type 'all)
                    arg
                  (cons (if (eq type 'active) alpha
                          (car (frame-parameter nil 'alpha)))
                        (if (eq type 'inactive) alpha
                          (cdr (frame-parameter nil 'alpha)))))))))
(defun frame-alpha-get (type)
  "Get the frame alpha, TYPE can be \"active\", \"inactive\"
or \"all\"."
  (let ((alpha (frame-parameter nil 'alpha)))
    (cond
   ((eq type 'active)
    (car alpha))
   ((eq type 'inactive)
    (cdr alpha))
   ((eq type 'all)
    alpha))))

(defun frame-alpha-show ()
  (interactive)
  (message "%s" (frame-parameter (selected-frame) 'alpha)))
(defun frame-alpha-reset ()
  (interactive)
  (set-frame-parameter (selected-frame) 'alpha frame-alpha-default))



;;;###autoload
(defun peek (arg)
  "Temporary set transparent to ARG seconds."
  (interactive "p")
  (let ((alpha (car (frame-alpha-get 'all)))
        (time (1+ (log (+ 1 (abs arg)) 4))))
    (when (< 50 alpha)
      (frame-alpha-set 'active frame-alpha-min)
      (message "%d" time)
      (sleep-for (abs time) 500)
      (frame-alpha-set 'active alpha))))

;;;###autoload
(defun perspective ()
  "Be transparent until a key stroke."
  (interactive)
  (let ((alpha (frame-alpha-get 'all)))
    (frame-alpha-set 'all (cons frame-alpha-min frame-alpha-min))
    (read-event)
    (when last-input-event
      (frame-alpha-set 'all alpha)
      (setq unread-command-events (list last-input-event)))))

(defadvice make-frame-command (around same-transparency activate compile)
  "Create a new frame with the same transparency."
  (if (display-graphic-p)
      (make-frame (list (cons 'alpha (frame-parameter (selected-frame) 'alpha))))))

(provide 'config-transparency)

花时间改了一下,因为 Spacemacs 用了 cons cell 来设置 alpha,所以和原先的版本起冲突。我把不必要的部分去除了,然后精简了下函数。(我的风格是用 let 和 条件从句 少写代码。不知道算不算坏事。)

1 个赞

spacemacs 自带了透明度设置 SPC-T-T

1 个赞

。。。抓到一个看帖不认真的同学。(滑稽)

先不说这里还有一些没有用 Spacemacs 的。 然后我的关注点是在于 Spacemacs 没有的两个函数。

设置 Emacs 窗口透明:

(set-frame-parameter nil 'alpha '(85 . 100))

其中 85 指定当 Emacs 在使用中时的透明度,而 100 则指定其它应用在使用中时 Emacs 的透明度。

取消透明效果(数字 100 表示不透明):

(set-frame-parameter nil 'alpha '(100 . 100))

(set-frame-parameter nil 'alpha 100)

N(N . N) 的效果相同。

顺便写了一个简单的命令来切换透明与否:

(defun chunyang-toggle-frame-transparency ()
  (interactive)
  (if (equal (frame-parameter nil 'alpha) 85)
      (set-frame-parameter nil 'alpha 100)
    (set-frame-parameter nil 'alpha 85)))

GNU Emacs 26.0.50 (build 5, x86_64-apple-darwin16.5.0, NS appkit-1504.82 Version 10.12.4 (Build 16E195)) of 2017-05-14

2 个赞

虽然 用 (85 100) 也可以,但是最好用 (85 . 100) ,这样可以分别改。

1 个赞

一开始我以为 alpha 的值是个数字,后来我看了上面的几个帖子中的代码

发现也可以是个 List。刚才我看下文档 (elisp) Font and Color Parameters

‘alpha’
     This parameter specifies the opacity of the frame, on graphical
     displays that support variable opacity.  It should be an integer
     between 0 and 100, where 0 means completely transparent and 100
     means completely opaque.  It can also have a ‘nil’ value, which
     tells Emacs not to set the frame opacity (leaving it to the window
     manager).

     The ‘alpha’ frame parameter can also be a cons cell ‘(ACTIVE .
     INACTIVE)’, where ACTIVE is the opacity of the frame when it is
     selected, and INACTIVE is the opacity when it is not selected.

发现它可以是 nil 或数字或 Cons Cell。

安装文档的说明,的确应该用 Cons Cell。但是我没有发现实际的区别,"可以分别改"是什么意思?

我的意思是方便单独修改不活跃窗口和活动窗口的位置 alpha。现在看起来我上面的例子写的有点蹩脚了,明明用setf可以把代码写的更 terse 一点。

虽然用 list 也可以,我也是看了上面提到的 Spacemacs 自带的实现才意识到用 cons cell 才是比较正常的办法。

这跟用 (list 85 100) 还是 (cons 85 100) 有关系吗?

1 个赞
;; 举个栗子
;; for a cons cell `alpha' 
(setf (cdr alpha) 90)
;; for a list `alpha'
(setf (second alpha) 90)

我相信前者肯定更有效率那么一点点。虽然对这一点点效率吹毛求疵有点奇怪。

哦,有点明白你的意思了,但是如果是我的话,直接构造一个新的值传入就完了

(set-frame-parameter nil 'alpha '(85 . 100))

(let ((alpha (frame-parameter nil 'alpha)))
  (set-frame-parameter nil 'alpha (cons (car alpha) 85)))

setf 做同样的事情并不会更容易

(let ((alpha (frame-parameter nil 'alpha)))
  (setf (cdr alpha) 85
        (frame-parameter nil 'alpha) alpha))

但假设 setf 支持这么用就另说了(目前不支持)

(setf (cdr (frame-parameter nil 'alpha)) 85)
3 个赞

kde表示自帶所有窗口獨立透明度調節, 非常方便QAQ

1 个赞

赞!用上了,i3上有了强烈的透明背景需求,就搜到了你的这个帖子 08

有个疑问,这个透明是整个窗口的, 不像alacritty透明度只是背景透明, 但是文字不透明,emacs该如何做到?

Seems not possible :frowning_face:

2 个赞

你想想,在你那透明的 alacritty 里开个 emacs 不就行了(

3 个赞

Purcell 的窗口透明函数,可以调透明度的那种 :joy:

;; @purcell
(defun sanityinc/adjust-opacity (frame incr)
  "Adjust the background opacity of FRAME by increment INCR."
  (unless (display-graphic-p frame)
    (error "Cannot adjust opacity of this frame"))
  (let* ((oldalpha (or (frame-parameter frame 'alpha) 100))
         (oldalpha (if (listp oldalpha) (car oldalpha) oldalpha))
         (newalpha (+ incr oldalpha)))
    (when (and (<= frame-alpha-lower-limit newalpha) (>= 100 newalpha))
      (modify-frame-parameters frame (list (cons 'alpha newalpha))))))

(global-set-key (kbd "M-C-8") (lambda () (interactive) (sanityinc/adjust-opacity nil -2)))
(global-set-key (kbd "M-C-9") (lambda () (interactive) (sanityinc/adjust-opacity nil 2)))
(global-set-key (kbd "M-C-7") (lambda () (interactive) (modify-frame-parameters nil `((alpha . 100)))))
5 个赞

非常喜欢作者的org-mode 博客,发现新大陆的感觉.谢谢分享!

这功能好像挺早以前的了

非常棒!已用上!