18

I want to force emacs to be activated, be bought to frond and 'steal' focus in certain circumstances. E.g when I finish a org-Pomodoro or during an important appointment reminder.

Now, I'm looking for a 'native' way to do so, just to reduce external dependencies. (just Linux is ok for me, cross-platform would be better).

Is this technically possible from inside emacs?

[edit] Solution:

If using the GUI, this works well:

(x-focus-frame nil)

[For historical reasons...] I have tried:

Frame visibility (doesn't work)

(make-frame-visible)

And also:

(make-frame-invisible)
(make-frame-visible)

But these seem to only work if Emacs is already activated.

Frame raising (doesn't work)

Lowering frame seems to actually hide emacs.

(lower-frame)

But raising the frame from a timer doesn't. I.e, nothing happens.

(raise-frame)

It seems there is a missing 'activate-emacs' before raising it.

[NOTE on external solution]

Currently, as a (workaround/solution?) I use a bit of elisp:

(call-process "activateEmacs")

And the respective bash script: (you may need to install xdotool on your system first)

#!/bin/sh 
sleep 0.5
xdotool search --onlyvisible --class emacs windowactivate
Drew
  • 75,699
  • 9
  • 109
  • 225
Leo Ufimtsev
  • 4,488
  • 3
  • 22
  • 45
  • 4
    Try `raise-frame`. – Tom Tromey Mar 05 '15 at 00:13
  • Thank you for the suggestiong. lowering the frame works, but raising the frame doesn't re-raise it for some reason? – Leo Ufimtsev Mar 05 '15 at 17:10
  • I believe @TomTromey is correct. You can test as follows. First, create an idle timer: `(defvar my-timer (run-with-idle-timer 5 t (lambda () (raise-frame))))`. Suspend the frame with `M-x (suspend-frame)`. In 5 seconds, that frame will reappear. – Dan Mar 05 '15 at 19:11
  • Well, it works if you `(suspend-frame)` and wait there without clicking into another window. But if you suspend the frame and go work in another application, then emacs doesn't re-appear. At least not on my system (fedora 21 with Mate desktop). A simple example is this: `: (run-at-time "5 sec" nil '(lambda () (interactive) (message "trying to raise frame") (raise-frame)))` run this and alt-tab onto another application. The message will appear in the buffer but emacs doesn't get raised... Thoughts? – Leo Ufimtsev Mar 05 '15 at 19:20
  • I did notice that on my system some windows don't activate properly, e.g opening a link opens it in chrome but chrome isn't bought to the foreground. If the above 100% works for you, it could be just my system... – Leo Ufimtsev Mar 05 '15 at 19:22
  • @LeoUfimtsev: when I do it and then open a terminal window, the raised frame reclaims focus (using fedora with openbox). – Dan Mar 05 '15 at 19:56
  • 1
    I'm using the Gui version of emacs? (not the terminal version), were you using the gui also? – Leo Ufimtsev Mar 05 '15 at 19:58
  • How about taking a look at the code used for `select-frame-set-input-focus` and see if anything in there looks like it might be helpful. – lawlist Mar 05 '15 at 23:55

2 Answers2

17

If you're using a Window System, you might be able to use x-focus-frame.

Note:

  • x-focus-frame works for Windows as well as for Linux
  • prior to Emacs 23.1, use w32-focus-frame on Windows.
TaylanKammer
  • 626
  • 5
  • 5
4

Either (x-focus-frame nil) or (other-frame 0) will do it. I'm not sure if there is any difference in behavior between the two.

Brian Z
  • 2,863
  • 16
  • 22