// needs to be run after SelectEGLConfiguration() // for gEglConfig to be valid int PVRShellInitOS::OpenX11Window(const PVRShell &shell) { XSetWindowAttributes wa; XSizeHints sh; XEvent event; unsigned long mask; #ifdef BUILD_OGL XF86VidModeModeInfo **modes; // modes of display int numModes; // number of modes of display int chosenMode; int edimx,edimy; //established width and height of the chosen modeline int i; #endif MyHints mwmhints; Atom prop; int depth = DefaultDepth(x11display, x11screen); x11visual = new XVisualInfo; XMatchVisualInfo( x11display, x11screen, depth, TrueColor, x11visual); if( !x11visual ) { shell.PVRShellOutputDebug( "Unable to acquire visual" ); return false; } x11colormap = XCreateColormap( x11display, RootWindow(x11display, x11screen), x11visual->visual, AllocNone ); #ifdef BUILD_OGL originalMode_dotclock = XF86VidModeBadClock; if(shell.m_pShellData->bFullScreen) { // Get mode lines to see if there is requested modeline XF86VidModeGetAllModeLines(x11display, x11screen, &numModes, &modes); /* look for mode with requested resolution */ chosenMode = -1; i=0; while((chosenMode == -1)&&(i<numModes)) { if ((modes[i]->hdisplay == shell.m_pShellData->nShellDimX) && (modes[i]->vdisplay == shell.m_pShellData->nShellDimY)) { chosenMode = i; } ++i; } // If there is no requested resolution among modelines then terminate if(chosenMode == -1) { shell.PVRShellOutputDebug( "Chosen resolution for full screen mode does not match any modeline available.\n" ); return false; } /* save desktop-resolution before switching modes */ XF86VidModeGetModeLine(x11display,x11screen, &originalMode_dotclock, &originalMode ); XF86VidModeSwitchToMode(x11display, x11screen, modes[chosenMode]); XF86VidModeSetViewPort(x11display, x11screen, 0, 0); edimx = modes[chosenMode]->hdisplay; edimy = modes[chosenMode]->vdisplay; printf("Fullscreen Resolution %dx%d (chosen mode = %d)\n", edimx, edimy,chosenMode); XFree(modes); //to musi byc globalne wa.colormap = x11colormap; wa.background_pixel = 0xFFFFFFFF; wa.border_pixel = 0; wa.override_redirect = true; // add to these for handling other events wa.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; // The diffrence is that we want to ignore influence of window manager for outr fullscreen window mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap | CWOverrideRedirect; x11window = XCreateWindow( x11display, RootWindow(x11display, x11screen), 0, 0, edimx, edimy, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &wa); // keeping the pointer of mouse and keyboard in window to prevent from scrolling the virtual screen XWarpPointer(x11display, None ,x11window, 0, 0, 0, 0, 0, 0); // Map and then wait till mapped, grabbing should be after mapping the window XMapWindow( x11display, x11window ); XGrabKeyboard(x11display, x11window, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(x11display, x11window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, x11window, None, CurrentTime); XIfEvent( x11display, &event, WaitForMapNotify, (char*)x11window ); } else { #endif wa.colormap = x11colormap; wa.background_pixel = 0xFFFFFFFF; wa.border_pixel = 0; // add to these for handling other events wa.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap ; x11window = XCreateWindow( x11display, RootWindow(x11display, x11screen), shell.m_pShellData->nShellPosX, shell.m_pShellData->nShellPosY, shell.m_pShellData->nShellDimX, shell.m_pShellData->nShellDimY, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &wa); // todo:meh remove this? sh.flags = USPosition; sh.x = shell.m_pShellData->nShellPosX; sh.y = shell.m_pShellData->nShellPosY; XSetStandardProperties( x11display, x11window, szTitle, szTitle, None, 0, 0, &sh ); // Map and then wait till mapped XMapWindow( x11display, x11window ); XIfEvent( x11display, &event, WaitForMapNotify, (char*)x11window ); // An attempt to hide a border for fullscreen on non OGL apis (OGLES,OGLES2) if(shell.m_pShellData->bFullScreen) { memset(&mwmhints, 0, sizeof(mwmhints)); prop = XInternAtom(x11display, "_MOTIF_WM_HINTS", False); mwmhints.flags = 2;//MWM_HINTS_DECORATIONS; mwmhints.decorations = 0; XChangeProperty(x11display, x11window, prop, prop, 32, PropModeReplace, (unsigned char *) &mwmhints,5); } // Atom wmDelete = XInternAtom(x11display, "WM_DELETE_WINDOW", True); XSetWMProtocols(x11display, x11window, &wmDelete, 1); XSetWMColormapWindows( x11display, x11window, &x11window, 1 ); #ifdef BUILD_OGL } #endif XFlush( x11display ); return true; }
/*!*********************************************************************** @Function OpenX11Window @Return true on success @Description Opens an X11 window. This must be called after SelectEGLConfiguration() for gEglConfig to be valid *************************************************************************/ int PVRShellInitOS::OpenX11Window(const PVRShell &shell) { XSetWindowAttributes WinAttibutes; XSizeHints sh; XEvent event; unsigned long mask; #ifdef BUILD_OGL XF86VidModeModeInfo **modes; // modes of display int numModes; // number of modes of display int chosenMode; int edimx,edimy; //established width and height of the chosen modeline int i; #endif int depth = DefaultDepth(m_X11Display, m_X11Screen); m_X11Visual = new XVisualInfo; XMatchVisualInfo( m_X11Display, m_X11Screen, depth, TrueColor, m_X11Visual); if( !m_X11Visual ) { shell.PVRShellOutputDebug( "Unable to acquire visual" ); return false; } m_X11ColorMap = XCreateColormap( m_X11Display, RootWindow(m_X11Display, m_X11Screen), m_X11Visual->visual, AllocNone ); #ifdef BUILD_OGL m_i32OriginalModeDotClock = XF86VidModeBadClock; if(shell.m_pShellData->bFullScreen) { // Get mode lines to see if there is requested modeline XF86VidModeGetAllModeLines(m_X11Display, m_X11Screen, &numModes, &modes); // look for mode with requested resolution chosenMode = -1; i=0; while((chosenMode == -1)&&(i<numModes)) { if ((modes[i]->hdisplay == shell.m_pShellData->nShellDimX) && (modes[i]->vdisplay == shell.m_pShellData->nShellDimY)) { chosenMode = i; } ++i; } // If there is no requested resolution among modelines then terminate if(chosenMode == -1) { shell.PVRShellOutputDebug( "Chosen resolution for full screen mode does not match any modeline available.\n" ); return false; } // save desktop-resolution before switching modes XF86VidModeGetModeLine(m_X11Display,m_X11Screen, &m_i32OriginalModeDotClock, &m_OriginalMode ); XF86VidModeSwitchToMode(m_X11Display, m_X11Screen, modes[chosenMode]); XF86VidModeSetViewPort(m_X11Display, m_X11Screen, 0, 0); edimx = modes[chosenMode]->hdisplay; edimy = modes[chosenMode]->vdisplay; printf("Fullscreen Resolution %dx%d (chosen mode = %d)\n", edimx, edimy,chosenMode); XFree(modes); WinAttibutes.colormap = m_X11ColorMap; WinAttibutes.background_pixel = 0xFFFFFFFF; WinAttibutes.border_pixel = 0; WinAttibutes.override_redirect = true; // add to these for handling other events WinAttibutes.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | Button1MotionMask | KeyPressMask | KeyReleaseMask; // The diffrence is that we want to ignore influence of window manager for our fullscreen window mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap | CWOverrideRedirect; m_X11Window = XCreateWindow( m_X11Display, RootWindow(m_X11Display, m_X11Screen), 0, 0, edimx, edimy, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &WinAttibutes); // keeping the pointer of mouse and keyboard in window to prevent from scrolling the virtual screen XWarpPointer(m_X11Display, None ,m_X11Window, 0, 0, 0, 0, 0, 0); // Map and then wait till mapped, grabbing should be after mapping the window XMapWindow( m_X11Display, m_X11Window ); XGrabKeyboard(m_X11Display, m_X11Window, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(m_X11Display, m_X11Window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_X11Window, None, CurrentTime); XIfEvent( m_X11Display, &event, WaitForMapNotify, (char*)m_X11Window ); } else #endif { // For OGLES we assume that chaning of video mode is not available (freedesktop does not allow to do it) // so if requested resolution differs from the display dims then we quit #ifndef BUILD_OGL int display_width = XDisplayWidth(m_X11Display,m_X11Screen); int display_height = XDisplayHeight(m_X11Display,m_X11Screen); if((shell.m_pShellData->bFullScreen)&&((shell.m_pShellData->nShellDimX != display_width)||(shell.m_pShellData->nShellDimY != display_height)) ) { shell.PVRShellOutputDebug( "Chosen resolution for full screen mode does not match available modeline.\n" ); return false; } #endif WinAttibutes.colormap = m_X11ColorMap; WinAttibutes.background_pixel = 0xFFFFFFFF; WinAttibutes.border_pixel = 0; // add to these for handling other events WinAttibutes.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | Button1MotionMask | KeyPressMask | KeyReleaseMask; // The attribute mask mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap ; m_X11Window = XCreateWindow( m_X11Display, // Display RootWindow(m_X11Display, m_X11Screen), // Parent shell.m_pShellData->nShellPosX, // X position of window shell.m_pShellData->nShellPosY, // Y position of window shell.m_pShellData->nShellDimX, // Window width shell.m_pShellData->nShellDimY, // Window height 0, // Border width CopyFromParent, // Depth (taken from parent) InputOutput, // Window class CopyFromParent, // Visual type (taken from parent) mask, // Attributes mask &WinAttibutes); // Attributes // Set the window position sh.flags = USPosition; sh.x = shell.m_pShellData->nShellPosX; sh.y = shell.m_pShellData->nShellPosY; XSetStandardProperties( m_X11Display, m_X11Window, shell.m_pShellData->pszAppName, shell.m_pShellData->pszAppName, None, 0, 0, &sh ); // Map and then wait till mapped XMapWindow( m_X11Display, m_X11Window ); XIfEvent( m_X11Display, &event, WaitForMapNotify, (char*)m_X11Window ); // An attempt to hide a border for fullscreen on non OGL apis (OGLES,OGLES2) if(shell.m_pShellData->bFullScreen) { XEvent xev; Atom wmState = XInternAtom(m_X11Display, "_NET_WM_STATE", False); Atom wmStateFullscreen = XInternAtom(m_X11Display, "_NET_WM_STATE_FULLSCREEN", False); memset(&xev, 0, sizeof(XEvent)); xev.type = ClientMessage; xev.xclient.window = m_X11Window; xev.xclient.message_type = wmState; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = wmStateFullscreen; xev.xclient.data.l[2] = 0; XSendEvent(m_X11Display, RootWindow(m_X11Display, m_X11Screen), False, SubstructureNotifyMask, &xev); } Atom wmDelete = XInternAtom(m_X11Display, "WM_DELETE_WINDOW", True); XSetWMProtocols(m_X11Display, m_X11Window, &wmDelete, 1); XSetWMColormapWindows( m_X11Display, m_X11Window, &m_X11Window, 1 ); } XFlush( m_X11Display ); return true; }
/***************************************************************************** Global code *****************************************************************************/ static int32_t handle_input(struct android_app* app, AInputEvent* event) { PVRShellInit* init = (PVRShellInit*) app->userData; if(init) { switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: // Handle keyboard events { switch(AKeyEvent_getAction(event)) { case AKEY_EVENT_ACTION_DOWN: { switch(AKeyEvent_getKeyCode(event)) { case AKEYCODE_Q: init->KeyPressed(PVRShellKeyNameQUIT); break; case AKEYCODE_BACK: init->KeyPressed(PVRShellKeyNameQUIT); break; case AKEYCODE_DPAD_CENTER: init->KeyPressed(PVRShellKeyNameSELECT); break; case AKEYCODE_SPACE: init->KeyPressed(PVRShellKeyNameACTION1); break; case AKEYCODE_SHIFT_LEFT: init->KeyPressed(PVRShellKeyNameACTION2); break; case AKEYCODE_DPAD_UP: init->KeyPressed(init->m_eKeyMapUP); break; case AKEYCODE_DPAD_DOWN: init->KeyPressed(init->m_eKeyMapDOWN); break; case AKEYCODE_DPAD_LEFT: init->KeyPressed(init->m_eKeyMapLEFT); break; case AKEYCODE_DPAD_RIGHT: init->KeyPressed(init->m_eKeyMapRIGHT); break; case AKEYCODE_S: init->KeyPressed(PVRShellKeyNameScreenshot);break; default: break; } } return 1; default: break; } return 1; } case AINPUT_EVENT_TYPE_MOTION: // Handle touch events { switch(AMotionEvent_getAction(event)) { case AMOTION_EVENT_ACTION_DOWN: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchBegan(vec2TouchPosition); } break; } case AMOTION_EVENT_ACTION_MOVE: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchMoved(vec2TouchPosition); } break; } case AMOTION_EVENT_ACTION_UP: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchEnded(vec2TouchPosition); } break; } } return 1; } } } return 1; }