MINT64 OS의 GUI 시스템은 윈도우 풀, 윈도우, 윈도우 매니저 3가지로 구성된다.
윈도우 풀(Window Pool)
윈도우 정보를 저장하는 자료구조의 코드
// 윈도우 제목의 최대 길이
#define WINDOW_TITLEMAXLENGTH 40
typedef struct kWindowStruct
{
// 다음 데이터의 위치와 현재 윈도우의 ID
LISTLINK stLink;
// 자료구조 동기화를 위한 뮤텍스
MUTEX stLock;
// 윈도우 영역 정보
RECT stArea;
// 윈도우의 화면 버퍼 어드레스
COLOR* pstWindowBuffer;
// 윈도우가 있는 태스크의 ID
QWORD qwTaskID;
// 윈도우 속성
DWORD dwFlags;
// 윈도우 제목
char vcWindowTitle[ WINDOW_TITLEMAXLENGTH + 1 ];
} WINDOW;
윈도우 풀을 관리하는 자료구조의 코드
typedef struct kWindowPoolManagerStruct
{
// 자료구조 동기화를 위한 뮤텍스
MUTEX stLock;
// 윈도우 풀에 대한 정보
WINDOWS* pstStartAddress;
int iMaxCount;
int iUSeCount;
// 윈도우가 할당된 횟수
int iAllocatedCount;
} WINDOWPOOLMANAGER;
윈도우 풀 초기화 함수의 코드
// 윈도우를 생성할 수 있는 최대 개수
#define WINDOW_MAXCOUNT 2048
static void kInitializeWindowPool( void )
{
int i;
void* pvWindowPoolAddress;
// 자료구조 초기화
kMemSet( &gs_stWindowPoolManager, 0, sizeof( gs_stWindowPoolManager ) );
// 윈도우 풀의 메모리를 할당
pvWindowPoolAddress = ( void* ) kAllocateMemory( sizeof( WINDOW ) * WINDOW_MAXCOUNT );
if( pvWindowPoolAddress == NULL ){
kPrintf( "Window Pool Allocate Fail\\n" );
while( 1 ){
;
}
}
// 윈도우 풀의 어드레스를 지정하고 초기화
gs_stWindowPoolManager.pstStartAddress = ( WINDOW* ) pvWindowPoolAddress;
kMemSEt( pvWindowPoolAddress, 0, sizeof( WINDOW ) * WINDOW_MAXCOUNT );
// 윈도우 풀에 ID를 할당
for( i = 0 ; i < WINDOW_MAXCOUNT ; i++ )
{
gs_stWindowPoolManager.pstStartAddress[ i ].stLink.qwID = i;
}
// 윈도우 최대 개수와 할당된 횟수를 초기화
gs_stWindowPoolManager.iMaxCount = WINDOW_MAXCOUNT;
gs_stWindowPoolManager.iAllocatedCount = 1;
// 뮤텍스 초기화
kInitializeMutex( &( gs_stWindowPoolManager.stLock ) );
}
윈도우 자료구조를 할당하고, 해제하는 함수의 코드
// 윈도우 ID로 윈도우 풀 내의 오프셋을 계산하는 매크로
#define GETWINDOWOFFSET( x ) ( ( x ) & 0xFFFFFFFF )
// 윈도우 자료구조를 할당
static WINDOW* kAllocateWindow( void )
{
WINDOW* pstEmptyWindow;
int i;
// 동기화 처리
kLock( &( gs_stWindowPoolManager.stLock ) );
// 윈도우가 모두 할당되었으면 실패
if( gs_stWindowPoolManager.iUseCount == gs_stWindowPoolManager.iMaxCount )
{
// 동기화 처리
kUnlock( &gs_stWindowPoolManager.stLock );
return NULL;
}
// 윈도우 풀을 모두 돌면서 빈 영역 검색
for( i = 0 ; i < gs_stWindowPoolManager.iMaxCount ; i++ )
{
// ID의 상위 32비트가 0이면 비어 있는 윈도우 자료구조임
if( (gs_stWindowPoolManager.pstStartAddress[ i ].stLink.qwID >> 32 ) == 0 )
{
pstEmptyWindow = &( gs_stWIndowPoolMnager.pstStartAddress[ i ] );
break;
}
}
// 상위 32비트를 0이 아닌 값으로 설정해서, 할당된 윈도우로 설정
pstEmptyWindow->stLink.qwID =
((QWORD) gs_stWindowPoolManager.iAllocatedCount << 32 ) | i;
// 자료구조가 사용 중인 개수와 할당된 횟수를 증가
gs_stWindowPoolManager.iUseCount++;
gs_stWIndowPoolManager.iAllocatedCount++;
if( gs_stWindowPoolManager.iAllocatedCount == 0 )
{
gs_stWindowPoolManager.iAllocatedCount = 1;
}
// 동기화 처리
kUnlock( &( gs+stWindowPoolManager.stLock ) );
// 윈도우의 뮤텍스 초기화
kInitialzieMutex( &( pstEmptyWindow->stLock ) );
return pstEmptyWindow;
}
// 윈도우 자료구조를 해제
static void kFreeWindow( QWORD qwID ){
int i;
// 윈도우 ID로 윈도우 풀의 오프셋을 계산, 윈도우 ID의 하위 32비트가 인덱스 역할을 함
i = GETWINDOWOFFSET( qwID );
// 동기화 처리
kLock( &( gs_stWindowPoolManager.stLock ) );
// 윈도우 자료구조를 초기화하고 ID 설정
kMemSet( &( gs_stWindowPoolManager.pstStartAddress[ i ] ), 0, sizeof( WINDOW ) );
gs_stWindowPoolManager.pstStartAddress[ i ].stLink.qwID = i;
// 사용 중인 자료구조의 개수를 감소
gs_stWindowPoolManager.iUseCount--;
// 동기화 처리
kUnlock( &( gs_stWindowPoolManager.stLock ) );
}
윈도우 매니저 자료구조의 코드
typedef struct kWindowManagerStruct
{
// 자료구조 동기화를 위한 뮤텍스
MUTEX stLock;
// 윈도우 리스트
LIST stWindowList;
// 현재 마우스 커서의 X, Y 좌표
int iMouseX;
int iMouseY;
// 화면 영역 정보
RECT stScreenArea;
// 비디오 메모리의 어드레스
COLOR* pstVideoMemory;
// 배경 윈도우의 ID
QWORD qwBackgroundWindowID;
} WINDOWMANAGER;
(1) GUI 시스템 초기화 함수
GUI 시스템 초기화 함수의 코드
// 배경 윈도우의 제목
#define WINDOW_BACKGROUNDWINDOWTITLE "SYS_BACKGROUND"
void kInitializeGUISystem( void )
{
VBEMODEINFOBLOCK* pstModeInfo;
QWORD qwBackgroundWindowID;
// 윈도우 풀을 초기화
kInitializeWindowPool();
// VBE 모드 정보 블록을 반환
pstModeInfo = kGetVBEModeInfoBlock();
// 비디오 메모리 어드레스 설정
gs_stWindowManager.pstVideoMemory = ( COLOR* )
( (QWORD) pstModeInfo->dwPhysicalBasePointer & 0xFFFFFFFF );
// 마우스 커서의 초기 위치 설정
gs_stWindowManager.iMouseX = pstModeInfo->wXResolution / 2;
gs_stWindowManager.iMouseY = pstModeInfo->wYResolution / 2;
// 화면 영역의 범위 설정
gs_stWindowManager.stScreenArea.iX1 = 0;
gs_stWindowManager.stScreenArea.iY1 = 0;
gs_stWindowManager.stScreanArea.iX2 = pstModeInfo->wXResolution - 1;
gs_stWindowManager.stScreenArea.iY2 = pstModeInfo->wYResolution - 1;
// 뮤텍스 초기화
kInitializeMutex( &( gs_stWindowManager.stLock ) );
// 윈도우 리스트 초기화
kInitializeList( &( gs_stWindowManager.stWIndowList ) );
//-------------------------------------------------------
// 배경 윈도우 생성
//-------------------------------------------------------
// 플래그에 0을 넘겨서 화면에 윈도우를 그리지 않도록 함
// 배경 윈도우는 윈도우 내에 배경색을 모두 칠한 뒤 나타냄
qwBackgroundWindowID = kCreateWindow( 0, 0, pstModeInfo->wXResolution,
pstModeInfo->wYResolution, 0, WINDOW_BACKGROUNDWINDOWTITLE );
gs_stWindowManager.qwBackgroundWindowID = qwBackgroundWindowID;
// 배경 윈도우 내부에 배경을 채움
kDrawRect( qwBackgroundWindowID, 0, 0, pstModeInfo->wXResolution - 1,
pstModeInfo->wYResolution - 1, WINDOW_COLOR_SYSTEMBACKGROUND, TRUE );
// 배경 윈도우 화면에 나타냄
kShowWindow( qwBackgroundWindowID, TRUE );
}
(2) 윈도우 생성 및 삭제 함수
윈도우 속성 값
// 윈도우를 화면에 나타냄
#define WINDOW_FLAGS_SHOW 0x00000001
// 윈도우 테두리 그림
#define WINDOW_FLAGS_DRAWFRAME 0x00000002
// 윈도우 제목 표시줄 그림
#define WINDOW_FLAGS_DRAWTITLE 0x00000004
// 윈도우 기본 속성, 제목 표시줄과 프레임을 모두 그리고 화면에 윈도우를 보이게 설정
#define WINDOW_FLAGS_DEFAULT ( WINDOW_FLAGS_SHOW | WINDOW_FLAGS_DRAWFRAME | WINDOW_FLAGS_DRAWTITLE )
윈도우를 생성하는 함수의 코드
// 유효하지 않은 윈도우 ID
#define WINDOW_INVALIDID 0xFFFFFFFFFFFFFFFF
QWORD kCreateWindow( int iX, int iY, int iWidth, int iHeight, DWORD dwFlags, const char* pcTitle )
{
WINDOW* pstWindow;
TCB* pstTask;
// 크기가 0인 윈도우는 만들 수 없음
if( ( iWidth <= 0 ) || ( iHeight <= 0 ) )
{
return WINDOW_INVALIDID;
}
// 윈도우 자료구조를 할당
pstWindow = kAllocateWindow();
if( pstWindow == NULL )
{
return WINDOW_INVALIDID;
}
// 윈도우 영역 설정
pstWindow->stArea.iX1 = iX;
pstWindow->stArea.iY1 = iY;
pstWindow->stArea.iX2 = iX + iWidth - 1;
pstWindow->stArea.iY2 = iY + iHeight - 1;
// 윈도우 제목 저장
kMemCpy( pstWindow->vcWindowTitle, pcTitle, WINDOW_TITLEMAXLENGTH );
pstWindow->vcWindowTitle[ WINDOW_TITLEMAXLENGTH ] = '\\0';
// 윈도우 화면 버퍼 할당
pstWindow->pstWindowBuffer = ( COLOR* ) kAllocateMemory( iWidth + iHeight * sizeof( COLOR ) );
if( pstWindow == NULL )
{
// 윈도우 화면 버퍼 할당에 실패하면 윈도우 자료구조 반환
kFreeWindow( pstWindow->stLink.qwID );
return WINDOW_INVALIDID;
}
// 윈도우를 생성한 태스크의 ID를 저장
pstTask = kGetRunningTask( kGetAPICID() );
pstWindow->qwTaskID = pstTask->stLink.qwID;
// 윈도우 속성 설정
pstWindow->dwFlags = dwFlags;
// 윈도우 배경 그리기
kDrawWindowBackground( pstWindow->stLink.qwID );
// 윈도우 테두리 그리기
if( dwFlags & WINDOW_FLAGS_DRAWFRAME )
{
kDrawWindowFrame( pstWindow->stLink.qwID );
}
// 윈도우 제목 표시줄 그리기
if( dwFlags & WINDOW_FLAGS_DRAWTITLE )
{
kDrawWindowTitle( pstWindow->stLink.qwID, pcTitle );
}
// 동기화 처리
kLock( &( gs_stWindowManager.stLock ) );
// 윈도우 리스트의 가장 마지막에 추가하여, 최상위 윈도우로 설정
kAddListToTail( &gs_stWindowManager.stWindowList, pstWindow );
// 동기화 처리
kUnlock( &( gs_stWindowManager.stLock ) );
// 윈도우를 그리는 옵션이 들어 있으면, 해당 윈도우를 그림
if( dwFlags & WINDOW_FLAGS_SHOW ){
// 윈도우 영역만큼 화면에 업데이트
kRedrawWindowByArea( &( pstWindow->stArea ) );
}
return pstWindow->stLink.qwID;
}
윈도우를 삭제하는 함수와 태스크에서 생성한 모든 윈도우를 삭제하는 함수의 코드
// 윈도우를 삭제
BOOL kDeleteWindow( QWORD qwWindowID )
{
WINDOW* pstWindow;
RECT stArea;
// 동기화 처리
kLock( &( gs_stWindowManager.stLock ) );
// 윈도우 검색
pstWindow = kGetWindowWithWindowLock( qwWindowID );
if( pstWindow == NULL )
{
// 동기화 처리
kUnlock( &( gs_stWindowManager.stLock ) );
return FALSE;
}
// 윈도우를 삭제하기 전에 영역을 저장
kMemCpy( &stArea, &( pstWindow->stArea ), sizeof( RECT ) );
// 윈도우 리스트에서 윈도우 삭제
if( kRemoveList( &( gs_stWindowManager.stWindowList ), qwWindowID ) == NULL )
{
// 동기화 처리
kUnlock( &( pstWindow->stLock ) );
kUnlock( &( gs_stWindowManager.stLock ) );
return FALSE;
}
// 동기화 처리
kLock( &( pstWindow->stLock ) );
// 윈도우 화면 버퍼를 반환
kFreeMemory( pstWindow->pstWindowBuffer );
// 동기화 처리
kUnlock( &( pstWindow->stLock ) );
// 윈도우 자료구조를 반환
kFreeWindow( qwWindowID );
// 동기화 처리
kUnlock( &( gs_stWindowManager.stLock ) );
// 삭제되기 전에 윈도우가 있던 영역을 화면에 다시 업데이트
kRedrawWindowByArea( &stArea );
return TRUE;
}
// 태스크 ID가 일치하는 모든 윈도우를 삭제
BOOL kDeleteAllWindowInTaskID( QWORD qwTaskID )
{
WINDOW* pstWindow;
WINDOW* pstNextWindow;
// 동기화 처리
kLock( &( gs_stWindowManager.stLock ) );
// 리스트에서 첫번째 윈도우를 반환
pstWindow = kGetHeaderFromList( &( gs_stWindowManager.stWindowList ) );
while( pstWindow != NULL ){
// 다음 윈도우를 미리 구함
pstNextWindow = kGetNextFromList( &( gs_stWindowManager.stWindowList ), pstWindow );
// 배경 윈도우가 아니고 태스크 ID가 일치하면 윈도우 삭제
if( ( pstWindow->stLink.qwID != gs_stWindowManager.qwBackgroundWindowID ) &&
( pstWindow->qwTaskID == qwTaskID ) )
{
kDeleteWindow( pstWindow->stLink.qwID );
}
// 미리 구해둔 다음 윈도우의 값을 설정
pstWindow = pstNextWindow;
}
// 동기화 처리
kUnlock( &( gs_stWindowManager.stLock ) );
}