format ELF64
extrn XOpenDisplay
extrn XDefaultRootWindow
extrn XCreateSimpleWindow
extrn XSelectInput
extrn XMapWindow
extrn XNextEvent
extrn XInternAtom
extrn XSetWMProtocols
extrn XFlush
extrn XCreateGC
public main
section '.text' executable
main:
push rbp
mov rbp, rsp
sub rsp, 32 ; Выравниваем стек и выделяем место под параметры
; Открыть дисплей
xor rdi, rdi
call XOpenDisplay
cmp rax, 0
je exit_error
mov [x_display], rax
; Получить корневое окно
mov rdi, [x_display]
call XDefaultRootWindow
mov [root_window], rax
; Создать окно 400x300 с фоном 0x1A1A1A
; Передаем 7, 8 и 9 параметры через стек согласно ABI
mov qword [rsp + 16], 0x1A1A1A ; 9-й параметр: фоновый цвет окна (теперь задан жестко)
mov qword [rsp + 8], 0 ; 8-й параметр: цвет рамки (border)
mov qword [rsp], 0 ; 7-й параметр: ширина рамки (border_width)
mov rdi, [x_display] ; 1-й параметр: Display
mov rsi, [root_window] ; 2-й параметр: Parent
mov rdx, 100 ; 3-й параметр: x
mov rcx, 100 ; 4-й параметр: y
mov r8, 400 ; 5-й параметр: width
mov r9, 300 ; 6-й параметр: height
call XCreateSimpleWindow
mov [window], rax
; Получить WM_DELETE_WINDOW атом для корректного закрытия
mov rdi, [x_display]
lea rsi, [delete_str]
xor rdx, rdx
call XInternAtom
mov [wm_delete], rax
; Установить WM_PROTOCOLS
mov rdi, [x_display]
mov rsi, [window]
lea rdx, [wm_delete]
mov rcx, 1
call XSetWMProtocols
; Подписаться на события (ExposureMask = 0x8000, StructureNotifyMask = 0x20000)
mov rdi, [x_display]
mov rsi, [window]
mov rdx, 0x28000
call XSelectInput
; Показать окно
mov rdi, [x_display]
mov rsi, [window]
call XMapWindow
; Создать GC (графический контекст) для будущей отрисовки объектов
mov rdi, [x_display]
mov rsi, [window]
xor rdx, rdx
xor rcx, rcx
call XCreateGC
mov [gc], rax
; Сбросить буфер X11, чтобы окно отобразилось сразу
mov rdi, [x_display]
call XFlush
event_loop:
mov rdi, [x_display]
lea rsi, [event_buffer]
call XNextEvent
movzx eax, byte [event_buffer] ; Первый байт структуры XEvent — это тип события
cmp al, 2 ; KeyPress (любая клавиша закрывает приложение)
je exit_ok
cmp al, 33 ; ClientMessage (нажатие на крестик окна)
je check_delete
; Событие Expose (al = 12) убрано, так как фон теперь перерисовывается сервером X11 автоматически
jmp event_loop
check_delete:
; Проверяем, что пришло именно событие WM_DELETE_WINDOW
mov rax, [event_buffer + 56]
cmp rax, [wm_delete]
je exit_ok
jmp event_loop
exit_ok:
add rsp, 32
mov rsp, rbp
pop rbp
xor rax, rax
ret
exit_error:
add rsp, 32
mov rsp, rbp
pop rbp
mov rax, 1
ret
section '.data' writeable
delete_str db 'WM_DELETE_WINDOW', 0
section '.bss' writeable
x_display: rq 1
root_window: rq 1
window: rq 1
wm_delete: rq 1
gc: rq 1
event_buffer: rb 192