Last active
September 11, 2018 01:08
-
-
Save frednora/3a01f0e761d9f52ebe552c6aa5480abf to your computer and use it in GitHub Desktop.
mouse support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gist para a rotina de mouse. | |
// | |
// ************* C ********************* | |
// | |
//======================================================= | |
//++ Usadas pelo mouse. | |
// hardwarelib.inc | |
// | |
#define MOUSE_X_SIGN 0x10 | |
#define MOUSE_Y_SIGN 0x20 | |
//Coordenadas do cursor. | |
extern int mouse_x; | |
extern int mouse_y; | |
//Bytes do controlador. | |
extern char mouse_packet_data; | |
extern char mouse_packet_x; | |
extern char mouse_packet_y; | |
//extern char mouse_packet_scroll; | |
extern void update_mouse(); | |
//Estado dos botões do mouse | |
int mouse_buttom_1; | |
int mouse_buttom_2; | |
int mouse_buttom_3; | |
//Estado anterior dos botões do mouse. | |
int old_mouse_buttom_1; | |
int old_mouse_buttom_2; | |
int old_mouse_buttom_3; | |
//se ouve alguma modificação no estado | |
//dos botões. | |
int mouse_button_action; | |
//-- | |
//========================================================= | |
//?? usado pelo mouse | |
#define outanyb(p) __asm__ __volatile__( "outb %%al,%0" : : "dN"((p)) : "eax" ) | |
/* | |
************** | |
* mouseHandler: | |
* Handler de mouse. | |
* | |
* *Importante: | |
* Se estamos aqui é porque os dados disponíveis no | |
* controlador 8042 pertencem ao mouse. | |
* | |
* @todo: Essa rotina não pertence ao line discipline. | |
* Obs: Temos externs no início desse arquivo. | |
* | |
*/ | |
#define MOUSE_DATA_BIT 1 | |
#define MOUSE_SIG_BIT 2 | |
#define MOUSE_F_BIT 0x20 | |
#define MOUSE_V_BIT 0x08 | |
//contador | |
static int count_mouse = 0; | |
// Buffer. | |
static char buffer_mouse[3]; | |
void mouseHandler (){ | |
// ?? #bugbug. | |
// ?? Porque isso é local. ?? | |
// ?? Não tem um contador global para isso ?? | |
// E o fato de serem 'static' ??? | |
// Obs: A função entra com esse mouse count zerado. | |
// Coordenadas do mouse. | |
// Obs: Isso pode ser global. | |
// O tratador em assembly tem as variáveis globais do posicionamento. | |
int posX=0; | |
int posY=0; | |
//Char para o cursor provisório. | |
static char mouse_char[] = "T"; | |
// | |
// Lendo um char no controlador. | |
// | |
char *_byte; | |
*_byte = (char) mouse_read(); | |
//buffer_mouse[count_mouse++] = mouse_read(); | |
// | |
// Contagem de interruções: | |
// Obs: Precisamos esperar 3 interrupções. | |
// | |
//#bugbug essa variável está inicializando toda vez que | |
//se chama o handler porque ela é interna. ?? | |
switch( count_mouse ) | |
{ | |
case 0: | |
buffer_mouse[0] = (char) *_byte; | |
if(*_byte & MOUSE_V_BIT) | |
count_mouse++; | |
break; | |
case 1: | |
buffer_mouse[1] = (char) *_byte; | |
count_mouse++; | |
break; | |
case 2: | |
buffer_mouse[2] = (char) *_byte; | |
count_mouse = 0; | |
//pega os valores dos deltas ?? | |
//mouse_x = mouse_byte[1]; | |
//mouse_y = mouse_byte[2]; | |
//isso ficará assim caso não aja overflow ... | |
mouse_packet_data = buffer_mouse[0]; | |
mouse_packet_x = buffer_mouse[1]; | |
mouse_packet_y = buffer_mouse[2]; | |
//#importante: | |
//Isso está em assembly, lá em hwlib.inc | |
//mas queremos que seja feito em C. | |
//Uma rotina interna aqui nesse arquivo está tentando isso. | |
update_mouse(); | |
mouse_x = (mouse_x & 0x00000FFF ); | |
mouse_y = (mouse_y & 0x00000FFF ); | |
// Limits. | |
if( mouse_x < 1 ){ mouse_x = 1; } | |
if( mouse_y < 1 ){ mouse_y = 1; } | |
if( mouse_x > (800-16) ){ mouse_x = (800-16); } | |
if( mouse_y > (600-16) ){ mouse_y = (600-16); } | |
// | |
// # Draw BMP # | |
// | |
//bmpDisplayBMP( mouseBMPBuffer, mouse_x, mouse_y ); | |
bmpDisplayMousePointerBMP( mouseBMPBuffer, mouse_x, mouse_y ); | |
refresh_rectangle( mouse_x, mouse_y, 16, 16 ); | |
break; | |
default: | |
count_mouse = 0; | |
break; | |
}; | |
// | |
// *importante: | |
// Esse é o memento em que enviamos a mensagem !! | |
// | |
// | |
// *importante: | |
// Devemos enviar a mensagem de mouse para quem. ?? | |
// First responder ?? (wwf) | |
// | |
// O aplicativo poderá interceptar mensgens como mouse hover. | |
// mousehover é flutuando por cima do objeto. | |
// | |
// FIRST RESPONDER | |
// | |
struct window_d *w; | |
w = (void *) windowList[window_with_focus]; | |
if( (void*) w != NULL ) | |
{ | |
// Envia as mensagens para os aplicativos intercepta-las. | |
if( w->used == 1 && w->magic == 1234 ) | |
{ | |
// ?? O que sabemos sobre o evento de mouse até aqui ?? | |
// sabemos que ele se movimentou e temos as coordenadas dele. | |
// se o mouse alcançar as coordenadas da janela com o foco de | |
// entrada podemos enviar uma mensagem para ela. assim ela | |
// pode criar uma janelinha que alerta sobre o mouse hover. | |
// essa mesagem pode ser de mouse hover. | |
//windowSendMessage( 0, 0, 0, 0); | |
}; | |
//Chama o procedimento de janelas do sistema. | |
//O procedimento de janela do terminal está em cascata. | |
//system_procedure( w, (int) 0, (unsigned long) 0, (unsigned long) 0 ); | |
}; | |
// | |
// #importante | |
// Por outro lado o mouse deve confrontar seu posicionamento com | |
// todas as janelas, para saber se as coordenadas atuais estão passando | |
// por alguma das janelas. Se estiver, então enviaremos mensagens para essa | |
// janela que o mouse passou por cima. Ela deve ser sinalizada como hover, | |
// | |
// #importante: | |
// Se houver um click, o elemento com mousehover será afetado, e enviaremos, | |
// mesagens para ele, se apertarem enter ou application key, quem | |
// recebe a mensagem é o first responder, ou seja. a janela com o focod e entrada. | |
// | |
// Se clicarmos com o botão da direita, quem recebe a mensagem é | |
// a janela que o mouse está passando por cima. | |
// | |
// | |
// ## Button ## | |
// | |
//Apenas obtendo o estado dos botões. | |
mouse_buttom_1 = 0; | |
mouse_buttom_2 = 0; | |
mouse_buttom_3 = 0; | |
if( ( mouse_packet_data & 0x01 ) == 0 ) | |
{ | |
//liberada. | |
mouse_buttom_1 = 0; | |
}else if( ( mouse_packet_data & 0x01 ) != 0 ) | |
{ | |
//pressionada. | |
//Não tem como pressionar mais de um botão por vez. | |
mouse_buttom_1 = 1; | |
mouse_buttom_2 = 0; | |
mouse_buttom_3 = 0; | |
} | |
if( ( mouse_packet_data & 0x02 ) == 0 ) | |
{ | |
//liberada. | |
mouse_buttom_2 = 0; | |
}else if( ( mouse_packet_data & 0x02 ) != 0 ) | |
{ | |
//pressionada. | |
//Não tem como pressionar mais de um botão por vez. | |
mouse_buttom_1 = 0; | |
mouse_buttom_2 = 1; | |
mouse_buttom_3 = 0; | |
} | |
if( ( mouse_packet_data & 0x04 ) == 0 ) | |
{ | |
//liberada. | |
mouse_buttom_3 = 0; | |
}else if( ( mouse_packet_data & 0x04 ) != 0 ) | |
{ | |
//pressionada. | |
//Não tem como pressionar mais de um botão por vez. | |
mouse_buttom_1 = 0; | |
mouse_buttom_2 = 0; | |
mouse_buttom_3 = 1; | |
} | |
//mouse_button_action | |
//Confrontando o estado atual com o estado anterior | |
//para saber se ouve alguma alteração ou não. | |
if( mouse_buttom_1 != old_mouse_buttom_1 || | |
mouse_buttom_2 != old_mouse_buttom_2 || | |
mouse_buttom_3 != old_mouse_buttom_3 ) | |
{ | |
//Sinalizamos que ouve alteração. | |
mouse_button_action = 1; | |
}else{ | |
mouse_button_action = 0; | |
}; | |
// | |
// #bugbug | |
// ?? E no caso de apenas considerarmos que | |
// que o mouse está se movendo, mandaremos | |
// para janela over. ??? | |
// Obs: A mensagen over pode ser enviada apenas uma vez. | |
// será usada para 'capturar' o mouse ... e depois | |
// tem a mensagem para 'descapturar'. | |
// | |
// | |
// | |
// ## On mouse over ## (capture) | |
// | |
int wID; | |
struct window_d *wScan; | |
//Escaneamos para achar qual janela bate com | |
//os valores indicados. | |
//return: (int) window id. | |
wID = (int) windowScan( mouse_x, mouse_y ); | |
//#IMPORTANTE | |
//Se for válido e diferente da atual. | |
//significa que estamos dentro de uma janela. | |
if( wID != -1 ) | |
{ | |
wScan = (struct window_d *) windowList[wID]; | |
//redraw_window(wScan); | |
//#importante | |
//Se um botão foi pressionado ou liberado, então | |
//enviaremos o uma mensagem relativa ao estado do botão | |
//caso contrário enviaremos uma mensagem sobre a movimentação | |
//do mouse. | |
//#importante | |
// Se houve mudança em relação ao estado anterior. | |
if( mouse_button_action == 1 ) | |
{ | |
//Qual botão mudou seu estado?? | |
//Checaremos um por um. | |
//1 | |
//igual ao estado anterior | |
if( mouse_buttom_1 == old_mouse_buttom_1 ) | |
{ | |
//... | |
}else{ | |
//down | |
if( mouse_buttom_1 == 1 ) | |
{ | |
//clicou | |
if( old_mouse_buttom_1 == 0 ){ | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYDOWN, (unsigned long) 1, (unsigned long) 0 ); | |
//atualiza o estado anterior. | |
old_mouse_buttom_1 = 1; | |
} | |
}else{ | |
//up | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYUP, (unsigned long) 1, (unsigned long) 0 ); | |
old_mouse_buttom_1 = 0; | |
} | |
}; | |
//2 | |
//igual ao estado anterior | |
if( mouse_buttom_2 == old_mouse_buttom_2 ) | |
{ | |
//... | |
}else{ | |
//down | |
if( mouse_buttom_2 == 1 ) | |
{ | |
//clicou | |
if( old_mouse_buttom_2 == 0 ){ | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYDOWN, (unsigned long) 2, (unsigned long) 0 ); | |
//atualiza o estado anterior. | |
old_mouse_buttom_2 = 1; | |
} | |
}else{ | |
//up | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYUP, (unsigned long) 2, (unsigned long) 0 ); | |
old_mouse_buttom_2 = 0; | |
} | |
}; | |
//3 | |
//igual ao estado anterior | |
if( mouse_buttom_3 == old_mouse_buttom_3 ) | |
{ | |
//... | |
}else{ | |
//down | |
if( mouse_buttom_3 == 1 ) | |
{ | |
//clicou | |
if( old_mouse_buttom_3 == 0 ){ | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYDOWN, (unsigned long) 3, (unsigned long) 0 ); | |
//atualiza o estado anterior. | |
old_mouse_buttom_3 = 1; | |
} | |
}else{ | |
//up | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEKEYUP, (unsigned long) 3, (unsigned long) 0 ); | |
old_mouse_buttom_3 = 0; | |
} | |
}; | |
//Ação concluída. | |
mouse_button_action = 0; | |
}else{ | |
//#importante | |
//lembrando que estamos dentro de uma janela ... | |
//por isso a mensagen é over e não move. | |
//se NÂO ouve alteração no estado dos botões | |
//então apenas enviaremos a mensagem de movimento | |
//do mouse. | |
//Obs: Se a janela for a mesma que capturou o mouse, | |
//então não precisamos reenviar a mensagem. | |
if( wScan->id != mouseover_window ) | |
{ | |
windowSendMessage( (unsigned long) wScan, | |
(unsigned long) MSG_MOUSEOVER, | |
(unsigned long) 0, | |
(unsigned long) 0 ); | |
mouseover_window = wScan->id; | |
}else{ }; | |
//Ação concluída. | |
//Para o caso de um valor incostante na flag. | |
mouse_button_action = 0; | |
}; | |
//#debug. (+) | |
draw_text( wScan, | |
0, | |
0, | |
COLOR_RED, | |
"+" ); | |
//refresh bmp rectangle. | |
//isso coloca o (+) no frontbuffer. | |
refresh_rectangle( wScan->left, | |
wScan->top, | |
8, | |
8 ); | |
}; | |
exit_irq: | |
// EOI. | |
outportb(0xa0, 0x20); | |
outportb(0x20, 0x20); | |
}; | |
// | |
// ************* ASM ********************* | |
// | |
;; | |
;; ============================ Mouse support ============================ | |
;; | |
; Format Of Mouse Packet Data. | |
MOUSE_LEFT_BTN EQU 0x01 | |
MOUSE_RIGHT_BTN EQU 0x02 | |
MOUSE_MIDDLE_BTN EQU 0x04 | |
MOUSE_X_SIGN EQU 0x10 | |
MOUSE_Y_SIGN EQU 0x20 | |
MOUSE_X_OVERFLOW EQU 0x40 | |
MOUSE_Y_OVERFLOW EQU 0x80 | |
;Posicionamento do cursor. | |
;X. | |
global _mouse_x | |
_mouse_x: | |
dd 0 | |
;Y. | |
global _mouse_y | |
_mouse_y: | |
dd 0 | |
;Bytes do controlador. | |
;Status. | |
global _mouse_packet_data | |
_mouse_packet_data: | |
db 0 | |
;Delta x. | |
global _mouse_packet_x | |
_mouse_packet_x: | |
db 0 | |
;Delta y. | |
global _mouse_packet_y | |
_mouse_packet_y: | |
db 0 | |
;Scroll. | |
global _mouse_packet_scroll | |
_mouse_packet_scroll: | |
db 0 | |
;;===================================================== | |
;; _update_mouse: | |
;; Updates the mouse position. | |
;; | |
;; Credits: | |
;; Omar Mohammad. Maadi, Cairo, Egypt. | |
;; | |
global _update_mouse | |
_update_mouse: | |
nop | |
;;======== X ========== | |
; | |
; Testando o sinal de x. | |
; | |
; Do the x pos first. | |
.do_x: | |
;;pega o delta x | |
movzx eax, byte [_mouse_packet_x] | |
;testa o sinal para x | |
test byte [_mouse_packet_data], MOUSE_X_SIGN | |
jnz .x_neg | |
;caso x seja positivo. | |
.x_pos: | |
add [_mouse_x], eax | |
jmp .do_y | |
;;caso x seja negativo. | |
.x_neg: | |
not al | |
inc al | |
sub [_mouse_x], eax | |
jns .do_y | |
xor eax, eax | |
mov [_mouse_x], eax | |
;;======== Y ========== | |
; | |
; Testando o sinal de x. | |
; | |
; Do the same for y position. | |
.do_y: | |
;Pega o delta y. | |
movzx eax, byte [_mouse_packet_y] | |
;Testa o sinal para y. | |
test byte[_mouse_packet_data], MOUSE_Y_SIGN | |
jnz .y_neg | |
;Caso y seja positivo. | |
.y_pos: | |
sub [_mouse_y], eax | |
jns .quit | |
xor eax, eax | |
mov [_mouse_y], eax | |
jmp .quit | |
;Caso y seja negativo. | |
.y_neg: | |
not al | |
inc al | |
add [_mouse_y], eax | |
;Done. | |
.quit: | |
ret | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment