Skip to content

Instantly share code, notes, and snippets.

@frednora
Last active September 11, 2018 01:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frednora/3a01f0e761d9f52ebe552c6aa5480abf to your computer and use it in GitHub Desktop.
Save frednora/3a01f0e761d9f52ebe552c6aa5480abf to your computer and use it in GitHub Desktop.
mouse support
// 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