in build_all.bat: delete config.inc after compiling delete /kernel/trunk/lib git-svn-id: svn://kolibrios.org@529 a494cfbc-eb01-0410-851d-a64ba20cac60
402 lines
10 KiB
NASM
402 lines
10 KiB
NASM
;
|
||
; DESKTOP CONTEXT MENU
|
||
; written by Ivan Poddubny
|
||
;
|
||
; Автор - Иван Поддубный
|
||
; e-mail: ivan-yar@bk.ru
|
||
;
|
||
; Compile with flat assembler
|
||
;
|
||
include 'lang.inc'
|
||
include '..\..\..\macros.inc'
|
||
|
||
meos_app_start
|
||
code
|
||
|
||
mov eax, 48 ; получить системные цвета
|
||
mov ebx, 3
|
||
mov ecx, sc ; адрес структуры
|
||
mov edx, sizeof.system_colors ; и ее размер
|
||
mcall
|
||
|
||
mov eax,40 ; установим маску событий
|
||
mov ebx,100000b ; нас интересует только мышь
|
||
mcall
|
||
|
||
still: ; главный цикл основного процесса
|
||
|
||
mov eax,10 ; ждём события
|
||
mcall
|
||
|
||
mov eax,37 ; какие нажаты кпопки?
|
||
mov ebx,2
|
||
mcall
|
||
|
||
cmp eax,2 ; если не правая, возврат
|
||
jne still
|
||
|
||
;---поехали!---
|
||
|
||
; mov eax,37 ; это для отладки - если мышь в точке (0;0), закроемся
|
||
; xor ebx,ebx
|
||
; mcall
|
||
; test eax,eax ; курсор в точке (0;0), т.е. eax = 0
|
||
; je exit
|
||
|
||
|
||
mov eax,9 ; получим число процессов в системе
|
||
mov ebx,procinfo
|
||
xor ecx,ecx
|
||
mcall
|
||
|
||
inc eax ; теперь в eax содержится число процессов + 1
|
||
mov [processes],eax
|
||
mov ecx,1
|
||
|
||
new_process:
|
||
pushad
|
||
mov eax,9 ; получим информацию о процессе; номер - в ecx
|
||
mov ebx,procinfo
|
||
mcall
|
||
mov eax,37 ; координаты курсора
|
||
xor ebx,ebx
|
||
mcall
|
||
mov ebx,eax ; eax = cursor_x
|
||
shr eax,16 ; ebx = cursor_y
|
||
and ebx,0xffff
|
||
mov [curx1],eax ; curx1 = cursor_x
|
||
mov [cury1],ebx ; cury1 = cursor_y
|
||
; \begin{diamond}[18.09.2006]
|
||
; ignore minimized windows
|
||
test [procinfo.wnd_state], 2
|
||
jnz ne_goden
|
||
; \end{diamond}[18.09.2006]
|
||
mov eax,[procinfo.box.left] ; eax = wnd_x_start
|
||
mov ebx,[procinfo.box.top] ; ebx = wnd_y_start
|
||
|
||
mov ecx,[procinfo.box.width]
|
||
add ecx,eax ; ecx = wnd_x_end
|
||
mov edx,[procinfo.box.height]
|
||
add edx,ebx ; ecx = wnd_y_end
|
||
|
||
cmp eax,[curx1] ; wnd_x_start > cursor_x => курсор левее окна
|
||
jg ne_goden
|
||
cmp ecx,[curx1] ; wnd_x_end < cursor_x => курсор правее окна
|
||
jl ne_goden
|
||
cmp ebx,[cury1] ; wnd_y_start > cursor_y => курсор выше окна
|
||
jg ne_goden
|
||
cmp edx,[cury1] ; wnd_y_end < cursor_y => курсор ниже окна
|
||
jl ne_goden
|
||
|
||
goden: ; клик был внутри какого-то окна, поэтому ничего не делаем
|
||
popad
|
||
jmp still
|
||
|
||
ne_goden: ; клик был снаружи рассматриваемого окна, поэтому
|
||
popad
|
||
inc ecx
|
||
cmp ecx,[processes]
|
||
jl new_process ; либо сморим следующее окно, либо запускаем меню
|
||
|
||
|
||
@@: ; подождём, пока пользователь не отпустил правую кнопку мыши
|
||
mov eax,37
|
||
mov ebx,2 ; функция 37-2:
|
||
mcall ; нажаты ли кнопки мыши?
|
||
cmp eax,ebx ; если отпустил, (eax != 2)
|
||
jnz @f ; идём в начало главного цикла
|
||
|
||
mov eax,5 ; иначе
|
||
mov ebx,2 ; подождём 2 мс
|
||
mcall
|
||
|
||
jmp @b ; и проверим мышь опять
|
||
@@:
|
||
|
||
; если уже было открыто меню, нужно подождать, пока оно закроется:
|
||
@@:
|
||
cmp [menu_opened],0
|
||
je @f
|
||
mov eax,5
|
||
mov ebx,3 ; ждём 3 мс
|
||
mcall
|
||
jmp @b
|
||
@@:
|
||
|
||
mov eax,51 ; а теперь можно смело запускать процесс (поток) меню
|
||
mov ebx,1 ; создаём поток (thread)
|
||
mov ecx,start_wnd ; точка входа потока
|
||
mov edx,stack_wnd ; вершина стэка для потока
|
||
mcall
|
||
|
||
jmp still
|
||
|
||
|
||
|
||
exit_menu: ; если выходим из меню, надо записать в [menu_opened] 0
|
||
mov [menu_opened],0
|
||
exit: ; сюда мы идём, когда выходим из основного процесса
|
||
or eax,-1 ; eax = -1
|
||
mcall
|
||
|
||
|
||
|
||
|
||
; здесь стартует процесс меню
|
||
start_wnd:
|
||
mov [menu_opened],1
|
||
mov eax,40 ; установим маску желаемых событий для этого процесса
|
||
mov ebx,100101b ; меню + кнопки + перерисовка
|
||
mcall
|
||
|
||
red:
|
||
call draw_window
|
||
|
||
still2: ; главный цикл процесса меню
|
||
|
||
mov eax,10 ; ждём события
|
||
mcall
|
||
|
||
cmp eax,1 ; перерисовка?
|
||
je red
|
||
cmp eax,3 ; кнопка?
|
||
je button
|
||
cmp eax,6 ; мышь?
|
||
je mouse
|
||
|
||
jmp still2 ; вернёмся в начало главного цикла
|
||
|
||
|
||
; ОБРАБОТЧИК МЫШИ
|
||
mouse: ; когда пользователь нажмёт кнопку мыши, закроемся
|
||
mov eax,37
|
||
mov ebx,2 ; какие кнопки нажаты?
|
||
mcall
|
||
test eax,eax ; никакие? - тогда прекрасно! вернёмся в гланый цикл
|
||
jz still2
|
||
jmp exit_menu ; а если всё-таки нажаты - закроем окно
|
||
|
||
|
||
; НАЖАТА КНОПКА
|
||
button:
|
||
mov eax,17 ; получить идентификатор нажатой кнопки
|
||
mcall
|
||
|
||
sub ah,10 ; сравниваем с 10
|
||
jl nofuncbtns ; если меньше - закрываем меню
|
||
|
||
movzx ebx,ah ; получили номер программы в списке в ebx
|
||
mov esi, [startapps + ebx*4]
|
||
mov edi, start_info.path
|
||
cld
|
||
@@:
|
||
lodsb
|
||
stosb
|
||
test al, al
|
||
jnz @b
|
||
mcall 70, start_info
|
||
|
||
; mov eax,5 ; подождём, пока программа запуститься
|
||
; mov ebx,1 ; а то её окно не будет отрисовано (баг в ядре???)
|
||
; mcall ; раскомментируйте эти строки, если у вас проблемы
|
||
; с отрисовкой
|
||
|
||
nofuncbtns: ; закрываем меню
|
||
jmp exit_menu
|
||
|
||
|
||
|
||
_BTNS_ = 6 ; количество кнопок ("пунктов меню")
|
||
|
||
if lang eq ru
|
||
font = 0x00000000
|
||
string_length = 20 ; длина строки
|
||
wnd_x_size = 133 ; ширина окна
|
||
title_pos = 36 shl 16 + 7
|
||
else
|
||
font = 0x10000000
|
||
string_length = 12 ; длина строки
|
||
wnd_x_size = 105 ; ширина окна
|
||
title_pos = 23 shl 16 + 7
|
||
end if
|
||
|
||
;*******************************
|
||
;******** РИСУЕМ ОКНО ********
|
||
;*******************************
|
||
|
||
draw_window:
|
||
|
||
mov eax,12 ; начинаем "рисовать"
|
||
mov ebx,1
|
||
mcall
|
||
|
||
mov eax,[curx1] ; текущие координаты курсора
|
||
mov [curx],eax ; запишем в координаты окна
|
||
mov eax,[cury1]
|
||
mov [cury],eax
|
||
|
||
; теперь будем считать координаты окна, чтобы оно за край экрана не вылезло
|
||
mov eax,14 ; получим размер экрана
|
||
mcall
|
||
mov ebx,eax
|
||
shr eax,16 ; в eax - x_screen
|
||
and ebx,0xffff ; в ebx - y_screen
|
||
add eax,-wnd_x_size ; eax = [x_screen - ширина окна]
|
||
add ebx,-_BTNS_*15-21 ; ebx = [y_screen - высота окна]
|
||
|
||
cmp eax,[curx]
|
||
jg .okx ; если окно слишком близко к правому краю,
|
||
add [curx],-wnd_x_size ; сдвинем его влево на 100
|
||
.okx:
|
||
|
||
cmp ebx, [cury]
|
||
jg .oky ; по вертикали точно также
|
||
add [cury], -_BTNS_*15-21
|
||
.oky:
|
||
|
||
xor eax, eax ; функция 0 - создать окно
|
||
mov ebx, [curx] ; ebx = [координата по x] shl 16 + [ширина]
|
||
shl ebx, 16
|
||
add ebx, wnd_x_size
|
||
mov ecx, [cury] ; ecx = [координата по y] shl 16 + [высота]
|
||
shl ecx, 16
|
||
add ecx, _BTNS_*15+21
|
||
mov edx, [sc.work] ; цвет рабочей области
|
||
mov esi, [sc.grab] ; цвет заголовка
|
||
or esi, 0x81000000
|
||
mov edi, [sc.frame] ; цвет рамки
|
||
mcall
|
||
|
||
mov eax, 4 ; заголовок
|
||
mov ebx, title_pos ; [x] shl 16 + [y]
|
||
mov ecx, [sc.grab_text]; шрифт и цвет (серый)
|
||
or ecx, 0x10000000
|
||
; add ecx, -0x333333
|
||
push ecx
|
||
push ecx
|
||
xor edx,edx
|
||
.dec_color:
|
||
sub byte [esp+edx], 0x33
|
||
jae @f
|
||
mov byte [esp+edx], 0
|
||
@@:
|
||
inc edx
|
||
jnp .dec_color
|
||
pop ecx
|
||
mov edx, title ; адрес заголовка
|
||
mov esi, title.size ; длина заголовка ("M E N U")
|
||
mcall
|
||
pop ecx
|
||
add ebx, 1 shl 16 ; сдвинем вправо на 1
|
||
mcall
|
||
|
||
mov ebx, 1*65536+wnd_x_size-2 ; начинаем делать кнопки
|
||
mov ecx, 20*65536+15
|
||
mov edx, 10 or 0x40000000 ; бит 30 установлен => кнопка не рисуется
|
||
|
||
mov edi,_BTNS_ ; количество кнопок (счётчик)
|
||
|
||
newbtn: ; начало цикла
|
||
mov eax,8 ; создаём кнопку
|
||
mcall
|
||
|
||
; пишем текст на кнопке
|
||
pushad ; спасаем регистры
|
||
shr ecx, 16
|
||
and ebx, 0xffff0000
|
||
add ebx, ecx ; ebx = [x] shl 16 + [y];
|
||
add ebx, 10*65536+4 ; ebx += смещение относительно края кнопки;
|
||
mov ecx, [sc.work_text] ; шрифт и цвет
|
||
or ecx, font
|
||
add edx, -10 ; edx = номер кнопки;
|
||
imul edx, string_length ; edx *= длина строки;
|
||
add edx, text ; edx += text; теперь в edx адрес строки
|
||
mov esi, string_length ; в esi - длина строки
|
||
mov eax, 4 ; функция 4 - вывод текста
|
||
mcall
|
||
popad
|
||
|
||
inc edx ; номер кнопки++;
|
||
add ecx,15*65536 ; увеличим смещение по y
|
||
dec edi ; уменьшим счётчик
|
||
jnz newbtn ; если не ноль, повторим всё ещё раз
|
||
|
||
mov eax,12 ; закончили "рисовать"
|
||
mov ebx,2
|
||
mcall
|
||
|
||
ret ; возврат
|
||
|
||
|
||
|
||
; ДАННЫЕ ПРОГРАММЫ
|
||
DATA
|
||
|
||
macro strtbl name, [string]
|
||
{
|
||
common
|
||
label name dword
|
||
forward
|
||
local str
|
||
dd str
|
||
forward
|
||
str db string
|
||
}
|
||
|
||
strtbl startapps ,\
|
||
<"/sys/PIC4",0> ,\
|
||
<"/sys/DESKTOP",0> ,\
|
||
<"/sys/ICON",0>,\
|
||
<"/sys/SETUP",0> ,\
|
||
<"/sys/VRR",0> ,\
|
||
<"/sys/CPU",0>
|
||
|
||
sz title, "KolibriOS"
|
||
|
||
lsz text,\
|
||
en, 'Background ',\
|
||
en, 'Desktop ',\
|
||
en, 'Icon manager',\
|
||
en, 'Device setup',\
|
||
en, 'VRR ',\
|
||
en, 'Processes ',\
|
||
\
|
||
ru, 'Генератор обоев ',\
|
||
ru, 'Настройка окон ',\
|
||
ru, 'Управление иконками ',\
|
||
ru, 'Настройка устройств ',\
|
||
ru, 'Настройка монитора ',\
|
||
ru, 'Процессы '
|
||
|
||
start_info:
|
||
.mode dd 7
|
||
dd 0
|
||
.params dd 0
|
||
dd 0
|
||
dd 0
|
||
db 0
|
||
dd start_info.path
|
||
|
||
; НЕИНИЦИАЛИЗИРОВАННЫЕ ДАННЫЕ
|
||
UDATA
|
||
processes dd ? ; количество процессов в системе
|
||
curx1 dd ? ; координаты курсора
|
||
cury1 dd ?
|
||
curx dd ? ; координаты окна меню
|
||
cury dd ?
|
||
|
||
menu_opened db ? ; открыто меню или нет? (1-да, 0-нет)
|
||
|
||
align 4
|
||
start_info.path rb 256
|
||
|
||
sc system_colors ; системные цвета
|
||
procinfo process_information ; информация о процессе
|
||
|
||
rb 1024 ; стэк для окна меню - хватит и 1 Кб
|
||
align 32
|
||
stack_wnd:
|
||
|
||
|
||
MEOS_APP_END
|
||
; КОНЕЦ ПРОГРАММЫ |