fox32os/kernel/window/window.asm

471 lines
8.9 KiB
NASM
Raw Normal View History

; window management routines
; window struct:
; data.32 framebuffer_ptr - pointer to this window's framebuffer
; data.32 event_queue_ptr - current event queue pointer
; data.32 event_queue_bottom - pointer to beginning of this window's event queue
; data.32 title_ptr - pointer to null-terminated title string
; data.16 width - width of this window
; data.16 height - height of this window, not including the title bar
; data.16 x_pos - X coordinate of this window (top left corner of title bar)
; data.16 y_pos - Y coordinate of this window (top left corner of title bar)
; data.8 overlay - overlay number of this window
; data.8 reserved_1
; data.16 reserved_2
; data.32 reserved_3
const WINDOW_STRUCT_SIZE: 32 ; 8 words = 32 bytes
const TITLE_BAR_HEIGHT: 16
; create a new window and allocate memory as required
; inputs:
; r0: pointer to empty 32 byte window struct
; r1: pointer to null-terminated title string
; r2: window width
; r3: window height, not including the title bar
; r4: initial X coordinate (top left corner of title bar)
; r5: initial Y coordinate (top left corner of title bar)
; outputs:
; none
new_window:
push r1
push r2
push r3
push r4
push r5
push r10
push r11
push r12
; first, set up the initial struct values
; title string
mov r10, r0
add r10, 12
mov [r10], r1
; window size
add r10, 4
mov.16 [r10], r2
add r10, 2
mov.16 [r10], r3
; window position
add r10, 2
mov.16 [r10], r4
add r10, 2
mov.16 [r10], r5
; then, allocate memory for the framebuffer
; the space required is width * (height + TITLE_BAR_HEIGHT) * 4
mov r10, r2
mov r11, r3
add r11, TITLE_BAR_HEIGHT
mul r10, r11
mul r10, 4
push r0
mov r0, r10
call allocate_memory
cmp r0, 0
ifz jmp memory_error
mov r10, r0
pop r0
mov [r0], r10
mov r12, r10
; then, allocate memory for the event queue
; 32 events * 8 entries per event * 4 bytes per word = 1024 bytes
push r0
mov r0, 1024
call allocate_memory
cmp r0, 0
ifz jmp memory_error
mov r11, r0
pop r0
mov r10, r0
add r10, 8
mov [r10], r11
sub r10, 4
mov [r10], r11
; then, find an overlay to use for this window
push r0
call get_unused_overlay
mov r11, r0
pop r0
mov r10, r0
add r10, 24
mov.8 [r10], r11
; finally, set the properties of the overlay
push r0
push r1
push r2
mov r0, r4
mov r1, r5
mov r2, r11
call move_overlay
pop r2
pop r1
mov r0, r2
mov r1, r3
add r1, TITLE_BAR_HEIGHT
mov r2, r11
call resize_overlay
mov r0, r12
mov r1, r11
call set_overlay_framebuffer_pointer
mov r0, r11
call enable_overlay
mov r0, 0xFF000000
mov r1, r11
call fill_overlay
pop r0
mov [active_window], r0
call draw_title_bar_to_window
pop r12
pop r11
pop r10
pop r5
pop r4
pop r3
pop r2
pop r1
ret
; destroy a window and free memory used by it
; note that this does not free the memory used by the window struct itself
; inputs:
; r0: pointer to window struct
; outputs:
; none
destroy_window:
push r0
push r1
mov r1, r0
; free framebuffer memory
mov r0, [r1]
call free_memory
; free event queue memory
add r1, 8
mov r0, [r1]
call free_memory
add r1, 16
movz.8 r0, [r1]
call disable_overlay
pop r1
pop r0
ret
; call this if the user clicks on a window's title bar
; inputs:
; r0: pointer to window struct
; outputs:
; none
start_dragging_window:
push r0
push r1
push r2
push r4
mov r2, r0
mov r4, r0
add r4, 16
movz.16 r4, [r4]
div r4, 2
start_dragging_window_loop:
call get_mouse_position
sub r0, r4
sub r1, 8
call move_window
call get_mouse_button
bts r0, 2
ifnz jmp start_dragging_window_loop
pop r4
pop r2
pop r1
pop r0
ret
; move a window
; r0: X position
; r1: Y position
; r2: pointer to window struct
move_window:
push r0
push r1
push r2
push r3
push r4
push r5
push r6
; prevent windows from being moved off-screen
add r2, 16
movz.16 r3, [r2]
add r2, 2
movz.16 r4, [r2]
mov r5, 640
mov r6, 480
sub r5, r3
sub r6, r4
cmp r0, 0x80000000
ifgt mov r0, 0
cmp r1, 0x80000000
ifgt mov r1, 0
cmp r0, r5
ifgt mov r0, r5
cmp r1, r6
ifgt mov r1, r6
; move the window
add r2, 2
mov.16 [r2], r0
add r2, 2
mov.16 [r2], r1
add r2, 2
movz.8 r2, [r2]
call move_overlay
pop r6
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
ret
; fill a whole window with a color
; inputs:
; r0: color
; r1: pointer to window struct
; outputs:
; none
fill_window:
push r1
push r2
mov r2, r1
add r1, 24
movz.8 r1, [r1]
call fill_overlay
mov r0, r2
call draw_title_bar_to_window
pop r2
pop r1
ret
; get the overlay used by a window
; DO NOT CACHE THIS VALUE, it can change any time the window order changes
; inputs:
; r0: pointer to window struct
; outputs:
; r0: overlay number
get_window_overlay_number:
add r0, 24
movz.8 r0, [r0]
ret
; draw a window's title bar
; inputs:
; r0: pointer to window struct
; outputs:
; none
draw_title_bar_to_window:
push r0
push r3
push r4
push r10
push r11
push r12
push r31
; get the title string
add r0, 12
mov r12, [r0]
; get the width of this window
add r0, 4
movz.16 r11, [r0]
; get overlay number of this window
add r0, 8
movz.8 r10, [r0]
; save the old tilemap
call get_tilemap
push r0
push r1
push r2
; set the tilemap to our 1x16 tile patterns
mov r0, window_title_bar_patterns
mov r1, 1
mov r2, 16
call set_tilemap
mov r1, 0
mov r2, 0
mov r3, r10
mov r31, r11
draw_title_bar_to_window_loop:
mov r4, r31
rem r4, 2
cmp r4, 0
ifz mov r0, 0
ifnz mov r0, 1
call draw_tile_to_overlay
inc r1
loop draw_title_bar_to_window_loop
; restore the old tilemap
pop r2
pop r1
pop r0
call set_tilemap
; draw the title text
mov r0, r12
mov r1, 8
mov r2, 0
mov r3, 0xFF000000
mov r4, 0xFFFFFFFF
mov r5, r10
call draw_str_to_overlay
; draw the close button
mov r0, 1
mov r1, 4
mov r2, 6
mov r3, 8
mov r4, 0xFFFFFFFF
mov r5, r10
call draw_filled_rectangle_to_overlay
mov r0, 2
mov r1, 5
mov r2, 4
mov r3, 6
mov r4, 0xFF000000
mov r5, r10
call draw_filled_rectangle_to_overlay
pop r31
pop r12
pop r11
pop r10
pop r4
pop r3
pop r0
ret
; add an event to the active window
; inputs:
; r0-r7: event
; outputs:
; none
add_event_to_active_window:
mov r8, [active_window]
call new_window_event
ret
; add a mouse event to the active window if the mouse was clicked inside the active window
; if so, automatically convert the X and Y coords to be relative to the window
; inputs:
; r0-r7: event
; outputs:
; none
add_mouse_event_to_active_window:
push r0
push r2
push r10
push r11
push r12
; save X and Y coords of the click and the event type
mov r10, r1
mov r11, r2
mov r12, r0
; get the window's overlay number
mov r0, [active_window]
call get_window_overlay_number
; check if the window's overlay covers the clicked position
mov r2, r0
mov r0, r10
mov r1, r11
call check_if_overlay_covers_position
; if it doesn't, then end here
ifnz jmp add_mouse_event_to_active_window_end
; if it does, then make the X and Y coords relative to the overlay
call make_coordinates_relative_to_overlay
; add the event
mov r2, r1
mov r1, r0
mov r0, r12
call add_event_to_active_window
add_mouse_event_to_active_window_end:
pop r12
pop r11
pop r10
pop r2
pop r0
ret
window_title_bar_patterns:
; 1x16 tile
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
; 1x16 tile
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
data.32 0xFFFFFFFF
2022-10-06 06:02:56 +02:00
data.32 0x00000000
active_window: data.32 0
#include "window/event.asm"
#include "window/event_manager_task.asm"