Mercurial > ecos
diff packages/services/gfx/mw/current/src/mwin/winmain.c @ 208:e0c0827131d1 ecos
Merge from eCos master repository on 2002-05-20-20:11:54-BST
| author | jlarmour |
|---|---|
| date | Mon, 20 May 2002 22:19:26 +0000 |
| parents | |
| children |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/services/gfx/mw/current/src/mwin/winmain.c @@ -0,0 +1,558 @@ +/* + * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com> + * + * Main module of Microwindows + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> + +#ifndef __PACIFIC__ +#include <errno.h> +#include <sys/types.h> +#endif + +#if UNIX | DOS_DJGPP +#include <unistd.h> +#if _MINIX +#include <sys/times.h> +#else +#include <sys/time.h> +#endif +#endif + +#if ELKS +#include <linuxmt/posix_types.h> +#include <linuxmt/time.h> +#endif + +#include "windows.h" +#include "wintern.h" +#include "device.h" +/* + * External definitions defined here. + */ +HWND listwp; /* list of all windows */ +HWND rootwp; /* root window pointer */ +HWND focuswp; /* focus window for keyboard */ +HWND mousewp; /* window mouse is currently in */ +HWND capturewp; /* capture window*/ +HWND dragwp; /* window user is dragging*/ +HCURSOR curcursor; /* currently enabled cursor */ +MWCOORD cursorx; /* current x position of cursor */ +MWCOORD cursory; /* current y position of cursor */ +DWORD startTicks; /* tickcount on startup */ +int keyb_fd; /* the keyboard file descriptor */ +int mouse_fd; /* the mouse file descriptor */ +int escape_quits = 1; /* terminate when pressing ESC */ + +int +main(int ac,char **av) +{ + /* call user hook routine before anything*/ + if(MwUserInit(ac, av) < 0) + exit(1); + + if(MwOpen() < 0) + exit(1); + + /* call windows main program entry point*/ + WinMain(NULL, NULL, NULL, SW_SHOW); + + MwClose(); + return 0; +} + +/* + * Open a connection from a new client to the server. + * Returns -1 on failure. + */ +int +MwOpen(void) +{ + /* Client calls this routine once. We + * init everything here + */ + if(MwInitialize() < 0) + return -1; + return 1; +} + +/* + * Close the connection to the server. + */ +void +MwClose(void) +{ + MwTerminate(); +} + +#if (UNIX | DOS_DJGPP) && !_MINIX +/* + * Support for more than one user fd. + * Chris Johns (ccj@acm.org) + * + * Register the specified file descriptor to post + * WM_FDINPUT/WM_FDOUTPUT/WM_FDEXCEPT to the passed hwnd + * when input/output/except is ready. + * + * Allow for any fd to be selected on. + * + * The user fd's are listed and scanned helping keep the + * overhead down for a large list of fd's being selected on. + */ + +typedef struct { + HWND read; + HWND write; + HWND except; + int next; +} WNDUSERFD; + +static WNDUSERFD userregfd[FD_SETSIZE]; +static int userregfd_head; + +void +MwRegisterFdInput(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (!userregfd[fd].read) { + userregfd[fd].read = hwnd; + if (userregfd[fd].next == -1 && !userregfd[fd].write && !userregfd[fd].except) { + userregfd[fd].next = userregfd_head; + userregfd_head = fd; + } + } + } +} + +void +MwUnregisterFdInput(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (userregfd[fd].read == hwnd) { + userregfd[fd].read = NULL; + if (!userregfd[fd].write && !userregfd[fd].except) { + int *listfd = &userregfd_head; + while (*listfd != -1) { + if (*listfd == fd) { + *listfd = userregfd[fd].next; + userregfd[fd].next = -1; + return; + } + listfd = &userregfd[*listfd].next; + } + userregfd_head = fd; + } + } + } +} + +void +MwRegisterFdOutput(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (!userregfd[fd].write) { + userregfd[fd].write = hwnd; + if (userregfd[fd].next == -1 && !userregfd[fd].read && !userregfd[fd].except) { + userregfd[fd].next = userregfd_head; + userregfd_head = fd; + } + } + } +} + +void +MwUnregisterFdOutput(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (userregfd[fd].write == hwnd) { + userregfd[fd].write = NULL; + if (!userregfd[fd].read && !userregfd[fd].except) { + int *listfd = &userregfd_head; + while (*listfd != -1) { + if (*listfd == fd) { + *listfd = userregfd[fd].next; + userregfd[fd].next = -1; + return; + } + listfd = &userregfd[*listfd].next; + } + userregfd_head = fd; + } + } + } +} + +void +MwRegisterFdExcept(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (!userregfd[fd].except) { + userregfd[fd].except = hwnd; + if (userregfd[fd].next == -1 && !userregfd[fd].read && !userregfd[fd].write) { + userregfd[fd].next = userregfd_head; + userregfd_head = fd; + } + } + } +} + +void +MwUnregisterFdExcept(HWND hwnd, int fd) +{ + if (fd < FD_SETSIZE && fd != mouse_fd && fd != keyb_fd) { + if (userregfd[fd].except == hwnd) { + userregfd[fd].except = NULL; + if (!userregfd[fd].read && !userregfd[fd].write) { + int *listfd = &userregfd_head; + while (*listfd != -1) { + if (*listfd == fd) { + *listfd = userregfd[fd].next; + userregfd[fd].next = -1; + return; + } + listfd = &userregfd[*listfd].next; + } + userregfd_head = fd; + } + } + } +} + +#endif /* UNIX | DOS_DJGPP*/ + +#if MSDOS | _MINIX +void +MwSelect(void) +{ + /* If mouse data present, service it*/ + if(mousedev.Poll()) + while(MwCheckMouseEvent()) + continue; + + /* If keyboard data present, service it*/ + if(kbddev.Poll()) + while(MwCheckKeyboardEvent()) + continue; + + MwHandleTimers(); +} +#endif + +#if UNIX && defined(HAVESELECT) +#if ANIMATEPALETTE +static int fade = 0; +#endif + +void +MwSelect(void) +{ + fd_set rfds; + fd_set wfds; + fd_set efds; + int fd; + int e; + int setsize = 0; + UINT timeout; + struct timeval to; + + /* perform pre-select duties, if any*/ + if(scrdev.PreSelect) + scrdev.PreSelect(&scrdev); + + /* Set up the FDs for use in the main select(): */ + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + if(mouse_fd >= 0) { + FD_SET(mouse_fd, &rfds); + if(mouse_fd > setsize) + setsize = mouse_fd; + } + if(keyb_fd >= 0) { + FD_SET(keyb_fd, &rfds); + if(keyb_fd > setsize) + setsize = keyb_fd; + } + + /* handle registered file descriptors */ + fd = userregfd_head; + while (fd != -1) { + if (userregfd[fd].read) FD_SET(fd, &rfds); + if (userregfd[fd].write) FD_SET(fd, &wfds); + if (userregfd[fd].except) FD_SET(fd, &efds); + if(fd > setsize) setsize = fd; + fd = userregfd[fd].next; + } + + ++setsize; + + /* Set up the timeout for the main select(). If + * the mouse is captured we're probably moving a window, + * so poll quickly to allow other windows to repaint while + * checking for more event input. + */ + if(dragwp) + timeout = to.tv_sec = to.tv_usec = 0L; + else { + timeout = MwGetNextTimeoutValue(); /* returns ms*/ +#if ANIMATEPALETTE + if(fade < 100) + timeout = 40; +#endif +if (!timeout) timeout = 10; /* temp kluge required for mdemo to run ok*/ + GdGetNextTimeout(&to, timeout); + } + + /* Wait for some input on any of the fds in the set or a timeout: */ + if((e = select(setsize, &rfds, &wfds, &efds, &to)) > 0) { + + /* If data is present on the mouse fd, service it: */ + if(mouse_fd >= 0 && FD_ISSET(mouse_fd, &rfds)) + while(MwCheckMouseEvent()) + continue; + + /* If data is present on the keyboard fd, service it: */ + if(keyb_fd >= 0 && FD_ISSET(keyb_fd, &rfds)) + while(MwCheckKeyboardEvent()) + continue; + + /* If registered descriptor, handle it */ + fd = userregfd_head; + while (fd != -1) { + if (userregfd[fd].read && FD_ISSET(fd, &rfds)) + PostMessage(userregfd[fd].read, WM_FDINPUT, fd, 0); + if (userregfd[fd].write && FD_ISSET(fd, &wfds)) + PostMessage(userregfd[fd].write, WM_FDOUTPUT, fd, 0); + if (userregfd[fd].except && FD_ISSET(fd, &efds)) + PostMessage(userregfd[fd].except, WM_FDEXCEPT, fd, 0); + fd = userregfd[fd].next; + } + } + else if(e == 0) { + /* timeout has occured*/ + if(GdTimeout() == FALSE) + return; +#if ANIMATEPALETTE + if(fade <= 100) { + setfadelevel(&scrdev, fade); + fade += 5; + } +#endif + MwHandleTimers(); + } else + if(errno != EINTR) + EPRINTF("Select() call in main failed\n"); +} +#endif + +#if VTSWITCH +static void +CheckVtChange(void *arg) +{ + if(MwCheckVtChange()) { +#if ANIMATEPALETTE + fade = 0; +#endif + MwRedrawScreen(); + } + GdAddTimer(50, CheckVtChange, NULL); +} +#endif + +/* + * Initialize the graphics and mouse devices at startup. + * Returns nonzero with a message printed if the initialization failed. + */ +int +MwInitialize(void) +{ + HWND wp; /* root window */ + PSD psd; + WNDCLASS wc; + int fd; + static MWCURSOR arrow = { /* default arrow cursor*/ + 16, 16, + 0, 0, + RGB(255, 255, 255), RGB(0, 0, 0), + { 0xe000, 0x9800, 0x8600, 0x4180, + 0x4060, 0x2018, 0x2004, 0x107c, + 0x1020, 0x0910, 0x0988, 0x0544, + 0x0522, 0x0211, 0x000a, 0x0004 }, + { 0xe000, 0xf800, 0xfe00, 0x7f80, + 0x7fe0, 0x3ff8, 0x3ffc, 0x1ffc, + 0x1fe0, 0x0ff0, 0x0ff8, 0x077c, + 0x073e, 0x021f, 0x000e, 0x0004 } + }; + + extern MWLISTHEAD mwClassHead; + +#if (UNIX | DOS_DJGPP) && !_MINIX + for (fd = 0; fd < FD_SETSIZE; fd++) { + userregfd[fd].read = NULL; + userregfd[fd].write = NULL; + userregfd[fd].except = NULL; + userregfd[fd].next = -1; + } + userregfd_head = -1; +#endif + /* catch terminate signal to restore tty state*/ + signal(SIGTERM, (void *)MwTerminate); + + startTicks = GetTickCount(); + + if ((keyb_fd = GdOpenKeyboard()) == -1) { + EPRINTF("Cannot initialise keyboard\n"); + return -1; + } + + if ((psd = GdOpenScreen()) == NULL) { + EPRINTF("Cannot initialise screen\n"); + GdCloseKeyboard(); + return -1; + } + + if ((mouse_fd = GdOpenMouse()) == -1) { + EPRINTF("Cannot initialise mouse\n"); + GdCloseScreen(psd); + GdCloseKeyboard(); + return -1; + } + +#if ANIMATEPALETTE + setfadelevel(psd, 0); +#endif + /* + * Initialize the root window. + */ + wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; + wc.lpfnWndProc = (WNDPROC)DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = 0; + wc.hIcon = 0; /*LoadIcon(GetHInstance(), MAKEINTRESOURCE( 1));*/ + wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/ + wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND)); + wc.lpszMenuName = NULL; + wc.lpszClassName = "DeskTop"; + RegisterClass( &wc); + + wp = GdItemNew(struct hwnd); + if (!wp) { + EPRINTF("No memory for root window\n"); + GdCloseMouse(); + GdCloseScreen(psd); + GdCloseKeyboard(); + return -1; + } + /* remove the WS_CAPTION to have bare desktop window*/ + /*wp->style = WS_CLIPCHILDREN | WS_CAPTION | WS_VISIBLE;*/ + wp->style = WS_CLIPCHILDREN | WS_VISIBLE; + wp->exstyle = 0; + wp->pClass = (PWNDCLASS)mwClassHead.head; + wp->parent = NULL; + wp->children = NULL; + wp->siblings = NULL; + wp->next = NULL; + SetRect(&wp->winrect, 0, 0, psd->xvirtres, psd->yvirtres); + MwCalcClientRect(wp); + wp->cursor = NULL; + wp->unmapcount = 0; + wp->id = 0; + strcpy(wp->szTitle, "Microwindows"); + wp->gotPaintMsg = PAINT_PAINTED; +#if UPDATEREGIONS + wp->update = GdAllocRegion(); +#endif + + listwp = wp; + rootwp = wp; + focuswp = wp; + mousewp = wp; + + /* schedule desktop window paint*/ + InvalidateRect(rootwp, NULL, TRUE); + +#if VTSWITCH + MwInitVt(); + /* Check for VT change every 50 ms: */ + GdAddTimer(50, CheckVtChange, NULL); +#endif + + /* + * Initialize and position the default cursor. + */ + curcursor = NULL; + cursorx = -1; + cursory = -1; + GdShowCursor(psd); + MwMoveCursor(psd->xvirtres / 2, psd->yvirtres / 2); + MwSetCursor(rootwp, &arrow); + + /* + * Finally tell the mouse driver some things. + */ + GdRestrictMouse(0, 0, psd->xvirtres - 1, psd->yvirtres - 1); + GdMoveMouse(psd->xvirtres / 2, psd->yvirtres / 2); + + return 0; +} + +/* + * Here to close down the server. + */ +void +MwTerminate(void) +{ + GdCloseScreen(&scrdev); + GdCloseMouse(); + GdCloseKeyboard(); +#if VTSWITCH + MwRedrawVt(mwvterm); + MwExitVt(); +#endif + exit(0); +} + +/* + * Return # milliseconds elapsed since start of Microwindows + * Granularity is 25 msec + */ +DWORD WINAPI +GetTickCount(VOID) +{ +#if MSDOS +#include <time.h> + return (DWORD)(clock() * 1000 / CLOCKS_PER_SEC); +#else +#if _MINIX + struct tms t; + + return (DWORD)times(&t) * 16; +#else +#if UNIX + struct timeval t; + + gettimeofday(&t, NULL); + return ((t.tv_sec * 1000) + (t.tv_usec / 25000) * 25) - startTicks; +#else + return 0L; +#endif +#endif +#endif +} + +VOID WINAPI +Sleep(DWORD dwMilliseconds) +{ + int i, j, k; + const int loops_per_ms = 20000; + + /* FIXME this is not calibrated */ + for(i=0; i < dwMilliseconds; i++) + for(j=0; j < loops_per_ms; j++) + k = i * j; +}
