Last active
November 4, 2024 03:55
-
-
Save verygoodlee/51a54415b4e77191da97db029aef383d to your computer and use it in GitHub Desktop.
mpv-disableIME
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 取消mpv窗口与输入上下文的关联,达到禁用IME的效果 | |
-- https://learn.microsoft.com/zh-cn/windows/win32/api/imm/nf-imm-immassociatecontext | |
local ffi_ok, ffi = pcall(require, 'ffi') | |
if not ffi_ok then return end | |
ffi.cdef[[ | |
typedef void* HWND; | |
typedef void* HIMC; | |
typedef int BOOL; | |
typedef unsigned int DWORD; | |
typedef unsigned int LPDWORD[1]; | |
typedef int LPARAM; | |
typedef BOOL (*WNDENUMPROC)(HWND, LPARAM); | |
HIMC ImmAssociateContext(HWND hwnd, HIMC himc); | |
BOOL ImmReleaseContext(HWND hwnd, HIMC himc); | |
DWORD GetCurrentThreadId(); | |
HWND GetForegroundWindow(); | |
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam); | |
DWORD GetWindowThreadProcessId(HWND hwnd, LPDWORD lpdwProcessId); | |
BOOL AttachThreadInput(DWORD idAttach, DWORD idAttachTo, BOOL fAttach); | |
HWND SetFocus(HWND hWnd); | |
]] | |
local imm32 = ffi.load('imm32') | |
local kernel32 = ffi.load('kernel32') | |
local user32 = ffi.load('user32') | |
local mpv_pid = require('mp.utils').getpid() | |
-- https://mpv.io/manual/master/#lua-scripting-exit() | |
if not _G.exit then | |
function exit() mp.keep_running = false end | |
end | |
-- 在首次获取焦点后执行,确保mpv窗口已经初始化 | |
function on_focused_change(_, val) | |
if not val then return end | |
mp.unobserve_property(on_focused_change) | |
disable_ime() | |
exit() | |
end | |
mp.observe_property('focused', 'bool', on_focused_change) | |
-- 禁用mpv窗口的IME | |
function disable_ime() | |
local mpv_hwnd = find_mpv_window() | |
if not mpv_hwnd then return end | |
-- 取消窗口与输入上下文的关联 | |
local himc = imm32.ImmAssociateContext(mpv_hwnd, nil) | |
imm32.ImmReleaseContext(mpv_hwnd, himc) | |
refocus(mpv_hwnd) | |
end | |
-- 查找mpv窗口句柄 | |
function find_mpv_window() | |
local mpv_hwnd = nil | |
local foreground_hwnd = user32.GetForegroundWindow() | |
if is_mpv_window(foreground_hwnd) then | |
mpv_hwnd = foreground_hwnd | |
else | |
user32.EnumWindows(function(each_hwnd, _) | |
if is_mpv_window(each_hwnd) then | |
mpv_hwnd = each_hwnd | |
return false | |
end | |
return true | |
end, 0) | |
end | |
if not mpv_hwnd then mp.msg.warn('mpv window not found') end | |
return mpv_hwnd | |
end | |
function is_mpv_window(hwnd) | |
if not hwnd then return false end | |
local lpdwProcessId = ffi.new('LPDWORD') | |
user32.GetWindowThreadProcessId(hwnd, lpdwProcessId) | |
return lpdwProcessId[0] == mpv_pid | |
end | |
-- 窗口重新获取输入焦点,触发IME状态刷新 | |
function refocus(mpv_hwnd) | |
local curr_tid = kernel32.GetCurrentThreadId() | |
local mpv_tid = user32.GetWindowThreadProcessId(mpv_hwnd, _) | |
user32.AttachThreadInput(curr_tid, mpv_tid, 1) | |
user32.SetFocus(nil) | |
user32.SetFocus(mpv_hwnd) | |
user32.AttachThreadInput(curr_tid, mpv_tid, 0) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment