激活窗口獲取鍵盤輸入

更詳細的講解和代碼調試演示過程,請參看視頻
Linux kernel Hacker, 從零構建本身的內核vue

咱們實現了鍵盤的輸入焦點切換,但儘管控制命令臺激活後,若是咱們敲擊鍵盤,會發現字符輸入的仍是前頭的Message box.這一節,咱們要實現把鍵盤敲擊的內容輸入到被切換的窗口。微信

實現的思路是這樣的,咱們爲每一個任務配置一個輸入隊列,當窗口被激活時,一旦有鍵盤輸入,主進程首先會把鍵盤數據獲取到,而後判斷當前被激活的是哪一個窗口,而後找到運行窗口所對應的進程對象,經過進程對象得到其對應的輸入隊列,因而把鍵盤傳過來的信息放入到輸入隊列中,而後激活對應的進程對象。markdown

爲此,咱們對代碼作以下修改,首先是multi_task.h:app

struct TASK {
    int sel, flags;
    int priority;
    int level;
    struct FIFO8 fifo;
    struct TSS32 tss;
};

上面的改動就是添加了一個隊列,用來獲取信息輸入。接下來修改的是主進程的CMain 函數,一旦鍵盤事件產生後,CMain會被激活,這時它能夠把接收到的字符投入到對應窗口進程的隊列中:函數

void CMain(void) {
    ....
    for(;;) {
    ....
    else if (key_to == 0) {
               if (keytable[data] != 0 && cursor_x < 144) {
                   boxfill8(shtMsgBox->buf, shtMsgBox->bxsize, COL8_FFFFFF,cursor_x,
                   28, cursor_x + 7, 43);
                   sheet_refresh(shtctl, shtMsgBox, cursor_x, 28, cursor_x+8, 44);

                   char buf[2] = {keytable[data], 0};
                   showString(shtctl,  shtMsgBox, cursor_x, 28, COL8_000000, buf);
                   cursor_x += 8;

                  stop_task_A = 1;

                  boxfill8(shtMsgBox->buf, shtMsgBox->bxsize, cursor_c, cursor_x,
                  28, cursor_x + 7, 43);
                  sheet_refresh(shtctl, shtMsgBox, cursor_x, 28, cursor_x+8, 44);
              } 
           } else {
              task_sleep(task_a);
              fifo8_put(&task_cons->fifo, data);
           }

       }
    ....
    }
    ....
}

若是當前激活的窗口是Message Box 那麼字符就直接顯示在文本框中,要否則咱們把當前主進程掛起,而後把鍵盤數據經過fifo8_put把數據投入到控制檯進程對應的隊列中。咱們必定要記得把主進程掛起,要否則主進程會一直佔據CPU資源,從而控制檯進程不能運行,進而沒法及時處理鍵盤數據。ui

咱們再看看控制檯進程的改變:url

void console_task(struct SHEET *sheet) {
    ....
    else {
                if (i == 0x0e && cursor_x > 8) {
                      boxfill8(sheet->buf, sheet->bxsize, COL8_000000, cursor_x,
                28, cursor_x + 7, 43);
                      sheet_refresh(shtctl, sheet, cursor_x, 28, cursor_x+8, 44);

                     cursor_x -= 8;

                     boxfill8(sheet->buf, sheet->bxsize, COL8_000000, cursor_x,
                28, cursor_x + 7, 43);
                     sheet_refresh(shtctl, sheet, cursor_x, 28, cursor_x+8, 44);
                } else {
                           if (cursor_x < 240 &&i< 0x54 && keytable[i] != 0) {
                           boxfill8(sheet->buf, sheet->bxsize, COL8_000000, cursor_x,
                28, cursor_x + 7, 43);
                           sheet_refresh(shtctl, sheet, cursor_x, 28, cursor_x+8, 44);

                           s[0] = keytable[i];
                           s[1] = 0;
                           showString(shtctl, sheet, cursor_x, 28, COL8_FFFFFF, s);
                           cursor_x += 8;
                       }
                }
            }

    ....
}

變量i的值就是CMain傳進來鍵盤數據,若是i的值是0x0e,表示鍵盤按鈕是退格鍵,接收到這個按鍵時,咱們要作的是把光標前面的字符給刪除掉。在刪除字符時,咱們須要注意一點,就是對光標的處理,因爲光標效果是經過繪製一個白色方塊,而後再繪製一個黑色方塊來實現的,若是退格時,光標正好是白色方塊,那麼咱們把光標向前移動一個字符的位置後,就會在光標的原來位置留下一個白色方塊,所以在把光標向前移動前,咱們先要在光標原來的位置用背景色繪製同等大小的方塊,把白色方塊給覆蓋的,這就是爲什麼在cursor_x -= 8; 這條語句前會有三條用於繪製窗口的語句。spa

把光標向前移動一個字符的位置後,光標前面的字符就會被光標的方塊給覆蓋掉,從而實現字符刪除的特效。.net

若是輸入的是其餘字符,那麼同理,先把光標當前的位置用背景色覆蓋掉,而後在把字符顯示出來,接着把光標向後移動一個字符的位置,在新位置上交替繪製光標方塊。命令行

上面的代碼完成後,效果以下:

你們能夠看到,系統運行後,經過tab把輸入焦點切換到後面的控制檯,而後點擊鍵盤,鍵盤對應的字符會出如今命令行窗口上,一旦命令行窗口能接收字符,咱們後面就能夠在系統上開發其餘程序,而後經過命令行窗口來運行。

更詳實的代碼講解和演示調試過程請參看視頻。

本文分享自微信公衆號 - Coding迪斯尼(gh_c9f933e7765d)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索