起源
筆者有使用快捷鍵的習慣,相信不少人也都有在不同軟件上定制 HotKey 的需求。然而 Chrome 自帶的快捷鍵有些是不能改的,當使用 Chrome 連接遠程桌面開發調試軟件時,F1 ~ F12 功能鍵中有相當多是無法正常使用的。
- 有些能通過 Chrome 腳本插件(如 tampermonkey)截斷按鍵的捕獲來解決沖突,有些則處理不了————例如 F11 這種瀏覽器標准中所要求的快捷鍵,優先級是很高的,無法從 js 的層面進行處理。
- 當然了,第三方改鍵軟件也不失為一種簡單方便的 Workaround,但會影響到其他軟件,終究不是那么的優雅。
因此打算把 Chromium 源碼下載下來,直接修改快捷鍵的處理邏輯,將不需要的快捷鍵屏蔽掉。
代碼下載與編譯
Chromium 的下載最重要的就是 官方文檔。由於國內特殊的網絡環境,一些額外工作也是必不可少,貼一些我在解決問題的過程中搜到的感覺很有用的文檔:
另外,設置 --no-history 也是很重要的。一開始沒有設置,下載了 10G+ 的文件都才 60%,實在太慢。設置以后直接不到 1G 搞定。
此處記錄一個小坑,在 fetch chromium --no-history 的執行上報錯,提示 --no-history 參數錯誤,以為是命令行環境錯誤,一查官方文檔提醒使用 cmd,我使用的就是 cmd,沒辦法只能去改腳本了,修改 depot_tools/fetch.py:
def handle_args(argv):
"""Gets the config name from the command line arguments."""
if len(argv) <= 1:
usage('Must specify a config.')
if argv[1] in ('-h', '--help', 'help'):
usage()
dry_run = False
nohooks = False
no_history = True // 修改此處
force = False
while len(argv) >= 2:
arg = argv[1]
if not arg.startswith('-'):
break
argv.pop(1)
if arg in ('-n', '--dry-run'):
dry_run = True
elif arg == '--nohooks':
nohooks = True
elif arg == '--no-history':
no_history = True
elif arg == '--force':
force = True
else:
usage('Invalid option %s.' % arg)
代碼下載完成后就是漫長的編譯了: autoninja -C out\Default chrome
i5 7500的 CPU,16g 內存,默認開啟 6 個進程,總耗時約 6 個小時。
修改代碼
首先還是官方文檔,大概掃了一遍,對主要的幾個工程有一定的了解,其他的先暫時不管,畢竟好幾千個工程,估計代碼能看好幾年... 全看是不現實了,直指目標,搜索關鍵詞 "F11" 看一下,直接出來幾百個搜索結果,而且文件太多了,搜索一直停不下來。將搜索停掉,忽略 ".html", ".js", ".xtb", ".inc", "*unittest.cc" 等可能與主程序邏輯不相關的搜索結果,從文件名開始掃視,fullscreen_control_host.cc 進入眼簾,打開該文件及其頭文件,原來是全屏狀態下顯示退出的 "X" 圖標。
繼續找,搜索了若干相似的關鍵詞,都沒有想要的結果,好吧看來找捷徑失敗,滾回去乖乖看文檔。
Life of a "mouse click" message: 演示了鼠標事件從 browser 到 renderer 的流程。emm,貌似 mouse 事件跟 keyboard 事件處理流程是類似的,這個沒准可行!
- 找到關鍵類
RenderWidgetHostViewWin,去代碼中搜一搜,竟然沒有,難道這個文件沒有被 VS 收錄?先去 Google 一下RenderWidgetHostViewWin site:chromium.googlesource.com,得到結果 render_widget_host_view_win.h,這個文件貌似在最新版本沒有了。 - 既然官方文檔沒有及時更新,那就換個思路,從功能的名稱來搜索。"F11" 對應的是全屏開關,果然,通過 "fullscreen" 關鍵詞找到了
fullscreen_control.cc,其中有兩個相關的方法:
void FullscreenController::ExitFullscreenModeInternal();
void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents);
根據之前文檔中的描述,Tab-initiated 是由 Flash 或 Api 調用產生的全屏,那剩下的只有 ExitFullscreenModeInternal,進去加斷點,在按 "F11" 退出全屏狀態時成功觸發斷點。
找到切入點后,閱讀上下文的代碼就不會如無頭蒼蠅一般了。
修改代碼,編譯,運行,測試快捷鍵,如預期被修改成功!(此處還是要吐槽一下 chromium 的編譯,哪怕只改了一個模塊,增量編譯也要接近 10 分鍾,吃掉 5g 的內存)
暫告段落
一番折騰,周末也快過去了...但是在 Chromium 源碼的閱讀過程中,還是能發現不少設計模式的影子。作為一款大型桌面軟件,它對軟件模塊的分層也值得學習,特別是插件的設計,還有 web 頁面的渲染機制是什么樣的(例如之前做 WPF 表格控件的時候,無法做到靈活的樣式,而 HTML 中 <table> 能輕松做出合並單元格的樣式),以后有時間再進一步研究。
update: 找到個文檔:Chromium中文文檔,對入門還是有些幫助的
