Subversion Repositories Kolibri OS

Rev

Rev 604 | Rev 1411 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;
  2. ;   DESKTOP CONTEXT MENU
  3. ;   written by Ivan Poddubny
  4. ;
  5. ;   Автор - Иван Поддубный
  6. ;   e-mail: ivan-yar@bk.ru
  7. ;
  8. ;   Compile with flat assembler
  9. ;
  10. include 'lang.inc'
  11. include '..\..\..\macros.inc'
  12.  
  13. meos_app_start
  14. code
  15.  
  16.   mov   eax, 48                   ; получить системные цвета
  17.   mov   ebx, 3
  18.   mov   ecx, sc                   ;  адрес структуры
  19.   mov   edx, sizeof.system_colors ;  и ее размер
  20.   mcall
  21.  
  22.   mov   eax,40       ; установим маску событий
  23.   mov   ebx,100000b  ; нас интересует только мышь
  24.   mcall
  25.  
  26. still:               ; главный цикл основного процесса
  27.  
  28.   mov   eax,10       ; ждём события
  29.   mcall
  30.  
  31.   mov   eax,37       ; какие нажаты кпопки?
  32.   mov   ebx,2
  33.   mcall
  34.  
  35.   cmp   eax,ebx        ; если не правая, возврат
  36.   jne   still
  37.  
  38. ;---поехали!---
  39.  
  40. ;  mov   eax,37       ; это для отладки - если мышь в точке (0;0), закроемся
  41. ;  xor   ebx,ebx
  42. ;  mcall
  43. ;  test  eax,eax      ; курсор в точке (0;0), т.е. eax = 0
  44. ;  je    exit
  45.  
  46.  
  47.   mov   eax,9        ; получим число процессов в системе
  48.   mov   ebx,procinfo
  49.   xor   ecx,ecx
  50.   mcall
  51.  
  52.   inc   eax          ; теперь в eax содержится число процессов + 1
  53.   mov   [processes],eax
  54.   mov   ecx,1
  55.  
  56.  new_process:
  57.   pushad
  58.   mov   eax,9        ; получим информацию о процессе; номер - в ecx
  59.   mov   ebx,procinfo
  60.   mcall
  61.   mov   eax,37       ; координаты курсора
  62.   xor   ebx,ebx
  63.   mcall
  64.   mov   ebx,eax                  ; eax = cursor_x
  65.   shr   eax,16                   ; ebx = cursor_y
  66.   and   ebx,0xffff
  67.   mov   [curx1],eax              ; curx1 = cursor_x
  68.   mov   [cury1],ebx              ; cury1 = cursor_y
  69. ; \begin{diamond}[18.09.2006]
  70. ; ignore minimized windows
  71.         test    [procinfo.wnd_state], 2
  72.         jnz     ne_goden
  73. ; \end{diamond}[18.09.2006]
  74.   mov   eax,[procinfo.box.left]   ; eax = wnd_x_start
  75.   mov   ebx,[procinfo.box.top]    ; ebx = wnd_y_start
  76.  
  77.   mov   ecx,[procinfo.box.width]
  78.   add   ecx,eax                  ; ecx = wnd_x_end
  79.   mov   edx,[procinfo.box.height]
  80.   add   edx,ebx                  ; ecx = wnd_y_end
  81.  
  82.   cmp   eax,[curx1]  ; wnd_x_start > cursor_x => курсор левее окна
  83.   jg    ne_goden
  84.   cmp   ecx,[curx1]  ; wnd_x_end   < cursor_x => курсор правее окна
  85.   jl    ne_goden
  86.   cmp   ebx,[cury1]  ; wnd_y_start > cursor_y => курсор выше окна
  87.   jg    ne_goden
  88.   cmp   edx,[cury1]  ; wnd_y_end   < cursor_y => курсор ниже окна
  89.   jl    ne_goden
  90.  
  91. goden:               ; клик был внутри какого-то окна, поэтому ничего не делаем
  92.   popad
  93.   jmp   still
  94.  
  95. ne_goden:            ; клик был снаружи рассматриваемого окна, поэтому
  96.   popad
  97.   inc   ecx
  98.   cmp   ecx,[processes]
  99.   jl    new_process  ; либо сморим следующее окно, либо запускаем меню
  100.  
  101.  
  102. @@:             ; подождём, пока пользователь не отпустил правую кнопку мыши
  103.   mov   eax,37
  104.   mov   ebx,2   ; функция 37-2:
  105.   mcall    ;   нажаты ли кнопки мыши?
  106.   test  eax,ebx ; если отпустил, (eax != 2)
  107.   jz    @f      ;   идём в начало главного цикла
  108.  
  109.   mov   eax,5   ; иначе
  110.   ;mov   ebx,2   ;   подождём 2 мс
  111.   mcall
  112.  
  113.   jmp   @b      ;   и проверим мышь опять
  114. @@:
  115.  
  116. ; если уже было открыто меню, нужно подождать, пока оно закроется:
  117. @@:
  118.   cmp   [menu_opened],0
  119.   je    @f
  120.   mov   eax,5
  121.   mov   ebx,3  ; ждём 3 мс
  122.   mcall
  123.   jmp   @b
  124. @@:
  125.  
  126.   mov   eax,51           ; а теперь можно смело запускать процесс (поток) меню
  127.   mov   ebx,1            ; создаём поток (thread)
  128.   mov   ecx,start_wnd    ; точка входа потока
  129.   mov   edx,stack_wnd    ; вершина стэка для потока
  130.   mcall
  131.  
  132.   jmp   still
  133.  
  134.  
  135.  
  136. exit_menu:            ; если выходим из меню, надо записать в [menu_opened] 0
  137.   mov   [menu_opened],0
  138. exit:                 ; сюда мы идём, когда выходим из основного процесса
  139.   or    eax,-1        ; eax = -1
  140.   mcall
  141.  
  142.  
  143.  
  144.  
  145. ; здесь стартует процесс меню
  146. start_wnd:
  147.   mov   [menu_opened],1
  148.   mov   eax,40      ; установим маску желаемых событий для этого процесса
  149.   mov   ebx,100101b ; меню + кнопки + перерисовка
  150.   mcall
  151.  
  152. red:
  153.   call  draw_window
  154.  
  155. still2:             ; главный цикл процесса меню
  156.  
  157.   mov   eax,10      ; ждём события
  158.   mcall
  159.  
  160.   cmp   eax,1       ; перерисовка?
  161.   je    red
  162.   cmp   eax,3       ; кнопка?
  163.   je    button
  164.   cmp   eax,6       ; мышь?
  165.   je    mouse
  166.  
  167.   jmp   still2      ; вернёмся в начало главного цикла
  168.  
  169.  
  170. ; ОБРАБОТЧИК МЫШИ
  171. mouse:            ; когда пользователь нажмёт кнопку мыши, закроемся
  172.   mov   eax,37
  173.   mov   ebx,2     ; какие кнопки нажаты?
  174.   mcall
  175.   test  eax,eax   ; никакие? - тогда прекрасно! вернёмся в гланый цикл
  176.   jz    still2
  177.   jmp   exit_menu ; а если всё-таки нажаты - закроем окно
  178.  
  179.  
  180. ; НАЖАТА КНОПКА
  181. button:
  182.   mov   eax,17        ; получить идентификатор нажатой кнопки
  183.   mcall
  184.  
  185.   sub   ah,10         ; сравниваем с 10
  186.   jl    nofuncbtns    ; если меньше - закрываем меню
  187.  
  188.   movzx ebx,ah        ; получили номер программы в списке в ebx
  189.   mov   esi, [startapps + ebx*4]
  190.   mov   edi, start_info.path
  191.   cld
  192.  @@:
  193.   lodsb
  194.   stosb
  195.   test  al, al
  196.   jnz   @b
  197.   mcall 70, start_info
  198.  
  199. ;  mov   eax,5         ; подождём, пока программа запуститься
  200. ;  mov   ebx,1         ; а то её окно не будет отрисовано (баг в ядре???)
  201. ;  mcall          ; раскомментируйте эти строки, если у вас проблемы
  202.                        ; с отрисовкой
  203.  
  204. nofuncbtns:           ; закрываем меню
  205.   jmp   exit_menu
  206.  
  207.  
  208.  
  209. _BTNS_            = 6     ; количество кнопок ("пунктов меню")
  210.  
  211. if lang eq ru
  212.   font            = 0x00000000
  213.   string_length   = 20          ; длина строки
  214.   wnd_x_size      = 133         ; ширина окна
  215.   title_pos      = 36 shl 16 + 7
  216. else
  217.   font            = 0x10000000
  218.   string_length   = 12          ; длина строки
  219.   wnd_x_size      = 105         ; ширина окна
  220.   title_pos      = 23 shl 16 + 7
  221. end if
  222.  
  223. ;*******************************
  224. ;********  РИСУЕМ ОКНО  ********
  225. ;*******************************
  226.  
  227. draw_window:
  228.  
  229.   mov   eax,12           ; начинаем "рисовать"
  230.   mov   ebx,1
  231.   mcall
  232.  
  233.   mov   eax,[curx1]      ; текущие координаты курсора
  234.   mov   [curx],eax       ; запишем в координаты окна
  235.   mov   eax,[cury1]
  236.   mov   [cury],eax
  237.  
  238. ; теперь будем считать координаты окна, чтобы оно за край экрана не вылезло
  239.   mov   eax,14                ; получим размер экрана
  240.   mcall
  241.   mov   ebx,eax
  242.   shr   eax,16                ; в eax - x_screen
  243.   and   ebx,0xffff            ; в ebx - y_screen
  244.   add   eax,-wnd_x_size       ; eax = [x_screen - ширина окна]
  245.   add   ebx,-_BTNS_*15-21     ; ebx = [y_screen - высота окна]
  246.  
  247.   cmp   eax,[curx]
  248.   jg    .okx                  ; если окно слишком близко к правому краю,
  249.   add   [curx],-wnd_x_size    ; сдвинем его влево на 100
  250.  .okx:
  251.  
  252.   cmp   ebx, [cury]
  253.   jg    .oky                  ; по вертикали точно также
  254.   add   [cury], -_BTNS_*15-21
  255.  .oky:
  256.  
  257.   xor   eax, eax           ; функция 0 - создать окно
  258.   mov   ebx, [curx]        ;  ebx = [координата по x] shl 16 + [ширина]
  259.   shl   ebx, 16
  260.   add   ebx, wnd_x_size
  261.   mov   ecx, [cury]        ;  ecx = [координата по y] shl 16 + [высота]
  262.   shl   ecx, 16
  263.   add   ecx, _BTNS_*15+21
  264.   mov   edx, [sc.work]     ;  цвет рабочей области
  265.   mov   esi, [sc.grab]     ;  цвет заголовка
  266.   or    esi, 0x81000000
  267.   mov   edi, [sc.frame]    ;  цвет рамки
  268.   mcall
  269.  
  270.   mov   eax, 4             ; заголовок
  271.   mov   ebx, title_pos    ;  [x] shl 16 + [y]
  272.   mov   ecx, [sc.grab_text];  шрифт и цвет (серый)
  273.   or    ecx, 0x10000000
  274. ;  add   ecx, -0x333333
  275.   push  ecx
  276.   push  ecx
  277.   xor   edx,edx
  278. .dec_color:
  279.   sub   byte [esp+edx], 0x33
  280.   jae   @f
  281.   mov   byte [esp+edx], 0
  282. @@:
  283.   inc   edx
  284.   jnp   .dec_color
  285.   pop   ecx
  286.   mov   edx, title        ;  адрес заголовка
  287.   mov   esi, title.size   ;  длина заголовка ("M E N U")
  288.   mcall
  289.   pop   ecx
  290.   add   ebx, 1 shl 16      ;  сдвинем вправо на 1
  291.   mcall
  292.  
  293.   mov   ebx, 1*65536+wnd_x_size-2  ; начинаем делать кнопки
  294.   mov   ecx, 20*65536+15
  295.   mov   edx, 10 or 0x40000000 ; бит 30 установлен => кнопка не рисуется
  296.  
  297.   mov   edi,_BTNS_           ; количество кнопок (счётчик)
  298.  
  299.  newbtn:                     ; начало цикла
  300.   mov   eax,8                ;  создаём кнопку
  301.   mcall
  302.  
  303.                              ;  пишем текст на кнопке
  304.   pushad                     ;   спасаем регистры
  305.   shr   ecx, 16
  306.   and   ebx, 0xffff0000
  307.   add   ebx, ecx             ;   ebx = [x] shl 16 + [y];
  308.   add   ebx, 10*65536+4      ;   ebx += смещение относительно края кнопки;
  309.   mov   ecx, [sc.work_text]  ;   шрифт и цвет
  310.   or    ecx, font
  311.   add   edx, -10             ;   edx = номер кнопки;
  312.   imul  edx, string_length   ;   edx *= длина строки;
  313.   add   edx, text            ;   edx += text;  теперь в edx адрес строки
  314.   mov   esi, string_length   ;   в esi - длина строки
  315.   mov   eax, 4               ;   функция 4 - вывод текста
  316.   mcall
  317.   popad
  318.  
  319.   inc   edx                  ;  номер кнопки++;
  320.   add   ecx,15*65536         ;  увеличим смещение по y
  321.   dec   edi                  ;  уменьшим счётчик
  322.   jnz   newbtn               ; если не ноль, повторим всё ещё раз
  323.  
  324.   mov   eax,12               ; закончили "рисовать"
  325.   mov   ebx,2
  326.   mcall
  327.  
  328. ret                          ; возврат
  329.  
  330.  
  331.  
  332. ; ДАННЫЕ ПРОГРАММЫ
  333. DATA
  334.  
  335.   macro strtbl name, [string]
  336.   {
  337.    common
  338.      label name dword
  339.    forward
  340.      local str
  341.      dd str
  342.    forward
  343.      str db string
  344.   }
  345.  
  346.   strtbl startapps       ,\
  347.     <"/sys/PIC4",0>     ,\
  348.     <"/sys/DESKTOP",0>  ,\
  349.     <"/sys/ICONMNGR",0>,\
  350.     <"/sys/SETUP",0>    ,\
  351.     <"/sys/VRR",0> ,\
  352.     <"/sys/CPU",0>
  353.    
  354.   sz title, "KolibriOS"
  355.  
  356.   lsz text,\
  357.     en, 'Background  ',\
  358.     en, 'Desktop     ',\
  359.     en, 'Icon manager',\
  360.     en, 'Device setup',\
  361.     en, 'VRR         ',\
  362.     en, 'Processes   ',\
  363.     \
  364.     ru, 'Генератор обоев     ',\
  365.     ru, 'Настройка окон      ',\
  366.     ru, 'Управление иконками ',\
  367.     ru, 'Настройка устройств ',\
  368.     ru, 'Настройка монитора  ',\
  369.     ru, 'Процессы            '
  370.  
  371. start_info:
  372.         .mode   dd      7
  373.                 dd      0
  374.         .params dd      0
  375.                 dd      0
  376.                 dd      0
  377.                 db      0
  378.                 dd      start_info.path
  379.  
  380. ; НЕИНИЦИАЛИЗИРОВАННЫЕ ДАННЫЕ
  381. UDATA
  382.   processes   dd ?              ; количество процессов в системе
  383.   curx1       dd ?              ; координаты курсора
  384.   cury1       dd ?
  385.   curx        dd ?              ; координаты окна меню
  386.   cury        dd ?
  387.  
  388.   menu_opened db ?              ; открыто меню или нет? (1-да, 0-нет)
  389.  
  390. align 4
  391. start_info.path rb 256
  392.  
  393.   sc       system_colors        ; системные цвета
  394.   procinfo process_information  ; информация о процессе
  395.  
  396.   rb 1024                       ; стэк для окна меню - хватит и 1 Кб
  397.   align 32
  398.   stack_wnd:
  399.  
  400.  
  401. MEOS_APP_END
  402. ; КОНЕЦ ПРОГРАММЫ