;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; ;; Distributed under terms of the GNU General Public License ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ align 4 init_events: stdcall kernel_alloc, 512*EVENT_SIZE mov [events], eax xor eax, eax mov [event_uid], eax not eax mov edi, event_map mov [event_start], edi mov ecx, 64/4 cld rep stosd mov [event_end], edi ret align 4 proc alloc_event pushfd cli mov ebx, [event_start] mov ecx, [event_end] .l1: bsf eax,[ebx] jnz .found add ebx,4 cmp ebx, ecx jb .l1 popfd xor eax,eax ret .found: btr [ebx], eax mov [event_start],ebx inc [event_uid] sub ebx, event_map lea eax,[eax+ebx*8] lea ebx, [eax+eax*4] shl eax,5 lea eax,[eax+ebx*4] ;eax*=52 (EVENT_SIZE) add eax, [events] mov ebx, [event_uid] popfd ret endp align 4 free_event: sub eax, [events] mov ecx, EVENT_SIZE mov ebx, event_map cdq div ecx pushfd cli bts [ebx], eax shr eax, 3 and eax, not 3 add eax, ebx cmp [event_start], eax ja @f popfd ret @@: mov [event_start], eax popfd ret EVENT_WATCHED equ 0x10000000 EVENT_SIGNALED equ 0x20000000 MANUAL_RESET equ 0x40000000 MANUAL_DESTROY equ 0x80000000 ; param ; eax= event data ; ebx= flags ; ; retval ; eax= event ; edx= id create_event: .flags equ esp+4 .data equ esp push ebx push eax call alloc_event test eax, eax jz .fail mov [eax+APPOBJ.magic], 'EVNT' mov [eax+APPOBJ.destroy], destroy_event.internal mov [eax+EVENT.id], ebx mov ebx, [CURRENT_TASK] shl ebx, 5 mov ebx, [CURRENT_TASK+ebx+4] mov [eax+APPOBJ.pid], ebx mov edx, [.flags] mov [eax+EVENT.state], edx mov esi, [.data] test esi, esi jz @F lea edi, [eax+EVENT.code] mov ecx, 6 cld rep movsd @@: mov ecx, [current_slot] add ecx, APP_OBJ_OFFSET pushfd cli mov edx, [ecx+APPOBJ.fd] mov [eax+APPOBJ.fd], edx mov [eax+APPOBJ.bk], ecx mov [ecx+APPOBJ.fd], eax mov [edx+APPOBJ.bk], eax popfd mov edx, [eax+EVENT.id] .fail: add esp, 8 ret restore .flags restore .data ; param ; eax= event ; ebx= id destroy_event: cmp [eax+APPOBJ.magic], 'EVNT' jne .fail cmp [eax+EVENT.id], ebx jne .fail .internal: mov ebx, [eax+APPOBJ.fd] mov ecx, [eax+APPOBJ.bk] mov [ebx+APPOBJ.bk], ecx mov [ecx+APPOBJ.fd], ebx .force: xor edx, edx ;clear common header mov [eax], edx mov [eax+4], edx mov [eax+8], edx mov [eax+12], edx mov [eax+16], edx call free_event ;release object memory .fail: ret align 4 proc send_event stdcall pid:dword, event:dword locals slot dd ? endl mov eax, [pid] call pid_to_slot test eax, eax jz .fail shl eax, 8 cmp [SLOT_BASE+eax+APPDATA.ev_count], 32 ja .fail mov [slot], eax call alloc_event test eax, eax jz .fail lea edi, [eax+EVENT.code] mov ecx, 6 mov esi, [event] cld rep movsd mov ecx, [slot] add ecx, SLOT_BASE+APP_EV_OFFSET mov [eax+APPOBJ.magic], 'EVNT' mov [eax+APPOBJ.destroy], destroy_event mov ebx, [pid] mov [eax+APPOBJ.pid], ebx mov [eax+EVENT.state], EVENT_SIGNALED pushfd cli ;insert event into mov edx, [ecx+APPOBJ.fd] ;events list mov [eax+APPOBJ.fd], edx ;and set events flag mov [eax+APPOBJ.bk], ecx mov [ecx+APPOBJ.fd], eax mov [edx+APPOBJ.bk], eax inc [ecx+APPDATA.ev_count-APP_EV_OFFSET] or [ecx+APPDATA.event_mask-APP_EV_OFFSET], EVENT_EXTENDED popfd .fail: ret endp ; timeout ignored align 4 proc get_event_ex stdcall, p_ev:dword, timeout:dword .wait: mov edx,[current_slot] ; cmp [SLOT_BASE+edx+APPDATA.ev_count], 0 ; je .switch add edx, APP_EV_OFFSET mov eax, [edx+APPOBJ.fd] cmp eax, edx je .switch lea esi, [eax+EVENT.code] mov edi, [p_ev] ;copy event data mov ecx, 6 cld rep movsd and dword [edi-24], 0xFF00FFFF ;clear priority field ; test [eax+EVENT.state], MANUAL_RESET jnz .done pushfd cli ;remove event from events mov ebx, [eax+APPOBJ.fd] ;list (reset event) mov ecx, [eax+APPOBJ.bk] ;and clear events flag mov [ebx+APPOBJ.bk], ecx ;if no active events mov [ecx+APPOBJ.fd], ebx and [eax+EVENT.state], not (EVENT_SIGNALED+EVENT_WATCHED) dec [edx+APPDATA.ev_count-APP_EV_OFFSET] jnz @F and [edx+APPDATA.event_mask-APP_EV_OFFSET], not EVENT_EXTENDED @@: popfd test [eax+EVENT.state], MANUAL_DESTROY jz .destroy add edx, (APP_OBJ_OFFSET-APP_EV_OFFSET) pushfd cli mov ebx, [edx+APPOBJ.fd] ;insert event into mov [eax+APPOBJ.fd], ebx ;objects list mov [eax+APPOBJ.bk], edx mov [edx+APPOBJ.fd], eax mov [ebx+APPOBJ.bk], eax popfd .done: ret .destroy: call destroy_event.force ret .switch: mov eax, [TASK_BASE] mov [eax+TASKDATA.state], byte 5 call change_task jmp .wait endp ; param ; eax= event ; ebx= id align 4 wait_event: .event equ esp push eax .wait: cmp [eax+APPOBJ.magic], 'EVNT' jne .done cmp [eax+EVENT.id], ebx jne .done test [eax+EVENT.state], EVENT_SIGNALED jz .switch test [eax+EVENT.state], MANUAL_RESET jnz .done mov edx,[current_slot] pushfd cli ;remove event from events mov ebx, [eax+APPOBJ.fd] ;list (reset event) mov ecx, [eax+APPOBJ.bk] ;and clear events flag mov [ebx+APPOBJ.bk], ecx ;if no active events mov [ecx+APPOBJ.fd], ebx dec [edx+APPDATA.ev_count] jnz @F and [edx+APPDATA.event_mask], not EVENT_EXTENDED @@: and [eax+EVENT.state], not (EVENT_SIGNALED+EVENT_WATCHED) popfd test [eax+EVENT.state], MANUAL_DESTROY jz .destroy add edx, APP_OBJ_OFFSET pushfd cli mov ecx, [edx+APPOBJ.fd] ;insert event into mov [eax+APPOBJ.fd], ecx ;objects list mov [eax+APPOBJ.bk], edx mov [edx+APPOBJ.fd], eax mov [ecx+APPOBJ.bk], eax popfd .done: add esp, 4 ret .destroy: call destroy_event.force add esp, 4 ret .switch: or [eax+EVENT.state], EVENT_WATCHED mov eax, [TASK_BASE] mov [eax+TASKDATA.state], byte 5 call change_task mov eax, [.event] jmp .wait restore .event ; param ; eax= event ; ebx= id ; ecx= flags ; edx= event data raise_event: .event equ esp push eax cmp [eax+APPOBJ.magic], 'EVNT' jne .fail cmp [eax+EVENT.id], ebx jne .fail mov eax, [eax+APPOBJ.pid] call pid_to_slot test eax, eax jz .fail mov esi, edx test esi, esi mov edx, [.event] jz @F push ecx lea edi, [edx+EVENT.code] mov ecx, 6 cld rep movsd pop ecx @@: test [edx+EVENT.state], EVENT_SIGNALED jnz .done test ecx, EVENT_WATCHED jz @F test [edx+EVENT.state], EVENT_WATCHED jz .done @@: shl eax, 8 add eax, SLOT_BASE+APP_EV_OFFSET pushfd cli mov ebx, [edx+APPOBJ.fd] mov ecx, [edx+APPOBJ.bk] mov [ebx+APPOBJ.bk], ecx mov [ecx+APPOBJ.fd], ebx mov ecx, [eax+APPOBJ.fd] mov [edx+APPOBJ.fd], ecx mov [edx+APPOBJ.bk], eax mov [eax+APPOBJ.fd], edx mov [ecx+APPOBJ.bk], edx or [edx+EVENT.state], EVENT_SIGNALED inc [eax+APPDATA.ev_count-APP_EV_OFFSET] or [eax+APPDATA.event_mask-APP_EV_OFFSET], EVENT_EXTENDED popfd .fail: .done: add esp, 4 ret restore .event ; param ; eax= event ; ebx= id align 4 clear_event: .event equ esp push eax cmp [eax+APPOBJ.magic], 'EVNT' jne .fail cmp [eax+EVENT.id], ebx jne .fail mov eax, [eax+APPOBJ.pid] call pid_to_slot test eax, eax jz .fail shl eax, 8 add eax, SLOT_BASE+APP_EV_OFFSET mov edx, [.event] pushfd cli ;remove event from events mov ebx, [edx+APPOBJ.fd] ;list (reset event) mov ecx, [edx+APPOBJ.bk] ;and clear events flag mov [ebx+APPOBJ.bk], ecx ;if no active events mov [ecx+APPOBJ.fd], ebx and [edx+EVENT.state], not (EVENT_SIGNALED+EVENT_WATCHED) dec [eax+APPDATA.ev_count-APP_EV_OFFSET] jnz @F and [eax+APPDATA.event_mask-APP_EV_OFFSET], not EVENT_EXTENDED @@: add eax, (APP_OBJ_OFFSET-APP_EV_OFFSET) mov ecx, [eax+APPOBJ.fd] ;insert event into mov [edx+APPOBJ.fd], ecx ;objects list mov [edx+APPOBJ.bk], eax mov [eax+APPOBJ.fd], edx mov [ecx+APPOBJ.bk], edx popfd .fail: .done: add esp, 4 ret restore .event sys_getevent: call get_event_for_app mov [esp + 32],eax ret sys_waitforevent: or ebx, 0xFFFFFFFF ; infinite timeout jmp @f sys_wait_event_timeout: add ebx, [timer_ticks] @@: mov eax, [current_slot] mov [eax + APPDATA.wait_timeout], ebx call get_event_for_app test eax, eax jnz eventoccur mov eax, [TASK_BASE] mov [eax+TASKDATA.state], byte 5 call change_task mov eax, [event_sched] eventoccur: mov [esp+32], eax ret sys_sendwindowmsg: dec eax jnz .ret cmp ebx, 3 jz .sendbtn cmp ebx, 2 jnz .ret .sendkey: pushf cli movzx eax, byte [KEY_COUNT] cmp al, 120 jae .overflow inc eax mov [KEY_COUNT], al mov [KEY_COUNT+eax], cl jmp .ok .overflow: popf mov dword [esp+36], 1 ret .sendbtn: pushf cli cmp byte [BTN_COUNT], 0 jnz .overflow mov byte [BTN_COUNT], 1 mov [BTN_BUFF], ecx .ok: popf and dword [esp+36], 0 .ret: ret get_event_for_app: pushad mov edi,[TASK_BASE] ; WINDOW REDRAW test [edi+TASKDATA.event_mask], 1 jz no_eventoccur1 ;mov edi,[TASK_BASE] cmp [edi-twdw+WDATA.fl_redraw],byte 0 je no_eventoccur1 popad mov eax,1 ret no_eventoccur1: ;mov edi,[TASK_BASE] ; KEY IN BUFFER test [edi+TASKDATA.event_mask],dword 2 jz no_eventoccur2 mov ecx, [CURRENT_TASK] movzx edx,word [WIN_STACK+ecx*2] mov eax, [TASK_COUNT] cmp eax,edx jne no_eventoccur2x cmp [KEY_COUNT],byte 0 je no_eventoccur2x eventoccur2: popad mov eax,2 ret no_eventoccur2x: mov eax, hotkey_buffer @@: cmp [eax], ecx jz eventoccur2 add eax, 8 cmp eax, hotkey_buffer+120*8 jb @b no_eventoccur2: ;mov edi,[TASK_BASE] ; BUTTON IN BUFFER test [edi+TASKDATA.event_mask],dword 4 jz no_eventoccur3 cmp [BTN_COUNT],byte 0 je no_eventoccur3 mov ecx, [CURRENT_TASK] movzx edx, word [WIN_STACK+ecx*2] mov eax, [TASK_COUNT] cmp eax,edx jnz no_eventoccur3 popad mov eax,[BTN_BUFF] cmp eax,65535 je no_event_1 mov eax,3 ret no_event_1: mov [window_minimize],1 mov [BTN_COUNT],byte 0 xor eax, eax ret no_eventoccur3: ;mov edi,[TASK_BASE] ; mouse event mov eax, [CURRENT_TASK] shl eax, 8 add eax, SLOT_BASE test [edi+TASKDATA.event_mask],dword 00100000b jz no_mouse_event test [eax+APPDATA.event_mask],dword 00100000b jz no_mouse_event and [eax+APPDATA.event_mask],dword (not 00100000b) popad mov eax,6 ret no_mouse_event: ;mov edi,[TASK_BASE] ; DESKTOP BACKGROUND REDRAW test [edi+TASKDATA.event_mask], 16 jz no_eventoccur5 ; cmp [REDRAW_BACKGROUND],byte 2 ; jnz no_eventoccur5 test [eax+APPDATA.event_mask], 16 jz no_eventoccur5 and [eax+APPDATA.event_mask], not 16 popad mov eax,5 ret no_eventoccur5: ;mov edi,[TASK_BASE] ; IPC test [edi+TASKDATA.event_mask],dword 01000000b jz no_ipc test [eax+APPDATA.event_mask],dword 01000000b jz no_ipc and [eax+APPDATA.event_mask],dword 0xffffffff-01000000b popad mov eax,7 ret no_ipc: ;mov edi,[TASK_BASE] ; STACK test [edi+TASKDATA.event_mask],dword 10000000b jz no_stack_event test [eax+APPDATA.event_mask],dword 10000000b jz no_stack_event and [eax+APPDATA.event_mask],dword 0xffffffff-10000000b popad mov eax,8 ret no_stack_event: test byte [edi+TASKDATA.event_mask+1], 1 ; DEBUG jz .test_IRQ test byte [eax+APPDATA.event_mask+1], byte 1 jz .test_IRQ and byte [eax+APPDATA.event_mask+1], not 1 popad mov eax, 9 ret ;.test_ext: ; mov eax, [CURRENT_TASK] ; shl eax, 8 ; test dword [eax+SLOT_BASE+APPDATA.event_mask], EVENT_EXTENDED ; jz .test_IRQ ; popad ; mov eax, 10 ; ret .test_IRQ: cmp dword [edi+TASKDATA.event_mask], 0xFFFF jbe no_events mov esi,IRQ_SAVE ; IRQ'S AND DATA mov ebx,0x00010000 xor ecx, ecx irq_event_test: mov edi,[TASK_BASE] test [edi+TASKDATA.event_mask],ebx jz no_irq_event mov edi,ecx shl edi,2 add edi,irq_owner mov edx,[edi] mov eax,[TASK_BASE] mov eax,[eax+TASKDATA.pid] cmp edx,eax jne no_irq_event cmp [esi],dword 0 jz no_irq_event mov eax,ecx add eax,16 mov [esp+28],eax popad ret no_irq_event: add esi,0x1000 shl ebx,1 inc ecx cmp ecx,16 jb irq_event_test no_events: popad xor eax, eax ret