psect->key_nr_alloc = NR_KEYS_INIT_ALLOC;
psect->keys = malloc (sizeof (char* ) * NR_KEYS_INIT_ALLOC); psect->values = malloc (sizeof (char* ) * NR_KEYS_INIT_ALLOC); } } }
return etc_GetSectionValue (psect, pKey, pValue, iLen); }
3、在InitGUI()函数中设置空闲时段的运行函数:SetDskIdleHandler
static inline void SetDskIdleHandler (IDLEHANDLER idle_handler) {
__mg_dsk_msg_queue->OnIdle = idle_handler; }
SetDskIdleHandler (IdleHandler4StandAlone); 此处将其设置为IdleHandler4StandAlone。
4、standalone模式下的空闲操作函数:IdleHandler4StandAlone
函数作用:将输入事件转换成对应的消息并放入消息队列中
BOOL IdleHandler4StandAlone (PMSGQUEUE msg_queue) {
int i, n; int rset, wset, eset; int * wsetptr = NULL; int * esetptr = NULL;
if (old_timer_counter != __mg_timer_counter) { old_timer_counter = __mg_timer_counter; SetDesktopTimerFlag (); }
rset = mg_rfdset; /* rset gets modified each time around */ if (mg_wfdset) { wset = *mg_wfdset; wsetptr = &wset; }
if (mg_efdset) { eset = *mg_efdset; esetptr = &eset; }
n = IAL_WaitEvent (IAL_MOUSEEVENT | IAL_KEYEVENT, mg_maxfd, &rset, wsetptr, esetptr, NULL);
if (msg_queue == NULL) msg_queue = __mg_dsk_msg_queue;
if (n < 0) {//表示等待事件函数IAL_WaitEvent中出错
/* It is time to check event again. */
if (errno == EINTR) {//出错类型为中断,则解析消息队列 //if (msg_queue)
ParseEvent (msg_queue, 0); }
return FALSE; } /*
else if (msg_queue == NULL) return (n > 0); */
/* handle intput event (mouse/touch-screen or keyboard) */ //等待事件为鼠标事件,解析消息队列
if (n & IAL_MOUSEEVENT) ParseEvent (msg_queue, IAL_MOUSEEVENT); //等待事件为键盘事件,解析消息队列
if (n & IAL_KEYEVENT) ParseEvent (msg_queue, IAL_KEYEVENT); //等待事件为超时事件,解析消息队列
if (n == 0) ParseEvent (msg_queue, 0);
/* go through registered listen fds */
for (i = 0; i < MAX_NR_LISTEN_FD; i++) { MSG Msg;
Msg.message = MSG_FDEVENT;
if (mg_listen_fds [i].fd) { fd_set* temp = NULL;
int type = mg_listen_fds [i].type;
switch (type) { case POLLIN: temp = &rset; break; case POLLOUT: temp = wsetptr; break; case POLLERR: temp = esetptr;
break; } } }
return (n > 0); }
5、输入等待事件: IAL_WaitEvent
1、输入引擎的选用
#define IAL_WaitEvent (*__mg_cur_input->wait_event) 当前为qvfb输入引擎的wait_event,位于qvfbial.c中
2、相关数据结构
typedef struct {
/* XPG4.2 requires this member name. Otherwise avoid the name from the global namespace. */ #ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; # define __FDS_BITS(set) ((set)->fds_bits) #else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS]; # define __FDS_BITS(set) ((set)->__fds_bits) #endif } fd_set;
FD_ZERO,FD_SET,FD_CLR,FD_ISSET:
FD_ZERO(fd_set *fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。 FD_CLR(fd_set *fdset);用于在文件描述符集合中删除一个文件描述符。
FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中。
('fd_set') 是一组文件描述符(fd)的集合。由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量: fd_set set;
FD_ZERO(&set); /* 将set清零 */ FD_SET(fd, &set); /* 将fd加入set */
FD_CLR(fd, &set); /* 将fd从set中清除 */
FD_ISSET(fd, &set); /* 如果fd在set中则真 */
struct timeval结构:
struct timeval{
long tv_sec;//second
long tv_usec;//minisecond
}
Static __inline__ void __set_bit(int nr, volatile void * addr) {
__asm__( \ :\ :\ }
btsl功能是将(*addr)的第 nr 位设为 1。第一个占位符%0 与 C 语言变量 ADDR 对应,第二个占位符%1 与 C 语言变量 nr 对应。因此上面的汇编语句代码与下面的伪代码等价:btsl nr, ADDR,该指令的两个操作数不能全是内存变量,因此将 nr 的限定字符串指定为“Ir”,将 nr 与立即数或者寄存器相关联,这样两个操作数中只有 ADDR 为内存变量。 汇编语句btrl的作用是对操作数的一个位进行清 除。btsl的作用是对操作数的一位置1。
3、相关函数:select
int select (int nfds, fd_set *read-fds, fd_set *write-fds, fd_set *except-fds, struct timeval *timeout)
本函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用fd_set结构来表示一组等待检查的套接口。在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。有一组宏可用于对fd_set的操作。
timeout参数控制select()完成的时间。若timeout参数为空指针,则select()将一直阻塞到有一个描述字满足条件。否则的话,timeout指向一个timeval结构,其中指定了select()调用在返回前等待多长时间。如果timeval为{0,0},则select()立即返回,这可用于探询所选套接口的状态。如果处于这种状态,则select()调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它。
使用select函数的过程一般是:
先调用宏FD_ZERO将指定的fd_set清零,然后调用宏FD_SET将需要测试的fd加入fd_set,接着调用函数select测试fd_set中的所有fd,最后用宏FD_ISSET检查某个fd在函数select调用后,相应位是否仍然为1。
select()调用的返回值:
(1)正常情况下返回处于就绪状态并且已经包含在fd_set结构中的描述字总数; (2)如果超时则返回0;
(3)否则的话,返回-1。有以下几种错误情况:
EBADF One of the file descriptor sets specified an invalid file descriptor. EINTR The operation was interrupted by a signal. . EINVAL
The timeout argument is invalid; one of the components is negative or too large.
4、wait_event函数分析
函数参数:
(1)第一个参数表示等待事件的类型,在此为IAL_MOUSEEVENT|IAL_KEYEVENT,表示等待的事件类型为鼠标事件或者键盘事件。
(2)第二个参数表示需要监视的最大的文件描述符值+1。 (3)第三个参数表示需要检测的可读文件描述符的集合。
(4)第四个参数表示可写文件描述符的集合 (5)第五个参数表示异常文件描述符的集合
(6)第六个参数struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。 函数返回值:
(1)如果处于就绪状态并且已经包含在fd_set结构中的描述符总数大于0,返回retvalue=
IAL_MOUSEEVENT| IAL_KEYEVENT,此值大于0 (2)e<0,表示出现错误,返回-1
static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except, struct timeval *timeout) {
fprintf(stderr,\); fd_set rfds; int retvalue = 0; int fd, e;
if (!in) { //如果可读文件描述符集合为空 in = &rfds; //设置可读文件描述符指向rfds
FD_ZERO (in);//将rfds对应的内存空间的文件描述符清空 }
//如果事件类型为鼠标事件且鼠标的文件描述符mouse_fd >= 0 if (which & IAL_MOUSEEVENT && mouse_fd >= 0) { fd = mouse_fd; //文件描述符等于鼠标文件描述符 FD_SET (fd, in); //将文件描述符fd加入到可读文件描述符中 #ifdef _LITE_VERSION //如果为非多线程模式,
if (fd > maxfd) maxfd = fd; //如果文件描述符大于最大文件描述符大于0, #endif }
//如果事件类型为键盘事件且键盘的文件描述符kbd_fd >= 0 if (which & IAL_KEYEVENT && kbd_fd >= 0) { fd = kbd_fd; //文件描述符等于鼠标文件描述符
FD_SET (kbd_fd, in); //将文件描述符fd加入到可读文件描述符中 #ifdef _LITE_VERSION
if (fd > maxfd) maxfd = fd; //如果文件描述符大于最大文件描述符 #endif
}
//将处于就绪状态并且已经包含在fd_set结构中的描述符总数赋给e e = select (maxfd + 1, in, out, except, timeout) ; if (e > 0) {//如果e大于0
fd = mouse_fd; //设置文件描述符为鼠标描述符 /* If data is present on the mouse fd, service it: */
if (fd >= 0 && FD_ISSET (fd, in)) { //如果fd大于0且位于可读文件描述符集中 FD_CLR (fd, in); //从可读文件描述符集中删除该描述符
retvalue |= IAL_MOUSEEVENT; //返回值设为包含IAL_MOUSEEVENT
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库minigui代码分析(6)在线全文阅读。
相关推荐: