⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 desktop.c

📁 这是一个介绍 linux 编程知识的文章。
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// desktop.c: The Desktop module.
//
// Copyright (C) 1999, Wei Yongming.
//
// Current maintainer: Wei Yongming.

/*
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Library General Public
**  License as published by the Free Software Foundation; either
**  version 2 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Library General Public License for more details.
**
**  You should have received a copy of the GNU Library General Public
**  License along with this library; if not, write to the Free
**  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
**  MA 02111-1307, USA
*/

// Create date: 1999.04.19
//
// Modify records:
//
//  Who             When        Where       For What                Status
//-----------------------------------------------------------------------------
//  Wei Yongming    1999.9.11   Tsinghua    WS_DISABLED             done
//  Wei Yongming    1999.9.28   Tsinghua    Remove collector thread done
//  Wei Yongming    1999.9.28   Tsinghua    Timer module to desktop done
//  Wei Yongming    1999.10.28  Tsinghua    Desktop Menu            done
//
// TODO:
//

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <vgakeyboard.h>
#include <unistd.h>
#include <termios.h>

#include "common.h"
#include "cliprect.h"
#include "gdi.h"
#include "cursor.h"
#include "event.h"
#include "window.h"
#include "internals.h"
#include "misc.h"
#include "menu.h"
#include "fixstr.h"
#include "timer.h"
#include "ctrlclass.h"
#include "accelkey.h"
#include "main.h"
#include "vcswitch.h"

#ifdef _MULFONT
#include "cfont.h"
#endif

#ifdef _DEBUG
#include "msgstr.h"
#endif

#ifndef lint
static char fileid[] = "$Id: desktop.c,v 1.2 2000/04/20 03:18:23 weiym Exp $";
#endif

/******************************* extern data *********************************/
extern int timer_counter;

/******************************* static data *********************************/
static pthread_t desktop, parsor, timer;
static int DesktopProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam);

/********************* Window management support *****************************/
MSGQUEUE DskMsgs;
RECT sg_rcScr;
FREECLIPRECTLIST sg_FreeInvRectList;

static FREECLIPRECTLIST sg_FreeClipRectList;
static PMAINWIN pActiveMainWnd;
static HWND hCaptureWnd;
static ZORDERINFO MainWinZOrder;
static ZORDERINFO TopMostWinZOrder;

static PTRACKMENUINFO sg_ptmi;

static HWND sg_hIMEWnd;

static HWND sg_hCaretWnd;
static UINT sg_uCaretBTime;

static GCRINFO sg_ScrGCRInfo;

static void InitWndManagementInfo(void)
{
    InitMainWinMetrics();

    hCaptureWnd = HWND_DESKTOP;
    pActiveMainWnd = NULL;

    sg_ptmi = NULL;

    sg_hIMEWnd = HWND_DESKTOP;
    sg_hCaretWnd = HWND_DESKTOP;

    sg_rcScr.left = sg_rcScr.top = 0;
    sg_rcScr.right = GetGDCapability (HDC_SCREEN, GDCAP_MAXX) + 1;
    sg_rcScr.bottom = GetGDCapability (HDC_SCREEN, GDCAP_MAXY) + 1;

    InitClipRgn (&sg_ScrGCRInfo.crgn, &sg_FreeClipRectList);
    SetClipRgn (&sg_ScrGCRInfo.crgn, &sg_rcScr);
    pthread_mutex_init (&sg_ScrGCRInfo.lock, NULL);
    sg_ScrGCRInfo.age = 0;
}

BITMAP SystemBitmap[SYSBMP_ITEM_NUMBER];
HICON  LargeSystemIcon [SYSICO_ITEM_NUMBER] = {0};
HICON  SmallSystemIcon [SYSICO_ITEM_NUMBER] = {0};
BOOL InitDesktop ()
{
    int i;
    int nIconNr;
    char szValue [12];
    
    /*
     * Load system bitmaps here.
     */
    if (!LoadSystemBitmap (SystemBitmap,     "minimize")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 1, "maximize")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 2, "restore")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 3, "close")) return FALSE;

    if (!LoadSystemBitmap (SystemBitmap + 4,  "arrowup")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 5,  "arrowupd")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 6,  "arrowdown")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 7,  "arrowdownd")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 8,  "arrowleft")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 9,  "arrowleftd")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 10, "arrowright")) return FALSE;
    if (!LoadSystemBitmap (SystemBitmap + 11, "arrowrightd")) return FALSE;

    /*
     * Load system icons here.
     */
    if( GetValueFromEtcFile(ETCFILEPATH, "iconinfo", "iconnumber", 
                            szValue, 10) < 0 )
        return FALSE;
    nIconNr = atoi(szValue);
    if (nIconNr <= 0)
        return FALSE;
    nIconNr = nIconNr < SYSICO_ITEM_NUMBER ? nIconNr : SYSICO_ITEM_NUMBER;

    for (i = 0; i < nIconNr; i++) {
        sprintf(szValue, "icon%d", i);
        
        SmallSystemIcon [i] = LoadSystemIcon (szValue, 1);
        LargeSystemIcon [i] = LoadSystemIcon (szValue, 0);

        if (SmallSystemIcon [i] == 0
                || LargeSystemIcon [i] == 0)
            return FALSE;
    }
    
    // Init Window Management information.
    InitWndManagementInfo();

    return TRUE;
}

void TerminateDesktop ()
{
    int i;
    
    for (i=0; i<SYSBMP_ITEM_NUMBER; i++)
        UnloadBitmap (SystemBitmap + i);

    for (i=0; i<SYSICO_ITEM_NUMBER; i++) {
        if (SmallSystemIcon [i])
            DestroyIcon (SmallSystemIcon [i]);

        if (LargeSystemIcon [i])
            DestroyIcon (LargeSystemIcon [i]);
    }
}

PGCRINFO GetGCRgnInfo(HWND hWnd)
{
    PMAINWIN pWin;

    if (hWnd == HWND_DESKTOP)
        return &sg_ScrGCRInfo;

    pWin = GetMainWindow (hWnd);

    return &pWin->GCRInfo;
}

inline void DesktopSetActiveWindow(PMAINWIN pWin)
{
    if (sg_hIMEWnd != HWND_DESKTOP && pWin) {
        if (pWin->dwExStyle & WS_EX_IMECOMPOSE)
            SendNotifyMessage (sg_hIMEWnd, MSG_IME_OPEN, 0, 0);
        else
            SendNotifyMessage (sg_hIMEWnd, MSG_IME_CLOSE, 0, 0);
            
        SendNotifyMessage (sg_hIMEWnd, MSG_IME_SETTARGET, (WPARAM)pWin, 0);
    }

    pActiveMainWnd = pWin;
}

static HWND DesktopSetCapture(HWND hwnd)
{
    HWND hTemp;

    hTemp = hCaptureWnd;
    hCaptureWnd = hwnd;

    return hTemp;
}

/************************* ZOrder operation **********************************/
static void InitZOrderInfo(PZORDERINFO pZOrderInfo, HWND hHost)
{
    pZOrderInfo->nNumber = 0;
    pZOrderInfo->hWnd = hHost;
    pZOrderInfo->pTopMost = NULL;
}

// When show an invisible new main window, 
// call this function to update all other windows' GCRInfo.
//
// Window functions which lead to calling this function:
// ShowWindow: show an invisible main window with a SW_SHOW parameter.
// 
// this main window is a normal main window.
static void dskUpdateGCRInfoOnShowNewMainWin(MAINWIN* pWin)
{
    PZORDERNODE pNode;
    PGCRINFO pGCRInfo;
    PMAINWIN pTemp;
    
    // this main window's GCR Info
    pGCRInfo = &pWin->GCRInfo;
    pthread_mutex_lock (&pGCRInfo->lock);

    // clip by all top most windows
    pNode = TopMostWinZOrder.pTopMost;
    while (pNode)
    {
        pTemp = (PMAINWIN)(pNode->hWnd);
        if (pTemp->dwStyle & WS_VISIBLE)
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pTemp->left));

        pNode = pNode->pNext;
    }
    pGCRInfo->age ++;
    pthread_mutex_unlock (&pGCRInfo->lock);

    // update all main windows' global clip region under this window.
    // pWin is the top most window.
    pNode = MainWinZOrder.pTopMost->pNext;
    while (pNode)
    {
        if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
            pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
        
        pthread_mutex_lock (&pGCRInfo->lock);
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pWin->left));
    pGCRInfo->age ++;
            pthread_mutex_unlock (&pGCRInfo->lock);
        }

        pNode = pNode->pNext;
    }
    
    // update desktop's global clip region.
    pthread_mutex_lock (&sg_ScrGCRInfo.lock);
    SubtractClipRect (&sg_ScrGCRInfo.crgn, (PRECT)(&pWin->left));
    sg_ScrGCRInfo.age ++;
    pthread_mutex_unlock (&sg_ScrGCRInfo.lock);
}

// this main window is a top most window.
static void dskUpdateGCRInfoOnShowNewMainWinEx(MAINWIN* pWin)
{
    PZORDERNODE pNode;
    PGCRINFO pGCRInfo;
    
    // update all top most windows' global clip region under this window.
    // pWin is the top most window.
    pNode = TopMostWinZOrder.pTopMost->pNext;
    while (pNode)
    {
        if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
            pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
        
            pthread_mutex_lock (&pGCRInfo->lock);
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pWin->left));
            pGCRInfo->age ++;
            pthread_mutex_unlock (&pGCRInfo->lock);
        }

        pNode = pNode->pNext;
    }
    
    // update all normal main windows' global clip region
    pNode = MainWinZOrder.pTopMost;
    while (pNode)
    {
        if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
            pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
        
            pthread_mutex_lock (&pGCRInfo->lock);
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pWin->left));
            pGCRInfo->age ++;
            pthread_mutex_unlock (&pGCRInfo->lock);
        }

        pNode = pNode->pNext;
    }

    // update desktop's global clip region.
    pthread_mutex_lock (&sg_ScrGCRInfo.lock);
    SubtractClipRect (&sg_ScrGCRInfo.crgn, (PRECT)(&pWin->left));
    sg_ScrGCRInfo.age ++;
    pthread_mutex_unlock (&sg_ScrGCRInfo.lock);
}

// When show a main window, all main windows which are covered by
// this showing main window will be updated.
// 
// Window functions which lead to calling this function:
// ShowWindow: show an invisible main window with a SW_SHOW parameter.
//
// this is a normal main window.
static void dskUpdateGCRInfoOnShowMainWin(MAINWIN* pWin)
{
    PMAINWIN pTemp;
    PZORDERNODE pNode;
    PGCRINFO pGCRInfo;
    RECT rcWin, rcTemp;
    
    // update this showing window's clip region info.

    pGCRInfo = &pWin->GCRInfo;
    IntersectRect (&rcTemp, (PRECT)(&pWin->left), &sg_rcScr);
    pthread_mutex_lock (&pGCRInfo->lock);
    SetClipRgn (&pGCRInfo->crgn, &rcTemp);

    // clip by all top most windows
    pNode = TopMostWinZOrder.pTopMost;
    while (pNode)
    {
        pTemp = (PMAINWIN)(pNode->hWnd);
        if (pTemp->dwStyle & WS_VISIBLE)
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pTemp->left));

        pNode = pNode->pNext;
    }
    
    // clip by all normal windows which cover this showing window.
    pNode = MainWinZOrder.pTopMost;
    while (pNode)
    {
        if (pNode->hWnd == (HWND)pWin)
            break;
            
        pTemp = (PMAINWIN)(pNode->hWnd);
        if (pTemp->dwStyle & WS_VISIBLE)
            SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pTemp->left));

        pNode = pNode->pNext;
    }

    pGCRInfo->age ++;
    pthread_mutex_unlock (&pGCRInfo->lock);
    
    // where is the showing window?
    pNode = MainWinZOrder.pTopMost;
    while (pNode)
    {
        if (pNode->hWnd == (HWND)pWin)
            break;
        pNode = pNode->pNext;
    }
    
    // the showing main window's rect
    memcpy (&rcWin, &pWin->left, sizeof(RECT));

    // clip all main windows covered by this showing window.
    pNode = pNode->pNext;
    while (pNode)
    {
        if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
            pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
        
            pthread_mutex_lock (&pGCRInfo->lock);
            SubtractClipRect (&pGCRInfo->crgn, &rcWin);
            pGCRInfo->age ++;
            pthread_mutex_unlock (&pGCRInfo->lock);
        }

        pNode = pNode->pNext;
    }
    
    // update desktop's global clip region.
    pthread_mutex_lock (&sg_ScrGCRInfo.lock);
    SubtractClipRect (&sg_ScrGCRInfo.crgn, &rcWin);
    sg_ScrGCRInfo.age ++;
    pthread_mutex_unlock (&sg_ScrGCRInfo.lock);
}

// this window is a main window with WS_EX style
static void dskUpdateGCRInfoOnShowMainWinEx(MAINWIN* pWin)
{
    PMAINWIN pTemp;
    PZORDERNODE pNode;
    PGCRINFO pGCRInfo;
    RECT rcWin, rcTemp;
    
    // update this showing window's clip region info.

    pGCRInfo = &pWin->GCRInfo;
    IntersectRect (&rcTemp, (PRECT)(&pWin->left), &sg_rcScr);
    pthread_mutex_lock (&pGCRInfo->lock);
    SetClipRgn (&pGCRInfo->crgn, &rcTemp);

    // clip by all top most windows which cover this showing window.
    pNode = TopMostWinZOrder.pTopMost;
    while (pNode)
    {
        if (pNode->hWnd == (HWND)pWin)
            break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -