Commits

kankri committed 9f6551d

Match windows by application name

Match windows not only by their titles but also by the name of the executable file of the owning process.

Comments (0)

Files changed (2)

doc/source/pygoy.rst

    Unfortunately PyGo-Y cannot control whether matching windows appear in the
    list before or after programs.
 
-PyGo-Y compares your input against the title of the window and if it matches the
-window is listed in the Launchy dialog. Selecting any of those will focus
-it.
+When matching windows, PyGo-Y looks for the following information:
+
+ * The window title. The title is shown along the window icon in the Lauchy
+   list of matching items.
+ * The name of the program. E.g. if you have opened a "Command Prompt"
+   window, PyGo-Y matches that when you type "cmd.exe" even though it's not
+   visible on the title.
+
+PyGo-Y matches your input against both the title and the program name in turn.
+If either of them match, the window is listed in the Launchy dialog. Selecting
+any of those will focus it.
 
 The matching is done as a case-insensitive substring match. E.g. "Md.E" matches
 with "cmd.exe".

plugins/pygo-y.py

 import win32gui
 from win32con import SW_SHOW, SW_RESTORE, SW_SHOWMINIMIZED
 import ctypes
+from ctypes.wintypes import HWND, LPWSTR, UINT
+
 ACP = 'cp%d'%ctypes.windll.kernel32.GetACP()
 
+GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
+def GetWindowProcess(hwnd):
+	pid = ctypes.c_int()
+	tid = GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
+	return pid.value
+
+OpenProcess = ctypes.windll.kernel32.OpenProcess
+CloseHandle = ctypes.windll.kernel32.CloseHandle
+GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW
+def GetProcessFilename(pid):
+	PROCESS_QUERY_INFORMATION = 0x0400
+	PROCESS_VM_READ = 0x0010
+	hProc = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, 0, pid)
+	filename = ctypes.create_unicode_buffer(1024)
+	size = GetModuleFileNameExW(hProc, 0, filename, 1024)
+	CloseHandle(hProc)
+	return filename.value[:size]
+
 def GetAppdataDir():
 	shell32 = ctypes.windll.shell32
 	CSIDL_LOCAL_APPDATA = 0x001c
 
 	def _windowEnumTopLevel(hwnd, (windowsList, is_match)):
 		""" Window Enum function for getTopLevelWindows """
+		if (
+			win32gui.GetParent(hwnd) != 0 or
+			not win32gui.IsWindowVisible(hwnd)
+		):
+			return
 		title = unicode(win32gui.GetWindowText(hwnd), ACP)
-		if (
-			win32gui.GetParent(hwnd) == 0 and
-			is_match(title) and
-			win32gui.IsWindowVisible(hwnd)
-		):
+		path = GetProcessFilename(GetWindowProcess(hwnd))
+		if (is_match(title) or is_match(os.path.basename(path))):
 			windowsList.append( (hwnd, title) )
 
 	_windowEnumTopLevel = staticmethod(_windowEnumTopLevel)