📄 minigui 体系结构之四 图形抽象层和输入抽象层及 native engine 的实现(一).htm
字号:
309
310 pClipRect = pClipRect->next;
311 }
312
313 if (!dc_IsMemHDC (hdc)) ShowCursorForGDI (TRUE, &rcOutput);
314 }
</PRE></TD></TR></TBODY></TABLE>
<P>在 MiniGUI 的所有绘图函数中,要依次做如下几件事:</P>
<OL>
<LI>进行逻辑坐标到设备坐标的转换;
<LI>检查是否应该重新生成有效剪切域;
<LI>计算输出矩形,并判断是否隐藏鼠标;
<LI>由于底层引擎尚不支持剪切域,因此,对剪切域中的每个剪切矩形,调用底层绘图函数输出一次。 </LI></OL>
<P>在上面的四个步骤当中,第 3 步和第 4 步实际可以放到底层引擎当中,从而能够大大提高 MiniGUI
的绘图效率。不过,这种性能上的提高,对块输出,比如填充矩形、输出位图来讲,并不是非常明显。在将来的底层图形引擎当中,我们将针对上述两点,进行较大的优化以提高图形输出效率。</P><STRONG>2.2
IAL 和输入引擎</STRONG>
<P>如前所属,MiniGUI IAL 结构和 GAL 结构类似。在代码实现上,MiniGUI 通过 INPUT数据结构来表示输入引擎,见清单
3。</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 清单 3 MiniGUI 中的输入引擎结构(src/include/ial.h)
34 typedef struct tagINPUT
35 {
36 char* id;
37
38 // Initialization and termination
39 BOOL (*init_input) (struct tagINPUT *input, const char* mdev, const char* mtype);
40 void (*term_input) (void);
41
42 // Mouse operations
43 int (*update_mouse) (void);
44 int (*get_mouse_x) (void);
45 int (*get_mouse_y) (void);
46 void (*set_mouse_xy) (int x, int y);
47 int (*get_mouse_button) (void);
48 void (*set_mouse_range) (int minx, int miny,int maxx,int maxy);
49
50 // Keyboard operations
51 int (*update_keyboard) (void);
52 char* (*get_keyboard_state) (void);
53 void (*suspend_keyboard) (void);
54 void (*resume_keyboard) (void);
55 void (*set_leds) (unsigned int leds);
56
57 // Event
58 #ifdef _LITE_VERSION
59 int (*wait_event) (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
60 struct timeval *timeout);
61 #else
62 int (*wait_event) (int which, fd_set *in, fd_set *out, fd_set *except,
63 struct timeval *timeout);
64 #endif
65 }INPUT;
66
67 extern INPUT* cur_input;
</PRE></TD></TR></TBODY></TABLE>
<P>系统启动之后,将根据配置寻找特定的输入引擎作为当前的输入引擎,并且对全局变量 cur_input 赋值。</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE>(*cur_gfx->drawhline) (gc, x, y, w, pixel);
</PRE></TD></TR></TBODY></TABLE>
<P>为方便程序书写,我们还定义了如下 C 语言宏:</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 69 #define IAL_InitInput (*cur_input->init_input)
70 #define IAL_TermInput (*cur_input->term_input)
71 #define IAL_UpdateMouse (*cur_input->update_mouse)
72 #define IAL_GetMouseX (*cur_input->get_mouse_x)
73 #define IAL_GetMouseY (*cur_input->get_mouse_y)
74 #define IAL_SetMouseXY (*cur_input->set_mouse_xy)
75 #define IAL_GetMouseButton (*cur_input->get_mouse_button)
76 #define IAL_SetMouseRange (*cur_input->set_mouse_range)
77
78 #define IAL_UpdateKeyboard (*cur_input->update_keyboard)
79 #define IAL_GetKeyboardState (*cur_input->get_keyboard_state)
80 #define IAL_SuspendKeyboard (*cur_input->suspend_keyboard)
81 #define IAL_ResumeKeyboard (*cur_input->resume_keyboard)
82 #define IAL_SetLeds(leds) if (cur_input->set_leds) (*cur_input->set_leds) (leds)
83
84 #define IAL_WaitEvent (*cur_input->wait_event)
</PRE></TD></TR></TBODY></TABLE>
<P>在 src/kernel/event.c 中,我们如下调用底层的输入引擎,从而将输入引擎的数据转换为 MiniGUI 上层能够理解的消息(以
MiniGUI-Lite 为例),见清单 4:</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 清单 4 MiniGUI 对底层输入事件的处理
172 #ifdef _LITE_VERSION
173 BOOL GetLWEvent (int event, PLWEVENT lwe)
174 {
175 static LWEVENT old_lwe = {0, 0};
176 unsigned int interval;
177 int button;
178 PMOUSEEVENT me = &(lwe->data.me);
179 PKEYEVENT ke = &(lwe->data.ke);
180 unsigned char* keystate;
181 int i;
182 int make; /* 0 = release, 1 = presse */
183
184 if (event == 0) {
185 if (timer_counter >= timeout_count) {
186
187 timeout_count = timer_counter + repeat_threshold;
188
189 // repeat last event
190 if (old_lwe.type == LWETYPE_KEY
191 && old_lwe.data.ke.event == KE_KEYDOWN) {
192 memcpy (lwe, &old_lwe, sizeof (LWEVENT));
193 lwe->data.ke.status |= KE_REPEATED;
194 return 1;
195 }
196
197 if (!(old_lwe.type == LWETYPE_MOUSE
198 && (old_lwe.data.me.event == ME_LEFTDOWN ||
199 old_lwe.data.me.event == ME_RIGHTDOWN ||
200 old_lwe.data.me.event == ME_MIDDLEDOWN))) {
201 // reset delay time
202 timeout_count = timer_counter + timeout_threshold;
203 }
204
205 // reset delay time
206 lwe->type = LWETYPE_TIMEOUT;
207 lwe->count = timer_counter;
208 return 1;
209 }
210 return 0;
211 }
212
213 timeout_count = timer_counter + timeout_threshold;
214 // There was a event occurred.
215 if (event & IAL_MOUSEEVENT) {
216 lwe->type = LWETYPE_MOUSE;
217 if (RefreshCursor(&me->x, &me->y, &button)) {
218 me->event = ME_MOVED;
219 time1 = 0;
220 time2 = 0;
221
222 if (oldbutton == button)
223 return 1;
224 }
225
226 if ( !(oldbutton & IAL_MOUSE_LEFTBUTTON) &&
227 (button & IAL_MOUSE_LEFTBUTTON) )
228 {
229 if (time1) {
230 interval = timer_counter - time1;
231 if (interval <= dblclicktime)
232 me->event = ME_LEFTDBLCLICK;
233 else
234 me->event = ME_LEFTDOWN;
235 time1 = 0;
236 }
237 else {
238 time1 = timer_counter;
239 me->event = ME_LEFTDOWN;
240 }
241 goto mouseret;
242 }
243
244 if ( (oldbutton & IAL_MOUSE_LEFTBUTTON) &&
245 !(button & IAL_MOUSE_LEFTBUTTON) )
246 {
247 me->event = ME_LEFTUP;
248 goto mouseret;
249 }
250
251 if ( !(oldbutton & IAL_MOUSE_RIGHTBUTTON) &&
252 (button & IAL_MOUSE_RIGHTBUTTON) )
253 {
254 if (time2) {
255 interval = timer_counter - time2;
256 if (interval <= dblclicktime)
257 me->event = ME_RIGHTDBLCLICK;
258 else
259 me->event = ME_RIGHTDOWN;
260 time2 = 0;
261 }
262 else {
263 time2 = timer_counter;
264 me->event = ME_RIGHTDOWN;
265 }
266 goto mouseret;
267 }
268
269 if ( (oldbutton & IAL_MOUSE_RIGHTBUTTON) &&
270 !(button & IAL_MOUSE_RIGHTBUTTON) )
271 {
272 me->event = ME_RIGHTUP;
273 goto mouseret;
274 }
275 }
276
277 if(event & IAL_KEYEVENT) {
278 lwe->type = LWETYPE_KEY;
279 keystate = IAL_GetKeyboardState ();
280 for(i = 0; i < NR_KEYS; i++) {
281 if(!oldkeystate[i] && keystate[i]) {
282 ke->event = KE_KEYDOWN;
283 ke->scancode = i;
284 olddownkey = i;
285 break;
286 }
287 if(oldkeystate[i] && !keystate[i]) {
288 ke->event = KE_KEYUP;
289 ke->scancode = i;
290 break;
291 }
292 }
293 if (i == NR_KEYS) {
294 ke->event = KE_KEYDOWN;
295 ke->scancode = olddownkey;
296 }
297
298 make = (ke->event == KE_KEYDOWN)?1:0;
299
300 if (i != NR_KEYS) {
301 unsigned leds;
302
303 switch (ke->scancode) {
304 case SCANCODE_CAPSLOCK:
305 if (make && caps_off) {
306 capslock = 1 - capslock;
307 leds = slock | (numlock << 1) | (capslock << 2);
308 IAL_SetLeds (leds);
309 status = (DWORD)leds << 16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -