static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC dc; PAINTSTRUCT ps; #if GINPUT_NEED_TOGGLE HBRUSH hbrOn, hbrOff; HPEN pen; RECT rect; HGDIOBJ old; POINT p; coord_t pos; uint8_t bit; #endif switch (Msg) { case WM_CREATE: break; case WM_LBUTTONDOWN: #if GINPUT_NEED_MOUSE if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons |= GINPUT_MOUSE_BTN_LEFT; goto mousemove; } #endif #if GINPUT_NEED_TOGGLE bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth); toggles ^= bit; rect.left = 0; rect.right = wWidth; rect.top = wHeight; rect.bottom = wHeight + WIN32_BUTTON_AREA; InvalidateRect(hWnd, &rect, FALSE); UpdateWindow(hWnd); #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE ginputToggleWakeup(); #endif #endif break; case WM_LBUTTONUP: #if GINPUT_NEED_TOGGLE if ((toggles & 0xF0)) { toggles &= 0x0F; rect.left = 0; rect.right = wWidth; rect.top = wHeight; rect.bottom = wHeight + WIN32_BUTTON_AREA; InvalidateRect(hWnd, &rect, FALSE); UpdateWindow(hWnd); #if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE ginputToggleWakeup(); #endif } #endif #if GINPUT_NEED_MOUSE if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; goto mousemove; } #endif break; #if GINPUT_NEED_MOUSE case WM_MBUTTONDOWN: if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; goto mousemove; } break; case WM_MBUTTONUP: if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; goto mousemove; } break; case WM_RBUTTONDOWN: if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; goto mousemove; } break; case WM_RBUTTONUP: if ((coord_t)HIWORD(lParam) < wHeight) { mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; goto mousemove; } break; case WM_MOUSEMOVE: if ((coord_t)HIWORD(lParam) >= wHeight) break; mousemove: mousex = (coord_t)LOWORD(lParam); mousey = (coord_t)HIWORD(lParam); #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE ginputMouseWakeup(); #endif break; #endif case WM_SYSKEYDOWN: case WM_KEYDOWN: case WM_SYSKEYUP: case WM_KEYUP: break; case WM_CHAR: case WM_DEADCHAR: case WM_SYSCHAR: case WM_SYSDEADCHAR: break; case WM_PAINT: dc = BeginPaint(hWnd, &ps); BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, (ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top, dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); #if GINPUT_NEED_TOGGLE if (ps.rcPaint.bottom >= wHeight) { pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black)); hbrOn = CreateSolidBrush(COLOR2BGR(Blue)); hbrOff = CreateSolidBrush(COLOR2BGR(Gray)); old = SelectObject(dc, pen); MoveToEx(dc, 0, wHeight, &p); LineTo(dc, wWidth, wHeight); for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) { rect.left = pos; rect.right = pos + wWidth/8; rect.top = wHeight; rect.bottom = wHeight + WIN32_BUTTON_AREA; FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff); if (pos > 0) { MoveToEx(dc, rect.left, rect.top, &p); LineTo(dc, rect.left, rect.bottom); } } DeleteObject(hbrOn); DeleteObject(hbrOff); SelectObject(dc, old); } #endif EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); SelectObject(dcBuffer, dcOldBitmap); DeleteDC(dcBuffer); DeleteObject(dcBitmap); winRootWindow = NULL; break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }
static DECLARE_THREAD_FUNCTION(NetThread, param) { SOCKET_TYPE listenfd, fdmax, i, clientfd; socklen_t len; int leni; fd_set master, read_fds; struct sockaddr_in addr; GDisplay * g; netPriv * priv; (void)param; // Start the sockets layer StartSockets(); gfxSleepMilliseconds(100); // Make sure the thread has time to start. /* clear the master and temp sets */ FD_ZERO(&master); FD_ZERO(&read_fds); if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == (SOCKET_TYPE)-1) gfxHalt("GDISP: uGFXnet - Socket failed"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(GDISP_GFXNET_PORT); if (bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) gfxHalt("GDISP: uGFXnet - Bind failed"); if (listen(listenfd, 10) == -1) gfxHalt("GDISP: uGFXnet - Listen failed"); /* add the listener to the master set */ FD_SET(listenfd, &master); /* keep track of the biggest file descriptor */ fdmax = listenfd; /* so far, it's this one*/ #if GDISP_GFXNET_BROKEN_LWIP_ACCEPT { #warning "Using GDISP_GFXNET_BROKEN_LWIP_ACCEPT limits the number of displays and the use of GFXNET. Avoid if possible!" len = sizeof(addr); if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1) gfxHalt("GDISP: uGFXnet - Accept failed"); // Look for a display that isn't connected for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { // Ignore displays for other controllers #ifdef GDISP_DRIVER_LIST if (gvmt(g) != &GDISPVMT_uGFXnet) continue; #endif if (!(g->flags & GDISP_FLG_CONNECTED)) break; } // Was anything found? if (!g) { // No Just close the connection closesocket(clientfd); gfxHalt("GDISP: uGFXnet - Can't find display for connection"); return 0; } // Save the descriptor FD_SET(clientfd, &master); if (clientfd > fdmax) fdmax = clientfd; priv = g->priv; memset(priv, 0, sizeof(netPriv)); priv->netfd = clientfd; //printf(New connection from %s on socket %d allocated to display %u\n", inet_ntoa(addr.sin_addr), clientfd, disp+1); // Send the initialisation data (2 words at a time) priv->data[0] = GNETCODE_INIT; priv->data[1] = GNETCODE_VERSION; sendpkt(priv->netfd, priv->data, 2); priv->data[0] = GDISP_SCREEN_WIDTH; priv->data[1] = GDISP_SCREEN_HEIGHT; sendpkt(priv->netfd, priv->data, 2); priv->data[0] = GDISP_LLD_PIXELFORMAT; priv->data[1] = (g->flags & GDISP_FLG_HASMOUSE) ? 1 : 0; MUTEX_ENTER; sendpkt(priv->netfd, priv->data, 2); MUTEX_EXIT; // The display is now working g->flags |= GDISP_FLG_CONNECTED; // Send a redraw all #if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER gdispGClear(g, gwinGetDefaultBgColor()); gwinRedrawDisplay(g, FALSE); #endif } #endif /* loop */ for(;;) { /* copy it */ read_fds = master; if (select(fdmax+1, &read_fds, 0, 0, 0) == -1) gfxHalt("GDISP: uGFXnet - Select failed"); // Run through the existing connections looking for data to be read for(i = 0; i <= fdmax; i++) { if(!FD_ISSET(i, &read_fds)) continue; // Handle new connections if(i == listenfd) { len = sizeof(addr); if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1) gfxHalt("GDISP: uGFXnet - Accept failed"); // Look for a display that isn't connected for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { // Ignore displays for other controllers #ifdef GDISP_DRIVER_LIST if (gvmt(g) != &GDISPVMT_uGFXnet) continue; #endif if (!(g->flags & GDISP_FLG_CONNECTED)) break; } // Was anything found? if (!g) { // No Just close the connection closesocket(clientfd); //printf(New connection from %s on socket %d rejected as all displays are already connected\n", inet_ntoa(addr.sin_addr), clientfd); continue; } // Save the descriptor FD_SET(clientfd, &master); if (clientfd > fdmax) fdmax = clientfd; priv = g->priv; memset(priv, 0, sizeof(netPriv)); priv->netfd = clientfd; //printf(New connection from %s on socket %d allocated to display %u\n", inet_ntoa(addr.sin_addr), clientfd, disp+1); // Send the initialisation data (2 words at a time) priv->data[0] = GNETCODE_INIT; priv->data[1] = GNETCODE_VERSION; sendpkt(priv->netfd, priv->data, 2); priv->data[0] = GDISP_SCREEN_WIDTH; priv->data[1] = GDISP_SCREEN_HEIGHT; sendpkt(priv->netfd, priv->data, 2); priv->data[0] = GDISP_LLD_PIXELFORMAT; priv->data[1] = (g->flags & GDISP_FLG_HASMOUSE) ? 1 : 0; MUTEX_ENTER; sendpkt(priv->netfd, priv->data, 2); MUTEX_EXIT; // The display is now working g->flags |= GDISP_FLG_CONNECTED; // Send a redraw all #if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER gdispGClear(g, gwinGetDefaultBgColor()); gwinRedrawDisplay(g, FALSE); #endif continue; } // Handle data from a client // Look for a display that is connected and the socket descriptor matches for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) { // Ignore displays for other controllers #ifdef GDISP_DRIVER_LIST if (gvmt(g) != &GDISPVMT_uGFXnet) continue; #endif priv = g->priv; if ((g->flags & GDISP_FLG_CONNECTED) && priv->netfd == i) break; } if (!g) gfxHalt("GDISP: uGFXnet - Got data from unrecognized connection"); if ((g->flags & GDISP_FLG_HAVEDATA)) { // The higher level is still processing the previous data. // Give it a chance to run by coming back to this data. gfxSleepMilliseconds(1); continue; } /* handle data from a client */ MUTEX_ENTER; if ((leni = recv(i, ((char *)priv->data)+priv->databytes, sizeof(priv->data)-priv->databytes, 0)) <= 0) { // Socket closed or in error state MUTEX_EXIT; g->flags &= ~GDISP_FLG_CONNECTED; memset(priv, 0, sizeof(netPriv)); closesocket(i); FD_CLR(i, &master); continue; } MUTEX_EXIT; // Do we have a full reply yet priv->databytes += leni; if (priv->databytes < sizeof(priv->data)) continue; priv->databytes = 0; // Convert network byte or to host byte order priv->data[0] = ntohs(priv->data[0]); priv->data[1] = ntohs(priv->data[1]); // Process the data received switch(priv->data[0]) { #if GINPUT_NEED_MOUSE case GNETCODE_MOUSE_X: priv->mousex = priv->data[1]; break; case GNETCODE_MOUSE_Y: priv->mousey = priv->data[1]; break; case GNETCODE_MOUSE_B: priv->mousebuttons = priv->data[1]; // Treat the button event as the sync signal #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE ginputMouseWakeup(); #endif break; #endif case GNETCODE_CONTROL: case GNETCODE_READ: g->flags |= GDISP_FLG_HAVEDATA; break; case GNETCODE_KILL: gfxHalt("GDISP: uGFXnet - Display sent KILL command"); break; default: // Just ignore unrecognised data break; } } } return 0; }