4 提高窗口移动速度(4)(harib23d)

虽说窗口移动的速度已经快了很多,但还是无法完全跟上鼠标指针那矫健的身影(啊,在真机环境下当然还是跟得上的,这里是说在QEMU中运行的情形,大家别误会哦)。更进一步的提速我们现在还做不到,不过我们可以动点脑筋,在真正的速度不变的情况下,给用户带来好像变快了的错觉(笑)。

说起来,用“纸娃娃系统”之所以会感到速度慢,是因为移动窗口的时候,窗口移动的速度赶不上鼠标的速度,在放开鼠标键之后窗口还在那里挪动,因此我们只要针对这个现象想想办法就可以了。

为什么明明已经放开了鼠标键,窗口却还在挪动呢?这是因为伴随图层移动所进行的绘图操作非常消耗时间,导致系统来不及处理FIFO中的鼠标移动数据。那么我们可以在接收到鼠标移动数据后不立即进行绘图操作,但如果一直不绘图的话鼠标和窗口就静止不动了,那不就没意义了吗?我们可以等FIFO为空时再进行绘图操作嘛。

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. int mx, my, i, new_mx = -1, new_my = 0, new_wx = 0x7fffffff, new_wy = 0; /*这里!*/
  5. (中略)
  6. for (;;) {
  7. (中略)
  8. if (fifo32_status(&fifo) == 0) {
  9. /* FIFO为空,当存在搁置的绘图操作时立即执行*/ /*从此开始*/
  10. if (new_mx >= 0) {
  11. io_sti();
  12. sheet_slide(sht_mouse, new_mx, new_my);
  13. new_mx = -1;
  14. } else if (new_wx != 0x7fffffff) {
  15. io_sti();
  16. sheet_slide(sht, new_wx, new_wy);
  17. new_wx = 0x7fffffff;
  18. } else {
  19. task_sleep(task_a);
  20. io_sti();
  21. } /*到此结束*/
  22. } else {
  23. (中略)
  24. } else if (512 <= i && i <= 767) { /*到此结束*/
  25. if (mouse_decode(&mdec, i - 512) != 0) {
  26. (中略)
  27. new_mx = mx; /*这里!*/
  28. new_my = my; /*这里!*/
  29. if ((mdec.btn & 0x01) != 0) {
  30. /*按下鼠标左键*/
  31. if (mmx < 0) {
  32. (中略)
  33. for (j = shtctl->top - 1; j > 0; j--) {
  34. (中略)
  35. if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
  36. if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
  37. (中略)
  38. if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) {
  39. mmx = mx; /*切换到窗口移动模式*/
  40. mmy = my;
  41. mmx2 = sht->vx0;
  42. new_wy = sht->vy0; /*这里!*/
  43. }
  44. (中略)
  45. }
  46. }
  47. }
  48. } else {
  49. /*如果处于窗口移动模式*/
  50. x = mx - mmx; /*计算鼠标指针移动量*/
  51. y = my - mmy;
  52. new_wx = (mmx2 + x + 2) & ~3; /*这里!*/
  53. new_wy = new_wy + y; /*这里!*/
  54. mmy = my; /*更新到移动后的坐标*/
  55. }
  56. } else {
  57. /*没有按下鼠标左键*/
  58. mmx = -1; /*切换到一般模式*/
  59. if (new_wx != 0x7fffffff) { /*从此开始*/
  60. sheet_slide(sht, new_wx, new_wy); /*固定图层位置*/
  61. new_wx = 0x7fffffff;
  62. } /*到此结束*/
  63. }
  64. }
  65. }
  66. }
  67. }
  68. }

这次我们增加了new_mx和new_wy两个变量,并将原来的sheet_slide(sht_mouse, mx, my);改成了new_mx = mx; new_my = my;,也就是说,我们并不真的移动鼠标图层的位置,而是将移动后的坐标暂且保存起来,当FIFO为空时,再执行sheet_slide(sht_mouse, new_mx, new_my);。

窗口移动我们也采用相同的方法,只不过有一点小小的区别,代表FIFO为空时不需要执行sheet_slide的值从-1变成了0x7fffffff,这是因为鼠标的坐标不可能为负数,但窗口的坐标却有可能为负数,因此用-1会造成歧义,我们只好改用另外一个不可能会出现的值,即0x7fffffff。

当放开鼠标左键退出窗口移动模式时,即便FIFO不为空也需要立即更新窗口的位置,这是因为用户可能马上会去移动别的窗口,那样的话sht变量的值就会发生变化,因此我们必须在sht变量的值改变之前将当前窗口移动到指定的位置。

■■■■■

好了,我们来“make run”……哇!即便在CPU很慢的电脑上用QEMU运行我们的系统,窗口也能跟鼠标同步快速移动,太好了!

4 提高窗口移动速度(4)(harib23d) - 图1

截图上看不出来,不过跟鼠标完全同步