Sublime Forum

Retain focus on Sublime Text

#1

in my package MarkdownBuild I try to use

webbrowser.open("file://" + output.name)

to open an html file.

However, after opening the file in a web browser, the focus is shifted to the web browser.

Any idea on how to switch the focus back to Sublime Text?

0 Likes

#2

Didn’t try it and only work (if it work at all) on Windows:

import ctypes ctypes.windll.user32.SetForegroundWindow(self.window.hwnd())

0 Likes

#3

I’ve tried exactly the same thing but it didn’t work.

I also try to import win32com …and it says that there is no module named win32com

I don’t mind if it only works on windows…if there is a way to do it.

0 Likes

#4

The webbrowser.open call is likely async … such that your call to SetForegroundWindow happens before focus has even shifted …

You likely want to use sublime.set_timeout to do the call at some point in the future … the exact amount of ms depending a lot I guess on your computer …

If you set a bunch of timeouts in 25ms increments you can be sure that it will happen fairly snappily … worst case you get a few redundant SetForegroundWindow calls …

Tweak the increments / num of timeouts to your hearts content - but overall much less of a wrist slasher than having to alt - tab …

0 Likes

#5

[quote=“erinata”]I’ve tried exactly the same thing but it didn’t work.

I also try to import win32com …and it says that there is no module named win32com

I don’t mind if it only works on windows…if there is a way to do it.[/quote]

Bringing a window in front is tricky in Windows, and look worst in Win7:

[quote]MS Documentation for SetForegroundWindow reads as follows:
“Windows NT 5.0 and later: An application cannot force a window to the foreground while the user is working with another window. Instead, SetForegroundWindow will activate the window (see SetActiveWindow) and call the FlashWindowEx function to notify the user.”[/quote]

So the only way I found is this, however I cannot put the focus back to ST2:

[code]import sublime, sublime_plugin
import ctypes, time

class ExampleCommand(sublime_plugin.WindowCommand):
def run(self):
time.sleep(5)
# ctypes.windll.user32.BringWindowToTop(self.window.hwnd())
ctypes.windll.user32.SwitchToThisWindow(self.window.hwnd(), 0)
# ctypes.windll.user32.SetForegroundWindow(self.window.hwnd())
# ctypes.windll.user32.SetActiveWindow(self.window.hwnd())
# ctypes.windll.user32.SetFocus(self.window.hwnd())
# ctypes.windll.user32.ShowWindow(self.window.hwnd(), 5)[/code]
Hope it help.

0 Likes

#6

[quote]“Windows NT 5.0 and later: An application cannot force a window to the foreground while the user is working with another window. Instead, SetForegroundWindow will activate the window (see SetActiveWindow) and call the FlashWindowEx function to notify the user.”
[/quote]

IIRC the rules are different for subprocesses of the caller of SetForegroundWindow

ie. If you launch a subprocess from sublime, are focused there, and a set_timeout calls you back to sublime it should work …

[pre=#0C1021]import sublime, webbrowser
from functools import partial
from ctypes import windll

def do():
“”"

>>> from tester import do
>>> do()

"""
webbrowser.open("http://www.google.com.au")
sublime.set_timeout (partial( windll.user32.SetForegroundWindow,
                              sublime.active_window().hwnd()), 500 )

[/pre]

Bisect from 500 downwards towards and you’ll converge on a point where it’s just too slow.

0 Likes

#7

err, too quick :wink:

0 Likes

#8

Yes you’re right, focus work fine with your code.
I only have to change this line to make it work (on Win7 64):

sublime.set_timeout(partial(ctypes.windll.user32.SwitchToThisWindow, sublime.active_window().hwnd(), 0), 500)
It don’t work for me with SetForegroundWindow.

0 Likes

#9

Ah man, what a clusterfuck :smile: Yeah, I’m on Windows 7 x32

Queue the relentlessly branching code

0 Likes

#10

So this function prettily avoids all the rules that apply to SetForegroundWindow huh?

Seems to have been around since Win 2000 :smile:

Learn something new everyday

0 Likes

#11

Thanks for you guys’ reply!

I am on window 7 x64…and I tried the

webbrowser.open(................)
sublime.set_timeout(partial(ctypes.windll.user32.SetForegroundWindow,sublime.active_window().hwnd(), 0), 500)

And it’s not working

But for

webbrowser.open(................)
sublime.set_timeout(partial(ctypes.windll.user32.SwitchToThisWindow,sublime.active_window().hwnd(), 0), 500)

After the webbrowser call, the sublime text editor become the foreground window…but when I press up arrow or down arrow, I am still scrolling the browser output instead of move the caret on sublime text. How can this happen?

0 Likes

#12

Oops, you’re right.
I thought it works because my cursor still blink in ST2 after web browser launch but actually the focus is still in the browser.

I tried everything I know, now I’m clueless… :unamused:

0 Likes

#13

I also tried setfocus() …etc. (in bizoo’s commented code). They do not work…

Looks like I just need to press alt+tab to switch it then :frowning:

0 Likes

#14

Just a thought :wink: but perhaps switch these two lines:

webbrowser.open(................) sublime.set_timeout(partial(ctypes.windll.user32.SetForegroundWindow,sublime.active_window().hwnd(), 0), 500)
and possibly increase the delay.

0 Likes