Skip to content

Instantly share code, notes, and snippets.

@verygoodlee
Created May 13, 2024 03:38
Show Gist options
  • Save verygoodlee/51a54415b4e77191da97db029aef383d to your computer and use it in GitHub Desktop.
Save verygoodlee/51a54415b4e77191da97db029aef383d to your computer and use it in GitHub Desktop.
mpv-disableIME
-- 取消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()
-- 在首次获取焦点后执行,确保mpv窗口已经初始化
function on_focused_change(_, val)
if not val then return end
mp.unobserve_property(on_focused_change)
disable_ime()
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