/////////////////////////////////////////////////////////////////////////////// // // IMPORTANT NOTICE // // The following open source license statement does not apply to any // entity in the Exception List published by FMSoft. // // For more information, please visit: // // https://www.fmsoft.cn/exception-list // ////////////////////////////////////////////////////////////////////////////// /* * This file is part of MiniGUI, a mature cross-platform windowing * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. * * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Or, * * As this program is a library, any link to this program must follow * GNU General Public License version 3 (GPLv3). If you cannot accept * GPLv3, you need to be licensed from FMSoft. * * If you have got a commercial license of this program, please use it * under the terms and conditions of the commercial license. * * For more information about the commercial license, please refer to * . */ /* ** cursor-lite.c: Cursor support module for MiniGUI-Processes. ** ** Current maintainer: Wei Yongming. ** ** Create date: 1999/01/06 */ #include #include #include #include #include #include "common.h" #ifdef _MGRM_PROCESSES #include "minigui.h" #include "gdi.h" #include "window.h" #include "cliprect.h" #include "internals.h" #include "ctrlclass.h" #include "inline.h" #include "memops.h" #include "gal.h" #include "dc.h" #include "cursor.h" #include "ial.h" #include "sharedres.h" #include "ourhdr.h" #include "client.h" #include "server.h" #include "drawsemop.h" #include "readbmp.h" static int oldx = -1, oldy; static RECT cliprc = {0, 0, 0, 0}; #ifdef _MGHAVE_CURSOR #define CSR_CURSORX (((PG_RES)mgSharedRes)->cursorx) #define CSR_CURSORY (((PG_RES)mgSharedRes)->cursory) #define CSR_OLDBOXLEFT (((PG_RES)mgSharedRes)->oldboxleft) #define CSR_OLDBOXTOP (((PG_RES)mgSharedRes)->oldboxtop) #define CSR_CURRENT ((PCURSOR)((PG_RES)mgSharedRes)->csr_current) #define CSR_CURRENT_SET (((PG_RES)mgSharedRes)->csr_current) #define CSR_XHOTSPOT (((PG_RES)mgSharedRes)->xhotspot) #define CSR_YHOTSPOT (((PG_RES)mgSharedRes)->yhotspot) #define CSR_SHOW_COUNT (((PG_RES)mgSharedRes)->csr_show_count) static PCURSOR *_sys_cursors; static HCURSOR _def_cursor; /* Cursor pointer shape and hiding and showing. */ inline static int boxleft (void) { if (!CSR_CURRENT) return -100; return CSR_CURSORX - CSR_XHOTSPOT; } inline static int boxtop (void) { if (!CSR_CURRENT) return -100; return CSR_CURSORY - CSR_YHOTSPOT; } #ifdef _MGSCHEMA_SHAREDFB unsigned int __mg_csrimgsize; unsigned int __mg_csrimgpitch; #define CSR_SAVEDBITS ((BYTE*)mgSharedRes + (((PG_RES)mgSharedRes)->svdbitsoffset)) static BYTE* _cursor_bits = NULL; #endif #ifdef _MGSCHEMA_COMPOSITING /* the empty global DC for cursor */ static HDC _dc_cursor; /* Cursor creating and destroying. */ static HCURSOR srvCreateCursor (int xhotspot, int yhotspot, int w, int h, const BYTE* pANDBits, const BYTE* pXORBits, int colornum) { GAL_Surface* csr_surf; PCURSOR pcsr; gal_pixel trans_pixel = RGBA2Pixel (_dc_cursor, 0x00, 0x00, 0x00, 0x00); if (w != CURSORWIDTH || h != CURSORHEIGHT) return 0; if (!(pcsr = (PCURSOR)malloc (sizeof (CURSOR)))) return 0; csr_surf = GAL_CreateCursorSurface (NULL, w, h); if (!csr_surf) { free (pcsr); return 0; } pcsr->xhotspot = xhotspot; pcsr->yhotspot = yhotspot; pcsr->surface = csr_surf; if (colornum == 1) { int x, y; BYTE and_byte = 0; BYTE xor_byte = 0; gal_pixel white_pixel = RGBA2Pixel (_dc_cursor, 0xFF, 0xFF, 0xFF, 0xFF); gal_pixel black_pixel = RGBA2Pixel (_dc_cursor, 0x00, 0x00, 0x00, 0xFF); pANDBits += MONOPITCH * (CURSORHEIGHT - 1); pXORBits += MONOPITCH * (CURSORHEIGHT - 1); Uint32* pixels = (Uint32*)csr_surf->pixels; for (y = 0; y < CURSORHEIGHT; y++) { const BYTE* and_bytes = pANDBits; const BYTE* xor_bytes = pXORBits; for (x = 0; x < CURSORWIDTH; x++) { if (x % 8 == 0) { and_byte = *and_bytes++; xor_byte = *xor_bytes++; } if (and_byte & (0x80 >> (x % 8))) { pixels [x] = trans_pixel; } else { if (xor_byte & (0x80 >> (x % 8))) { pixels [x] = white_pixel; } else { pixels [x] = black_pixel; } } } pANDBits -= MONOPITCH; pXORBits -= MONOPITCH; pixels += (csr_surf->pitch >> 2); } } else if (colornum == 4) { int x, y; BYTE and_byte = 0; BYTE xor_byte = 0; int idx_16c = 0; const RGB* std16c_rgb = __mg_bmp_get_std_16c (); pANDBits += MONOPITCH * (CURSORHEIGHT - 1); pXORBits += MONOPITCH * 4 * (CURSORHEIGHT - 1); Uint32* pixels = (Uint32*)csr_surf->pixels; for (y = 0; y < CURSORHEIGHT; y++) { const BYTE* and_bytes = pANDBits; const BYTE* xor_bytes = pXORBits; for (x = 0; x < CURSORWIDTH; x++) { if (x % 8 == 0) { and_byte = *and_bytes++; } if (x % 2 == 0) { xor_byte = *xor_bytes++; idx_16c = (xor_byte >> 4) & 0x0F; } else { idx_16c = xor_byte & 0x0F; } if (and_byte & (0x80 >> (x % 8))) { pixels [x] = trans_pixel; } else { pixels [x] = RGBA2Pixel (_dc_cursor, std16c_rgb[idx_16c].r, std16c_rgb[idx_16c].g, std16c_rgb[idx_16c].b, 0xFF); } } pANDBits -= MONOPITCH; pXORBits -= (MONOPITCH * 4); pixels += (csr_surf->pitch >> 2); } } return (HCURSOR)pcsr; } static HCURSOR srvCopyCursor (HCURSOR hcsr) { PCURSOR pcsr = (PCURSOR)hcsr; PCURSOR pdcsr; GAL_Surface* dcsr_surf; GAL_Surface* scsr_surf; if (!(pdcsr = (PCURSOR)malloc (sizeof (CURSOR)))) return 0; scsr_surf = pcsr->surface; dcsr_surf = GAL_CreateCursorSurface (NULL, scsr_surf->w, scsr_surf->h); if (dcsr_surf == NULL) { free (pdcsr); return 0; } pdcsr->xhotspot = pcsr->xhotspot; pdcsr->yhotspot = pcsr->yhotspot; memcpy(dcsr_surf->pixels, scsr_surf->pixels, scsr_surf->h * scsr_surf->pitch); return (HCURSOR) pdcsr; } static BOOL srvDestroyCursor (HCURSOR hcsr) { int i; PCURSOR pcsr = (PCURSOR)hcsr; if (pcsr == NULL) return TRUE; for (i = 0; i < ((PG_RES)mgSharedRes)->csrnum; i++) { if (pcsr == _sys_cursors [i]) return FALSE; } if (pcsr == CSR_CURRENT) SetCursor(_def_cursor); GAL_FreeCursorSurface(pcsr->surface); free(pcsr); return TRUE; } static BOOL my_buff_allocator (void* context, BITMAP* bmp) { PCURSOR* pcsr = context; GAL_Surface* csr_surf; if (bmp->bmWidth <= 0 || bmp->bmWidth > MAX_CURSORWIDTH || bmp->bmHeight <= 0 || bmp->bmHeight > MAX_CURSORHEIGHT) return FALSE; assert (bmp->bmAlphaPitch == 0); csr_surf = GAL_CreateCursorSurface (NULL, bmp->bmWidth, bmp->bmHeight); if (!csr_surf) { return FALSE; } bmp->bmBits = csr_surf->pixels; (*pcsr)->surface = csr_surf; return TRUE; } static PCURSOR srvLoadCursorFromPNG (MG_RWops* area) { BITMAP bmp; PCURSOR pcsr; int ret; if (!(pcsr = (PCURSOR)malloc (sizeof (CURSOR)))) return NULL; ret = LoadBitmapEx2 (_dc_cursor, &bmp, area, "png", my_buff_allocator, &pcsr); if (ret) { goto error; } return (HCURSOR)pcsr; error: if (pcsr->surface) { GAL_FreeCursorSurface(pcsr->surface); } free (pcsr); return NULL; } static HCURSOR srvLoadCursorFromPNGFile (const char* filename, int xhotspot, int yhotspot) { PCURSOR csr; MG_RWops* area; if (!(area = MGUI_RWFromFile (filename, "rb"))) { _WRN_PRINTF ("Failed to make RWOps\n"); return NULL; } csr = srvLoadCursorFromPNG(area); if (csr) { csr->xhotspot = xhotspot; csr->yhotspot = yhotspot; } MGUI_RWclose (area); return csr; } HCURSOR GUIAPI LoadCursorFromPNGFile (const char* filename, int xhotspot, int yhotspot) { if (mgIsServer) { return srvLoadCursorFromPNGFile (filename, xhotspot, yhotspot); } else { HCURSOR hcursor; REQUEST req; int hotspot[2] = { xhotspot, yhotspot }; req.id = REQID_LOADCURSOR_PNG; req.data = hotspot; req.len_data = sizeof (hotspot); if (ClientRequestEx (&req, filename, strlen (filename) + 1, &hcursor, sizeof (HCURSOR)) < 0) return 0; return hcursor; } } static HCURSOR srvLoadCursorFromPNGMem (const void* mem, size_t size, int xhotspot, int yhotspot) { PCURSOR csr; MG_RWops* area; if (!(area = MGUI_RWFromMem ((void*)mem, size))) { _WRN_PRINTF ("Failed to make RWOps\n"); return NULL; } csr = srvLoadCursorFromPNG(area); if (csr) { csr->xhotspot = xhotspot; csr->yhotspot = yhotspot; } MGUI_RWclose (area); return csr; } HCURSOR GUIAPI LoadCursorFromPNGMem (const void* area, size_t size, int xhotspot, int yhotspot) { if (mgIsServer) { return srvLoadCursorFromPNGMem (area, size, xhotspot, yhotspot); } else { HCURSOR hcursor; REQUEST req; int hotspot[2] = { xhotspot, yhotspot }; req.id = REQID_LOADCURSOR_PNG_MEM; req.data = hotspot; req.len_data = sizeof(hotspot); if (ClientRequestEx (&req, area, size, &hcursor, sizeof (HCURSOR)) < 0) return 0; return hcursor; } } BOOL mg_InitCursor (void) { if (mgIsServer) { CSR_CURRENT_SET = 0; CSR_SHOW_COUNT = 0; CSR_OLDBOXLEFT = -100; CSR_OLDBOXTOP = -100; static char fake_bits [4]; _dc_cursor = CreateMemDCEx (1, 1, 32, MEMDC_FLAG_SWSURFACE | MEMDC_FLAG_SRCALPHA, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, fake_bits, sizeof (fake_bits)); if (_dc_cursor == HDC_INVALID) return FALSE; } _sys_cursors = (PCURSOR*)((PG_RES)mgSharedRes)->sys_cursors; return TRUE; } /* The following function must be called at last. */ void mg_TerminateCursor (void) { int i; if (mgIsServer) { CSR_CURRENT_SET = 0; CSR_SHOW_COUNT = 0; for (i = 0; i < ((PG_RES)mgSharedRes)->csrnum; i++) { if (_sys_cursors [i]) { GAL_FreeCursorSurface (_sys_cursors[i]->surface); free (_sys_cursors [i]); _sys_cursors [i] = NULL; } } DeleteMemDC (_dc_cursor); } } #else /* _MGSCHEMA_COMPOSITING */ #if 0 /* FIXME: I do not know why this can not work :( */ Uint8* GetPixelUnderCursor (int x, int y, gal_pixel* pixel) { Uint8* dst = NULL; lock_cursor_sem (); if (CSR_SHOW_COUNT >= 0 && CSR_CURRENT && x >= CSR_OLDBOXLEFT && y >= CSR_OLDBOXTOP && (x < CSR_OLDBOXLEFT + CURSORWIDTH) && (y < CSR_OLDBOXTOP + CURSORHEIGHT) && get_hidecursor_sem_val () == 0) { int _x = x - CSR_OLDBOXLEFT; int _y = y - CSR_OLDBOXTOP; dst = CSR_SAVEDBITS + _y * __mg_csrimgpitch + _x * __gal_screen->format->BytesPerPixel; *pixel = _mem_get_pixel (dst, __gal_screen->format->BytesPerPixel); } unlock_cursor_sem (); return dst; } #endif /* Cursor creating and destroying. */ static HCURSOR srvCreateCursor (int xhotspot, int yhotspot, int w, int h, const BYTE* pANDBits, const BYTE* pXORBits, int colornum) { PCURSOR pcsr; if (w != CURSORWIDTH || h != CURSORHEIGHT) return 0; if (!(pcsr = (PCURSOR)malloc (sizeof (CURSOR)))) return 0; if (!(pcsr->AndBits = malloc (__mg_csrimgsize))) { free(pcsr); return 0; } if (!(pcsr->XorBits = malloc (__mg_csrimgsize))) { free (pcsr->AndBits); free (pcsr); return 0; } pcsr->xhotspot = xhotspot; pcsr->yhotspot = yhotspot; pcsr->width = w; pcsr->height = h; if (colornum == 1) { ExpandMonoBitmap (HDC_SCREEN_SYS, pcsr->AndBits, __mg_csrimgpitch, pANDBits, MONOPITCH, w, h, MYBMP_FLOW_UP, RGBA2Pixel (HDC_SCREEN_SYS, 0, 0, 0, 0xFF), RGBA2Pixel (HDC_SCREEN_SYS, 0xFF, 0xFF, 0xFF, 0xFF)); ExpandMonoBitmap (HDC_SCREEN_SYS, pcsr->XorBits, __mg_csrimgpitch, pXORBits, MONOPITCH, w, h, MYBMP_FLOW_UP, RGBA2Pixel (HDC_SCREEN_SYS, 0, 0, 0, 0x00), RGBA2Pixel (HDC_SCREEN_SYS, 0xFF, 0xFF, 0xFF, 0x00)); } else if (colornum == 4) { ExpandMonoBitmap (HDC_SCREEN_SYS, pcsr->AndBits, __mg_csrimgpitch, pANDBits, MONOPITCH, w, h, MYBMP_FLOW_UP, RGBA2Pixel (HDC_SCREEN_SYS, 0, 0, 0, 0xFF), RGBA2Pixel (HDC_SCREEN_SYS, 0xFF, 0xFF, 0xFF, 0xFF)); Expand16CBitmapEx (HDC_SCREEN_SYS, pcsr->XorBits, __mg_csrimgpitch, pXORBits, MONOPITCH*4, w, h, MYBMP_FLOW_UP, NULL, FALSE, 0x00); } return (HCURSOR)pcsr; } static HCURSOR srvCopyCursor (HCURSOR hcsr) { PCURSOR pcsr = (PCURSOR)hcsr; PCURSOR pdcsr; if (!(pdcsr = (PCURSOR)malloc (sizeof (CURSOR)))) return 0; if (!(pdcsr->AndBits = malloc (__mg_csrimgsize))) { free(pdcsr); return 0; } if (!(pdcsr->XorBits = malloc (__mg_csrimgsize))) { free (pdcsr->AndBits); free (pdcsr); return 0; } pdcsr->xhotspot = pcsr->xhotspot; pdcsr->yhotspot = pcsr->yhotspot; pdcsr->width = pcsr->width; pdcsr->height = pcsr->height; memcpy(pdcsr->XorBits, pcsr->XorBits, __mg_csrimgsize); memcpy(pdcsr->AndBits, pcsr->AndBits, __mg_csrimgsize); return (HCURSOR) pdcsr; } static BOOL srvDestroyCursor (HCURSOR hcsr) { int i; PCURSOR pcsr = (PCURSOR)hcsr; if (pcsr == NULL) return TRUE; for (i = 0; i < ((PG_RES)mgSharedRes)->csrnum; i++) { if (pcsr == _sys_cursors [i]) return FALSE; } if (pcsr == CSR_CURRENT) SetCursor(_def_cursor); free(pcsr->AndBits); free(pcsr->XorBits); free(pcsr); return TRUE; } static void init_system_cursor (void) { int csrid; unsigned char* temp; temp = mgSharedRes + ((PG_RES)mgSharedRes)->csroffset; temp += sizeof (PCURSOR) * ((PG_RES)mgSharedRes)->csrnum; for (csrid = 0; csrid < ((PG_RES)mgSharedRes)->csrnum; csrid++) { if (!(_sys_cursors [csrid] = (PCURSOR) malloc (sizeof(CURSOR)))) return; _sys_cursors [csrid]->xhotspot = ((PCURSOR)temp)->xhotspot; _sys_cursors [csrid]->yhotspot = ((PCURSOR)temp)->yhotspot; _sys_cursors [csrid]->width = ((PCURSOR)temp)->width; _sys_cursors [csrid]->height = ((PCURSOR)temp)->height; _sys_cursors [csrid]->AndBits = temp + sizeof(CURSOR); _sys_cursors [csrid]->XorBits = temp + sizeof(CURSOR) + __mg_csrimgsize; temp += (sizeof(CURSOR) + 2 * __mg_csrimgsize); } } static BITMAP csr_bmp; BOOL mg_InitCursor (void) { _sys_cursors = mgSharedRes + ((PG_RES)mgSharedRes)->csroffset; if (mgIsServer) { if (!(_cursor_bits = malloc (__mg_csrimgsize))) { return FALSE; } init_system_cursor (); CSR_CURRENT_SET = 0; CSR_SHOW_COUNT = 0; CSR_OLDBOXLEFT = -100; CSR_OLDBOXTOP = -100; } /* NOTE: Always initialize the structue fields with explicit assignments */ csr_bmp.bmType = BMP_TYPE_NORMAL; csr_bmp.bmBitsPerPixel = __gal_screen->format->BitsPerPixel; csr_bmp.bmBytesPerPixel = __gal_screen->format->BytesPerPixel; csr_bmp.bmWidth = CURSORWIDTH; csr_bmp.bmHeight = CURSORHEIGHT; csr_bmp.bmPitch = __gal_screen->format->BytesPerPixel * CURSORWIDTH; return TRUE; } /* The following function must be called at last. */ void mg_TerminateCursor (void) { int i; if (mgIsServer) { free (_cursor_bits); CSR_CURRENT_SET = 0; CSR_SHOW_COUNT = 0; for (i = 0; i < ((PG_RES)mgSharedRes)->csrnum; i++) { if (_sys_cursors [i]) { free (_sys_cursors [i]); _sys_cursors [i] = NULL; } } } } static GAL_Rect csr_rect = {0, 0, CURSORWIDTH, CURSORHEIGHT}; static void hidecursor (void) { csr_rect.x = CSR_OLDBOXLEFT; csr_rect.y = CSR_OLDBOXTOP; csr_bmp.bmBits = CSR_SAVEDBITS; GAL_SetClipRect (__gal_screen, NULL); GAL_PutBox (__gal_screen, &csr_rect, &csr_bmp); GAL_UpdateRects (__gal_screen, 1, &csr_rect); #if 0 // Debug code if (!mgIsServer) { char filename [PATH_MAX + 1]; struct timeval tv; gettimeofday (&tv, NULL); sprintf (filename, "saved-cursor-bits-%d.%d.bmp", (int)tv.tv_sec, (int)tv.tv_usec); SaveBitmapToFile(HDC_SCREEN, &csr_bmp, filename); } #endif } void _dc_restore_alpha_in_bitmap (const GAL_PixelFormat* format, void* dst_bits, unsigned int nr_bytes); static void showcursor (void) { int x, y; x = boxleft (); y = boxtop (); csr_rect.x = x; csr_rect.y = y; csr_bmp.bmBits = CSR_SAVEDBITS; GAL_SetClipRect (__gal_screen, NULL); GAL_GetBox (__gal_screen, &csr_rect, &csr_bmp); CSR_OLDBOXLEFT = x; CSR_OLDBOXTOP = y; GAL_memcpy4 (_cursor_bits, CSR_SAVEDBITS, __mg_csrimgsize >> 2); #ifdef ASM_memandcpy4 ASM_memandcpy4 (_cursor_bits, CSR_CURRENT->AndBits, __mg_csrimgsize >> 2); ASM_memxorcpy4 (_cursor_bits, CSR_CURRENT->XorBits, __mg_csrimgsize >> 2); #else { int i; Uint32* andbits = (Uint32*) CSR_CURRENT->AndBits; Uint32* xorbits = (Uint32*) CSR_CURRENT->XorBits; Uint32* dst = (Uint32*) _cursor_bits; for (i = 0; i < __mg_csrimgsize >> 2; i++) { dst [i] &= andbits [i]; dst [i] ^= xorbits [i]; } } #endif csr_bmp.bmBits = _cursor_bits; GAL_PutBox (__gal_screen, &csr_rect, &csr_bmp); GAL_UpdateRects (__gal_screen, 1, &csr_rect); } #endif /* _MGSCHEMA_COMPOSITING */ HCURSOR GUIAPI CopyCursor (HCURSOR hcsr) { if (mgIsServer) { return srvCopyCursor(hcsr); } else { HCURSOR hcursor; REQUEST req; req.id = REQID_COPYCURSOR; req.len_data = sizeof(HCURSOR); req.data = &hcsr; if (ClientRequest (&req, &hcursor, sizeof (HCURSOR)) < 0) hcursor = 0; DEALLOCATE_LOCAL (tmp); return hcursor; } } #define _LEN_BITS (MONOPITCH * CURSORHEIGHT) HCURSOR GUIAPI CreateCursor (int xhotspot, int yhotspot, int w, int h, const BYTE* pANDBits, const BYTE* pXORBits, int colornum) { if (mgIsServer) { return srvCreateCursor (xhotspot, yhotspot, w, h, pANDBits, pXORBits, colornum); } else { HCURSOR hcursor; REQUEST req; int len_and_bits, len_xor_bits; int* tmp; if (w != CURSORWIDTH || h != CURSORHEIGHT) return 0; len_and_bits = _LEN_BITS; len_xor_bits = _LEN_BITS * ((colornum == 1) ? 1 : 4); req.id = REQID_CREATECURSOR; req.len_data = sizeof (int) * 6 + len_and_bits + len_xor_bits; if ((tmp = (int*) ALLOCATE_LOCAL (req.len_data)) == NULL) return 0; tmp [0] = xhotspot; tmp [1] = yhotspot; tmp [2] = w; tmp [3] = h; tmp [4] = colornum; tmp [5] = _LEN_BITS; memcpy (tmp + 6, pANDBits, len_and_bits); memcpy ((BYTE*)(tmp + 6) + len_and_bits, pXORBits, len_xor_bits); req.data = tmp; if (ClientRequest (&req, &hcursor, sizeof (HCURSOR)) < 0) hcursor = 0; DEALLOCATE_LOCAL (tmp); return hcursor; } } #include "cursor-comm.c" HCURSOR GUIAPI LoadCursorFromFile (const char* filename) { if (mgIsServer) { return load_cursor_from_file (filename); } else { HCURSOR hcursor; REQUEST req; req.id = REQID_LOADCURSOR; req.data = filename; req.len_data = strlen (filename) + 1; if (ClientRequest (&req, &hcursor, sizeof (HCURSOR)) < 0) return 0; return hcursor; } } HCURSOR GUIAPI LoadCursorFromMem (const void* area) { return load_cursor_from_mem (area); } BOOL GUIAPI DestroyCursor (HCURSOR hcsr) { if (mgIsServer) { return srvDestroyCursor (hcsr); } else { REQUEST req; BOOL ret_value; req.id = REQID_DESTROYCURSOR; req.data = &hcsr; req.len_data = sizeof (HCURSOR); if (ClientRequest (&req, &ret_value, sizeof (BOOL)) < 0) return FALSE; return ret_value; } } HCURSOR GUIAPI GetSystemCursor (int csrid) { if (csrid >= ((PG_RES)mgSharedRes)->csrnum || csrid < 0) return 0; return (HCURSOR) (_sys_cursors [csrid]); } HCURSOR GUIAPI GetDefaultCursor (void) { return _def_cursor; } #endif /* _MGHAVE_CURSOR */ /* The return value indicates whether mouse has moved. */ /* TRUE for moved. */ /* NOTE that only server can call this function. */ BOOL kernel_RefreshCursor (int* x, int* y, int* button) { int curx, cury; BOOL moved = FALSE; if (!mgIsServer) return FALSE; IAL_GetMouseXY (x, y); SHAREDRES_MOUSEX = curx = *x; SHAREDRES_MOUSEY = cury = *y; if (button) SHAREDRES_BUTTON = *button = IAL_GetMouseButton (); if (oldx != curx || oldy != cury) { #if defined (_MGHAVE_CURSOR) && defined(_MGSCHEMA_SHAREDFB) lock_cursor_sem (); CSR_CURSORX = curx; CSR_CURSORY = cury; if (CSR_SHOW_COUNT >= 0 && CSR_CURRENT) { if (get_hidecursor_sem_val ()) { reset_hidecursor_sem (); } else { hidecursor (); } showcursor (); } unlock_cursor_sem (); #endif /* _MGHAVE_CURSOR && _MGSCHEMA_SHAREDFB*/ oldx = curx; oldy = cury; moved = TRUE; } return moved; } #ifdef _MGHAVE_CURSOR #ifdef _MGSCHEMA_SHAREDFB /* show cursor hidden by client GDI function */ void kernel_ReShowCursor (void) { lock_cursor_sem (); if (CSR_SHOW_COUNT >= 0 && CSR_CURRENT) { if (get_hidecursor_sem_val ()) { reset_hidecursor_sem (); showcursor (); } } unlock_cursor_sem (); } #endif /* _MGSCHEMA_SHAREDFB */ /* Always call with "setdef = FALSE" for clients at server side. */ HCURSOR GUIAPI SetCursorEx (HCURSOR hcsr, BOOL setdef) { PCURSOR old, pcsr; if (!mgIsServer) { REQUEST req; req.id = REQID_SETCURSOR; req.data = &hcsr; req.len_data = sizeof (HCURSOR); if (ClientRequest (&req, &old, sizeof (PCURSOR)) < 0) return 0; return (HCURSOR) old; } if (setdef) { old = (PCURSOR) _def_cursor; _def_cursor = hcsr; } else old = CSR_CURRENT; if ((PCURSOR)hcsr == CSR_CURRENT) { return (HCURSOR) old; } pcsr = (PCURSOR)hcsr; lock_cursor_sem (); #ifdef _MGSCHEMA_COMPOSITING CSR_CURRENT_SET = (HCURSOR)pcsr; CSR_XHOTSPOT = pcsr ? pcsr->xhotspot : -100; CSR_YHOTSPOT = pcsr ? pcsr->yhotspot : -100; if (CSR_CURRENT && CSR_SHOW_COUNT >= 0) GAL_SetCursor (pcsr->surface, pcsr->xhotspot, pcsr->yhotspot); else GAL_SetCursor (NULL, 0, 0); #else /* _MGSCHEMA_SHAREDFB */ if (CSR_CURRENT && CSR_SHOW_COUNT >= 0 && get_hidecursor_sem_val () == 0) hidecursor(); CSR_CURRENT_SET = (HCURSOR)pcsr; CSR_XHOTSPOT = pcsr ? pcsr->xhotspot : -100; CSR_YHOTSPOT = pcsr ? pcsr->yhotspot : -100; if (CSR_CURRENT && CSR_SHOW_COUNT >= 0 && get_hidecursor_sem_val () == 0) showcursor(); #endif unlock_cursor_sem (); return (HCURSOR) old; } HCURSOR GUIAPI GetCurrentCursor (void) { return (HCURSOR)CSR_CURRENT; } #ifdef _MGSCHEMA_SHAREDFB static inline BOOL does_need_hide (const RECT* prc) { int csrleft, csrright, csrtop, csrbottom; int intleft, intright, inttop, intbottom; csrleft = boxleft(); csrright = csrleft + CURSORWIDTH; csrtop = boxtop(); csrbottom = csrtop + CURSORHEIGHT; intleft = (csrleft > prc->left) ? csrleft : prc->left; inttop = (csrtop > prc->top) ? csrtop : prc->top; intright = (csrright < prc->right) ? csrright : prc->right; intbottom = (csrbottom < prc->bottom) ? csrbottom : prc->bottom; if (intleft >= intright || inttop >= intbottom) { return FALSE; } return TRUE; } /* version for _MGSCHEMA_SHAREDFB */ void kernel_ShowCursorForGDI (BOOL fShow, void* pdc) { PDC cur_pdc = (PDC)pdc; const RECT* prc = NULL; prc = &cur_pdc->rc_output; if (cur_pdc->surface != __gal_screen) { if (fShow) GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); } else { if (!mgIsServer && (SHAREDRES_TOPMOST_LAYER != __mg_layer)) { return; } if (!fShow) { lock_cursor_sem (); if (CSR_SHOW_COUNT >= 0 && CSR_CURRENT && does_need_hide (prc)) { if (get_hidecursor_sem_val () == 0) { inc_hidecursor_sem (); hidecursor (); } } } else { GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); unlock_cursor_sem (); } } } #else /* version for _MGSCHEMA_COMPOSITING */ void kernel_ShowCursorForGDI (BOOL fShow, void* pdc) { PDC cur_pdc = (PDC)pdc; const RECT* prc = NULL; if (!mgIsServer && (SHAREDRES_TOPMOST_LAYER != __mg_layer)) { return; } prc = &cur_pdc->rc_output; if (cur_pdc->surface->video && fShow) { GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); } } #endif /* _MGSCHEMA_SHAREDFB */ int GUIAPI ShowCursor (BOOL fShow) { if (!mgIsServer) { REQUEST req; int ret_value; req.id = REQID_SHOWCURSOR; req.data = &fShow; req.len_data = sizeof (BOOL); ClientRequest (&req, &ret_value, sizeof (int)); return ret_value; } #ifdef _MGSCHEMA_SHAREDFB lock_cursor_sem (); if (fShow) { CSR_SHOW_COUNT++; if (CSR_SHOW_COUNT == 0 && CSR_CURRENT && get_hidecursor_sem_val () == 0) showcursor(); } else { CSR_SHOW_COUNT--; if (CSR_SHOW_COUNT == -1 && CSR_CURRENT) hidecursor(); } unlock_cursor_sem (); #else /* _MGSCHEMA_SHAREDFB */ if (fShow) { CSR_SHOW_COUNT++; if (CSR_SHOW_COUNT == 0 && CSR_CURRENT) { PCURSOR pcsr = (PCURSOR)CSR_CURRENT; GAL_SetCursor (pcsr->surface, pcsr->xhotspot, pcsr->yhotspot); } } else { CSR_SHOW_COUNT--; if (CSR_SHOW_COUNT == -1 && CSR_CURRENT) { GAL_SetCursor (NULL, 0, 0); } } #endif /* _MGSCHEMA_COMPOSITING */ return CSR_SHOW_COUNT; } #else /* _MGHAVE_CURSOR */ /* version for no cursor support */ void kernel_ShowCursorForGDI (BOOL fShow, void* pdc) { PDC cur_pdc = (PDC)pdc; const RECT* prc = NULL; prc = &cur_pdc->rc_output; /* houhh20080827, if --disable-cursor, mginit can not update auto(qvfb). */ #if 0 if (cur_pdc->surface == __gal_screen && mgIsServer && (SHAREDRES_TOPMOST_LAYER != __mg_layer)) return; if (fShow) GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); #else if (!mgIsServer && (SHAREDRES_TOPMOST_LAYER != __mg_layer)) { return; } if (fShow) GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); #endif } #endif /* _MGHAVE_CURSOR */ void GUIAPI GetCursorPos (POINT* ppt) { ppt->x = SHAREDRES_MOUSEX; ppt->y = SHAREDRES_MOUSEY; } void GUIAPI SetCursorPos (int x, int y) { if (mgIsServer) { IAL_SetMouseXY (x, y); kernel_RefreshCursor (&x, &y, NULL); } else { REQUEST req; POINT pt = {x, y}; req.id = REQID_SETCURSORPOS; req.data = &pt; req.len_data = sizeof (POINT); ClientRequest (&req, NULL, 0); } } /* Cursor clipping support. */ void GUIAPI ClipCursor (const RECT* prc) { RECT rc; if (!mgIsServer) { REQUEST req; req.id = REQID_CLIPCURSOR; if (prc) req.data = prc; else { SetRect (&rc, 0, 0, WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); req.data = &rc; } req.len_data = sizeof (RECT); ClientRequest (&req, NULL, 0); return; } SetRect (&cliprc, 0, 0, WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); if (prc == NULL) { IAL_SetMouseRange (0,0,WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); return; } memcpy (&rc, prc, sizeof(RECT)); NormalizeRect (&rc); IntersectRect (&cliprc, &rc, &cliprc); NormalizeRect (&cliprc); IAL_SetMouseRange (cliprc.left, cliprc.top, cliprc.right - 1, cliprc.bottom - 1); } void GUIAPI GetClipCursor (RECT* prc) { if (!mgIsServer) { REQUEST req; req.id = REQID_GETCLIPCURSOR; req.data = NULL; req.len_data = 0; ClientRequest (&req, prc, sizeof (RECT)); return; } if (IsRectEmpty (&cliprc)) SetRect (&cliprc, 0, 0, WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); memcpy (prc, &cliprc, sizeof(RECT)); } #endif /* _MGRM_PROCESSES */