1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
8,43 → 8,85 |
|
$Revision$ |
|
|
;============================================================================== |
;///// public functions /////////////////////////////////////////////////////// |
;============================================================================== |
|
macro FuncTable name, [label] |
window.BORDER_SIZE = 5 |
|
macro FuncTable name, table_name, [label] |
{ |
common |
align 4 |
\label name#.ftable dword |
\label name#.#table_name dword |
forward |
dd name#.#label |
common |
name#.sizeof.ftable = $ - name#.ftable |
name#.sizeof.#table_name = $ - name#.#table_name |
} |
|
iglobal |
FuncTable syscall_display_settings, \ |
00, 01, 02, 03, 04, 05, 06, 07, 08 |
endg |
|
uglobal |
common_colours rd 32 |
new_window_starting dd ? |
latest_window_touch dd ? |
latest_window_touch_delta dd ? |
old_window_pos BOX |
new_window_pos BOX |
draw_limits RECT |
bPressedMouseXY_W db ? |
do_resize db ? |
do_resize_from_corner db ? |
reposition db ? |
endg |
|
align 4 |
;------------------------------------------------------------------------------ |
syscall_draw_window: ;///// system function 0 ///////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
mov eax, edx |
shr eax, 24 |
and al, 0x0f |
cmp al, 5 |
jae .exit |
|
push eax |
inc [mouse_pause] |
call [_display.disable_mouse] |
call window._.sys_set_window |
call [_display.disable_mouse] |
pop eax |
|
or al, al |
jnz @f |
|
; type I - original style |
call drawwindow_I |
jmp window._.draw_window_caption.2 |
|
@@: dec al |
jnz @f |
|
; type II - only reserve area, no draw |
call sys_window_mouse |
dec [mouse_pause] |
call [draw_pointer] |
jmp .exit |
|
@@: dec al |
jnz @f |
|
; type III - new style |
call drawwindow_III |
jmp window._.draw_window_caption.2 |
|
; type IV & V - skinned window (resizable & not) |
@@: mov eax, [TASK_COUNT] |
movzx eax, word[WIN_POS + eax * 2] |
cmp eax, [CURRENT_TASK] |
setz al |
movzx eax, al |
push eax |
call drawwindow_IV |
jmp window._.draw_window_caption.2 |
|
.exit: |
ret |
|
align 4 |
;------------------------------------------------------------------------------ |
syscall_display_settings: ;///// system function 48 /////////////////////////// |
;------------------------------------------------------------------------------ |
;; Redraw screen: |
269,6 → 311,83 |
|
align 4 |
;------------------------------------------------------------------------------ |
syscall_move_window: ;///// system function 67 //////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
mov edi, [CURRENT_TASK] |
shl edi, 5 |
add edi, window_data |
|
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jnz .exit |
|
cmp ebx, -1 |
jne @f |
mov ebx, [edi + WDATA.box.left] |
@@: cmp ecx, -1 |
jne @f |
mov ecx, [edi + WDATA.box.top] |
@@: cmp edx, -1 |
jne @f |
mov edx, [edi + WDATA.box.width] |
@@: cmp esi, -1 |
jne @f |
mov esi, [edi + WDATA.box.height] |
|
@@: push esi edx ecx ebx |
mov eax, esp |
mov bl, [edi + WDATA.fl_wstate] |
call window._.set_window_box |
add esp, BOX.sizeof |
|
; NOTE: do we really need this? to be reworked |
; mov byte[DONT_DRAW_MOUSE], 0 ; mouse pointer |
; mov byte[MOUSE_BACKGROUND], 0 ; no mouse under |
; mov byte[MOUSE_DOWN], 0 ; react to mouse up/down |
|
; NOTE: do we really need this? to be reworked |
; call [draw_pointer] |
|
.exit: |
ret |
|
align 4 |
;------------------------------------------------------------------------------ |
syscall_window_settings: ;///// system function 71 ///////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
dec ebx ; subfunction #1 - set window caption |
jnz .exit_fail |
|
; NOTE: only window owner thread can set its caption, |
; so there's no parameter for PID/TID |
|
mov edi, [CURRENT_TASK] |
shl edi, 5 |
|
mov [edi * 8 + SLOT_BASE + APPDATA.wnd_caption], ecx |
or [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION |
|
call window._.draw_window_caption |
|
xor eax, eax ; eax = 0 (success) |
ret |
|
; .get_window_caption: |
; dec eax ; subfunction #2 - get window caption |
; jnz .exit_fail |
|
; not implemented yet |
|
.exit_fail: |
xor eax, eax |
inc eax ; eax = 1 (fail) |
ret |
|
align 4 |
;------------------------------------------------------------------------------ |
set_window_defaults: ;///////////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
429,7 → 548,7 |
mov [edi + WDATA.box.height], eax |
|
.fix_client_box: |
call set_window_clientbox |
call window._.set_window_clientbox |
|
add edi, WDATA.sizeof |
loop .next_window |
439,97 → 558,25 |
|
align 4 |
;------------------------------------------------------------------------------ |
check_window_position: ;/////////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? Check if window is inside screen area |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA |
;------------------------------------------------------------------------------ |
push eax ebx ecx edx esi |
|
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
|
mov esi, [Screen_Max_X] |
cmp ecx, esi |
ja .fix_width |
|
.check_left: |
or eax, eax |
jl .fix_left_low |
add eax, ecx |
cmp eax, esi |
jg .fix_left_high |
|
.check_height: |
mov esi, [Screen_Max_Y] |
cmp edx, esi |
ja .fix_height |
|
.check_top: |
or ebx, ebx |
jl .fix_top_low |
add ebx, edx |
cmp ebx, esi |
jg .fix_top_high |
|
.exit: |
pop esi edx ecx ebx eax |
ret |
|
.fix_width: |
mov ecx, esi |
mov [edi + WDATA.box.width], esi |
jmp .check_left |
|
.fix_left_low: |
xor eax, eax |
mov [edi + WDATA.box.left], eax |
jmp .check_height |
|
.fix_left_high: |
mov eax, esi |
sub eax, ecx |
mov [edi + WDATA.box.left], eax |
jmp .check_height |
|
.fix_height: |
mov edx, esi |
mov [edi + WDATA.box.height], esi |
jmp .check_top |
|
.fix_top_low: |
xor ebx, ebx |
mov [edi + WDATA.box.top], ebx |
jmp .exit |
|
.fix_top_high: |
mov ebx, esi |
sub ebx, edx |
mov [edi + WDATA.box.top], ebx |
jmp .exit |
|
align 4 |
;------------------------------------------------------------------------------ |
sys_window_mouse: ;//////////////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
push eax |
|
mov eax, [timer_ticks] |
cmp [new_window_starting], eax |
jb .exit |
|
mov byte[MOUSE_BACKGROUND], 0 |
mov byte[DONT_DRAW_MOUSE], 0 |
|
mov [new_window_starting], eax |
|
.exit: |
pop eax |
; NOTE: commented out since doesn't provide necessary functionality |
; anyway, to be reworked |
; push eax |
; |
; mov eax, [timer_ticks] |
; cmp [new_window_starting], eax |
; jb .exit |
; |
; mov byte[MOUSE_BACKGROUND], 0 |
; mov byte[DONT_DRAW_MOUSE], 0 |
; |
; mov [new_window_starting], eax |
; |
; .exit: |
; pop eax |
ret |
|
align 4 |
809,6 → 856,13 |
;------------------------------------------------------------------------------ |
;? Activate window, redrawing if necessary |
;------------------------------------------------------------------------------ |
push -1 |
mov eax, [TASK_COUNT] |
lea eax, [WIN_POS + eax * 2] |
cmp eax, esi |
pop eax |
je .exit |
|
; is it overlapped by another window now? |
push ecx |
call window._.check_window_draw |
841,15 → 895,19 |
|
; tell application to redraw itself |
mov [edi + WDATA.fl_redraw], 1 |
mov byte[MOUSE_DOWN], 0 |
ret |
xor eax, eax |
jmp .exit |
|
.do_not_draw: |
; no it's not, just activate the window |
call window._.window_activate |
mov byte[MOUSE_DOWN], 0 |
mov byte[MOUSE_BACKGROUND], 0 |
mov byte[DONT_DRAW_MOUSE], 0 |
xor eax, eax |
|
.exit: |
mov byte[MOUSE_DOWN], 0 |
inc eax |
ret |
|
align 4 |
940,16 → 998,15 |
ret |
|
align 4 |
; TODO: remove this proc |
;------------------------------------------------------------------------------ |
checkwindows: ;//////////////////////////////////////////////////////////////// |
window_check_events: ;///////////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? Check for user-initiated window operations |
;? <description> |
;------------------------------------------------------------------------------ |
pushad |
|
; do we have window minimize/restore request? |
cmp [window_minimize], 0 |
je .check_for_mouse_buttons_state |
je .exit |
|
; okay, minimize or restore top-most window and exit |
mov eax, [TASK_COUNT] |
958,443 → 1015,456 |
dec bl |
jnz @f |
call minimize_window |
jmp .check_for_mouse_buttons_state |
jmp .exit |
|
@@: call restore_minimized_window |
|
.check_for_mouse_buttons_state: |
; do we have any mouse buttons pressed? |
cmp byte[BTN_DOWN], 0 |
jne .mouse_buttons_pressed |
.exit: |
ret |
|
mov [bPressedMouseXY_W], 0 |
jmp .exit |
align 4 |
;------------------------------------------------------------------------------ |
sys_window_maximize_handler: ;///////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> esi = process slot |
;------------------------------------------------------------------------------ |
mov edi, esi |
shl edi, 5 |
add edi, window_data |
|
.mouse_buttons_pressed: |
; yes we do, iterate and ... |
mov esi, [TASK_COUNT] |
inc esi |
; can window change its height? |
mov dl, [edi + WDATA.fl_wstyle] |
and dl, 0x0f |
cmp dl, 0x04 |
je .exit |
|
cmp [bPressedMouseXY_W], 1 |
ja .next_window |
inc [bPressedMouseXY_W] |
jnc .next_window |
push dword[MOUSE_X] |
pop dword[mx] |
; toggle normal/maximized window state |
mov bl, [edi + WDATA.fl_wstate] |
xor bl, WSTATE_MAXIMIZED |
|
.next_window: |
cmp esi, 2 |
jb .exit |
; calculate and set appropriate window bounds |
test bl, WSTATE_MAXIMIZED |
jz .restore_size |
|
dec esi |
mov eax, [screen_workarea.left] |
mov ecx, [screen_workarea.top] |
push [screen_workarea.bottom] \ |
[screen_workarea.right] \ |
ecx \ |
eax |
sub [esp + BOX.width], eax |
sub [esp + BOX.height], ecx |
mov eax, esp |
jmp .set_box |
|
; is that window not minimized? |
movzx edi, word[WIN_POS + esi * 2] |
shl edi, 5 |
add edi, window_data |
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED |
jnz .next_window |
.restore_size: |
mov eax, esi |
shl eax, 8 |
add eax, SLOT_BASE + APPDATA.saved_box |
push [eax + BOX.height] \ |
[eax + BOX.width] \ |
[eax + BOX.top] \ |
[eax + BOX.left] |
mov eax, esp |
|
movzx eax, [mx] |
movzx ebx, [my] |
.set_box: |
test bl, WSTATE_ROLLEDUP |
jz @f |
|
; is the cursor inside screen bounds of that window? |
mov ecx, [edi + WDATA.box.left] |
mov edx, [edi + WDATA.box.top] |
cmp eax, ecx |
jl .next_window |
cmp ebx, edx |
jl .next_window |
add ecx, [edi + WDATA.box.width] |
add edx, [edi + WDATA.box.height] |
cmp eax, ecx |
jge .next_window |
cmp ebx, edx |
jge .next_window |
xchg eax, ecx |
call window._.get_rolledup_height |
mov [ecx + BOX.height], eax |
xchg eax, ecx |
|
; is that a top-most (which means active) window? |
cmp esi, [TASK_COUNT] |
je .check_for_moving_or_resizing |
@@: call window._.set_window_box |
add esp, BOX.sizeof |
|
; no it's not, did we just press mouse button down above it or was it |
; already pressed before? |
cmp [bPressedMouseXY_W], 1 |
ja .exit |
.exit: |
ret |
|
; okay, we just pressed the button, activate this window and exit |
lea esi, [WIN_POS + esi * 2] |
call waredraw |
jmp .exit |
align 4 |
;------------------------------------------------------------------------------ |
sys_window_rollup_handler: ;/////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> esi = process slot |
;------------------------------------------------------------------------------ |
mov edx, esi |
shl edx, 8 |
add edx, SLOT_BASE |
|
.check_for_moving_or_resizing: |
; is that window movable? |
test byte[edi + WDATA.cl_titlebar + 3], 0x01 |
jnz .exit |
; toggle normal/rolled up window state |
mov bl, [edi + WDATA.fl_wstate] |
xor bl, WSTATE_ROLLEDUP |
|
; yes it is, is it rolled up? |
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP |
jnz .check_for_cursor_on_caption |
; calculate and set appropriate window bounds |
test bl, WSTATE_ROLLEDUP |
jz .restore_size |
|
; no it's not, can it be resized then? |
mov [do_resize_from_corner], 0 |
mov dl, [edi + WDATA.fl_wstyle] |
and dl, 0x0f |
cmp dl, 0x00 |
je .check_for_cursor_on_caption |
cmp dl, 0x01 |
je .check_for_cursor_on_caption |
cmp dl, 0x04 |
je .check_for_cursor_on_caption |
call window._.get_rolledup_height |
push eax \ |
[edi + WDATA.box.width] \ |
[edi + WDATA.box.top] \ |
[edi + WDATA.box.left] |
mov eax, esp |
jmp .set_box |
|
; are we going to resize it? |
mov edx, [edi + WDATA.box.top] |
add edx, [edi + WDATA.box.height] |
sub edx, 6 |
cmp ebx, edx |
jl .check_for_cursor_on_caption |
.restore_size: |
test bl, WSTATE_MAXIMIZED |
jnz @f |
add esp, -BOX.sizeof |
lea eax, [edx + APPDATA.saved_box] |
jmp .set_box |
|
; yes we do, remember that |
mov [do_resize_from_corner], 1 |
jmp .set_move_resize_flag |
@@: mov eax, [screen_workarea.top] |
push [screen_workarea.bottom] \ |
[edi + WDATA.box.width] \ |
eax \ |
[edi + WDATA.box.left] |
sub [esp + BOX.height], eax |
mov eax, esp |
|
.check_for_cursor_on_caption: |
; is the cursor inside window titlebar? |
push eax |
call window._.get_titlebar_height |
add eax, [edi + WDATA.box.top] |
cmp ebx, eax |
pop eax |
jge .exit |
.set_box: |
call window._.set_window_box |
add esp, BOX.sizeof |
|
; calculate duration between two clicks |
mov ecx, [timer_ticks] |
mov edx, ecx |
sub edx, [latest_window_touch] |
mov [latest_window_touch], ecx |
mov [latest_window_touch_delta], edx |
ret |
|
.set_move_resize_flag: |
mov cl, [BTN_DOWN] |
mov [do_resize], cl |
align 4 |
;------------------------------------------------------------------------------ |
sys_window_start_moving_handler: ;///////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> eax = old (original) window box |
;> esi = process slot |
;------------------------------------------------------------------------------ |
mov edi, eax |
call window._.draw_negative_box |
|
mov ecx, [edi + WDATA.box.left] |
mov edx, [edi + WDATA.box.top] |
ret |
|
push ecx edx |
mov [draw_limits.left], ecx |
mov [draw_limits.top], edx |
add ecx, [edi + WDATA.box.width] |
add edx, [edi + WDATA.box.height] |
mov [draw_limits.right], ecx |
mov [draw_limits.bottom], edx |
pop edx ecx |
align 4 |
;------------------------------------------------------------------------------ |
sys_window_end_moving_handler: ;/////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> eax = old (original) window box |
;> ebx = new (final) window box |
;> esi = process slot |
;------------------------------------------------------------------------------ |
mov edi, ebx |
call window._.draw_negative_box |
|
; calculate window-relative cursor coordinates |
sub eax, ecx |
sub ebx, edx |
mov edi, esi |
shl edi, 5 |
add edi, window_data |
|
push dword[MOUSE_X] |
pop dword[WIN_TEMP_XY] |
mov eax, ebx |
mov bl, [edi + WDATA.fl_wstate] |
call window._.set_window_box |
ret |
|
; save old window coordinates |
push eax |
mov eax, [edi + WDATA.box.left] |
mov [old_window_pos.left], eax |
mov [new_window_pos.left], eax |
mov eax, [edi + WDATA.box.top] |
mov [old_window_pos.top], eax |
mov [new_window_pos.top], eax |
mov eax, [edi + WDATA.box.width] |
mov [old_window_pos.width], eax |
mov [new_window_pos.width], eax |
mov eax, [edi + WDATA.box.height] |
mov [old_window_pos.height], eax |
mov [new_window_pos.height], eax |
pop eax |
align 4 |
;------------------------------------------------------------------------------ |
sys_window_moving_handler: ;/////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> eax = old (from previous call) window box |
;> ebx = new (current) window box |
;> esi = process_slot |
;------------------------------------------------------------------------------ |
mov edi, eax |
call window._.draw_negative_box |
mov edi, ebx |
call window._.draw_negative_box |
ret |
|
; draw negative moving/sizing frame |
call window._.draw_window_frames |
;============================================================================== |
;///// private functions ////////////////////////////////////////////////////// |
;============================================================================== |
|
mov [reposition], 0 |
mov byte[MOUSE_DOWN], 1 |
iglobal |
FuncTable syscall_display_settings, ftable, \ |
00, 01, 02, 03, 04, 05, 06, 07, 08 |
|
.next_mouse_state_check: |
; process OS events |
mov byte[DONT_DRAW_MOUSE], 1 |
call checkidle |
call checkVga_N13 |
mov byte[MOUSE_BACKGROUND], 0 |
call [draw_pointer] |
pushad |
call stack_handler |
popad |
align 4 |
window_topleft dd \ |
1, 21, \ ;type 0 |
0, 0, \ ;type 1 |
5, 20, \ ;type 2 |
5, ?, \ ;type 3 {set by skin} |
5, ? ;type 4 {set by skin} |
endg |
|
; did cursor position change? |
mov esi, [WIN_TEMP_XY] |
cmp esi, [MOUSE_X] |
je .check_for_new_mouse_buttons_state |
;uglobal |
; NOTE: commented out since doesn't provide necessary functionality anyway, |
; to be reworked |
; new_window_starting dd ? |
;endg |
|
; yes it did, calculate window-relative cursor coordinates |
movzx ecx, word[MOUSE_X] |
movzx edx, word[MOUSE_Y] |
sub ecx, eax |
sub edx, ebx |
|
align 4 |
;------------------------------------------------------------------------------ |
window._.invalidate_screen: ;////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> eax = old (original) window box |
;> ebx = new (final) window box |
;> edi = pointer to WDATA struct |
;------------------------------------------------------------------------------ |
push eax ebx |
|
; we're going to draw new frame, erasing the old one |
call window._.draw_window_frames |
; TODO: do we really need `draw_limits`? |
mov ecx, [eax + BOX.left] |
mov edx, [ebx + BOX.left] |
cmp ecx, edx |
jle @f |
xchg ecx, edx |
@@: mov [draw_limits.left], ecx |
mov ecx, [eax + BOX.width] |
cmp ecx, [ebx + BOX.width] |
jae @f |
mov ecx, [ebx + BOX.width] |
@@: add ecx, edx |
mov [draw_limits.right], ecx |
mov ecx, [eax + BOX.top] |
mov edx, [ebx + BOX.top] |
cmp ecx, edx |
jle @f |
xchg ecx, edx |
@@: mov [draw_limits.top], ecx |
mov ecx, [eax + BOX.height] |
cmp ecx, [ebx + BOX.height] |
jae @f |
mov ecx, [ebx + BOX.height] |
@@: add ecx, edx |
mov [draw_limits.bottom], ecx |
|
; are we moving it right now? |
cmp [do_resize_from_corner], 0 |
jne .resize_window |
; recalculate screen buffer at old position |
push ebx |
mov edx, [eax + BOX.height] |
mov ecx, [eax + BOX.width] |
mov ebx, [eax + BOX.top] |
mov eax, [eax + BOX.left] |
add ecx, eax |
add edx, ebx |
call calculatescreen |
pop eax |
|
; yes we do, check if it's inside the screen area |
mov eax, [Screen_Max_X] |
mov ebx, [Screen_Max_Y] |
; recalculate screen buffer at new position |
mov edx, [eax + BOX.height] |
mov ecx, [eax + BOX.width] |
mov ebx, [eax + BOX.top] |
mov eax, [eax + BOX.left] |
add ecx, eax |
add edx, ebx |
call calculatescreen |
|
mov [new_window_pos.left], 0 |
or ecx, ecx |
jle .check_for_new_vert_cursor_pos |
mov [reposition], 1 |
sub eax, [new_window_pos.width] |
mov [new_window_pos.left], eax |
cmp ecx, eax |
jge .check_for_new_vert_cursor_pos |
mov [new_window_pos.left], ecx |
mov eax, edi |
call redrawscreen |
|
.check_for_new_vert_cursor_pos: |
mov [new_window_pos.top], 0 |
or edx, edx |
jle .draw_new_window_frame |
mov [reposition], 1 |
sub ebx, [new_window_pos.height] |
mov [new_window_pos.top], ebx |
cmp edx, ebx |
jge .draw_new_window_frame |
mov [new_window_pos.top], edx |
jmp .draw_new_window_frame |
; tell window to redraw itself |
mov [edi + WDATA.fl_redraw], 1 |
|
.resize_window: |
push eax ebx edx |
pop ebx eax |
ret |
|
mov edx, edi |
sub edx, window_data |
lea edx, [SLOT_BASE + edx * 8] |
align 4 |
;------------------------------------------------------------------------------ |
window._.set_window_box: ;///////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> eax = pointer to BOX struct |
;> bl = new window state flags |
;> edi = pointer to WDATA struct |
;------------------------------------------------------------------------------ |
push eax ebx esi |
|
movzx eax, word[MOUSE_X] |
cmp eax, [edi + WDATA.box.left] |
jb .fix_new_vert_size |
sub eax, [edi + WDATA.box.left] |
cmp eax, 32 |
jge @f |
mov eax, 32 |
@@: mov [new_window_pos.width], eax |
add esp, -BOX.sizeof |
|
.fix_new_vert_size: |
call window._.get_rolledup_height |
mov ebx, eax |
movzx eax, word[MOUSE_Y] |
cmp eax, [edi + WDATA.box.top] |
jb .set_reposition_flag |
sub eax, [edi + WDATA.box.top] |
cmp eax, ebx |
jge @f |
mov eax, ebx |
@@: mov [new_window_pos.height], eax |
mov ebx, esp |
lea esi, [edi + WDATA.box] |
xchg eax, esi |
mov ecx, BOX.sizeof |
call memmove |
xchg eax, esi |
xchg ebx, esi |
call memmove |
xchg ebx, esi |
|
.set_reposition_flag: |
mov [reposition], 1 |
call window._.check_window_position |
call window._.set_window_clientbox |
call window._.invalidate_screen |
|
pop edx ebx eax |
add esp, BOX.sizeof |
|
.draw_new_window_frame: |
pop ebx eax |
mov cl, [esp + 4] |
mov ch, cl |
xchg cl, [edi + WDATA.fl_wstate] |
|
; draw new window moving/sizing frame |
call window._.draw_window_frames |
or cl, ch |
test cl, WSTATE_MAXIMIZED |
jnz .exit |
|
mov esi, [MOUSE_X] |
mov [WIN_TEMP_XY], esi |
mov eax, edi |
sub eax, window_data |
shl eax, 3 |
add eax, SLOT_BASE |
|
.check_for_new_mouse_buttons_state: |
; did user release mouse button(s)? |
cmp byte[BTN_DOWN], 0 |
jne .next_mouse_state_check |
lea ebx, [edi + WDATA.box] |
xchg esp, ebx |
|
; yes he did, moving/sizing is over |
mov byte[DONT_DRAW_MOUSE], 1 |
mov cl, 0 |
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jnz .check_other_actions |
pop [eax + APPDATA.saved_box.left] \ |
[eax + APPDATA.saved_box.top] \ |
[eax + APPDATA.saved_box.width] \ |
edx |
|
mov cl, [reposition] |
xchg esp, ebx |
|
; draw negative frame once again to hide it |
call window._.draw_window_frames |
test ch, WSTATE_ROLLEDUP |
jnz .exit |
|
; save new window bounds |
mov eax, [new_window_pos.left] |
mov [edi + WDATA.box.left], eax |
mov eax, [new_window_pos.top] |
mov [edi + WDATA.box.top], eax |
mov eax, [new_window_pos.width] |
mov [edi + WDATA.box.width], eax |
mov eax, [new_window_pos.height] |
mov [edi + WDATA.box.height], eax |
call set_window_clientbox |
mov [eax + APPDATA.saved_box.height], edx |
|
cmp cl, 1 |
jne .check_other_actions |
push esi edi ecx |
mov esi, edi |
mov ecx, 2 |
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP or WSTATE_MAXIMIZED |
jnz @f |
add ecx, 2 |
@@: sub edi, window_data |
shr edi, 5 |
shl edi, 8 |
add edi, SLOT_BASE + APPDATA.saved_box |
cld |
rep movsd |
pop ecx edi esi |
.exit: |
pop esi ebx eax |
ret |
|
.check_other_actions: |
mov [reposition], cl |
align 4 |
;------------------------------------------------------------------------------ |
window._.set_window_clientbox: ;/////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA struct |
;------------------------------------------------------------------------------ |
push eax ecx edi |
|
pushad |
mov eax, [_skinh] |
mov [window_topleft + 8 * 3 + 4], eax |
mov [window_topleft + 8 * 4 + 4], eax |
|
mov dl, [edi + WDATA.fl_wstyle] |
and dl, 0x0f |
cmp dl, 0x00 |
je .check_if_window_fits_screen |
cmp dl, 0x01 |
je .check_if_window_fits_screen |
mov ecx, edi |
sub edi, window_data |
shl edi, 3 |
test [ecx + WDATA.fl_wstyle], WSTYLE_CLIENTRELATIVE |
jz .whole_window |
|
cmp cl, 1 |
je .no_window_sizing |
mov edx, edi |
sub edx, window_data |
shr edx, 5 |
shl edx, 8 |
add edx, SLOT_BASE |
movzx eax, [ecx + WDATA.fl_wstyle] |
and eax, 0x0F |
mov eax, [eax * 8 + window_topleft + 0] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax |
shl eax, 1 |
neg eax |
add eax, [ecx + WDATA.box.width] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax |
|
; did we right-click on titlebar? |
cmp [do_resize], 2 |
jne .check_maximization_request |
movzx eax, [ecx + WDATA.fl_wstyle] |
and eax, 0x0F |
push [eax * 8 + window_topleft + 0] |
mov eax, [eax * 8 + window_topleft + 4] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax |
neg eax |
sub eax, [esp] |
add eax, [ecx + WDATA.box.height] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax |
add esp, 4 |
jmp .exit |
|
; yes we did, toggle normal/rolled up window state |
xor [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP |
mov [reposition], 1 |
.whole_window: |
xor eax, eax |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax |
mov eax, [ecx + WDATA.box.width] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax |
mov eax, [ecx + WDATA.box.height] |
mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax |
|
; calculate and set appropriate window height |
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP |
jz @f |
call window._.get_rolledup_height |
jmp .set_new_window_height |
@@: mov eax, [edx + APPDATA.saved_box.height] |
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jz .set_new_window_height |
mov eax, [screen_workarea.bottom] |
sub eax, [screen_workarea.top] |
.exit: |
pop edi ecx eax |
ret |
|
.set_new_window_height: |
mov [edi + WDATA.box.height], eax |
add eax, [edi + WDATA.box.top] |
cmp eax, [Screen_Max_Y] |
jbe @f |
mov eax, [Screen_Max_Y] |
sub eax, [edi + WDATA.box.height] |
mov [edi + WDATA.box.top], eax |
@@: call check_window_position |
call set_window_clientbox |
align 4 |
;------------------------------------------------------------------------------ |
window._.sys_set_window: ;///////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;< edx = pointer to WDATA struct |
;------------------------------------------------------------------------------ |
mov eax, [CURRENT_TASK] |
shl eax, 5 |
add eax, window_data |
|
.check_maximization_request: |
; can window change its height? |
push edx |
mov dl, [edi + WDATA.fl_wstyle] |
and dl, 0x0f |
cmp dl, 0x04 |
pop edx |
je .check_if_window_fits_screen |
; save window colors |
mov [eax + WDATA.cl_workarea], edx |
mov [eax + WDATA.cl_titlebar], esi |
mov [eax + WDATA.cl_frames], edi |
|
; was it really a maximize/restore request? |
cmp [do_resize], 1 |
jne .check_if_window_fits_screen |
cmp [do_resize_from_corner], 0 |
jne .check_if_window_fits_screen |
cmp [latest_window_touch_delta], 50 |
jg .check_if_window_fits_screen |
mov edi, eax |
|
; yes is was, toggle normal/maximized window state |
xor [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
mov [reposition], 1 |
; was it already defined before? |
test [edi + WDATA.fl_wdrawn], 1 |
jnz .set_client_box |
|
; calculate and set appropriate window bounds |
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jz .restore_normal_window_size |
mov eax, [screen_workarea.left] |
mov [edi + WDATA.box.left], eax |
sub eax, [screen_workarea.right] |
neg eax |
; NOTE: commented out since doesn't provide necessary functionality |
; anyway, to be reworked |
; mov eax, [timer_ticks] ; [0xfdf0] |
; add eax, 100 |
; mov [new_window_starting], eax |
|
; no it wasn't, performing initial window definition |
movzx eax, bx |
mov [edi + WDATA.box.width], eax |
mov eax, [screen_workarea.top] |
mov [edi + WDATA.box.top], eax |
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP |
jnz .calculate_window_client_area |
sub eax, [screen_workarea.bottom] |
neg eax |
movzx eax, cx |
mov [edi + WDATA.box.height], eax |
jmp .calculate_window_client_area |
sar ebx, 16 |
sar ecx, 16 |
mov [edi + WDATA.box.left], ebx |
mov [edi + WDATA.box.top], ecx |
|
.restore_normal_window_size: |
push [edi + WDATA.box.height] |
push edi |
lea esi, [edx + APPDATA.saved_box] |
mov ecx, 4 |
cld |
rep movsd |
pop edi |
pop eax |
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP |
jz .calculate_window_client_area |
mov [edi + WDATA.box.height], eax |
call window._.check_window_position |
|
.calculate_window_client_area: |
call set_window_clientbox |
push ecx edi |
|
.check_if_window_fits_screen: |
; does window fit into screen area? |
mov eax, [edi + WDATA.box.top] |
add eax, [edi + WDATA.box.height] |
cmp eax, [Screen_Max_Y] |
jbe .no_window_sizing |
mov eax, [edi + WDATA.box.left] |
add eax, [edi + WDATA.box.width] |
cmp eax, [Screen_Max_X] |
jbe .no_window_sizing |
mov cl, [edi + WDATA.fl_wstyle] |
mov eax, [edi + WDATA.cl_frames] |
|
; no it doesn't, fix that |
mov eax, [Screen_Max_X] |
sub eax, [edi + WDATA.box.width] |
mov [edi + WDATA.box.left], eax |
mov eax, [Screen_Max_Y] |
sub eax, [edi + WDATA.box.height] |
mov [edi + WDATA.box.top], eax |
call set_window_clientbox |
sub edi, window_data |
shl edi, 3 |
add edi, SLOT_BASE |
|
.no_window_sizing: |
popad |
and cl, 0x0F |
cmp cl, 3 |
je @f |
cmp cl, 4 |
je @f |
|
; did somethins actually change its place? |
cmp [reposition], 0 |
je .reset_vars |
xor eax, eax |
|
mov byte[DONT_DRAW_MOUSE], 1 |
@@: mov [edi + APPDATA.wnd_caption], eax |
|
push eax ebx ecx edx |
mov esi, [esp] |
add edi, APPDATA.saved_box |
movsd |
movsd |
movsd |
movsd |
|
; recalculate screen buffer at new position |
pop edi ecx |
|
mov esi, [CURRENT_TASK] |
movzx esi, word[WIN_STACK + esi * 2] |
lea esi, [WIN_POS + esi * 2] |
call waredraw |
|
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
1403,50 → 1473,98 |
add edx, ebx |
call calculatescreen |
|
; recalculate screen buffer at old position |
mov eax, [old_window_pos.left] |
mov ebx, [old_window_pos.top] |
mov ecx, [old_window_pos.width] |
mov edx, [old_window_pos.height] |
add ecx, eax |
add edx, ebx |
call calculatescreen |
mov byte[KEY_COUNT], 0 ; empty keyboard buffer |
mov byte[BTN_COUNT], 0 ; empty button buffer |
|
pop edx ecx ebx eax |
.set_client_box: |
; update window client box coordinates |
call window._.set_window_clientbox |
|
mov eax, edi |
call redrawscreen |
; reset window redraw flag and exit |
mov [edi + WDATA.fl_redraw], 0 |
mov edx, edi |
ret |
|
; tell window to redraw itself |
mov [edi + WDATA.fl_redraw], 1 |
align 4 |
;------------------------------------------------------------------------------ |
window._.check_window_position: ;////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? Check if window is inside screen area |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA |
;------------------------------------------------------------------------------ |
push eax ebx ecx edx esi |
|
; wait a bit for window to redraw itself |
mov ecx, 100 |
mov eax, [edi + WDATA.box.left] |
mov ebx, [edi + WDATA.box.top] |
mov ecx, [edi + WDATA.box.width] |
mov edx, [edi + WDATA.box.height] |
|
.next_idle_cycle: |
mov byte[DONT_DRAW_MOUSE], 1 |
call checkidle |
cmp [edi + WDATA.fl_redraw], 0 |
jz .reset_vars |
loop .next_idle_cycle |
mov esi, [Screen_Max_X] |
cmp ecx, esi |
ja .fix_width_high |
|
.reset_vars: |
mov byte[DONT_DRAW_MOUSE], 0 ; mouse pointer |
mov byte[MOUSE_BACKGROUND], 0 ; no mouse under |
mov byte[MOUSE_DOWN], 0 ; react to mouse up/down |
.check_left: |
or eax, eax |
jl .fix_left_low |
add eax, ecx |
cmp eax, esi |
jg .fix_left_high |
|
.check_height: |
mov esi, [Screen_Max_Y] |
cmp edx, esi |
ja .fix_height_high |
|
.check_top: |
or ebx, ebx |
jl .fix_top_low |
add ebx, edx |
cmp ebx, esi |
jg .fix_top_high |
|
.exit: |
popad |
pop esi edx ecx ebx eax |
ret |
|
;============================================================================== |
;///// private functions ////////////////////////////////////////////////////// |
;============================================================================== |
.fix_width_high: |
mov ecx, esi |
mov [edi + WDATA.box.width], esi |
jmp .check_left |
|
.fix_left_low: |
xor eax, eax |
mov [edi + WDATA.box.left], eax |
jmp .check_height |
|
.fix_left_high: |
mov eax, esi |
sub eax, ecx |
mov [edi + WDATA.box.left], eax |
jmp .check_height |
|
.fix_height_high: |
mov edx, esi |
mov [edi + WDATA.box.height], esi |
jmp .check_top |
|
.fix_top_low: |
xor ebx, ebx |
mov [edi + WDATA.box.top], ebx |
jmp .exit |
|
.fix_top_high: |
mov ebx, esi |
sub ebx, edx |
mov [edi + WDATA.box.top], ebx |
jmp .exit |
|
align 4 |
;------------------------------------------------------------------------------ |
window._.get_titlebar_height: ;//////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA |
;------------------------------------------------------------------------------ |
mov al, [edi + WDATA.fl_wstyle] |
1462,6 → 1580,8 |
;------------------------------------------------------------------------------ |
window._.get_rolledup_height: ;//////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? <description> |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA |
;------------------------------------------------------------------------------ |
mov al, [edi + WDATA.fl_wstyle] |
1732,9 → 1852,9 |
;------------------------------------------------------------------------------ |
mov cl, [edi + WDATA.fl_wstyle] |
and cl, 0x0f |
cmp cl, 0x03 |
cmp cl, 3 |
je .exit.redraw ; window type 3 |
cmp cl, 0x04 |
cmp cl, 4 |
je .exit.redraw ; window type 4 |
|
push eax ebx edx esi |
1743,8 → 1863,6 |
sub eax, window_data |
shr eax, 5 |
|
; esi = process number |
|
movzx eax, word[WIN_STACK + eax * 2] ; get value of the curr process |
lea esi, [WIN_POS + eax * 2] ; get address of this process at 0xC400 |
|
1798,49 → 1916,142 |
|
align 4 |
;------------------------------------------------------------------------------ |
window._.draw_window_frames: ;///////////////////////////////////////////////// |
window._.draw_window_caption: ;//////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? Draw negative window frames |
;? <description> |
;------------------------------------------------------------------------------ |
;> edi = pointer to WDATA |
;------------------------------------------------------------------------------ |
push eax |
cli |
inc [mouse_pause] |
call [_display.disable_mouse] |
|
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED |
jnz .exit |
mov eax, [new_window_pos.left] |
cmp eax, [edi + WDATA.box.left] |
jnz .draw |
mov eax, [new_window_pos.width] |
cmp eax, [edi + WDATA.box.width] |
jnz .draw |
mov eax, [new_window_pos.top] |
cmp eax, [edi + WDATA.box.top] |
jnz .draw |
mov eax, [new_window_pos.height] |
cmp eax, [edi + WDATA.box.height] |
jnz .draw |
xor [edi + WDATA.fl_wdrawn], 2 |
xor eax, eax |
mov edx, [TASK_COUNT] |
movzx edx, word[WIN_POS + edx * 2] |
cmp edx, [CURRENT_TASK] |
jne @f |
inc eax |
@@: mov edx, [CURRENT_TASK] |
shl edx, 5 |
add edx, window_data |
movzx ebx, [edx + WDATA.fl_wstyle] |
and bl, 0x0F |
cmp bl, 3 |
je .draw_caption_style_3 |
cmp bl, 4 |
je .draw_caption_style_3 |
|
.draw: |
push ebx esi |
mov eax, [new_window_pos.left - 2] |
mov ax, word[new_window_pos.left] |
add ax, word[new_window_pos.width] |
mov ebx, [new_window_pos.top - 2] |
mov bx, word[new_window_pos.top] |
add bx, word[new_window_pos.height] |
mov esi, 0x01000000 |
call draw_rectangle.forced |
pop esi ebx |
jmp .not_style_3 |
|
.draw_caption_style_3: |
push edx |
call drawwindow_IV_caption |
add esp, 4 |
jmp .2 |
|
.not_style_3: |
cmp bl, 2 |
jne .not_style_2 |
|
call drawwindow_III_caption |
jmp .2 |
|
.not_style_2: |
cmp bl, 0 |
jne .2 |
|
call drawwindow_I_caption |
|
.2: mov edi, [CURRENT_TASK] |
shl edi, 5 |
test [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION |
jz .exit |
mov edx, [edi * 8 + SLOT_BASE + APPDATA.wnd_caption] |
or edx, edx |
jz .exit |
|
movzx eax, [edi + window_data + WDATA.fl_wstyle] |
and al, 0x0F |
cmp al, 3 |
je .skinned |
cmp al, 4 |
je .skinned |
|
jmp .not_skinned |
|
.skinned: |
mov ebp, [edi + window_data + WDATA.box.left - 2] |
mov bp, word[edi + window_data + WDATA.box.top] |
movzx eax, word[edi + window_data + WDATA.box.width] |
sub ax, [_skinmargins.left] |
sub ax, [_skinmargins.right] |
push edx |
cwde |
cdq |
mov ebx, 6 |
idiv ebx |
pop edx |
or eax, eax |
js .exit |
|
mov esi, eax |
mov ebx, dword[_skinmargins.left - 2] |
mov bx, word[_skinh] |
sub bx, [_skinmargins.bottom] |
sub bx, [_skinmargins.top] |
sar bx, 1 |
adc bx, 0 |
add bx, [_skinmargins.top] |
add bx, -3 |
add ebx, ebp |
jmp .dodraw |
|
.not_skinned: |
cmp al, 1 |
je .exit |
|
mov ebp, [edi + window_data + WDATA.box.left - 2] |
mov bp, word[edi + window_data + WDATA.box.top] |
movzx eax, word[edi + window_data + WDATA.box.width] |
sub eax, 16 |
push edx |
cwde |
cdq |
mov ebx, 6 |
idiv ebx |
pop edx |
or eax, eax |
js .exit |
|
mov esi, eax |
mov ebx, 0x00080007 |
add ebx, ebp |
|
.dodraw: |
mov ecx, [common_colours + 16] |
or ecx, 0x80000000 |
xor edi, edi |
call dtext_asciiz_esi |
|
.exit: |
sti |
pop eax |
dec [mouse_pause] |
call [draw_pointer] |
ret |
|
.forced: |
push eax |
cli |
jmp .draw |
align 4 |
;------------------------------------------------------------------------------ |
window._.draw_negative_box: ;////////////////////////////////////////////////// |
;------------------------------------------------------------------------------ |
;? Draw negative box |
;------------------------------------------------------------------------------ |
;> edi = pointer to BOX struct |
;------------------------------------------------------------------------------ |
push eax ebx esi |
mov eax, [edi + BOX.left - 2] |
mov ax, word[edi + BOX.left] |
add ax, word[edi + BOX.width] |
mov ebx, [edi + BOX.top - 2] |
mov bx, word[edi + BOX.top] |
add bx, word[edi + BOX.height] |
mov esi, 0x01000000 |
call draw_rectangle.forced |
pop esi ebx eax |
ret |