kernel: A more complete window manager implementation

It's currently pretty buggy, but at least it's better than what we
had before :P
This commit is contained in:
Ry 2022-12-23 22:26:16 -08:00
parent c6919d4168
commit a68e584c82
3 changed files with 353 additions and 8 deletions

View File

@ -35,14 +35,14 @@ event_manager_task_loop:
cmp r0, EVENT_TYPE_MENU_UPDATE cmp r0, EVENT_TYPE_MENU_UPDATE
ifz call new_event ifz call new_event
cmp [active_window], 0 cmp.8 [active_window_offset], 0xFF
ifz rjmp event_manager_task_loop_end ifz rjmp event_manager_task_loop_end
; mouse ; mouse
cmp r0, EVENT_TYPE_MOUSE_CLICK cmp r0, EVENT_TYPE_MOUSE_CLICK
ifz call add_mouse_event_to_active_window ifz call event_manager_task_mouse_event
cmp r0, EVENT_TYPE_MOUSE_RELEASE cmp r0, EVENT_TYPE_MOUSE_RELEASE
ifz call add_mouse_event_to_active_window ifz call event_manager_task_mouse_event
; keyboard ; keyboard
cmp r0, EVENT_TYPE_KEY_DOWN cmp r0, EVENT_TYPE_KEY_DOWN
@ -52,3 +52,75 @@ event_manager_task_loop:
event_manager_task_loop_end: event_manager_task_loop_end:
call yield_task call yield_task
rjmp event_manager_task_loop rjmp event_manager_task_loop
event_manager_task_mouse_event:
push r0
push r1
push r2
; find which overlay was clicked on
mov r0, r1
mov r1, r2
call find_overlay_convering_position
cmp r0, 0xFFFFFFFF
ifz pop r2
ifz pop r1
ifz pop r0
ifz ret
push r0
; get the overlay number of the active window
movz.8 r0, [active_window_offset]
call window_list_offset_to_struct
call get_window_overlay_number
; check if the click was inside the active window
; otherwise, activate the clicked window
pop r1
cmp r0, r1
ifnz jmp event_manager_task_mouse_event_inactive_window_was_clicked
pop r2
pop r1
pop r0
call add_mouse_event_to_active_window
ret
event_manager_task_mouse_event_inactive_window_was_clicked:
mov r2, r1
mov r1, r0
mov r0, r2
; r0: clicked window overlay number
; r1: currently active window overlay number
; get the window structs of the two windows
call get_window_with_overlay
mov r2, r0
mov r0, r1
call get_window_with_overlay
mov r1, r2
; give up if a window was not found for this overlay
cmp r0, 0x00000000
ifz pop r2
ifz pop r1
ifz pop r0
ifz ret
cmp r1, 0x00000000
ifz pop r2
ifz pop r1
ifz pop r0
ifz ret
; swap the two
call swap_windows
; mark the clicked window as the active window
mov r0, r1
call search_for_window_list_entry
mov.8 [active_window_offset], r0
pop r2
pop r1
pop r0
ret

95
kernel/window/overlay.asm Normal file
View File

@ -0,0 +1,95 @@
; overlay routines for window management
; given a position on screen, find which enabled overlay (if any) is covering it
; if multiple overlays are covering the same position, the highest priority one will be returned
; overlay 31 (the mouse cursor) is ignored
; inputs:
; r0: X coordinate
; r1: Y coordinate
; outputs:
; r0: overlay number, or 0xFFFFFFFF if none
find_overlay_convering_position:
push r2
push r31
mov r31, 31
find_overlay_convering_position_loop:
mov r2, r31
dec r2
call check_if_enabled_overlay_covers_position
ifz jmp find_overlay_convering_position_found
loop find_overlay_convering_position_loop
; none found, return 0xFFFFFFFF
mov r0, 0xFFFFFFFF
pop r31
pop r2
ret
find_overlay_convering_position_found:
; found one, return its overlay number
mov r0, r2
pop r31
pop r2
ret
; swap two overlays. this has the effect of swapping their priorities
; this does *not* effect the enable status of either overlay
; FIXME: this could use the stack instead
; inputs:
; r0: overlay number
; r1: overlay number
; outputs:
; none
swap_overlays:
push r10
; save first overlay
mov r10, r0
or r10, 0x80000000
in [overlay_0_position], r10
mov r10, r0
or r10, 0x80000100
in [overlay_0_size], r10
mov r10, r0
or r10, 0x80000200
in [overlay_0_ptr], r10
; save second overlay
mov r10, r1
or r10, 0x80000000
in [overlay_1_position], r10
mov r10, r1
or r10, 0x80000100
in [overlay_1_size], r10
mov r10, r1
or r10, 0x80000200
in [overlay_1_ptr], r10
; swap
mov r10, r1
or r10, 0x80000000
out r10, [overlay_0_position]
mov r10, r1
or r10, 0x80000100
out r10, [overlay_0_size]
mov r10, r1
or r10, 0x80000200
out r10, [overlay_0_ptr]
mov r10, r0
or r10, 0x80000000
out r10, [overlay_1_position]
mov r10, r0
or r10, 0x80000100
out r10, [overlay_1_size]
mov r10, r0
or r10, 0x80000200
out r10, [overlay_1_ptr]
pop r10
ret
overlay_0_position: data.32 0x00000000
overlay_0_size: data.32 0x00000000
overlay_0_ptr: data.32 0x00000000
overlay_1_position: data.32 0x00000000
overlay_1_size: data.32 0x00000000
overlay_1_ptr: data.32 0x00000000

View File

@ -94,7 +94,7 @@ new_window:
add r10, 24 add r10, 24
mov.8 [r10], r11 mov.8 [r10], r11
; finally, set the properties of the overlay ; then, set the properties of the overlay
push r0 push r0
push r1 push r1
push r2 push r2
@ -119,9 +119,19 @@ new_window:
call fill_overlay call fill_overlay
pop r0 pop r0
mov [active_window], r0 ; then, draw the title bar
call draw_title_bar_to_window call draw_title_bar_to_window
; finally, add this window to the window list
push r0
mov r0, 0x00000000
call search_for_window_list_entry
mov.8 [active_window_offset], r0
mul r0, 4
add r0, window_list
pop r1
mov [r0], r1
pop r12 pop r12
pop r11 pop r11
pop r10 pop r10
@ -153,10 +163,23 @@ destroy_window:
mov r0, [r1] mov r0, [r1]
call free_memory call free_memory
; disable the window's overlay
add r1, 16 add r1, 16
movz.8 r0, [r1] movz.8 r0, [r1]
call disable_overlay call disable_overlay
; remove the window from the window list
sub r1, 24
mov r0, r1
call search_for_window_list_entry
mul r0, 4
add r0, window_list
mov [r0], 0
; set the active window to whatever entry is found first
call search_for_nonempty_window_list_entry
mov.8 [active_window_offset], r0
pop r1 pop r1
pop r0 pop r0
ret ret
@ -244,6 +267,35 @@ move_window:
pop r0 pop r0
ret ret
; swap two windows
; inputs:
; r0: pointer to window struct
; r1: pointer to window struct
; outputs:
; none
swap_windows:
push r0
push r1
push r2
push r3
mov r2, r0
mov r3, r1
add r2, 24
movz.8 r0, [r2]
add r3, 24
movz.8 r1, [r3]
call swap_overlays
movz.8 [r2], r1
movz.8 [r3], r0
pop r3
pop r2
pop r1
pop r0
ret
; fill a whole window with a color ; fill a whole window with a color
; inputs: ; inputs:
; r0: color ; r0: color
@ -377,7 +429,11 @@ draw_title_bar_to_window_loop:
; outputs: ; outputs:
; none ; none
add_event_to_active_window: add_event_to_active_window:
mov r8, [active_window] push r0
movz.8 r0, [active_window_offset]
call window_list_offset_to_struct
mov r8, r0
pop r0
call new_window_event call new_window_event
ret ret
@ -401,7 +457,8 @@ add_mouse_event_to_active_window:
mov r12, r0 mov r12, r0
; get the window's overlay number ; get the window's overlay number
mov r0, [active_window] movz.8 r0, [active_window_offset]
call window_list_offset_to_struct
call get_window_overlay_number call get_window_overlay_number
; check if the window's overlay covers the clicked position ; check if the window's overlay covers the clicked position
@ -427,6 +484,125 @@ add_mouse_event_to_active_window_end:
pop r0 pop r0
ret ret
; search for an entry in the window list
; inputs:
; r0: entry (pointer to window struct)
; outputs:
; r0: window list offset, or 0xFFFFFFFF if not found
search_for_window_list_entry:
push r1
push r2
push r31
mov r1, window_list
mov r2, 0
mov r31, 31
search_for_window_list_entry_loop:
cmp [r1], r0
ifz jmp search_for_window_list_entry_found
inc r2
add r1, 4
loop search_for_window_list_entry_loop
; not found, return 0xFFFFFFFF
mov r0, 0xFFFFFFFF
pop r31
pop r2
pop r1
ret
search_for_window_list_entry_found:
; found the entry, return its offset
mov r0, r2
pop r31
pop r2
pop r1
ret
; search for the first non-empty entry in the window list
; inputs:
; none
; outputs:
; r0: window list offset, or 0xFFFFFFFF if not found
search_for_nonempty_window_list_entry:
push r1
push r2
push r31
mov r1, window_list
mov r2, 0
mov r31, 31
search_for_nonempty_window_list_entry_loop:
cmp [r1], 0
ifnz jmp search_for_nonempty_window_list_entry_found
inc r2
add r1, 4
loop search_for_nonempty_window_list_entry_loop
; not found, return 0xFFFFFFFF
mov r0, 0xFFFFFFFF
pop r31
pop r2
pop r1
ret
search_for_nonempty_window_list_entry_found:
; found the entry, return its offset
mov r0, r2
pop r31
pop r2
pop r1
ret
; given an overlay number, get the window struct of the window associated with that overlay
; inputs:
; r0: overlay number
; outputs:
; r0: pointer to window struct, or 0x00000000 if not found
get_window_with_overlay:
push r1
push r2
push r3
push r31
mov r1, window_list
mov r31, 31
get_window_with_overlay_loop:
mov r2, [r1]
add r2, 24
cmp.8 [r2], r0
ifz jmp get_window_with_overlay_found
add r1, 4
loop get_window_with_overlay_loop
; not found, return 0
mov r0, 0
pop r31
pop r3
pop r2
pop r1
ret
get_window_with_overlay_found:
; found the entry, return the pointer to its struct
mov r0, [r1]
pop r31
pop r3
pop r2
pop r1
ret
; get a window struct pointer from the window list
; inputs:
; r0: window list offset
; outputs:
; r0: pointer to window struct
window_list_offset_to_struct:
mul r0, 4
add r0, window_list
mov r0, [r0]
ret
window_title_bar_patterns: window_title_bar_patterns:
; 1x16 tile ; 1x16 tile
data.32 0x00000000 data.32 0x00000000
@ -464,7 +640,9 @@ window_title_bar_patterns:
data.32 0xFFFFFFFF data.32 0xFFFFFFFF
data.32 0x00000000 data.32 0x00000000
active_window: data.32 0 active_window_offset: data.8 0xFF
window_list: data.fill 0, 124 ; 31 window structs * 4 bytes each
#include "window/event.asm" #include "window/event.asm"
#include "window/event_manager_task.asm" #include "window/event_manager_task.asm"
#include "window/overlay.asm"