内核开发:实现切换窗口后的键盘输入

更详细的讲解和代码调试演示过程,请参看视频
Linux kernel Hacker, 从零构建自己的内核

我们实现了键盘的输入焦点切换,但尽管控制命令台激活后,如果我们敲击键盘,会发现字符输入的还是前头的Message box.这一节,我们要实现把键盘敲击的内容输入到被切换的窗口。

实现的思路是这样的,我们为每个任务配置一个输入队列,当窗口被激活时,一旦有键盘输入,主进程首先会把键盘数据获取到,然后判断当前被激活的是哪个窗口,然后找到运行窗口所对应的进程对象,通过进程对象获得其对应的输入队列,于是把键盘传过来的信息放入到输入队列中,然后激活对应的进程对象。

为此,我们对代码做如下修改,首先是multi_task.h:

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资源,从而控制台进程不能运行,进而无法及时处理键盘数据。

我们再看看控制台进程的改变:

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; 这条语句前会有三条用于绘制窗口的语句。

把光标向前移动一个字符的位置后,光标前面的字符就会被光标的方块给覆盖掉,从而实现字符删除的特效。

如果输入的是其他字符,那么同理,先把光标当前的位置用背景色覆盖掉,然后在把字符显示出来,接着把光标向后移动一个字符的位置,在新位置上交替绘制光标方块。

上面的代码完成后,效果如下:

《内核开发:实现切换窗口后的键盘输入》 这里写图片描述

大家可以看到,系统运行后,通过tab把输入焦点切换到后面的控制台,然后点击键盘,键盘对应的字符会出现在命令行窗口上,一旦命令行窗口能接收字符,我们后面就可以在系统上开发其他程序,然后通过命令行窗口来运行。

更详实的代码讲解和演示调试过程请参看视频。

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:

《内核开发:实现切换窗口后的键盘输入》 这里写图片描述

    原文作者:望月从良
    原文地址: https://www.jianshu.com/p/e8023cc68457
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞