Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1390 → Rev 1391

/kernel/trunk/gui/window.inc
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