|  | /****************************************************************************** | 
|  |  | 
|  | @File         LinuxX11/PVRShellOS.cpp | 
|  |  | 
|  | @Title        LinuxX11/PVRShellOS | 
|  |  | 
|  | @Version | 
|  |  | 
|  | @Copyright    Copyright (c) Imagination Technologies Limited. | 
|  |  | 
|  | @Platform     X11 | 
|  |  | 
|  | @Description  Makes programming for 3D APIs easier by wrapping window creation | 
|  | and other functions for use by a demo. | 
|  |  | 
|  | ******************************************************************************/ | 
|  |  | 
|  | #include <sys/time.h> | 
|  | #include <stdio.h> | 
|  | #include <stdarg.h> | 
|  | #include <time.h> | 
|  | #include <unistd.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "PVRShell.h" | 
|  | #include "PVRShellAPI.h" | 
|  | #include "PVRShellOS.h" | 
|  | #include "PVRShellImpl.h" | 
|  |  | 
|  | // No Doxygen for CPP files, due to documentation duplication | 
|  | /// @cond NO_DOXYGEN | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | Defines | 
|  | *****************************************************************************/ | 
|  |  | 
|  | /***************************************************************************** | 
|  | Declarations | 
|  | *****************************************************************************/ | 
|  | static Bool WaitForMapNotify( Display *d, XEvent *e, char *arg ); | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | Class: PVRShellInit | 
|  | *****************************************************************************/ | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		PVRShellOutputDebug | 
|  | @Input			format			printf style format followed by arguments it requires | 
|  | @Description	Writes the resultant string to the debug output (e.g. using | 
|  | printf(), OutputDebugString(), ...). Check the SDK release notes for | 
|  | details on how the string is output. | 
|  | *************************************************************************/ | 
|  | void PVRShell::PVRShellOutputDebug(char const * const format, ...) const | 
|  | { | 
|  | if(!format) | 
|  | return; | 
|  |  | 
|  | va_list arg; | 
|  | char	buf[1024]; | 
|  |  | 
|  | va_start(arg, format); | 
|  | vsnprintf(buf, 1024, format, arg); | 
|  | va_end(arg); | 
|  |  | 
|  | // Passes the data to a platform dependant function | 
|  | m_pShellInit->OsDisplayDebugString(buf); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsInit | 
|  | @description	Initialisation for OS-specific code. | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsInit() | 
|  | { | 
|  | XInitThreads(); | 
|  |  | 
|  | // set values to negative to mark that these are default values | 
|  | m_pShell->m_pShellData->nShellDimX = -240; | 
|  | m_pShell->m_pShellData->nShellDimY = -320; | 
|  |  | 
|  | m_X11Display = NULL; | 
|  | m_X11Visual = NULL; | 
|  |  | 
|  | // Pixmap support: init variables to 0 | 
|  | m_X11Pixmap = BadValue; | 
|  |  | 
|  | /* | 
|  | Construct the binary path for GetReadPath() and GetWritePath() | 
|  | */ | 
|  | // Get PID (Process ID) | 
|  | pid_t ourPid = getpid(); | 
|  | char *pszExePath, pszSrcLink[64]; | 
|  | int len = 64; | 
|  | int res; | 
|  |  | 
|  | sprintf(pszSrcLink, "/proc/%d/exe", ourPid); | 
|  | pszExePath = 0; | 
|  |  | 
|  | do | 
|  | { | 
|  | len *= 2; | 
|  | delete[] pszExePath; | 
|  | pszExePath = new char[len]; | 
|  | res = readlink(pszSrcLink, pszExePath, len); | 
|  |  | 
|  | if(res < 0) | 
|  | { | 
|  | m_pShell->PVRShellOutputDebug("Warning Readlink %s failed. The application name, read path and write path have not been set.\n", pszExePath); | 
|  | break; | 
|  | } | 
|  | } while(res >= len); | 
|  |  | 
|  | if(res >= 0) | 
|  | { | 
|  | pszExePath[res] = '\0'; // Null-terminate readlink's result | 
|  | SetReadPath(pszExePath); | 
|  | SetWritePath(pszExePath); | 
|  | SetAppName(pszExePath); | 
|  | } | 
|  |  | 
|  | delete[] pszExePath; | 
|  |  | 
|  | m_u32ButtonState = 0; | 
|  |  | 
|  | gettimeofday(&m_StartTime,NULL); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsInitOS | 
|  | @description	Saves instance handle and creates main window | 
|  | In this function, we save the instance handle in a global variable and | 
|  | create and display the main program window. | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsInitOS() | 
|  | { | 
|  | m_X11Display = XOpenDisplay( NULL ); | 
|  |  | 
|  | if(!m_X11Display) | 
|  | { | 
|  | m_pShell->PVRShellOutputDebug( "Unable to open X display\n"); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | m_X11Screen = XDefaultScreen( m_X11Display ); | 
|  |  | 
|  | /* | 
|  | If there is a full screen request then | 
|  | set the window size to the display size. | 
|  | If there is no full screen request then reduce window size while keeping | 
|  | the same aspect by dividing the dims by two until it fits inside the display area. | 
|  | If the position has not changed from its default value, set it to the middle of the screen. | 
|  | */ | 
|  |  | 
|  | int display_width  = XDisplayWidth(m_X11Display,m_X11Screen); | 
|  | int display_height = XDisplayHeight(m_X11Display,m_X11Screen); | 
|  |  | 
|  | if(m_pShell->m_pShellData->bFullScreen) | 
|  | { | 
|  | // For OGL we do real fullscreen for others API set a window of fullscreen size | 
|  | if(m_pShell->m_pShellData->nShellDimX < 0) { | 
|  | m_pShell->m_pShellData->nShellDimX = display_width; | 
|  | } | 
|  | if(m_pShell->m_pShellData->nShellDimY < 0) { | 
|  | m_pShell->m_pShellData->nShellDimY = display_height; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(m_pShell->m_pShellData->nShellDimX < 0) | 
|  | m_pShell->m_pShellData->nShellDimX = (display_width > display_height) ? 800 : 600; | 
|  |  | 
|  | if(m_pShell->m_pShellData->nShellDimY < 0) | 
|  | m_pShell->m_pShellData->nShellDimY = (display_width > display_height) ? 600 : 800; | 
|  |  | 
|  | if(m_pShell->m_pShellData->nShellDimX > display_width) | 
|  | m_pShell->m_pShellData->nShellDimX = display_width; | 
|  |  | 
|  | if(m_pShell->m_pShellData->nShellDimY > display_height) | 
|  | m_pShell->m_pShellData->nShellDimY = display_height; | 
|  | } | 
|  |  | 
|  | // Create the window | 
|  | if(!OpenX11Window(*m_pShell)) | 
|  | { | 
|  | m_pShell->PVRShellOutputDebug( "Unable to open X11 window\n" ); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Pixmap support: create the pixmap | 
|  | if(m_pShell->m_pShellData->bNeedPixmap) | 
|  | { | 
|  | int depth = DefaultDepth(m_X11Display, m_X11Screen); | 
|  | m_X11Pixmap = XCreatePixmap(m_X11Display,m_X11Window,m_pShell->m_pShellData->nShellDimX,m_pShell->m_pShellData->nShellDimY,depth); | 
|  | m_X11GC	  = XCreateGC(m_X11Display,m_X11Window,0,0); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsReleaseOS | 
|  | @description	Destroys main window | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsReleaseOS() | 
|  | { | 
|  | XCloseDisplay( m_X11Display ); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsExit | 
|  | @description	Destroys main window | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsExit() | 
|  | { | 
|  | // Show the exit message to the user | 
|  | m_pShell->PVRShellOutputDebug((const char*)m_pShell->PVRShellGet(prefExitMessage)); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsDoInitAPI | 
|  | @Return		true on success | 
|  | @description	Perform API initialisation and bring up window / fullscreen | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsDoInitAPI() | 
|  | { | 
|  | if(!ApiInitAPI()) | 
|  | { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // No problem occured | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsDoReleaseAPI | 
|  | @description	Clean up after we're done | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsDoReleaseAPI() | 
|  | { | 
|  | ApiReleaseAPI(); | 
|  |  | 
|  | if(m_pShell->m_pShellData->bNeedPixmap) | 
|  | { | 
|  | // Pixmap support: free the pixmap | 
|  | XFreePixmap(m_X11Display,m_X11Pixmap); | 
|  | XFreeGC(m_X11Display,m_X11GC); | 
|  | } | 
|  |  | 
|  | CloseX11Window(); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsRenderComplete | 
|  | @Returns		false when the app should quit | 
|  | @description	Main message loop / render loop | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsRenderComplete() | 
|  | { | 
|  | int		numMessages; | 
|  | XEvent	event; | 
|  | char*		atoms; | 
|  |  | 
|  | // Are there messages waiting, maybe this should be a while loop | 
|  | numMessages = XPending( m_X11Display ); | 
|  | for( int i = 0; i < numMessages; i++ ) | 
|  | { | 
|  | XNextEvent( m_X11Display, &event ); | 
|  |  | 
|  | switch( event.type ) | 
|  | { | 
|  | case ClientMessage: | 
|  | atoms = XGetAtomName(m_X11Display, event.xclient.message_type); | 
|  | if (*atoms == *"WM_PROTOCOLS") | 
|  | { | 
|  | gShellDone = true; | 
|  | } | 
|  | XFree(atoms); | 
|  | break; | 
|  |  | 
|  | case ButtonRelease: | 
|  | { | 
|  | XButtonEvent *button_event = ((XButtonEvent *) &event); | 
|  | switch( button_event->button ) | 
|  | { | 
|  | case 1 : | 
|  | { | 
|  | m_u32ButtonState &= ~1; | 
|  |  | 
|  | // Set the current pointer location | 
|  | float vec2PointerLocation[2]; | 
|  | vec2PointerLocation[0] = (float)button_event->x / (float)m_pShell->m_pShellData->nShellDimX; | 
|  | vec2PointerLocation[1] = (float)button_event->y / (float)m_pShell->m_pShellData->nShellDimY; | 
|  | TouchEnded(vec2PointerLocation); | 
|  | } | 
|  | break; | 
|  | case 2 : m_u32ButtonState &= ~4; break; | 
|  | case 3 : m_u32ButtonState &= ~2; break; | 
|  | default : break; | 
|  | } | 
|  | break; | 
|  | } | 
|  | case ButtonPress: | 
|  | { | 
|  | XButtonEvent *button_event = ((XButtonEvent *) &event); | 
|  | switch( button_event->button ) | 
|  | { | 
|  | case 1 : | 
|  | { | 
|  | m_u32ButtonState |= 1; | 
|  |  | 
|  | // Set the current pointer location | 
|  | float vec2PointerLocation[2]; | 
|  | vec2PointerLocation[0] = (float)button_event->x / (float)m_pShell->m_pShellData->nShellDimX; | 
|  | vec2PointerLocation[1] = (float)button_event->y / (float)m_pShell->m_pShellData->nShellDimY; | 
|  | TouchBegan(vec2PointerLocation); | 
|  | } | 
|  | break; | 
|  | case 2 : m_u32ButtonState |= 4; break; | 
|  | case 3 : m_u32ButtonState |= 2; break; | 
|  | default : break; | 
|  | } | 
|  | break; | 
|  | } | 
|  | case MotionNotify: | 
|  | { | 
|  | XMotionEvent *motion_event = ((XMotionEvent *) &event); | 
|  |  | 
|  | // Set the current pointer location | 
|  | float vec2PointerLocation[2]; | 
|  | vec2PointerLocation[0] = (float)motion_event->x / (float)m_pShell->m_pShellData->nShellDimX; | 
|  | vec2PointerLocation[1] = (float)motion_event->y / (float)m_pShell->m_pShellData->nShellDimY; | 
|  | TouchMoved(vec2PointerLocation); | 
|  | break; | 
|  | } | 
|  | // should SDK handle these? | 
|  | case MapNotify: | 
|  | case UnmapNotify: | 
|  | break; | 
|  |  | 
|  | case KeyPress: | 
|  | { | 
|  | XKeyEvent *key_event = ((XKeyEvent *) &event); | 
|  |  | 
|  | switch(key_event->keycode) | 
|  | { | 
|  | case 9:	 	nLastKeyPressed = PVRShellKeyNameQUIT;	break; 			// Esc | 
|  | case 95:	nLastKeyPressed = PVRShellKeyNameScreenshot;	break; 	// F11 | 
|  | case 36:	nLastKeyPressed = PVRShellKeyNameSELECT;	break; 		// Enter | 
|  | case 10:	nLastKeyPressed = PVRShellKeyNameACTION1;	break; 		// number 1 | 
|  | case 11:	nLastKeyPressed = PVRShellKeyNameACTION2;	break; 		// number 2 | 
|  | case 98: | 
|  | case 111:	nLastKeyPressed = m_eKeyMapUP;	break; | 
|  | case 104: | 
|  | case 116:	nLastKeyPressed = m_eKeyMapDOWN;	break; | 
|  | case 100: | 
|  | case 113:	nLastKeyPressed = m_eKeyMapLEFT;	break; | 
|  | case 102: | 
|  | case 114: 	nLastKeyPressed = m_eKeyMapRIGHT;	break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  | break; | 
|  |  | 
|  | case KeyRelease: | 
|  | { | 
|  | //				char buf[10]; | 
|  | //				XLookupString(&event.xkey,buf,10,NULL,NULL); | 
|  | //				charsPressed[ (int) *buf ] = 0; | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsPixmapCopy | 
|  | @Return		true if the copy succeeded | 
|  | @description	When using pixmaps, copy the render to the display | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsPixmapCopy() | 
|  | { | 
|  | XCopyArea(m_X11Display,m_X11Pixmap,m_X11Window,m_X11GC,0,0,m_pShell->m_pShellData->nShellDimX,m_pShell->m_pShellData->nShellDimY,0,0); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGetNativeDisplayType | 
|  | @Return		The 'NativeDisplayType' for EGL | 
|  | @description	Called from InitAPI() to get the NativeDisplayType | 
|  | *************************************************************************/ | 
|  | void *PVRShellInit::OsGetNativeDisplayType() | 
|  | { | 
|  | return m_X11Display; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGetNativePixmapType | 
|  | @Return		The 'NativePixmapType' for EGL | 
|  | @description	Called from InitAPI() to get the NativePixmapType | 
|  | *************************************************************************/ | 
|  | void *PVRShellInit::OsGetNativePixmapType() | 
|  | { | 
|  | // Pixmap support: return the pixmap | 
|  | return (void*)m_X11Pixmap; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGetNativeWindowType | 
|  | @Return		The 'NativeWindowType' for EGL | 
|  | @description	Called from InitAPI() to get the NativeWindowType | 
|  | *************************************************************************/ | 
|  | void *PVRShellInit::OsGetNativeWindowType() | 
|  | { | 
|  | return (void*)m_X11Window; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGet | 
|  | @Input			prefName	Name of value to get | 
|  | @Modified		pn A pointer set to the value asked for | 
|  | @Returns		true on success | 
|  | @Description	Retrieves OS-specific data | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsGet(const prefNameIntEnum prefName, int *pn) | 
|  | { | 
|  | switch( prefName ) | 
|  | { | 
|  | case prefButtonState: | 
|  | *pn = m_u32ButtonState; | 
|  | return true; | 
|  | default: | 
|  | return false; | 
|  | }; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGet | 
|  | @Input			prefName	Name of value to get | 
|  | @Modified		pp A pointer set to the value asked for | 
|  | @Returns		true on success | 
|  | @Description	Retrieves OS-specific data | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsGet(const prefNamePtrEnum prefName, void **pp) | 
|  | { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsSet | 
|  | @Input			prefName				Name of preference to set to value | 
|  | @Input			value					Value | 
|  | @Return		true for success | 
|  | @Description	Sets OS-specific data | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsSet(const prefNameBoolEnum prefName, const bool value) | 
|  | { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsSet | 
|  | @Input			prefName	Name of value to set | 
|  | @Input			i32Value 	The value to set our named value to | 
|  | @Returns		true on success | 
|  | @Description	Sets OS-specific data | 
|  | *************************************************************************/ | 
|  | bool PVRShellInit::OsSet(const prefNameIntEnum prefName, const int i32Value) | 
|  | { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsDisplayDebugString | 
|  | @Input			str		string to output | 
|  | @Description	Prints a debug string | 
|  | *************************************************************************/ | 
|  | void PVRShellInit::OsDisplayDebugString(char const * const str) | 
|  | { | 
|  | fprintf(stderr, "%s", str); | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		OsGetTime | 
|  | @Return		An incrementing time value measured in milliseconds | 
|  | @Description	Returns an incrementing time value measured in milliseconds | 
|  | *************************************************************************/ | 
|  | unsigned long PVRShellInit::OsGetTime() | 
|  | { | 
|  | timeval tv; | 
|  | gettimeofday(&tv,NULL); | 
|  |  | 
|  | if(tv.tv_sec < m_StartTime.tv_sec) | 
|  | m_StartTime.tv_sec = 0; | 
|  |  | 
|  | unsigned long sec = tv.tv_sec - m_StartTime.tv_sec; | 
|  | return (unsigned long)((sec*(unsigned long)1000) + (tv.tv_usec/1000.0)); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | Class: PVRShellInitOS | 
|  | *****************************************************************************/ | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @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; | 
|  | } | 
|  |  | 
|  | /*!*********************************************************************** | 
|  | @Function		CloseX11Window | 
|  | @Return		void | 
|  | @Description	destroy the instance of a window, and release all relevent memory | 
|  | *************************************************************************/ | 
|  | void PVRShellInitOS::CloseX11Window() | 
|  | { | 
|  | // revert introductional resolution (full screen case, bad clock is default value meaning that good was not acquired) | 
|  | #ifdef BUILD_OGL | 
|  | XF86VidModeModeInfo tmpmi; | 
|  |  | 
|  | if(m_i32OriginalModeDotClock != XF86VidModeBadClock) | 
|  | { | 
|  | // revert desktop-resolution (stored previously) before exiting | 
|  | tmpmi.dotclock = m_i32OriginalModeDotClock; | 
|  | tmpmi.c_private = m_OriginalMode.c_private; | 
|  | tmpmi.flags = m_OriginalMode.flags; | 
|  | tmpmi.hdisplay = m_OriginalMode.hdisplay; | 
|  | tmpmi.hskew = m_OriginalMode.hskew; | 
|  | tmpmi.hsyncend = m_OriginalMode.hsyncend; | 
|  | tmpmi.hsyncstart = m_OriginalMode.hsyncstart; | 
|  | tmpmi.htotal = m_OriginalMode.htotal; | 
|  | tmpmi.privsize = m_OriginalMode.privsize; | 
|  | tmpmi.vdisplay = m_OriginalMode.vdisplay; | 
|  | tmpmi.vsyncend = m_OriginalMode.vsyncend; | 
|  | tmpmi.vsyncstart = m_OriginalMode.vsyncstart; | 
|  | tmpmi.vtotal = m_OriginalMode.vtotal; | 
|  |  | 
|  | XF86VidModeSwitchToMode(m_X11Display,m_X11Screen,&tmpmi); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | XDestroyWindow( m_X11Display, m_X11Window ); | 
|  | XFreeColormap( m_X11Display, m_X11ColorMap ); | 
|  |  | 
|  | if(m_X11Visual) | 
|  | delete m_X11Visual; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | Global code | 
|  | *****************************************************************************/ | 
|  |  | 
|  | static Bool WaitForMapNotify( Display *d, XEvent *e, char *arg ) | 
|  | { | 
|  | return (e->type == MapNotify) && (e->xmap.window == (Window)arg); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @function		main | 
|  | @input			argc	count of args from OS | 
|  | @input			argv	array of args from OS | 
|  | @returns		result code to OS | 
|  | @description	Main function of the program | 
|  | *****************************************************************************/ | 
|  | int main(int argc, char **argv) | 
|  | { | 
|  | PVRShellInit init; | 
|  |  | 
|  | // Initialise the demo, process the command line, create the OS initialiser. | 
|  | if(!init.Init()) | 
|  | return EXIT_ERR_CODE; | 
|  |  | 
|  | init.CommandLine((argc-1),&argv[1]); | 
|  |  | 
|  | // Initialise/run/shutdown | 
|  | while(init.Run()); | 
|  |  | 
|  | return EXIT_NOERR_CODE; | 
|  | } | 
|  |  | 
|  | /// @endcond | 
|  |  | 
|  | /***************************************************************************** | 
|  | End of file (PVRShellOS.cpp) | 
|  | *****************************************************************************/ | 
|  |  |