【瞎折騰-01】deepin系統菜單快捷鍵魔改(恢復快捷鍵)

封面為最終的效果圖。

閱讀本文大約需要3分鐘。

起因

有一個很好用的國產操作系統deepin,有句玩笑話是說這大概是唯一不需要(*)補貼就能活下去的國產操作系統

去年版本從15.3升級到15.4以後,硬生生的砍掉了一個快捷鍵。然後我就粉轉黑了。

什麼快捷鍵呢?(如上圖所示的……)

任意窗體按alt+空格彈窗後:只有彈窗,沒有快捷鍵功能。所有附帶快捷鍵都不能用了。(比如最大化、最小化、移動、關於,以及對我而言最重要的alt+空格+C

詢(dui)問(ren)

在deepin交流群問了一圈,都不關心這個問題,說沒有了這個快捷鍵對我們(他們)影響不大啊,大不了自己設置快捷鍵唄。

但是我很不爽啊。哪怕是用super+Q也替代不了這種體驗,和蘋果的command+Q的體驗完全不一樣。而且我在windows下也都是用alt+空格+C來關閉窗口的。

聯繫上了deepin的一個工作人員,他說他自己都忘了這個了,平時也用不到,下一步有打算統一系統各種快捷鍵什麼的。(我就是針對alt+space重度患者)

所以我想了以我目前的水平魔改一個開源項目的代碼應該沒有太大難度吧???

二話不說先fork為敬,找到linuxdeepin/deepin-menu的倉庫拿去fork。然後看到各種依賴。嗯,搭建開發環境需要安裝一大堆的開發的依賴包。

安裝依賴

除了安裝qt,dbus等一大堆依賴以外……

sudo apt-get install libxcb*

sudo apt-get install dde*

sudo apt-get install deepin*

好吧,我就是這麼乾的……

依賴在那個什麼archlinux的網站能夠看得到。

缺什麼下什麼

最後還缺了一個com.deepin.api.滑鼠事件的東西,在deepin論壇上找到的解決方案。

開發環境

  • Qt Creator
  • CLion 2017.2.3(另外想說一聲夭壽啦,2.3 EAP 有kotlin插件,在2.3正式版不見了!!)
  • (前者用來編譯和寫代碼,後者拿來當git和查找全局代碼用,原諒我只會用git clone push pull命令行,當然了其實只是為了方便查看git log各種改動以便懟人)

所以我就輕而易舉地找到了 2016年11月1日 10:33的一條commit:

remove hot key

啊♂奧義很爽?

開發(dui)

所以我就照著這條記錄的改動把代碼反向更改,當然是不能按照我想像的那樣運行的啦~

為什麼呢?

因為架構改了,dmenubase這個文件已經「廢棄」掉不使用了。(雖然沒有這麼說但是qt的pro文件顯示構建過程並沒有包含這個)

src目錄(僅列出cpp文件,除了main之外都有其對應.h的頭文件):

└── srcn ├── dabstractmenu.cppn ├── dbus_manager_adaptor.cppn ├── dbus_menu_adaptor.cppn ├── ddesktopmenu.cppn ├── ddockmenu.cppn ├── dmenuapplication.cppn ├── dmenubase.cppn ├── dmenucontent.cppn ├── main.cppn ├── manager_object.cppn ├── menu_object.cppn ├── utils.cppn

結構分析

先從文件名入手:(不管開頭的d,估計因為是deepin所以每個前面都加了個d以示區分)

  • dabstractmenu: 菜單的抽象類。沒有繼承於任何類型。
  • dbus_manager_adaptor: This file was generated by qdbusxml2cpp,是通過qdbusxml2cpp命令行生成的一個文件,個人理解應該是對接deepin系統一些介面的。
  • dbus_menu_adaptor:同上
  • ddesktopmenu: (繞了半天才發現需要魔改的地方在這裡)
  • ddockmenu: dock是deepin系統底部的高仿的那個欄(咳咳)。具體作用是負責dock欄的圖標被右鍵點擊後的事件處理。
  • dmenuapplication: DMenuApplication的入口
  • dmenubase: (雖然沒有像Java那樣用Deprecated但是實際上已經被遺棄,)
  • dmenucontent: 菜單生成的內容的選取。其構造函數的參數是DDockMenu*的類型(導致什麼後果我等會再說……)
  • manager_object: 註冊menu的。(涉及到qt的signal和slots,據說是qt自己的關鍵字,以我不懂裝懂的水平就把他當做是一個很高級的回調函數。)
  • menu_object: 對這兩種東西(dockmenu和desktopmenu)的一層抽象。
  • utils: 工具類。計算一些坐標什麼的。

迷之架構

主要的就是我上面粗體的三個地方desktopmenu,dockmenu和menucontent。但是為什麼我感覺很困惑呢?這個設定很奇怪。

  • class DMenuContent繼承於QWidget,但是其構造函數參數類型為DDockMenu*
  • class DDockMenu 繼承於DArrowRectangleDAbstractMenu。裡面還聲明DMenuContent為友元類。
  • class DDesktopMenu繼承於 QMenuDAbstractMenu

看起來就是前面兩個東西糾纏不清。心疼DDesktopMenu還要吃狗糧。

我一開始也就是照著架構,在menucontent裡面把hot key的代碼加回去。加回去以後發現不夠啊。

然後才注意到了desktopmenu這玩意,也加上去。也有模有樣了,可以在alt+空格彈窗後看到每一行的item是有快捷鍵的樣子的,但是就是不能觸發。

接著又發現dock欄上的右鍵點擊後也出現了快捷鍵的標識,而這裡的快捷鍵是可以被觸發的。

(陷入沉思……)

憑什麼普通窗口的快捷鍵不能觸發呢?

void DDesktopMenu::keyPressEvent(QKeyEvent *event) n{ n if (event->key() == Qt::Key_Escape) { n hide(); n }n QMenu::keyPressEvent(event); n} n

合著這玩意只能觸發Esc的事件,並且把窗口隱藏。(要你何用?)

按照我這人的edbug習慣……能夠用輸出解決的問題堅決不用調試。不過這次我還是先打個斷點再說……因為前面一直沒找到內容

if(event->key()這一行設置斷點,一調試。死機了!!!!好開心!!!

在強行掐掉電源重啟電腦後……終於進入了最後的步驟了。

收尾階段

仿照著執行action的步驟

//int k = event->key();nauto kayChar = QString(char(k));nforeach(QMenu *q,m_ownMenus){n foreach(QAction *act,q->actions()){n qDebug()<<act->property("itemNavKey").toString();n if(kayChar==act->property("itemNavKey").toString()){n act->trigger();n }n }n}n

(不好意思忘記把debug輸出的內容一併刪掉了)n

這個m_ownMenusDDesktopMenu類裡面的存放 QMenu* 的一個QList。其實是不需要兩重foreach的,實際上m_ownMenus只有一個QMenu* 的元素,然後再對這個QMenu的actions進行遍歷。遍歷查找快捷鍵的內容,然後找到匹配的後觸發這個action,直接用trigger()

編碼結束

運行

然後按照官網的東西,到目錄下建立build文件夾,

mkdir buildncd buildnqmake ..nmakensudo make install n

(make install 就替換了/usr/bin目錄下的deepin-menu

有一件很神奇的事情就是……deepin-menu應該算是系統應用,但是如果我在ide中編譯運行,他就會臨時覆蓋掉deepin-menu這個程序,並且可以截取控制台的輸出結果……

已經可以了╮(╯_╰)╭

效果圖就是標題的那個……

感想

  • 這兩天因為deepin15.5beta版出了,想重新裝回deepin系統,又想到之前因為這個快捷鍵的原因直接棄坑deepin,乾脆試試自己手改看看行不行。順帶看看自己C++基礎還湊不湊合。一邊找資料一邊研究。然而我發現我電腦來來回回裝不上15.5,只能退而求其次裝15.4.1,結果系統更新自動更新上15.5了……
  • Qt才剛開始看,不過應該還是暫時用不上C++。可是我還是喜歡Kotlin。
  • 表示用慣了jb全家桶,qt creator那是真的不好用啊!
  • 之後應該考慮把kotlin協程的東西給寫好(其實一直在草稿箱沒發出去)
  • 下一步不知道要不要考慮折騰windows 1709(16299)更新之後的win+x+p控制面板

你學會了什麼?

你什麼也沒學到。


推薦閱讀:

想實現一個linux內核安全功能模塊的技術思路是怎樣的?
linux掛載機制,訪問父目錄的細節是怎樣的?
在Linux內核模塊中對空指針解引用,為什麼內核不掛?

TAG:Deepin | Linux | QtC开发框架 |