int main(int argc, char** argv, char** environ) { pthread_t Xevent_thread, Vchannel_thread; void *ret; l_config = g_malloc(sizeof(struct log_config), 1); if (cliprdr_init() != LOG_STARTUP_OK) { g_printf("cliprdr[main]: Enable to init log system\n"); g_free(l_config); return 1; } if (vchannel_init() == ERROR) { g_printf("cliprdr[main]: Enable to init channel system\n"); g_free(l_config); return 1; } pthread_cond_init(&reply_cond, NULL); pthread_mutex_init(&mutex, NULL); cliprdr_channel = vchannel_open("cliprdr"); if( cliprdr_channel == ERROR) { log_message(l_config, LOG_LEVEL_ERROR, "cliprdr[main]: " "Error while connecting to vchannel provider"); g_free(l_config); return 1; } XInitThreads(); log_message(l_config, LOG_LEVEL_DEBUG, "cliprdr[main]: " "Opening the default display : %s",getenv("DISPLAY")); if ((display = XOpenDisplay(0))== 0){ log_message(l_config, LOG_LEVEL_ERROR, "cliprdr[main]: " "Unable to open the default display : %s ",getenv("DISPLAY")); g_free(l_config); return 1; } XSynchronize(display, 1); XSetErrorHandler(error_handler); running = 1; if (pthread_create (&Xevent_thread, NULL, thread_Xvent_process, (void*)0) < 0) { log_message(l_config, LOG_LEVEL_ERROR, "cliprdr[main]: " "Pthread_create error for thread : Xevent_thread"); g_free(l_config); return 1; } if (pthread_create (&Vchannel_thread, NULL, thread_vchannel_process, (void*)0) < 0) { log_message(l_config, LOG_LEVEL_ERROR, "cliprdr[main]: " "Pthread_create error for thread : Vchannel_thread"); g_free(l_config); return 1; } (void)pthread_join (Xevent_thread, &ret); //(void)pthread_join (Vchannel_thread, &ret); pthread_mutex_destroy(&mutex); XCloseDisplay(display); g_free(l_config); return 0; }
// Clears the X error handler callback // void _glfwReleaseErrorHandlerX11(void) { // Synchronize to make sure all commands are processed XSync(_glfw.x11.display, False); XSetErrorHandler(NULL); }
static int untrap_errors() { XSetErrorHandler(old_handler); return (xerror != BadValue) && (xerror != BadWindow); }
bool create(std::string display, int buffer, bool fullscreen, bool border, int&x, int&y, unsigned int&w, unsigned int&h, bool transparent) { int modeNum=4; #ifdef HAVE_LIBXXF86VM XF86VidModeModeInfo **modes; #endif XSetErrorHandler (ErrorHandler); if ( (dpy = XOpenDisplay(display.c_str())) == NULL) { ::error("Could not open display %s",display.c_str()); return false; } screen = DefaultScreen(dpy); if ( !glXQueryExtension(dpy, NULL, NULL) ) { throw(GemException("X server has no OpenGL GLX extension")); return false; } if (fullscreen) { if (!display.empty()) { fullscreen=false; throw(GemException("fullscreen not available on remote display")); } else { #ifdef HAVE_LIBXXF86VM XF86VidModeGetAllModeLines(dpy, screen, &modeNum, &modes); deskMode = *modes[0]; #else throw(GemException("no xxf86vm-support: cannot switch to fullscreen")); #endif } } XVisualInfo *vi=0; #ifdef HAVE_LIBXRENDER if (transparent) { static GLXFBConfig *fbconfigs, fbconfig; static int numfbconfigs; // need to get some function pointer at runtime typedef GLXFBConfig*(*glXChooseFBConfigProc)(Display* dpy, int screen, const int* attribList, int* nitems); glXChooseFBConfigProc glXChooseFBConfigFn = (glXChooseFBConfigProc) glXGetProcAddress((const GLubyte*)"glXChooseFBConfig"); typedef XVisualInfo*(*glXGetVisualFromFBConfigProc)(Display* dpy, GLXFBConfig fbconfig); glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigFn = (glXGetVisualFromFBConfigProc)glXGetProcAddress((const GLubyte*) "glXGetVisualFromFBConfig"); if (glXChooseFBConfigFn && glXGetVisualFromFBConfigFn) { static int**fbbuf=0; switch(buffer) { default: ::error("only single/double buffer supported; defaulting to double"); case 2: fbbuf=dblBufFbCfg; break; case 1: fbbuf=snglBufFbCfg; break; } bool breakme=false; for(; *fbbuf; fbbuf++) { fbconfigs = glXChooseFBConfigFn(dpy, screen, *fbbuf, &numfbconfigs); fbconfig = 0; for(int i = 0; i<numfbconfigs; i++) { vi = (XVisualInfo*) glXGetVisualFromFBConfigFn(dpy, fbconfigs[i]); if(!vi) { continue; } XRenderPictFormat *pict_format = XRenderFindVisualFormat(dpy, vi->visual); if(!pict_format) { continue; } fbconfig = fbconfigs[i]; if(pict_format->direct.alphaMask > 0) { ::verbose(0,"choose fbconfig : %d", i); breakme = true; break; } } if ( breakme ) { break; } } if(!fbconfig) { ::error("Can't find valid framebuffer configuration, try again with legacy method."); } else { typedef void(*glXGetFBConfigAttribProc)(Display* dpy,GLXFBConfig fbconfig, int attr, int* val); glXGetFBConfigAttribProc glXGetFBConfigAttribFn = (glXGetFBConfigAttribProc)glXGetProcAddress((const GLubyte*) "glXGetFBConfigAttrib"); if ( glXGetFBConfigAttribFn ) { int doublebuffer; int red_bits, green_bits, blue_bits, alpha_bits, depth_bits; glXGetFBConfigAttribFn(dpy, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer); glXGetFBConfigAttribFn(dpy, fbconfig, GLX_RED_SIZE, &red_bits); glXGetFBConfigAttribFn(dpy, fbconfig, GLX_GREEN_SIZE, &green_bits); glXGetFBConfigAttribFn(dpy, fbconfig, GLX_BLUE_SIZE, &blue_bits); glXGetFBConfigAttribFn(dpy, fbconfig, GLX_ALPHA_SIZE, &alpha_bits); glXGetFBConfigAttribFn(dpy, fbconfig, GLX_DEPTH_SIZE, &depth_bits); ::verbose(0, "FBConfig selected:"); ::verbose(0, " Doublebuffer: %s", doublebuffer == True ? "Yes" : "No"); ::verbose(0, " Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d", red_bits, green_bits, blue_bits, alpha_bits, depth_bits); } else { ::error("can't get glXGetFBConfigAttrib function pointer"); } } } } #endif // HAVE_LIBXRENDER if (vi == NULL) { // if Xrender method doesn't work try legacy static int**buf=0; switch(buffer) { default: ::error("only single/double buffer supported; defaulting to double"); case 2: buf=dblBufs; break; case 1: buf=snglBufs; break; } // the user wants double buffer for(; *buf; buf++) { vi = glXChooseVisual(dpy, screen, *buf); if(vi) { break; } } } if (vi == NULL) { std::string errstr="Unable to create "; switch(buffer) { default: errstr+="???"; break; case 1: errstr+"single"; break; case 2: errstr+"double"; break; } errstr+=" buffer window"; throw(GemException(errstr)); return false; } if(vi->depth<24) { ::verbose(0, "Only using %d color bits", vi->depth); } if (vi->c_class != TrueColor && vi->c_class != DirectColor) { ::error("TrueColor visual required for this program (got %d)", vi->c_class); return false; } // create the rendering context try { // first check whether we have a shared context for 'display' GLXContext sharedContext=0; if(s_shared.count(display)>0) { sharedContext=s_shared[display].glxcontext;; } glxcontext = glXCreateContext(dpy, vi, sharedContext, GL_TRUE); } catch(void*e) { glxcontext=NULL; } if (glxcontext == NULL) { throw(GemException("Could not create rendering context")); return false; } // create the X color map cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); if (!cmap) { throw(GemException("Could not create X colormap")); return false; } XSetWindowAttributes swa; swa.colormap = cmap; swa.border_pixel = 0; // event_mask creates signal that window has been created swa.event_mask = EVENT_MASK; int flags; #ifdef HAVE_LIBXXF86VM if (fullscreen) { int bestMode=0; /* look for mode with requested resolution */ for (int i = 0; i < modeNum; i++) { if ((modes[i]->hdisplay == w) && (modes[i]->vdisplay == w)) { bestMode = i; } } XF86VidModeSwitchToMode(dpy, screen, modes[bestMode]); XF86VidModeSetViewPort(dpy, screen, 0, 0); w = modes[bestMode]->hdisplay; h = modes[bestMode]->vdisplay; x=y=0; XFree(modes); swa.override_redirect = True; flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect; } else #endif { // !fullscren if (border) { swa.override_redirect = False; flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect; } else { swa.override_redirect = True; flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect; } } fs = fullscreen; win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), x, y, w, h, 0, vi->depth, InputOutput, vi->visual, flags, &swa); XFree( vi ); if (!win) { throw(GemException("Could not create X window")); return false; } have_border=(True==swa.override_redirect); XSelectInput(dpy, win, EVENT_MASK); inputMethod = XOpenIM(dpy, NULL, NULL, NULL); if(inputMethod) { XIMStyle style=0; XIMStyles *stylePtr=NULL; const char *preedit_attname = NULL; XVaNestedList preedit_attlist = NULL; if ((XGetIMValues(inputMethod, XNQueryInputStyle, &stylePtr, NULL) != NULL)) { stylePtr=NULL; } /* * Select the best input style supported by both the IM and Tk. */ if(stylePtr) { for (int i = 0; i < stylePtr->count_styles; i++) { XIMStyle thisStyle = stylePtr->supported_styles[i]; if (thisStyle == (XIMPreeditPosition | XIMStatusNothing)) { style = thisStyle; break; } else if (thisStyle == (XIMPreeditNothing | XIMStatusNothing)) { style = thisStyle; } } XFree(stylePtr); } if (style & XIMPreeditPosition) { XPoint spot = {0, 0}; XFontSet inputXfs; memset(&inputXfs, 0, sizeof(inputXfs)); preedit_attname = XNPreeditAttributes; preedit_attlist = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, inputXfs, NULL); } inputContext=XCreateIC(inputMethod, XNInputStyle, style, XNClientWindow, win, XNFocusWindow, win, preedit_attname, preedit_attlist, NULL); } /* found a bit at * http://biology.ncsa.uiuc.edu/library/SGI_bookshelves/SGI_Developer/books/OpenGL_Porting/sgi_html/apf.html * LATER think about reacting on this event... */ delete_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True); if (delete_atom != None) { XSetWMProtocols(dpy, win, &delete_atom,1); } try { xerr=0; glXMakeCurrent(dpy, win, glxcontext); if(xerr!=0) { /* seems like the error-handler was called; so something did not work the way it should * should we really prevent window-creation in this case? * LATER re-think the entire dual-context thing */ throw(GemException("problems making glX-context current: refusing to continue\ntry setting the environment variable GEM_SINGLE_CONTEXT=1")); return false; } Window winDummy; unsigned int depthDummy; unsigned int borderDummy; //int x, y; XGetGeometry(dpy, win, &winDummy, &x, &y, &w, &h, &borderDummy, &depthDummy); } catch(void*e) { throw(GemException("Could not make glX-context current")); return false; } return true; }
/** * The main loop for the VBoxClient daemon. */ int main(int argc, char *argv[]) { /* Initialise our runtime before all else. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); int rcClipboard; const char *pszFileName = RTPathFilename(argv[0]); bool fDaemonise = true; /* Have any fatal errors occurred yet? */ bool fSuccess = true; /* Do we know which service we wish to run? */ bool fHaveService = false; if (NULL == pszFileName) pszFileName = "VBoxClient"; /* Initialise our global clean-up critical section */ rc = RTCritSectInit(&g_critSect); if (RT_FAILURE(rc)) { /* Of course, this should never happen. */ RTPrintf("%s: Failed to initialise the global critical section, rc=%Rrc\n", pszFileName, rc); return 1; } /* Parse our option(s) */ /** @todo Use RTGetOpt() if the arguments become more complex. */ for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon")) fDaemonise = false; else if (!strcmp(argv[i], "--clipboard")) { if (g_pService == NULL) g_pService = VBoxClient::GetClipboardService(); else fSuccess = false; } else if (!strcmp(argv[i], "--display")) { if (g_pService == NULL) g_pService = VBoxClient::GetDisplayService(); else fSuccess = false; } else if (!strcmp(argv[i], "--seamless")) { if (g_pService == NULL) g_pService = VBoxClient::GetSeamlessService(); else fSuccess = false; } else if (!strcmp(argv[i], "--checkhostversion")) { if (g_pService == NULL) g_pService = VBoxClient::GetHostVersionService(); else fSuccess = false; } #ifdef VBOX_WITH_DRAG_AND_DROP else if (!strcmp(argv[i], "--draganddrop")) { if (g_pService == NULL) g_pService = VBoxClient::GetDragAndDropService(); else fSuccess = false; } #endif /* VBOX_WITH_DRAG_AND_DROP */ else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { vboxClientUsage(pszFileName); return 0; } else { RTPrintf("%s: unrecognized option `%s'\n", pszFileName, argv[i]); RTPrintf("Try `%s --help' for more information\n", pszFileName); return 1; } } if (!fSuccess || !g_pService) { vboxClientUsage(pszFileName); return 1; } /* Get the path for the pidfiles */ rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile)); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc); LogRel(("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc)); return 1; } rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), g_pService->getPidFilePath()); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc); LogRel(("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc)); return 1; } /* Initialise the guest library. */ if (RT_FAILURE(VbglR3InitUser())) { RTPrintf("Failed to connect to the VirtualBox kernel service\n"); LogRel(("Failed to connect to the VirtualBox kernel service\n")); return 1; } if (fDaemonise) { rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: failed to daemonize. Exiting.\n"); LogRel(("VBoxClient: failed to daemonize. Exiting.\n")); # ifdef DEBUG RTPrintf("Error %Rrc\n", rc); # endif return 1; } } if (g_szPidFile[0] && RT_FAILURE(VbglR3PidFile(g_szPidFile, &g_hPidFile))) { RTPrintf("Failed to create a pidfile. Exiting.\n"); LogRel(("Failed to create a pidfile. Exiting.\n")); VbglR3Term(); return 1; } /* Set signal handlers to clean up on exit. */ vboxClientSetSignalHandlers(); /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */ XSetErrorHandler(vboxClientXLibErrorHandler); /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */ XSetIOErrorHandler(vboxClientXLibIOErrorHandler); g_pService->run(fDaemonise); VBoxClient::CleanUp(); return 1; /* We should never get here. */ }
//-------------------------------------------------------------------------------------------------// void GLXWindow::create(const String& name, uint width, uint height, bool fullScreen, const NameValuePairList *miscParams) { Display *xDisplay = mGLSupport->getXDisplay(); String title = name; uint samples = 0; short frequency = 0; bool vsync = false; bool hidden = false; unsigned int vsyncInterval = 1; int gamma = 0; ::GLXContext glxContext = 0; ::GLXDrawable glxDrawable = 0; Window externalWindow = 0; Window parentWindow = DefaultRootWindow(xDisplay); int left = DisplayWidth(xDisplay, DefaultScreen(xDisplay))/2 - width/2; int top = DisplayHeight(xDisplay, DefaultScreen(xDisplay))/2 - height/2; mIsFullScreen = fullScreen; if(miscParams) { NameValuePairList::const_iterator opt; NameValuePairList::const_iterator end = miscParams->end(); // NB: Do not try to implement the externalGLContext option. // // Accepting a non-current context would expose us to the // risk of segfaults when we made it current. Since the // application programmers would be responsible for these // segfaults, they are better discovering them in their code. if ((opt = miscParams->find("currentGLContext")) != end && StringConverter::parseBool(opt->second)) { if (! glXGetCurrentContext()) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "currentGLContext was specified with no current GL context", "GLXWindow::create"); } glxContext = glXGetCurrentContext(); glxDrawable = glXGetCurrentDrawable(); } // Note: Some platforms support AA inside ordinary windows if((opt = miscParams->find("FSAA")) != end) samples = StringConverter::parseUnsignedInt(opt->second); if((opt = miscParams->find("displayFrequency")) != end) frequency = (short)StringConverter::parseInt(opt->second); if((opt = miscParams->find("vsync")) != end) vsync = StringConverter::parseBool(opt->second); if((opt = miscParams->find("hidden")) != end) hidden = StringConverter::parseBool(opt->second); if((opt = miscParams->find("vsyncInterval")) != end) vsyncInterval = StringConverter::parseUnsignedInt(opt->second); if ((opt = miscParams->find("gamma")) != end) gamma = StringConverter::parseBool(opt->second); if((opt = miscParams->find("left")) != end) left = StringConverter::parseInt(opt->second); if((opt = miscParams->find("top")) != end) top = StringConverter::parseInt(opt->second); if((opt = miscParams->find("title")) != end) title = opt->second; if ((opt = miscParams->find("externalGLControl")) != end) mIsExternalGLControl = StringConverter::parseBool(opt->second); if((opt = miscParams->find("parentWindowHandle")) != end) { vector<String>::type tokens = StringUtil::split(opt->second, " :"); if (tokens.size() == 3) { // deprecated display:screen:xid format parentWindow = StringConverter::parseUnsignedLong(tokens[2]); } else { // xid format parentWindow = StringConverter::parseUnsignedLong(tokens[0]); } } else if((opt = miscParams->find("externalWindowHandle")) != end) { vector<String>::type tokens = StringUtil::split(opt->second, " :"); LogManager::getSingleton().logMessage( "GLXWindow::create: The externalWindowHandle parameter is deprecated.\n" "Use the parentWindowHandle or currentGLContext parameter instead."); if (tokens.size() == 3) { // Old display:screen:xid format // The old GLX code always created a "parent" window in this case: parentWindow = StringConverter::parseUnsignedLong(tokens[2]); } else if (tokens.size() == 4) { // Old display:screen:xid:visualinfo format externalWindow = StringConverter::parseUnsignedLong(tokens[2]); } else { // xid format externalWindow = StringConverter::parseUnsignedLong(tokens[0]); } } } // Ignore fatal XErrorEvents during parameter validation: oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); // Validate parentWindowHandle if (parentWindow != DefaultRootWindow(xDisplay)) { XWindowAttributes windowAttrib; if (! XGetWindowAttributes(xDisplay, parentWindow, &windowAttrib) || windowAttrib.root != DefaultRootWindow(xDisplay)) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid parentWindowHandle (wrong server or screen)", "GLXWindow::create"); } } // Validate externalWindowHandle if (externalWindow != 0) { XWindowAttributes windowAttrib; if (! XGetWindowAttributes(xDisplay, externalWindow, &windowAttrib) || windowAttrib.root != DefaultRootWindow(xDisplay)) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid externalWindowHandle (wrong server or screen)", "GLXWindow::create"); } glxDrawable = externalWindow; } // Derive fbConfig ::GLXFBConfig fbConfig = 0; if (glxDrawable) { fbConfig = mGLSupport->getFBConfigFromDrawable (glxDrawable, &width, &height); } if (! fbConfig && glxContext) { fbConfig = mGLSupport->getFBConfigFromContext (glxContext); } mIsExternal = (glxDrawable != 0); XSetErrorHandler(oldXErrorHandler); if (! fbConfig) { int minAttribs[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1, None }; int maxAttribs[] = { GLX_SAMPLES, samples, GLX_DOUBLEBUFFER, 1, GLX_STENCIL_SIZE, INT_MAX, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, 1, None }; fbConfig = mGLSupport->selectFBConfig(minAttribs, maxAttribs); if (gamma != 0) { mGLSupport->getFBConfigAttrib(fbConfig, GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &gamma); } mHwGamma = (gamma != 0); } if (! fbConfig) { // This should never happen. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unexpected failure to determine a GLXFBConfig","GLXWindow::create"); } mIsTopLevel = (! mIsExternal && parentWindow == DefaultRootWindow(xDisplay)); if (! mIsTopLevel) { mIsFullScreen = false; left = top = 0; } if (mIsFullScreen) { mGLSupport->switchMode (width, height, frequency); } if (! mIsExternal) { XSetWindowAttributes attr; ulong mask; XVisualInfo *visualInfo = mGLSupport->getVisualFromFBConfig (fbConfig); attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(xDisplay, DefaultRootWindow(xDisplay), visualInfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | VisibilityChangeMask | FocusChangeMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; if(mIsFullScreen && mGLSupport->mAtomFullScreen == None) { LogManager::getSingleton().logMessage("GLXWindow::switchFullScreen: Your WM has no fullscreen support"); // A second best approach for outdated window managers attr.backing_store = NotUseful; attr.save_under = False; attr.override_redirect = True; mask |= CWSaveUnder | CWBackingStore | CWOverrideRedirect; left = top = 0; } // Create window on server mWindow = XCreateWindow(xDisplay, parentWindow, left, top, width, height, 0, visualInfo->depth, InputOutput, visualInfo->visual, mask, &attr); XFree(visualInfo); if(!mWindow) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create an X Window", "GLXWindow::create"); } if (mIsTopLevel) { XWMHints *wmHints; XSizeHints *sizeHints; if ((wmHints = XAllocWMHints()) != NULL) { wmHints->initial_state = NormalState; wmHints->input = True; wmHints->flags = StateHint | InputHint; int depth = DisplayPlanes(xDisplay, DefaultScreen(xDisplay)); // Check if we can give it an icon if(depth == 24 || depth == 32) { if(mGLSupport->loadIcon("GLX_icon.png", &wmHints->icon_pixmap, &wmHints->icon_mask)) { wmHints->flags |= IconPixmapHint | IconMaskHint; } } } // Is this really necessary ? Which broken WM might need it? if ((sizeHints = XAllocSizeHints()) != NULL) { sizeHints->flags = USPosition; } XTextProperty titleprop; char *lst = (char*)title.c_str(); XStringListToTextProperty((char **)&lst, 1, &titleprop); XSetWMProperties(xDisplay, mWindow, &titleprop, NULL, NULL, 0, sizeHints, wmHints, NULL); XFree(titleprop.value); XFree(wmHints); XFree(sizeHints); XSetWMProtocols(xDisplay, mWindow, &mGLSupport->mAtomDeleteWindow, 1); XWindowAttributes windowAttrib; XGetWindowAttributes(xDisplay, mWindow, &windowAttrib); left = windowAttrib.x; top = windowAttrib.y; width = windowAttrib.width; height = windowAttrib.height; } glxDrawable = mWindow; // setHidden takes care of mapping or unmapping the window // and also calls setFullScreen if appropriate. setHidden(hidden); XFlush(xDisplay); WindowEventUtilities::_addRenderWindow(this); } mContext = new GLXContext(mGLSupport, fbConfig, glxDrawable, glxContext); // apply vsync settings. call setVSyncInterval first to avoid // setting vsync more than once. setVSyncInterval(vsyncInterval); setVSyncEnabled(vsync); int fbConfigID; mGLSupport->getFBConfigAttrib(fbConfig, GLX_FBCONFIG_ID, &fbConfigID); LogManager::getSingleton().logMessage("GLXWindow::create used FBConfigID = " + StringConverter::toString(fbConfigID)); mName = name; mWidth = width; mHeight = height; mLeft = left; mTop = top; mActive = true; mClosed = false; }
/* The main function */ int main(int argc, char const *argv[]) { Display *dpy; GString *line; unsigned xeventmask; int error_base, shape_event, damage_event; struct { Bool children, creation, mapping, configure, shape; Bool properties, clientmsg; Bool visibility, exposure, damages; Bool pointer, keyboard; } track; dpy = XOpenDisplay(NULL); XSetErrorHandler(xerror_handler); XA_utf8_string = XInternAtom(dpy, "UTF8_STRING", False); XA_wm_state = XInternAtom(dpy, "WM_STATE", False); if (argv[1] && !strcmp(argv[1], "-t")) { Opt_timestamp = 1; optind++; } /* Choose which events we're interested in. */ memset(&track, 0, sizeof(track)); track.children = True; track.creation = True; track.mapping = True; track.configure = True; track.shape = True; track.properties = True; track.clientmsg = True; track.visibility = True; track.keyboard = True; for (; argv[optind]; optind++) { char const *opt; Bool add, del, *which; opt = argv[optind]; add = opt[0] == '+'; del = opt[0] == '-'; if (add || del) opt++; if (!strcmp(opt, "children")) which = &track.children; else if (!strcmp(opt, "create")) which = &track.creation; else if (!strcmp(opt, "map")) which = &track.mapping; else if (!strcmp(opt, "config")) which = &track.configure; else if (!strcmp(opt, "shape")) which = &track.shape; else if (!strcmp(opt, "prop")) which = &track.properties; else if (!strcmp(opt, "ipc")) which = &track.clientmsg; else if (!strcmp(opt, "visibility")) which = &track.visibility; else if (!strcmp(opt, "expose")) which = &track.exposure; else if (!strcmp(opt, "damage")) which = &track.damages; else if (!strcmp(opt, "ptr")) which = &track.pointer; else if (!strcmp(opt, "kbd")) which = &track.keyboard; else break; if (!add && !del) memset(&track, 0, sizeof(track)); *which = !del; } /* for */ xeventmask = 0; if (track.creation || track.mapping || track.configure || track.clientmsg) xeventmask |= track.children ? SubstructureNotifyMask : StructureNotifyMask; if (track.shape) XShapeQueryExtension(dpy, &shape_event, &error_base); if (track.properties) xeventmask |= PropertyChangeMask; if (track.visibility) xeventmask |= VisibilityChangeMask; if (track.exposure) xeventmask |= ExposureMask; if (track.damages) XDamageQueryExtension(dpy, &damage_event, &error_base); if (track.pointer); xeventmask |= EnterWindowMask|LeaveWindowMask; if (track.keyboard) xeventmask |= KeyPressMask|KeyReleaseMask; /* XSelectInput() the windows we're interested in * or the root window. */ if (argv[optind]) do { Window win; char const *errp; win = strtoul(argv[optind], (char **)&errp, 0); if (errp == argv[optind] || *errp) { fprintf(stderr, "%s: what is `%s'?\n", argv[0], argv[optind]); exit(1); } XSelectInput(dpy, win, xeventmask); if (track.shape) XShapeSelectInput(dpy, win, ShapeNotifyMask); if (track.damages) XDamageCreate(dpy, win, XDamageReportRawRectangles); } while (argv[++optind]); else XSelectInput(dpy, DefaultRootWindow(dpy), xeventmask); /* The main loop */ line = g_string_new(""); for (;;) { XEvent ev; /* Wait for, get and process the next event. */ XNextEvent(dpy, &ev); if (ev.type == CreateNotify) { XCreateWindowEvent const *create = &ev.xcreatewindow; if (!track.creation) continue; fmtxid(line, create->parent); g_string_append_printf(line, "Create(0x%lx)", create->window); output(line, ev.xany.send_event); } else if (ev.type == DestroyNotify) { XDestroyWindowEvent const *destroy = &ev.xdestroywindow; if (!track.creation) continue; fmtxid(line, destroy->event); g_string_append_printf(line, "Destroy(0x%lx)", destroy->window); output(line, ev.xany.send_event); } else if (ev.type == MapNotify) { XMapEvent const *map = &ev.xmap; if (!track.mapping) continue; fmtxid(line, map->event); g_string_append_printf(line, "Map(0x%lx%s)", map->window, map->override_redirect ? ", override_redirected" : ""); output(line, ev.xany.send_event); } else if (ev.type == UnmapNotify) { XUnmapEvent const *unmap = &ev.xunmap; if (!track.mapping) continue; fmtxid(line, unmap->event); g_string_append_printf(line, "Unmap(0x%lx%s)", unmap->window, unmap->from_configure ? ", from_configure" : ""); output(line, ev.xany.send_event); } else if (ev.type == ReparentNotify) { XReparentEvent const *reparent = &ev.xreparent; if (!track.configure) continue; fmtxid(line, reparent->event); g_string_append_printf(line, "Reparent(0x%lx => 0x%lx)", reparent->window, reparent->parent); output(line, ev.xany.send_event); } else if (ev.type == ConfigureNotify) { XConfigureEvent const *cfg = &ev.xconfigure; if (!track.configure) continue; fmtxid(line, cfg->event); g_string_append_printf(line, "Configure(0x%lx => %dx%d%+d%+d, " "above=0x%lx%s)", cfg->window, cfg->width, cfg->height, cfg->x, cfg->y, cfg->above, cfg->override_redirect ? ", override_redirected" : ""); output(line, ev.xany.send_event); } else if (track.shape && ev.type == shape_event + ShapeNotify) { static char const *shapes[] = { "Bounding", "Clip", "Input" }; XShapeEvent sev; memcpy(&sev, &ev, sizeof(sev)); fmtxid(line, sev.window); g_string_append_printf(line, "Shape(%s => %dx%d%+d%+d)", shapes[sev.kind], sev.width, sev.height, sev.x, sev.y); output(line, ev.xany.send_event); } else if (ev.type == PropertyNotify) { assert(track.properties); property_event(dpy, &ev.xproperty, line); } else if (ev.type == ClientMessage) { if (!track.clientmsg) continue; client_message(dpy, &ev.xclient, line); } else if (ev.type == VisibilityNotify) { static char const *visibilities[] = { "unobscured", "partially obscured", "fully obscured", }; XVisibilityEvent const *vis = &ev.xvisibility; assert(track.visibility); fmtxid(line, vis->window); g_string_append_printf(line, "Visibility=%s", visibilities[vis->state]); output(line, ev.xany.send_event); } else if (ev.type == Expose) { XExposeEvent const *ex = &ev.xexpose; assert(track.exposure); fmtxid(line, ex->window); g_string_append_printf(line, "Expose(%dx%d%+d%+d)", ex->width, ex->height, ex->x, ex->y); output(line, ev.xany.send_event); } else if (track.damages && ev.type == damage_event) { XDamageNotifyEvent dev; memcpy(&dev, &ev, sizeof(dev)); fmtxid(line, dev.drawable); g_string_append_printf(line, "Damage(%dx%d%+d%+d)", dev.area.width, dev.area.height, dev.area.x, dev.area.y); output(line, ev.xany.send_event); XDamageSubtract(dpy, dev.damage, None, None); } else if (ev.type == EnterNotify || ev.type == LeaveNotify) { XCrossingEvent const *cross = &ev.xcrossing; if (!track.pointer) continue; fmtxid(line, cross->window); g_string_append_printf(line, "%s(%dx%d", cross->type == EnterNotify ? "Enter" : "Leave", cross->x, cross->y); if (cross->mode == NotifyGrab) g_string_append(line, ", grab"); else if (cross->mode == NotifyUngrab) g_string_append(line, ", ungrab"); g_string_append_c(line, ')'); output(line, ev.xany.send_event); } else if (ev.type == KeyPress || ev.type == KeyRelease) { static struct { int mask; char const *name; } states[] = { { ShiftMask, "Shift" }, { LockMask, "Lock" }, { ControlMask, "Ctrl" }, { Mod1Mask, "Mod1" }, { Mod2Mask, "Mod2" }, { Mod3Mask, "Mod3" }, { Mod4Mask, "Mod4" }, { Mod5Mask, "Mod5" }, }; unsigned i; int has_modifiers; XKeyEvent const *key; assert(track.keyboard); key = &ev.xkey; fmtxid(line, key->window); /* Prepend with the list of modifiers. */ has_modifiers = 0; for (i = 0; i < G_N_ELEMENTS(states); i++) if (key->state & states[i].mask) { if (!has_modifiers) { g_string_append_c(line, ' '); has_modifiers = 1; } else g_string_append_c(line, '-'); g_string_append(line, states[i].name); } if (has_modifiers) g_string_append_c(line, '-'); g_string_append_printf(line, "%s %s", XKeysymToString(XKeycodeToKeysym(dpy, key->keycode, 0)), ev.type == KeyPress ? "pressed" : "released"); output(line, ev.xany.send_event); } /* if */ } /* for ever */ return 0; } /* main */
static int x11_reset(struct vidisp_st *st, const struct vidsz *sz) { XWindowAttributes attrs; XGCValues gcv; size_t bufsz, pixsz; int err = 0; if (!XGetWindowAttributes(st->disp, st->win, &attrs)) { warning("x11: cant't get window attributes\n"); return EINVAL; } switch (attrs.depth) { case 24: st->pixfmt = VID_FMT_RGB32; pixsz = 4; break; case 16: st->pixfmt = VID_FMT_RGB565; pixsz = 2; break; case 15: st->pixfmt = VID_FMT_RGB555; pixsz = 2; break; default: warning("x11: colordepth not supported: %d\n", attrs.depth); return ENOSYS; } bufsz = sz->w * sz->h * pixsz; if (st->image) { XDestroyImage(st->image); st->image = NULL; } if (st->xshmat) XShmDetach(st->disp, &st->shm); if (st->shm.shmaddr != (char *)-1) shmdt(st->shm.shmaddr); if (st->shm.shmid >= 0) shmctl(st->shm.shmid, IPC_RMID, NULL); st->shm.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0777); if (st->shm.shmid < 0) { warning("x11: failed to allocate shared memory\n"); return ENOMEM; } st->shm.shmaddr = shmat(st->shm.shmid, NULL, 0); if (st->shm.shmaddr == (char *)-1) { warning("x11: failed to attach to shared memory\n"); return ENOMEM; } st->shm.readOnly = true; x11.shm_error = 0; x11.errorh = XSetErrorHandler(error_handler); if (!XShmAttach(st->disp, &st->shm)) { warning("x11: failed to attach X to shared memory\n"); return ENOMEM; } XSync(st->disp, False); XSetErrorHandler(x11.errorh); if (x11.shm_error) info("x11: shared memory disabled\n"); else st->xshmat = true; gcv.graphics_exposures = false; st->gc = XCreateGC(st->disp, st->win, GCGraphicsExposures, &gcv); if (!st->gc) { warning("x11: failed to create graphics context\n"); return ENOMEM; } if (st->xshmat) { st->image = XShmCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, st->shm.shmaddr, &st->shm, sz->w, sz->h); } else { st->image = XCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, 0, st->shm.shmaddr, sz->w, sz->h, 32, 0); } if (!st->image) { warning("x11: Failed to create X image\n"); return ENOMEM; } XResizeWindow(st->disp, st->win, sz->w, sz->h); st->size = *sz; return err; }
MyWindow::MyWindow(const std::string &title,int width,int height) : initError(false),clientWidth(0),clientHeight(0),iconified(false),focused(true),sized(false), justCreated(true),mouseMoveCallback(0),inputCallback(0),lockCursor(false),foreground(true) { #ifdef WIN32 hglrc=0; hdc=0; // HINSTANCE hInstance=GetModuleHandle(0); WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL,IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; #ifdef UNICODE wcex.lpszClassName = L"win32app"; #else wcex.lpszClassName = "win32app"; #endif wcex.hIconSm = LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_APPLICATION)); if(!RegisterClassEx(&wcex)) { std::cout << "MyWindow : Call to RegisterClassEx failed!\n"; } #ifdef UNICODE wchar_t title2[256]; MultiByteToWideChar(CP_ACP,0,title.c_str(),-1,title2,256); #else const char *title2=title.c_str(); #endif hWnd = CreateWindow(wcex.lpszClassName,title2,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,width,height,NULL,NULL,hInstance,NULL); SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)this); ShowWindow(hWnd,SW_SHOW); // hdc= GetDC(hWnd); PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd,sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cRedBits = pfd.cGreenBits = pfd.cBlueBits = 8; pfd.cDepthBits = 32; int iPixelFormat = ChoosePixelFormat(hdc,&pfd); if(iPixelFormat == 0) { std::cout << "MyWindow : ChoosePixelFormat failed.\n"; initError=true; return; } if(SetPixelFormat(hdc,iPixelFormat,&pfd) != TRUE) { std::cout << "MyWindow : SetPixelFormat failed.\n"; initError=true; return; } // HGLRC tempContext = wglCreateContext(hdc); wglMakeCurrent(hdc,tempContext); // PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB= (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); PFNWGLSWAPINTERVALEXTPROC wglSwapInterval= (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); // wglMakeCurrent(0,0); wglDeleteContext(tempContext); // int attribs[] ={ WGL_CONTEXT_MAJOR_VERSION_ARB,3, WGL_CONTEXT_MINOR_VERSION_ARB,3, WGL_CONTEXT_FLAGS_ARB,0, 0 }; hglrc=wglCreateContextAttribsARB(hdc,0,attribs); for(int i=2;i>=0;i--) { if(!hglrc) { attribs[3]=i; hglrc=wglCreateContextAttribsARB(hdc,0,attribs); } } if(!hglrc) { std::cout << "OpenGL 3+ not supported.\n"; initError=true; return; } wglMakeCurrent(hdc,hglrc); wglSwapInterval(1); // RAWINPUTDEVICE Rid[2]; Rid[0].usUsagePage = (USHORT)0x01;//HID_USAGE_PAGE_GENERIC; Rid[0].usUsage = (USHORT)0x02;//HID_USAGE_GENERIC_MOUSE; Rid[0].dwFlags = RIDEV_INPUTSINK; Rid[0].hwndTarget = hWnd; Rid[1].usUsagePage = (USHORT)0x01;//HID_USAGE_PAGE_GENERIC; Rid[1].usUsage = (USHORT)0x06;//HID_USAGE_GENERIC_KEYBOARD; Rid[1].dwFlags = RIDEV_INPUTSINK; Rid[1].hwndTarget = hWnd; RegisterRawInputDevices(Rid,2,sizeof(RAWINPUTDEVICE)); // //inputCodeMap[65]=keyA; //inputCodeMap[68]=keyD; //inputCodeMap[83]=keyS; //inputCodeMap[87]=keyW; #endif #ifdef LINUX // bool ctxErrorOccurred=false; display = XOpenDisplay(NULL); if(!display) { std::cout << "Window : Failed to open X display.\n"; initError=true; return; } static int visual_attribs[] ={ GLX_X_RENDERABLE,True, GLX_DRAWABLE_TYPE,GLX_WINDOW_BIT, GLX_RENDER_TYPE,GLX_RGBA_BIT, GLX_X_VISUAL_TYPE,GLX_TRUE_COLOR, GLX_RED_SIZE,8, GLX_GREEN_SIZE,8, GLX_BLUE_SIZE,8, GLX_ALPHA_SIZE,8, GLX_DEPTH_SIZE,24, GLX_STENCIL_SIZE,8, GLX_DOUBLEBUFFER,True, //GLX_SAMPLE_BUFFERS , 1, //GLX_SAMPLES , 4, None }; int glx_major,glx_minor; if(!glXQueryVersion(display,&glx_major,&glx_minor) || ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { std::cout << "Window : Invalid GLX version.\n"; initError=true; return; } int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(display,DefaultScreen(display),visual_attribs,&fbcount); if(!fbc) { std::cout << "Window :Failed to retrieve a framebuffer config.\n"; initError=true; return; } int best_fbc = -1,worst_fbc = -1,best_num_samp = -1,worst_num_samp = 999; for(int i=0; i<fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig(display,fbc[i]); if(vi) { int samp_buf,samples; glXGetFBConfigAttrib(display,fbc[i],GLX_SAMPLE_BUFFERS,&samp_buf); glXGetFBConfigAttrib(display,fbc[i],GLX_SAMPLES,&samples); std::cout << "Matching fbconfig " << i <<", visual ID 0x" << vi->visualid << ": SAMPLE_BUFFERS = " << samp_buf <<", SAMPLES = " << samples <<"\n"; if(best_fbc < 0 || samp_buf && samples > best_num_samp) { best_fbc = i; best_num_samp = samples; } if(worst_fbc < 0 || !samp_buf || samples < worst_num_samp) { worst_fbc = i; worst_num_samp = samples; } } XFree(vi); } GLXFBConfig bestFbc = fbc[best_fbc]; XFree(fbc); XVisualInfo *vi = glXGetVisualFromFBConfig(display,bestFbc); std::cout << "Chosen visual ID = 0x" << vi->visualid <<"\n"; XSetWindowAttributes swa; swa.colormap = cmap = XCreateColormap(display, RootWindow(display,vi->screen), vi->visual,AllocNone); swa.background_pixmap = None; swa.border_pixel = 0; swa.event_mask = ExposureMask | VisibilityChangeMask |KeyPressMask | PointerMotionMask |StructureNotifyMask; swa.bit_gravity = StaticGravity; win = XCreateWindow(display,RootWindow(display,vi->screen), 0,0,100,100,0,vi->depth,InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask,&swa); if(!win) { std::cout << "Window : Failed to create window.\n"; initError=true; return; } XFree(vi); XStoreName(display,win,title.c_str()); XMapWindow(display,win); const char *glxExts = glXQueryExtensionsString(display,DefaultScreen(display)); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); ctx = 0; ctxErrorOccurred = false; int(*oldHandler)(Display*,XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); if(!isExtensionSupported(glxExts,"GLX_ARB_create_context") || !glXCreateContextAttribsARB) { std::cout << "Window : glXCreateContextAttribsARB() not found.\n"; initError=true; return; } else { int context_attribs[] ={ GLX_CONTEXT_MAJOR_VERSION_ARB,3, GLX_CONTEXT_MINOR_VERSION_ARB,0, GLX_CONTEXT_FLAGS_ARB,0, None }; ctx = glXCreateContextAttribsARB(display,bestFbc,0, True,context_attribs); XSync(display,False); if(!ctxErrorOccurred && ctx) { std::cout << "Created GL 3.0 context\n"; } else { std::cout << "Window : Failed to create GL 3.0 context.\n"; initError=true; return; } } // XSync(display,False); XSetErrorHandler(oldHandler); if(ctxErrorOccurred || !ctx) { std::cout << "Window : Failed to create an OpenGL context.\n"; initError=true; return; } // Verifying that context is a direct context if(!glXIsDirect(display,ctx)) { std::cout << "Indirect GLX rendering context obtained.\n"; } else { std::cout << "Direct GLX rendering context obtained.\n"; } // glXMakeCurrent(display,win,ctx); if(PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA= (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA")) { glXSwapIntervalMESA(1); } else if(PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT= (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT")) { glXSwapIntervalEXT(display,glXGetCurrentDrawable(),1); } else if(PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI= (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI")) { glXSwapIntervalSGI(1); } #endif }
void GSWndOGL::CreateContext(int major, int minor) { if ( !m_NativeDisplay || !m_NativeWindow ) { fprintf( stderr, "Wrong X11 display/window\n" ); throw GSDXRecoverableError(); } // Get visual information static int attrListDbl[] = { // GLX_X_RENDERABLE: If True is specified, then only frame buffer configurations that have associated X // visuals (and can be used to render to Windows and/or GLX pixmaps) will be considered. The default value is GLX_DONT_CARE. GLX_X_RENDERABLE , True, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_DEPTH_SIZE , 0, GLX_DOUBLEBUFFER , True, None }; PFNGLXCHOOSEFBCONFIGPROC glX_ChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) glXGetProcAddress((GLubyte *) "glXChooseFBConfig"); int fbcount = 0; GLXFBConfig *fbc = glX_ChooseFBConfig(m_NativeDisplay, DefaultScreen(m_NativeDisplay), attrListDbl, &fbcount); if (!fbc || fbcount < 1) { throw GSDXRecoverableError(); } PFNGLXCREATECONTEXTATTRIBSARBPROC glX_CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB"); if (!glX_CreateContextAttribsARB) { throw GSDXRecoverableError(); } // Install a dummy handler to handle gracefully (aka not segfault) the support of GL version int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); // Be sure the handler is installed XSync( m_NativeDisplay, false); // Create a context int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major, GLX_CONTEXT_MINOR_VERSION_ARB, minor, #ifdef ENABLE_OGL_DEBUG GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, #else // Open Source isn't happy with an unsupported flags... //GLX_CONTEXT_FLAGS_ARB, GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR, #endif GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, None }; m_context = glX_CreateContextAttribsARB(m_NativeDisplay, fbc[0], 0, true, context_attribs); XFree(fbc); // Don't forget to reinstall the older Handler XSetErrorHandler(oldHandler); // Get latest error XSync( m_NativeDisplay, false); if (!m_context || ctxError) { fprintf(stderr, "Failed to create the opengl context. Check your drivers support openGL %d.%d. Hint: opensource drivers don't\n", major, minor ); throw GSDXRecoverableError(); } }
static bool gfx_ctx_xegl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { EGLint egl_attribs[16]; EGLint *attr; EGLint vid, num_visuals; bool windowed_full; bool true_full = false; int x_off = 0; int y_off = 0; struct sigaction sa = {{0}}; XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); int (*old_handler)(Display*, XErrorEvent*) = NULL; XEvent event; sa.sa_handler = egl_sighandler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); windowed_full = settings->video.windowed_fullscreen; true_full = false; attr = egl_attribs; attr = xegl_fill_attribs(attr); if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid)) goto error; temp.visualid = vid; vi = XGetVisualInfo(g_dpy, VisualIDMask, &temp, &num_visuals); if (!vi) goto error; swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen), vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask; swa.override_redirect = fullscreen ? True : False; if (fullscreen && !windowed_full) { if (x11_enter_fullscreen(g_dpy, width, height, &g_desktop_mode)) { g_should_reset_mode = true; true_full = true; } else RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } if (settings->video.monitor_index) g_screen = settings->video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_screen); else RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n"); if (fullscreen) { width = new_width; height = new_height; } } #endif RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n", x_off, y_off, width, height); g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa); XSetWindowBackground(g_dpy, g_win, 0); g_egl_ctx = eglCreateContext(g_egl_dpy, g_egl_config, EGL_NO_CONTEXT, attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx); if (g_egl_ctx == EGL_NO_CONTEXT) goto error; if (g_use_hw_ctx) { g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_egl_config, g_egl_ctx, attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx); if (g_egl_hw_ctx == EGL_NO_CONTEXT) goto error; } g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_egl_config, (EGLNativeWindowType)g_win, NULL); if (!g_egl_surf) goto error; if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) goto error; RARCH_LOG("[X/EGL]: Current context: %p.\n", (void*)eglGetCurrentContext()); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_show_mouse(g_dpy, g_win, false); if (true_full) { RARCH_LOG("[X/EGL]: Using true fullscreen.\n"); XMapRaised(g_dpy, g_win); } else if (fullscreen) { /* We attempted true fullscreen, but failed. * Attempt using windowed fullscreen. */ XMapRaised(g_dpy, g_win); RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n"); /* We have to move the window to the screen we * want to go fullscreen on first. * x_off and y_off usually get ignored in XCreateWindow(). */ x11_move_window(g_dpy, g_win, x_off, y_off, width, height); x11_windowed_fullscreen(g_dpy, g_win); } else { XMapWindow(g_dpy, g_win); /* If we want to map the window on a different screen, * we'll have to do it by force. * * Otherwise, we should try to let the window manager sort it out. * x_off and y_off usually get ignored in XCreateWindow(). */ if (g_screen) x11_move_window(g_dpy, g_win, x_off, y_off, width, height); } XIfEvent(g_dpy, &event, egl_wait_notify, NULL); g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False); if (g_quit_atom) XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); gfx_ctx_xegl_swap_interval(data, g_interval); /* This can blow up on some drivers. It's not fatal, * so override errors for this call. */ old_handler = XSetErrorHandler(egl_nul_handler); XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime); XSync(g_dpy, False); XSetErrorHandler(old_handler); XFree(vi); g_has_focus = true; g_inited = true; if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic)) goto error; driver->display_type = RARCH_DISPLAY_X11; driver->video_display = (uintptr_t)g_dpy; driver->video_window = (uintptr_t)g_win; g_true_full = true_full; return true; error: if (vi) XFree(vi); gfx_ctx_xegl_destroy(data); return false; }
static bool gfx_ctx_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { struct sigaction sa = {{0}}; sa.sa_handler = sighandler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); int x_off = 0; int y_off = 0; bool windowed_full = g_settings.video.windowed_fullscreen; bool true_full = false; int (*old_handler)(Display*, XErrorEvent*) = NULL; XSetWindowAttributes swa = {0}; XVisualInfo *vi = glXGetVisualFromFBConfig(g_dpy, g_fbc); if (!vi) goto error; swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen), vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask; swa.override_redirect = fullscreen ? True : False; if (fullscreen && !windowed_full) { if (x11_enter_fullscreen(g_dpy, width, height, &g_desktop_mode)) { g_should_reset_mode = true; true_full = true; } else RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } if (g_settings.video.monitor_index) g_screen = g_settings.video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[GLX]: Using Xinerama on screen #%u.\n", g_screen); else RARCH_LOG("[GLX]: Xinerama is not active on screen.\n"); if (fullscreen) { width = new_width; height = new_height; } } #endif RARCH_LOG("[GLX]: X = %d, Y = %d, W = %u, H = %u.\n", x_off, y_off, width, height); g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa); XSetWindowBackground(g_dpy, g_win, 0); g_glx_win = glXCreateWindow(g_dpy, g_fbc, g_win, 0); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_show_mouse(g_dpy, g_win, false); if (true_full) { RARCH_LOG("[GLX]: Using true fullscreen.\n"); XMapRaised(g_dpy, g_win); } else if (fullscreen) // We attempted true fullscreen, but failed. Attempt using windowed fullscreen. { XMapRaised(g_dpy, g_win); RARCH_LOG("[GLX]: Using windowed fullscreen.\n"); // We have to move the window to the screen we want to go fullscreen on first. // x_off and y_off usually get ignored in XCreateWindow(). x11_move_window(g_dpy, g_win, x_off, y_off, width, height); x11_windowed_fullscreen(g_dpy, g_win); } else { XMapWindow(g_dpy, g_win); // If we want to map the window on a different screen, we'll have to do it by force. // Otherwise, we should try to let the window manager sort it out. // x_off and y_off usually get ignored in XCreateWindow(). if (g_screen) x11_move_window(g_dpy, g_win, x_off, y_off, width, height); } XEvent event; XIfEvent(g_dpy, &event, glx_wait_notify, NULL); if (!g_ctx) { if (g_core || g_debug) { int attribs[16]; int *aptr = attribs; if (g_core) { *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB; *aptr++ = g_major; *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB; *aptr++ = g_minor; // Technically, we don't have core/compat until 3.2. // Version 3.1 is either compat or not depending on GL_ARB_compatibility. if ((g_major * 1000 + g_minor) >= 3002) { *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; } } if (g_debug) { *aptr++ = GLX_CONTEXT_FLAGS_ARB; *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB; } *aptr = None; g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs); if (g_use_hw_ctx) { RARCH_LOG("[GLX]: Creating shared HW context.\n"); g_hw_ctx = glx_create_context_attribs(g_dpy, g_fbc, g_ctx, True, attribs); if (!g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } else { g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); if (g_use_hw_ctx) { g_hw_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, g_ctx, True); if (!g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } if (!g_ctx) { RARCH_ERR("[GLX]: Failed to create new context.\n"); goto error; } } else { driver.video_cache_context_ack = true; RARCH_LOG("[GLX]: Using cached GL context.\n"); } glXMakeContextCurrent(g_dpy, g_glx_win, g_glx_win, g_ctx); XSync(g_dpy, False); g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False); if (g_quit_atom) XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); int val; glXGetConfig(g_dpy, vi, GLX_DOUBLEBUFFER, &val); g_is_double = val; if (g_is_double) { const char *swap_func = NULL; g_pglSwapIntervalEXT = (void (*)(Display*, GLXDrawable, int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); g_pglSwapInterval = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); if (g_pglSwapIntervalEXT) swap_func = "glXSwapIntervalEXT"; else if (g_pglSwapInterval) swap_func = "glXSwapIntervalMESA"; if (!g_pglSwapInterval && !g_pglSwapIntervalEXT) RARCH_WARN("[GLX]: Cannot find swap interval call.\n"); else RARCH_LOG("[GLX]: Found swap function: %s.\n", swap_func); } else RARCH_WARN("[GLX]: Context is not double buffered!.\n"); gfx_ctx_swap_interval(data, g_interval); // This can blow up on some drivers. It's not fatal, so override errors for this call. old_handler = XSetErrorHandler(nul_handler); XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime); XSync(g_dpy, False); XSetErrorHandler(old_handler); XFree(vi); g_has_focus = true; g_inited = true; if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic)) goto error; driver.display_type = RARCH_DISPLAY_X11; driver.video_display = (uintptr_t)g_dpy; driver.video_window = (uintptr_t)g_win; g_true_full = true_full; return true; error: if (vi) XFree(vi); gfx_ctx_destroy(data); return false; }
void wsXInit( void* mDisplay ) { int eventbase; int errorbase; if(mDisplay){ wsDisplay=mDisplay; } else { char * DisplayName = ":0.0"; if ( getenv( "DISPLAY" ) ) DisplayName=getenv( "DISPLAY" ); wsDisplay=XOpenDisplay( DisplayName ); if ( !wsDisplay ) { mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_CouldNotOpenDisplay ); exit( 0 ); } } /* enable DND atoms */ wsXDNDInitialize(); { /* on remote display XShm will be disabled - LGB */ char *dispname=DisplayString(wsDisplay); int localdisp=1; if (dispname&&*dispname!=':') { localdisp=0; wsUseXShm=0; } mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] display name: %s => %s display.\n",dispname,localdisp?"local":"REMOTE"); if (!localdisp) mp_msg( MSGT_GPLAYER,MSGL_V,MSGTR_WS_RemoteDisplay ); } if ( !XShmQueryExtension( wsDisplay ) ) { mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshm ); wsUseXShm=0; } #ifdef HAVE_XSHAPE if ( !XShapeQueryExtension( wsDisplay,&eventbase,&errorbase ) ) { mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshape ); wsUseXShape=0; } #else wsUseXShape=0; #endif XSynchronize( wsDisplay,True ); wsScreen=DefaultScreen( wsDisplay ); wsRootWin=RootWindow( wsDisplay,wsScreen ); #ifdef HAVE_XF86VM { int clock; XF86VidModeModeLine modeline; XF86VidModeGetModeLine( wsDisplay,wsScreen,&clock ,&modeline ); wsMaxX=modeline.hdisplay; wsMaxY=modeline.vdisplay; } #endif { wsOrgX = wsOrgY = 0; if ( !wsMaxX ) wsMaxX=DisplayWidth( wsDisplay,wsScreen ); if ( !wsMaxY ) wsMaxY=DisplayHeight( wsDisplay,wsScreen ); } vo_screenwidth = wsMaxX; vo_screenheight = wsMaxY; xinerama_x = wsOrgX; xinerama_y = wsOrgY; update_xinerama_info(); wsMaxX = vo_screenwidth; wsMaxY = vo_screenheight; wsOrgX = xinerama_x; wsOrgY = xinerama_y; wsGetDepthOnScreen(); #ifdef DEBUG { int minor,major,shp; mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Screen depth: %d\n",wsDepthOnScreen ); mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] size: %dx%d\n",wsMaxX,wsMaxY ); #ifdef HAVE_XINERAMA mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] origin: +%d+%d\n",wsOrgX,wsOrgY ); #endif mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] red mask: 0x%x\n",wsRedMask ); mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] green mask: 0x%x\n",wsGreenMask ); mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] blue mask: 0x%x\n",wsBlueMask ); if ( wsUseXShm ) { XShmQueryVersion( wsDisplay,&major,&minor,&shp ); mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShm version is %d.%d\n",major,minor ); } #ifdef HAVE_XSHAPE if ( wsUseXShape ) { XShapeQueryVersion( wsDisplay,&major,&minor ); mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShape version is %d.%d\n",major,minor ); } #endif } #endif wsOutMask=wsGetOutMask(); mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Initialized converter: " ); sws_rgb2rgb_init(get_sws_cpuflags()); switch ( wsOutMask ) { case wsRGB32: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb32\n" ); wsConvFunc=rgb32torgb32; break; case wsBGR32: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr32\n" ); wsConvFunc=rgb32tobgr32; break; case wsRGB24: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb24\n" ); wsConvFunc=rgb32to24; break; case wsBGR24: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr24\n" ); wsConvFunc=rgb32tobgr24; break; case wsRGB16: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb16\n" ); wsConvFunc=rgb32to16; break; case wsBGR16: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr16\n" ); wsConvFunc=rgb32tobgr16; break; case wsRGB15: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb15\n" ); wsConvFunc=rgb32to15; break; case wsBGR15: mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr15\n" ); wsConvFunc=rgb32tobgr15; break; } XSetErrorHandler( wsErrorHandler ); }
void X11EGLWindow::initNativeCreatedWindow(const NameValuePairList *miscParams) { if (miscParams) { NameValuePairList::const_iterator opt; NameValuePairList::const_iterator end = miscParams->end(); mExternalWindow = 0; mNativeDisplay = mGLSupport->getNativeDisplay(); mParentWindow = DefaultRootWindow((Display*)mNativeDisplay); if ((opt = miscParams->find("parentWindowHandle")) != end) { //vector<String>::type tokens = StringUtil::split(opt->second, " :"); StringVector tokens = StringUtil::split(opt->second, " :"); if (tokens.size() == 3) { // deprecated display:screen:xid format mParentWindow = (Window)StringConverter::parseUnsignedLong(tokens[2]); } else { // xid format mParentWindow = (Window)StringConverter::parseUnsignedLong(tokens[0]); } } else if ((opt = miscParams->find("externalWindowHandle")) != end) { //vector<String>::type tokens = StringUtil::split(opt->second, " :"); StringVector tokens = StringUtil::split(opt->second, " :"); LogManager::getSingleton().logMessage( "EGLWindow::create: The externalWindowHandle parameter is deprecated.\n" "Use the parentWindowHandle or currentGLContext parameter instead."); if (tokens.size() == 3) { // Old display:screen:xid format // The old EGL code always created a "parent" window in this case: mParentWindow = (Window)StringConverter::parseUnsignedLong(tokens[2]); } else if (tokens.size() == 4) { // Old display:screen:xid:visualinfo format mExternalWindow = (Window)StringConverter::parseUnsignedLong(tokens[2]); } else { // xid format mExternalWindow = (Window)StringConverter::parseUnsignedLong(tokens[0]); } } } // Ignore fatal XErrorEvents during parameter validation: oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); // Validate parentWindowHandle if (mParentWindow != DefaultRootWindow((Display*)mNativeDisplay)) { XWindowAttributes windowAttrib; if (!XGetWindowAttributes((Display*)mNativeDisplay, mParentWindow, &windowAttrib) || windowAttrib.root != DefaultRootWindow((Display*)mNativeDisplay)) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid parentWindowHandle (wrong server or screen)", "EGLWindow::create"); } } // Validate externalWindowHandle if (mExternalWindow != 0) { XWindowAttributes windowAttrib; if (!XGetWindowAttributes((Display*)mNativeDisplay, mExternalWindow, &windowAttrib) || windowAttrib.root != DefaultRootWindow((Display*)mNativeDisplay)) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid externalWindowHandle (wrong server or screen)", "EGLWindow::create"); } mEglConfig = 0; mEglSurface = createSurfaceFromWindow(mEglDisplay, (NativeWindowType)mExternalWindow); } XSetErrorHandler(oldXErrorHandler); mIsTopLevel = (!mIsExternal && mParentWindow == DefaultRootWindow((Display*)mNativeDisplay)); }
static void SetupImage (void) { TakedownImage(); #ifdef MITSHM GUI.use_shared_memory = TRUE; int major, minor; Bool shared; if (!XShmQueryVersion(GUI.display, &major, &minor, &shared) || !shared) GUI.image = NULL; else GUI.image = XShmCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, NULL, &GUI.sm_info, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2); if (!GUI.image) GUI.use_shared_memory = FALSE; else { GUI.sm_info.shmid = shmget(IPC_PRIVATE, GUI.image->bytes_per_line * GUI.image->height, IPC_CREAT | 0777); if (GUI.sm_info.shmid < 0) { XDestroyImage(GUI.image); GUI.use_shared_memory = FALSE; } else { GUI.image->data = GUI.sm_info.shmaddr = (char *) shmat(GUI.sm_info.shmid, 0, 0); if (!GUI.image->data) { XDestroyImage(GUI.image); shmctl(GUI.sm_info.shmid, IPC_RMID, 0); GUI.use_shared_memory = FALSE; } else { GUI.sm_info.readOnly = False; XSetErrorHandler(ErrorHandler); XShmAttach(GUI.display, &GUI.sm_info); XSync(GUI.display, False); // X Error handler might clear GUI.use_shared_memory if XShmAttach failed. if (!GUI.use_shared_memory) { XDestroyImage(GUI.image); shmdt(GUI.sm_info.shmaddr); shmctl(GUI.sm_info.shmid, IPC_RMID, 0); } } } } if (!GUI.use_shared_memory) { fprintf(stderr, "use_shared_memory failed, switching to XPutImage.\n"); #endif GUI.image = XCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, 0, NULL, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, BitmapUnit(GUI.display), 0); GUI.image->data = (char *) malloc(GUI.image->bytes_per_line * GUI.image->height); if (!GUI.image || !GUI.image->data) FatalError("XCreateImage failed."); #ifdef MITSHM } #endif #ifdef LSB_FIRST GUI.image->byte_order = LSBFirst; #else GUI.image->byte_order = MSBFirst; #endif GFX.Pitch = SNES_WIDTH * 2 * 2; GUI.snes_buffer = (uint8 *) calloc(GFX.Pitch * ((SNES_HEIGHT_EXTENDED + 4) * 2), 1); if (!GUI.snes_buffer) FatalError("Failed to allocate GUI.snes_buffer."); GFX.Screen = (uint16 *) (GUI.snes_buffer + (GFX.Pitch * 2 * 2)); GUI.filter_buffer = (uint8 *) calloc((SNES_WIDTH * 2) * 2 * (SNES_HEIGHT_EXTENDED * 2), 1); if (!GUI.filter_buffer) FatalError("Failed to allocate GUI.filter_buffer."); if (GUI.depth == 15 || GUI.depth == 16) { GUI.blit_screen_pitch = GUI.image->bytes_per_line; GUI.blit_screen = (uint8 *) GUI.image->data; GUI.need_convert = FALSE; } else { GUI.blit_screen_pitch = (SNES_WIDTH * 2) * 2; GUI.blit_screen = GUI.filter_buffer; GUI.need_convert = TRUE; } S9xGraphicsInit(); }
Bool dfb_x11_open_window( DFBX11 *x11, XWindow** ppXW, int iXPos, int iYPos, int iWidth, int iHeight, DFBSurfacePixelFormat format ) { XWindow *xw; XSetWindowAttributes attr = { .background_pixmap = 0 }; void *old_error_handler = 0; unsigned int cw_mask = CWEventMask; D_DEBUG_AT( X11_Window, "Creating %4dx%4d %s window...\n", iWidth, iHeight, dfb_pixelformat_name(format) ); xw = D_CALLOC( 1, sizeof(XWindow) ); if (!xw) return D_OOM(); /* We set the structure as needed for our window */ xw->width = iWidth; xw->height = iHeight; xw->display = x11->display; xw->screenptr = DefaultScreenOfDisplay(xw->display); xw->screennum = DefaultScreen(xw->display); xw->depth = DefaultDepthOfScreen(xw->screenptr); xw->visual = DefaultVisualOfScreen(xw->screenptr); attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask; if (dfb_config->x11_borderless) { attr.override_redirect = True; cw_mask |= CWOverrideRedirect; } XLockDisplay( x11->display ); old_error_handler = XSetErrorHandler( error_handler ); error_code = 0; xw->window = XCreateWindow( xw->display, RootWindowOfScreen(xw->screenptr), iXPos, iYPos, iWidth, iHeight, 0, xw->depth, InputOutput, xw->visual, cw_mask, &attr ); XSync( xw->display, False ); if (!xw->window || error_code) { D_FREE( xw ); XUnlockDisplay( x11->display ); return False; } XSizeHints Hints; /* * Here we inform the function of what we are going to change for the * window (there's also PPosition but it's obsolete) */ Hints.flags = PSize | PMinSize | PMaxSize; /* * Now we set the structure to the values we need for width & height. * For esthetic reasons we set Width=MinWidth=MaxWidth. * The same goes for Height. You can try whith differents values, or * let's use Hints.flags=Psize; and resize your window.. */ Hints.min_width = Hints.max_width = Hints.base_width = xw->width; Hints.min_height = Hints.max_height = Hints.base_height = xw->height; /* Now we can set the size hints for the specified window */ XSetWMNormalHints(xw->display,xw->window,&Hints); /* We change the title of the window (default:Untitled) */ XStoreName(xw->display,xw->window,"DFB X11 system window"); xw->gc = XCreateGC(xw->display, xw->window, 0, NULL); #if 0 // Create a null cursor Pixmap pixmp1; Pixmap pixmp2; XColor fore; XColor back; char zero = 0; pixmp1 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); pixmp2 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); xw->NullCursor = XCreatePixmapCursor( xw->display, pixmp1, pixmp2, &fore, &back, 0, 0 ); XFreePixmap ( xw->display, pixmp1 ); XFreePixmap ( xw->display, pixmp2 ); XDefineCursor( xw->display, xw->window, xw->NullCursor ); #endif /* maps the window and raises it to the top of the stack */ XMapRaised( xw->display, xw->window ); if (x11->use_shm) { // Shared memory xw->shmseginfo=(XShmSegmentInfo *)D_CALLOC(1, sizeof(XShmSegmentInfo)); if (!xw->shmseginfo) { x11->use_shm = false; goto no_shm; } xw->ximage=XShmCreateImage(xw->display, xw->visual, xw->depth, ZPixmap, NULL,xw->shmseginfo, xw->width, xw->height * 2); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR("X11: Error creating shared image (XShmCreateImage) \n"); x11->use_shm = false; D_FREE(xw->shmseginfo); error_code = 0; goto no_shm; } xw->bpp = (xw->ximage->bits_per_pixel + 7) / 8; /* we firstly create our shared memory segment with the size we need, and correct permissions for the owner, the group and the world --> 0777 */ xw->shmseginfo->shmid=shmget(IPC_PRIVATE, xw->ximage->bytes_per_line * xw->ximage->height * 2, IPC_CREAT|0777); if (xw->shmseginfo->shmid<0) { x11->use_shm = false; XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* Then, we have to attach the segment to our process, and we let the function search the correct memory place --> NULL. It's safest ! */ xw->shmseginfo->shmaddr = shmat( xw->shmseginfo->shmid, NULL, 0 ); if (!xw->shmseginfo->shmaddr) { x11->use_shm = false; shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* We set the buffer in Read and Write mode */ xw->shmseginfo->readOnly=False; xw->virtualscreen= xw->ximage->data = xw->shmseginfo->shmaddr; XSetErrorHandler( error_handler_shm ); XShmAttach(x11->display,xw->shmseginfo); XShmPutImage(x11->display, xw->window, xw->gc, xw->ximage, 0, 0, 0, 0, 1, 1, False); XSync(x11->display, False); XSetErrorHandler( error_handler ); if (!x11->use_shm) { shmdt(xw->shmseginfo->shmaddr); shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); } } no_shm: if (!x11->use_shm) { int pitch; xw->bpp = (xw->depth > 16) ? 4 : (xw->depth > 8) ? 2 : 1; pitch = (xw->bpp * xw->width + 3) & ~3; /* Use malloc(), not D_MALLOC() here, because XCreateImage() * will call free() on this data. */ xw->virtualscreen = malloc ( 2 * xw->height * pitch ); xw->ximage = XCreateImage( xw->display, xw->visual, xw->depth, ZPixmap, 0, xw->virtualscreen, xw->width, xw->height * 2, 32, pitch ); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR( "X11/Window: XCreateImage( Visual %02lu, depth %d, size %dx%d, buffer %p [%d] ) failed!\n", xw->visual->visualid, xw->depth, xw->width, xw->height * 2, xw->virtualscreen, pitch ); XFreeGC(xw->display,xw->gc); XDestroyWindow(xw->display,xw->window); XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_FREE( xw ); return False; } } XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_INFO( "X11/Display: %ssing XShm.\n", x11->use_shm ? "U" : "Not u" ); (*ppXW) = xw; return True; } void dfb_x11_close_window( DFBX11 *x11, XWindow* xw ) { if (x11->use_shm) { XShmDetach( xw->display, xw->shmseginfo ); shmdt( xw->shmseginfo->shmaddr ); shmctl( xw->shmseginfo->shmid, IPC_RMID, NULL ); D_FREE( xw->shmseginfo ); } XDestroyImage( xw->ximage ); XFreeGC( xw->display, xw->gc ); XDestroyWindow( xw->display, xw->window ); #if 0 XFreeCursor( xw->display, xw->NullCursor ); #endif D_FREE( xw ); }
static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_VideoDisplay *display = window->display; X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } texture->driverdata = data; if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { data->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); if (!data->yuv) { return -1; } data->format = display->current_mode.format; } else { /* The image/pixmap depth must be the same as the window or you get a BadMatch error when trying to putimage or copyarea. */ if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; } data->format = texture->format; } data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask; if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY XShmSegmentInfo *shminfo = &data->shminfo; shm_error = True; if (SDL_X11_HAVE_SHM) { shminfo->shmid = shmget(IPC_PRIVATE, texture->h * data->pitch, IPC_CREAT | 0777); if (shminfo->shmid >= 0) { shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); shminfo->readOnly = False; if (shminfo->shmaddr != (char *) -1) { shm_error = False; X_handler = XSetErrorHandler(shm_errhandler); XShmAttach(renderdata->display, shminfo); XSync(renderdata->display, False); XSetErrorHandler(X_handler); if (shm_error) { shmdt(shminfo->shmaddr); } } shmctl(shminfo->shmid, IPC_RMID, NULL); } } if (!shm_error) { data->pixels = shminfo->shmaddr; data->image = XShmCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); if (!data->image) { XShmDetach(renderdata->display, shminfo); XSync(renderdata->display, False); shmdt(shminfo->shmaddr); shm_error = True; } } if (shm_error) { shminfo->shmaddr = NULL; } if (!data->image) #endif /* not NO_SHARED_MEMORY */ { data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { X11_DestroyTexture(renderer, texture); SDL_OutOfMemory(); return -1; } data->image = XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, data->pixels, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreateImage() failed"); return -1; } } } else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, texture->h, renderdata->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } data->image = XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, NULL, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreateImage() failed"); return -1; } } return 0; }
void *mlx_int_new_xshm_image(t_xvar *xvar,int width,int height,int format) { t_img *img; int (*save_handler)(); if (!(img = malloc(sizeof(*img)))) return ((void *)0); bzero(img,sizeof(*img)); img->data = 0; img->image = XShmCreateImage(xvar->display,xvar->visual,xvar->depth, format,img->data,&(img->shm),width,height); if (!img->image) { free(img); return ((void *)0); } img->width = width; img->height = height; img->size_line = img->image->bytes_per_line; img->bpp = img->image->bits_per_pixel; img->format = format; img->shm.shmid = shmget(IPC_PRIVATE,(width+32)*height*4,IPC_CREAT|0777); if (img->shm.shmid==-1) { XDestroyImage(img->image); free(img); return ((void *)0); } img->data = img->shm.shmaddr = img->image->data = shmat(img->shm.shmid,0,0); if (img->data==(void *)-1) { shmctl(img->shm.shmid,IPC_RMID,0); XDestroyImage(img->image); free(img); return ((void *)0); } img->shm.readOnly = False; mlx_X_error = 0; save_handler = XSetErrorHandler(shm_att_pb); if (!XShmAttach(xvar->display,&(img->shm)) || 0&XSync(xvar->display,False) || mlx_X_error) { XSetErrorHandler(save_handler); shmdt(img->data); shmctl(img->shm.shmid,IPC_RMID,0); XDestroyImage(img->image); free(img); return ((void *)0); } XSetErrorHandler(save_handler); shmctl(img->shm.shmid,IPC_RMID,0); if (xvar->pshm_format==format) { img->pix = XShmCreatePixmap(xvar->display,xvar->root,img->shm.shmaddr, &(img->shm),width,height,xvar->depth); img->type = MLX_TYPE_SHM_PIXMAP; } else { img->pix = XCreatePixmap(xvar->display,xvar->root, width,height,xvar->depth); img->type = MLX_TYPE_SHM; } if (xvar->do_flush) XFlush(xvar->display); return (img); }
void setup() { int i, j; struct config *c; XSetWindowAttributes wattr; XModifierKeymap *modmap; xerrorxlib = XSetErrorHandler(handle_xerror); dpy = XOpenDisplay(NULL); root = DefaultRootWindow(dpy); screen = DefaultScreen(dpy); visual = DefaultVisual(dpy, screen); cmap = DefaultColormap(dpy, screen); gc = DefaultGC(dpy, screen); sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); wattr.override_redirect = True; wattr.background_pixel = bgcol.pixel; wattr.border_pixel = fgcol.pixel; win = XCreateWindow(dpy, root, 0, 0, ww, wh, bw, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWBackPixel | CWBorderPixel, &wattr); /* Grab keys */ /* modifier stuff taken from evilwm */ modmap = XGetModifierMapping(dpy); for (i = 0; i < 8; i++) { for (j = 0; j < modmap->max_keypermod; j++) { if (modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) { numlockmask = (1 << i); } } } for(c=config; c; c=c->next) grabkey(c->mod, c->key); XSelectInput(dpy, root, KeyPressMask | SubstructureNotifyMask); XSelectInput(dpy, win, ButtonPressMask); setup_font(&fontbig, fontstrbig); setup_font(&fontsmall, fontstrsmall); getcolor(fgcolor, &fgcol); getcolor(bgcolor, &bgcol); getcolor(errcolor, &errcol); NetWMWindowOpacity = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False); if(opacity > 1.0 || opacity < 0.0) opacity = 0.0; unsigned long real_opacity[] = { opacity * 0xffffffff }; XChangeProperty(dpy, win, NetWMWindowOpacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)real_opacity, 1); draw = XftDrawCreate(dpy, win, visual, cmap); signal(SIGALRM, sigalrm); signal(SIGCHLD, sigchld); }
void KSMServer::performLegacySessionSave() { kdDebug( 1218 ) << "Saving legacy session apps" << endl; // Setup error handler legacyWindows.clear(); windowMapPtr = &legacyWindows; XErrorHandler oldHandler = XSetErrorHandler(winsErrorHandler); // Compute set of leader windows that need legacy session management // and determine which style (WM_COMMAND or WM_SAVE_YOURSELF) KWinModule module; if( wm_save_yourself == (Atom)None ) { Atom atoms[ 3 ]; const char* const names[] = { "WM_SAVE_YOURSELF", "WM_PROTOCOLS", "WM_CLIENT_LEADER" }; XInternAtoms( tqt_xdisplay(), const_cast< char** >( names ), 3, False, atoms ); wm_save_yourself = atoms[ 0 ]; wm_protocols = atoms[ 1 ]; wm_client_leader = atoms[ 2 ]; } for ( TQValueList<WId>::ConstIterator it = module.windows().begin(); it != module.windows().end(); ++it) { WId leader = windowWmClientLeader( *it ); if (!legacyWindows.contains(leader) && windowSessionId( *it, leader ).isEmpty()) { SMType wtype = SM_WMCOMMAND; int nprotocols = 0; Atom *protocols = 0; if( XGetWMProtocols(tqt_xdisplay(), leader, &protocols, &nprotocols)) { for (int i=0; i<nprotocols; i++) if (protocols[i] == wm_save_yourself) { wtype = SM_WMSAVEYOURSELF; break; } XFree((void*) protocols); } SMData data; data.type = wtype; XClassHint classHint; if( XGetClassHint( tqt_xdisplay(), leader, &classHint ) ) { data.wmclass1 = classHint.res_name; data.wmclass2 = classHint.res_class; XFree( classHint.res_name ); XFree( classHint.res_class ); } legacyWindows.insert(leader, data); } } // Open fresh display for sending WM_SAVE_YOURSELF XSync(tqt_xdisplay(), False); Display *newdisplay = XOpenDisplay(DisplayString(tqt_xdisplay())); if (!newdisplay) { windowMapPtr = NULL; XSetErrorHandler(oldHandler); return; } WId root = DefaultRootWindow(newdisplay); XGrabKeyboard(newdisplay, root, False, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(newdisplay, root, False, Button1Mask|Button2Mask|Button3Mask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); // Send WM_SAVE_YOURSELF messages XEvent ev; int awaiting_replies = 0; for (WindowMap::Iterator it = legacyWindows.begin(); it != legacyWindows.end(); ++it) { if ( (*it).type == SM_WMSAVEYOURSELF ) { WId w = it.key(); awaiting_replies += 1; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = wm_protocols; ev.xclient.format = 32; ev.xclient.data.l[0] = wm_save_yourself; ev.xclient.data.l[1] = GET_QT_X_TIME(); XSelectInput(newdisplay, w, PropertyChangeMask|StructureNotifyMask); XSendEvent(newdisplay, w, False, 0, &ev); } } // Wait for change in WM_COMMAND with timeout XFlush(newdisplay); TQTime start = TQTime::currentTime(); while (awaiting_replies > 0) { if (XPending(newdisplay)) { /* Process pending event */ XNextEvent(newdisplay, &ev); if ( ( ev.xany.type == UnmapNotify ) || ( ev.xany.type == PropertyNotify && ev.xproperty.atom == XA_WM_COMMAND ) ) { WindowMap::Iterator it = legacyWindows.find( ev.xany.window ); if ( it != legacyWindows.end() && (*it).type != SM_WMCOMMAND ) { awaiting_replies -= 1; if ( (*it).type != SM_ERROR ) (*it).type = SM_WMCOMMAND; } } } else { /* Check timeout */ int msecs = start.elapsed(); if (msecs >= WM_SAVE_YOURSELF_TIMEOUT) break; /* Wait for more events */ fd_set fds; FD_ZERO(&fds); int fd = ConnectionNumber(newdisplay); FD_SET(fd, &fds); struct timeval tmwait; tmwait.tv_sec = (WM_SAVE_YOURSELF_TIMEOUT - msecs) / 1000; tmwait.tv_usec = ((WM_SAVE_YOURSELF_TIMEOUT - msecs) % 1000) * 1000; ::select(fd+1, &fds, NULL, &fds, &tmwait); } } // Terminate work in new display XAllowEvents(newdisplay, ReplayPointer, CurrentTime); XAllowEvents(newdisplay, ReplayKeyboard, CurrentTime); XSync(newdisplay, False); XCloseDisplay(newdisplay); // Restore old error handler XSync(tqt_xdisplay(), False); XSetErrorHandler(oldHandler); for (WindowMap::Iterator it = legacyWindows.begin(); it != legacyWindows.end(); ++it) { if ( (*it).type != SM_ERROR) { WId w = it.key(); (*it).wmCommand = windowWmCommand(w); (*it).wmClientMachine = windowWmClientMachine(w); } } kdDebug( 1218 ) << "Done saving " << legacyWindows.count() << " legacy session apps" << endl; }
nsresult XRemoteClient::SendCommandInternal(const char *aProgram, const char *aUsername, const char *aProfile, const char *aCommand, PRInt32 argc, char **argv, const char* aDesktopStartupID, char **aResponse, bool *aWindowFound) { *aWindowFound = false; bool isCommandLine = !aCommand; // FindBestWindow() iterates down the window hierarchy, so catch X errors // when windows get destroyed before being accessed. sOldHandler = XSetErrorHandler(HandleBadWindow); Window w = FindBestWindow(aProgram, aUsername, aProfile, isCommandLine); nsresult rv = NS_OK; if (w) { // ok, let the caller know that we at least found a window. *aWindowFound = true; // Ignore BadWindow errors up to this point. The last request from // FindBestWindow() was a synchronous XGetWindowProperty(), so no need to // Sync. Leave the error handler installed to detect if w gets destroyed. sGotBadWindow = false; // make sure we get the right events on that window XSelectInput(mDisplay, w, (PropertyChangeMask|StructureNotifyMask)); bool destroyed = false; // get the lock on the window rv = GetLock(w, &destroyed); if (NS_SUCCEEDED(rv)) { // send our command if (isCommandLine) { rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse, &destroyed); } else { rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse, &destroyed); } // if the window was destroyed, don't bother trying to free the // lock. if (!destroyed) FreeLock(w); // doesn't really matter what this returns } } XSetErrorHandler(sOldHandler); PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("SendCommandInternal returning 0x%x\n", rv)); return rv; }
int windowed_worker(int argc, char *argv[], fwin_entrypoint *fwin_main) { fwin_main1 = fwin_main; #ifdef WIN32 // The following is somewhat unsatisfactory so I will explain my options and // what is happening. // On Unix/Linux/Darwin etc I have here a single executable that, depending // on a command-line flag, runs either as a windowed or a command-line // program. All is pretty neat and convenient for me! However... // // On Windows when I link code I can link it either as subsystem:windows or // as subsystem:console. If I use the windows case then it detaches from // its console when started. The effect I have is that when launched from // a Windows command prompt asking to be run in console mode it can not // access the console. Windows XP provides an AttachConsole API that might // let me re-attach to the console but (a) that is not available with // earlier versions of Windows and (b) my experimenst with it have not been // great successes and others report delicacies! However note that even if // the code is linked as a windows binary it can be launched from the cygwin // shell and inherits standard input and output very happily! But from a // regular Windows command shell it does not. // If, on the other hand I link my code as a console application then when // launched from a command prompt or a script things work as I might like // and expect. When launched by double-clicking on an icon, Windows says to // itself "aha - a console application" and rapidly creates a console for it. // This pops up on your screen. But here (in the case I wanted a Windowed // interface) I just free that console, which then has no other users and // which therefore gets destroyed. So there is a visual glitch of an unwanted // console window popping up and instantly vanishing. // // The best solution that appears to be open to me under Windows is to // have two executable versions for each application. They would only need // to differ in the way they were linked (and hence, possibly, by one bit in // a header record in them!). One for console and one for windowed use. // That feels clumsy too. // // Web searches show that others have found the same sort of pain when they // have wanted to create applications that are both console and window // mode. Ah well. One final suggestion for the two-executable scheme is // to creats two executables, say cslw.exe and cslc.exe where cslw.exe is // linked in windows mode and cslc.exe in console mode. cslc.exe just // creates a process to run cslw.exe. When you do this the handles on // standard input and output can be inherited by the child process, which // can therefore read and write characters. However because it still does not // really have a CONSOLE it can not do the res of what one might like by way // of supporting curses-like screen updates. A final trick on this is to // rename those two programs as csl.exe (windowed) and csl.com (console). // The Windows command processor will use the ".com" extension before the // ".exe" one, but of course the executable is really in ".exe" format... // this trick maybe reduces the confusion over file-names! Or maybe it // makes it worse. #ifdef KEEP_CONSOLE_OPEN // I sometimes find a console REALLY useful for debugging.... but when you // launch by double-clicking on an icon it is truly ugly to have one around. // So I will allow myself to leave an "#ifdef" here in case that helps me make // a trick version for debugging... FreeConsole(); #endif #endif #define COMPANY_NAME "Codemist-Ltd" #define PRODUCT_NAME programName #define WINDOW_NAME programName // registry entries will be filed under Codemist-Ltd/<something>. application_object = new FXApp(PRODUCT_NAME, COMPANY_NAME); // args can be sent in via command-line args, if that is any help. // Just at present I do not fully understand what FOX does with these // arguments but it MAY be that it expects to allow "-geometry" or "-fn" // etc arguments as per standard for X11 applications. application_object->init(argc, argv, TRUE); #ifndef WIN32 debug_option = 0; for (int i=1; i<argc; i++) { if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-G") == 0) debug_option = 1; } /* * By default if there are any X protocol error (eg relating to missing * fonts) X send a message to stdout reporting. Unless I am in debug mode * there can be an unwanted distraction so I will hide them. If however * I am in debug mode I will set the X protocol to run in synchronous * mode, which will slow it down but make debugging easier. I believe I have * to set these options after X has been initialised and I want to do it as * soon as possible after that, hence this bit of decoding of command-line * options is separated from the main chunk. */ if (debug_option) _Xdebug = 1; else XSetErrorHandler(IgnoreXError); #endif FXRootWindow *r = application_object->getRootWindow(); rootWidth = r->getDefaultWidth(), rootHeight = r->getDefaultHeight(); // Now I will decide how big the main window should be. If I have information // in the registry left over from my last run I will use that. FXRegistry *reg = &application_object->reg(); int screenx = reg->readIntEntry("screen", "screenx", -1); int screeny = reg->readIntEntry("screen", "screeny", -1); int screenw = reg->readIntEntry("screen", "screenw", -1); int screenh = reg->readIntEntry("screen", "screenh", -1); if (screenx < 0 || screeny < 0 || screenw <= 100 || screenh < 20) { screenx = screeny = 50; // When I had 0 here that was off the screen! screenw = 0; screenh = (2*rootHeight)/3; } int fontsize = reg->readIntEntry("screen", "fontsize", -1); #if (FOX_MINOR<=4) int fontweight = reg->readIntEntry("screen", "fontweight", FONTWEIGHT_BOLD); int fontslant = reg->readIntEntry("screen", "fontslant", FONTSLANT_REGULAR); int fontencoding = reg->readIntEntry("screen", "fontencoding", FONTENCODING_DEFAULT); int fontsetwidth = reg->readIntEntry("screen", "fontsetwidth", FONTSETWIDTH_DONTCARE); int fonthints = reg->readIntEntry("screen", "fonthints", FONTPITCH_FIXED|FONTHINT_MODERN); #else int fontweight = reg->readIntEntry("screen", "fontweight", FXFont::Bold); int fontslant = reg->readIntEntry("screen", "fontslant", FXFont::Straight); int fontencoding = reg->readIntEntry("screen", "fontencoding", FONTENCODING_DEFAULT); int fontsetwidth = reg->readIntEntry("screen", "fontsetwidth", FXFont::NonExpanded); int fonthints = reg->readIntEntry("screen", "fonthints", FXFont::Fixed|FXFont::Modern); #endif const char *fontname = reg->readStringEntry("screen", "fontname", DEFAULT_FONT_NAME); // I have a concern here about how long the string that is returned will // remain valid. As a matter of caution I will not read other string values // from the registry until I have used or copied this. // The icon that I use here depends on the name that this program is // launched with. This situation in perhaps not perfect but it seems the // easiest route just for now. const unsigned char *icondata = fwin; // This sets alternative custom icons based on the name of the executable // and it clearly NOT portable... however I find it helpful, and it should // not impact anybody who wants to make independent use of this library. if (strcmp(programName, "csl") == 0) icondata = csl; else if (strcmp(programName, "bootstrapreduce") == 0) icondata = csl; else if (strcmp(programName, "reduce") == 0) icondata = reduce; main_window = new FXMainWindow1( application_object, WINDOW_NAME, new FXICOIcon(application_object, icondata, FXRGB(255,255,255), IMAGE_ALPHAGUESS), NULL, // mini-icon DECOR_ALL, screenx, screeny, screenw, screenh); main_menu_bar = new FXMenuBar(main_window, LAYOUT_SIDE_TOP | LAYOUT_FILL_X); // NB. NB. NB. // *NB* the TEXT_COLUMNWRAP flag is my own PATCH to FOX, and when I build // FOX I change the files FXText.h and FXText.cpp to implement it. It // lets me wrap lines at exactly 80 columns, regardless of how whitespace // happens to lie. text = new FXTerminal(main_window, NULL, 0, HSCROLLER_NEVER | TEXT_FIXEDWRAP | TEXT_WORDWRAP | TEXT_COLUMNWRAP | TEXT_SHOWACTIVE | LAYOUT_FILL_X | LAYOUT_FILL_Y); // I am really supposed to destroy menus as I exit. So somewhere I need to // arrange that - or maybe I can hope that my application only closes its // window when finally terminating, and somebody will tidy up at a system // level for me. fileMenu = new FXMenuPane(main_window); new FXMenuCommand(fileMenu, "&Read...", NULL, (FXObject *)text, FXTerminal::ID_READ); new FXMenuCommand(fileMenu, "&Save...", NULL, (FXObject *)text, FXTerminal::ID_SAVE); new FXMenuCommand(fileMenu, "Save Se&lection...", NULL, (FXObject *)text, FXTerminal::ID_SAVE_SELECTION); new FXMenuCommand(fileMenu, "&Print...", NULL, (FXObject *)text, FXTerminal::ID_PRINT); new FXMenuCommand(fileMenu, "Pri&nt Selection...", NULL, (FXObject *)text, FXTerminal::ID_PRINT_SELECTION); new FXMenuCommand(fileMenu, "&Break\tCtl-C\tInterrupt", NULL, (FXObject *)text, FXTerminal::ID_BREAK); new FXMenuCommand(fileMenu, "Bac&ktrace\tCtl-G\tInterrupt/backtrace", NULL, (FXObject *)text, FXTerminal::ID_BACKTRACE); new FXMenuCommand(fileMenu, "&Pause\tCtl-S", NULL, (FXObject *)text, FXTerminal::ID_PAUSE); new FXMenuCommand(fileMenu, "&Resume\tCtl-Q", NULL, (FXObject *)text, FXTerminal::ID_RESUME); new FXMenuCommand(fileMenu, "&Stop/Go\tCtl-Z", NULL, (FXObject *)text, FXTerminal::ID_STOP); new FXMenuCommand(fileMenu, "&Discard Output\tCtl-O", NULL, (FXObject *)text, FXTerminal::ID_DISCARD); new FXMenuCommand(fileMenu, "&Quit\tCtl-\\\tQuit the application.", NULL, application_object, FXApp::ID_QUIT); // I make this F&ile not &File since alt-F will be for "move forward one // word" using emacs-like key bindings. new FXMenuTitle(main_menu_bar, "F&ile", NULL, fileMenu); editMenu = new FXMenuPane(main_window); new FXMenuCommand(editMenu, "&Cut", NULL, (FXObject *)text, FXTerminal::ID_CUT_SEL_X); new FXMenuCommand(editMenu, "C&opy", NULL, (FXObject *)text, FXTerminal::ID_COPY_SEL_X); new FXMenuCommand(editMenu, "Copy &Text", NULL, (FXObject *)text, FXTerminal::ID_COPY_SEL_TEXT_X); new FXMenuCommand(editMenu, "&Paste\tCtl-V", NULL, (FXObject *)text, FXTerminal::ID_PASTE_SEL_X); new FXMenuCommand(editMenu, "&Reinput\tCtl-^\tReinput", NULL, (FXObject *)text, FXTerminal::ID_REINPUT); new FXMenuCommand(editMenu, "Select &All", NULL, (FXObject *)text, FXText::ID_SELECT_ALL); new FXMenuCommand(editMenu, "C&lear\tCtl-L", NULL, (FXObject *)text, FXTerminal::ID_CLEAR); new FXMenuCommand(editMenu, "Re&draw\tCtl-R", NULL, (FXObject *)text, FXTerminal::ID_REDRAW); new FXMenuCommand(editMenu, "&Home", NULL, (FXObject *)text, FXTerminal::ID_HOME); new FXMenuCommand(editMenu, "&End", NULL, (FXObject *)text, FXTerminal::ID_END); new FXMenuCommand(editMenu, "&Font...", NULL, (FXObject *)text, FXTerminal::ID_FONT); new FXMenuCommand(editMenu, "&Reset Font", NULL, (FXObject *)text, FXTerminal::ID_RESET_FONT); new FXMenuCommand(editMenu, "Reset &Window", NULL, (FXObject *)text, FXTerminal::ID_RESET_WINDOW); new FXMenuTitle(main_menu_bar, "&Edit", NULL, editMenu); // Add the special Reduce menus... { const char **red = reduceMenus, *p; char curTop[32], topName[32], subName[64], *q; curTop[0] = 0; reduceMenu = NULL; while (*red != NULL) { p = *red++; //@@ printf("p=%s\n", p); q = topName; while (*p != '@') *q++ = *p++; *q = 0; p++; q = subName; while (*p != '@') *q++ = *p++; *q = 0; //@@ printf("%s : %s\n", topName, subName); // Do I now have a new top-level menu name? if (strcmp(topName, curTop) != 0) { if (reduceMenu != NULL) { new FXMenuTitle(main_menu_bar, curTop, NULL, reduceMenu); //@@ printf("put %s at top\n", curTop); } reduceMenu = new FXMenuPane(main_window); strcpy(curTop, topName); //@@ printf("create new sub-menu for %s\n", curTop); } // Add a sub-menu item //@@ printf("Add in %s\n", subName); new FXMenuCommand(reduceMenu, subName, NULL, (FXObject *)text, FXTerminal::ID_REDUCE); } // The final top-level menu now needs setting up. //@@ printf("final top level item is %s\n", curTop); new FXMenuTitle(main_menu_bar, curTop, NULL, reduceMenu); } //@@ printf("Menus should be OK now\n"); helpMenu = new FXMenuPane(main_window); new FXMenuCommand(helpMenu, "&Help\tF1\tHelp", NULL, (FXObject *)text, FXTerminal::ID_HELP); #ifndef WIN32 #if !defined MACINTOSH || !defined MAC_FRAMEWORK new FXMenuCommand(helpMenu, "&Select Browser\t\tSelect Browser", NULL, (FXObject *)text, FXTerminal::ID_BROWSER); #endif #endif new FXMenuCommand(helpMenu, "&About\t\tAbout", NULL, (FXObject *)text, FXTerminal::ID_ABOUT); new FXMenuTitle(main_menu_bar, "Help", NULL, helpMenu, LAYOUT_RIGHT); text->setEditable(FALSE); text->setStyled(TRUE); text->argc = argc; text->argv = argv; strcpy(mid_stuff, programName); main_window->setTitle(programName); application_object->create(); // Selecting the font may involve measuring font sizes etc which may // need the font creating... FXFont *font1 = selectFont(fontname, fontsize, fontweight, fontslant, fontencoding, fontsetwidth, fonthints); font1->create(); text->setFont(font1); if (screenw == 0) text->onCmdResetWindow(NULL, 0, NULL); // // I will iconify the window AFTER I have adjusted its size since I do not // want to end up with a size that is silly and based on just an icon! // Also somewhere (and I now do not remember where) I picked up the idea // that minimizing twice over was a good idea... // if (windowed < 0) { main_window->minimize(); main_window->minimize(); } text->setupShowMath(); main_window->show(); text->onCmdHome(NULL, 0, NULL); // actually just to grab the focus! #ifdef WIN32 DWORD threadId; thread1 = CreateThread(NULL, // security attributes 0, // stack size worker_thread, (void *)text, 0, // flags &threadId); // Essential for Me/98/95 if (thread1 == NULL) { fprintf(stderr, "Fatal error attempting to create a thread\n"); application_object->exit(1); exit(1); } #else if (pthread_create(&thread1, NULL, worker_thread, (void *)text)) { fprintf(stderr, "Fatal error attempting to create a thread\n"); application_object->exit(1); exit(1); } #endif // Once a second I will try to flush any output buffers. But do not start // that until everything else is more or less going! application_object->addTimeout((FXObject *)text, FXTerminal::ID_TIMEOUT, 1000, NULL); if (windowed >= 0) main_window->raise(); // Bring to top. return application_object->run(); }
int main ( int argc, char** argv ) { dp = XOpenDisplay ( NULL ); int scr = DefaultScreen ( dp ); Window root = RootWindow ( dp, scr ); XEvent event; cfg_rule* rule; char* name; signal(SIGINT, SIGINT_handler); signal(SIGHUP, SIGHUP_handler); parse_options ( argc, argv ); char* configfile = (char*) malloc ( strlen ( getenv("HOME") ) + strlen ("/.transd") + 1 ); *configfile = '\0'; DEBUG(1, "configfile: %s\n", configfile ); DEBUG(1, "configfile: %s\n", configfile ); if ( cfg_parse_config_file ( configfile ) == -1 ) { DEBUG(1, "User-based config-file %s/transd.conf not found!\n", configfile); DEBUG(1, "Using global configuration file /etc/transd/transd.conf\n"); if ( cfg_parse_config_file ( "/etc/transd" ) == -1 ) { printf("Error: Could not find any config file! Exiting...\n"); return(1); } } free ( configfile ); XSetErrorHandler ( XmuSimpleErrorHandler ); /* select window-enter/-leave events from all currently existing windows */ walkWindowTree ( root, selectInput, NULL ); DEBUG(1, "got %d initial windows in list\n", slist_size(window_list)); /* select substructure events from root window (so we can keep track of new windows) */ XSelectInput ( dp, root, SubstructureNotifyMask | EnterWindowMask ); for (;;) { XNextEvent ( dp, &event ); switch ( event.type ) { case CreateNotify: DEBUG(5, "CreateNotify for 0x%x\n", event.xcreatewindow.window); selectInput ( event.xcreatewindow.window, NULL ); break; case EnterNotify: DEBUG(5, "EnterNotify for 0x%x (detail %d)\n", event.xcrossing.window, event.xcrossing.detail); rule = cfg_get_rule ( dp, event.xcrossing.window, "Enter" ); if ( rule != NULL ) { DEBUG(5, "got rule for 0x%x\n", event.xcrossing.window); if ( !strcmp ( rule->action.property, "__TRANSD_SELF" ) ) { Window dummy, parent, *children; unsigned int n; XQueryTree ( dp, event.xcrossing.window, &dummy, &parent, &children, &n ); setOpacity ( parent, rule->action.opacity ); } else walkWindowList ( executeRule, rule ); /* check whether this Enter-rule has reverted the cached Leave-rule */ if ( cached_rule != NULL ) { Window dummy, parent, *children; unsigned int n; DEBUG(4, "SMART: A1. found cached rule for 0x%x\n", cached_window); XQueryTree ( dp, cached_window, &dummy, &parent, &children, &n ); DEBUG(4, "Opacity matching: 0x%x == 0x%x ?\n", getOpacity(parent, 0), rule->action.opacity ); if ( getOpacity(parent, 0) == rule->action.opacity ) { DEBUG(4,"SMART: A2. opac matching\n"); if ( cfg_check_property ( dp, cached_window, rule->action.property, rule->action.value ) ) { DEBUG(4,"SMART: A3. rule was not reverted, executing...\n"); /* left window is not affected by this rule, execute cached rule */ if ( !strcmp ( cached_rule->action.property, "__TRANSD_SELF" ) ) { setOpacity ( parent, cached_rule->action.opacity ); } else walkWindowList ( executeRule, rule ); cached_rule = NULL; } } } } else if ( event.xcrossing.detail != 4 ) { DEBUG(5, "no rule for 0x%x\n", event.xcrossing.window); /* execute cached rule */ if ( cached_rule != NULL ) { DEBUG(5, "SMART: B1. found cached rule for 0x%x\n", cached_window); if ( !strcmp ( cached_rule->action.property, "__TRANSD_SELF" ) ) { Window dummy, parent, *children; unsigned int n; XQueryTree ( dp, cached_window, &dummy, &parent, &children, &n ); setOpacity ( parent, cached_rule->action.opacity ); } else walkWindowList ( executeRule, cached_rule ); cached_rule = NULL; } } break; case LeaveNotify: DEBUG(5, "LeaveNotify for 0x%x (detail %d)\n", event.xcrossing.window, event.xcrossing.detail); if ( event.xcrossing.detail != 2 ) { rule = cfg_get_rule ( dp, event.xcrossing.window, "Leave" ); if ( rule != NULL ) { DEBUG(5, "got rule for 0x%x\n", event.xcrossing.window); /* cache rule and current opacity */ DEBUG(5, "caching rule for 0x%x\n", event.xcrossing.window); cached_rule = rule; cached_window = event.xcrossing.window; } else { DEBUG(5, "no rule for 0x%x\n", event.xcrossing.window); } } break; case VisibilityNotify: DEBUG(5, "VisibilityNotify for 0x%x (state %d)\n", event.xvisibility.window, event.xvisibility.state); switch ( event.xvisibility.state ) { case VisibilityFullyObscured: DEBUG(5, "Removing 0x%x from our list\n", event.xvisibility.window); removeWindowFromList ( event.xvisibility.window ); DEBUG(1, "got %d windows in list now\n", slist_size(window_list)); break; default: DEBUG(5, "Adding 0x%x to our list\n", event.xvisibility.window); selectInput( event.xvisibility.window, NULL ); DEBUG(1, "got %d windows in list now\n", slist_size(window_list)); } break; case DestroyNotify: DEBUG(5, "DestroyNotify for 0x%x (state %d)\n", event.xdestroywindow.window); DEBUG(5, "Removing 0x%x from our list\n", event.xdestroywindow.window); removeWindowFromList ( event.xdestroywindow.window ); break; } } return(0); }
static int vigs_device_init(PCIDevice *dev) { VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev); struct vigs_backend *backend = NULL; XSetErrorHandler(x_error_handler); XInitThreads(); vigs_display = XOpenDisplay(0); if (!vigs_display) { fprintf(stderr, "Cannot open X display\n"); exit(1); } vigs_render_queue = work_queue_create("render_queue"); vigs_log_init(); if (s->vram_size < 16 * 1024 * 1024) { VIGS_LOG_WARN("\"vram_size\" is too small, defaulting to 16mb"); s->vram_size = 16 * 1024 * 1024; } if (s->ram_size < 1 * 1024 * 1024) { VIGS_LOG_WARN("\"ram_size\" is too small, defaulting to 1mb"); s->ram_size = 1 * 1024 * 1024; } pci_config_set_interrupt_pin(dev->config, 1); memory_region_init_ram(&s->vram_bar, OBJECT(s), TYPE_VIGS_DEVICE ".vram", s->vram_size); memory_region_init_ram(&s->ram_bar, OBJECT(s), TYPE_VIGS_DEVICE ".ram", s->ram_size); memory_region_init_io(&s->io_bar, OBJECT(s), &vigs_io_ops, s, TYPE_VIGS_DEVICE ".io", VIGS_IO_SIZE); pci_register_bar(&s->dev.pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar); pci_register_bar(&s->dev.pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar); pci_register_bar(&s->dev.pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar); backend = vigs_gl_backend_create(vigs_display); if (!backend) { goto fail; } s->fenceman = vigs_fenceman_create(); s->fence_ack_bh = qemu_bh_new(vigs_fence_ack_bh, s); s->con = graphic_console_init(DEVICE(dev), 0, &vigs_hw_ops, s); if (!s->con) { goto fail; } s->server = vigs_server_create(memory_region_get_ram_ptr(&s->vram_bar), memory_region_get_ram_ptr(&s->ram_bar), &vigs_dpy_ops, s, backend, vigs_render_queue); if (!s->server) { goto fail; } vigs_wsi = s->dev.wsi = &s->server->wsi; VIGS_LOG_INFO("VIGS initialized"); VIGS_LOG_DEBUG("vram_size = %u", s->vram_size); VIGS_LOG_DEBUG("ram_size = %u", s->ram_size); return 0; fail: if (backend) { backend->destroy(backend); } if (s->fence_ack_bh) { qemu_bh_delete(s->fence_ack_bh); } if (s->fenceman) { vigs_fenceman_destroy(s->fenceman); } memory_region_destroy(&s->io_bar); memory_region_destroy(&s->ram_bar); memory_region_destroy(&s->vram_bar); vigs_log_cleanup(); return -1; }
// Sets the X error handler callback // void _glfwGrabErrorHandlerX11(void) { _glfw.x11.errorCode = Success; XSetErrorHandler(errorHandler); }
static Error init_memory_visual (struct dispinfo *d) { int x, y; int w, h; int border; XSizeHints hint; Colormap colors; XColor shade; XColor exact; XGCValues val; long flags; if ((d->disp = open_memory_visual_display ()) == (Display *) NULL) return ERROR; d->fd = ConnectionNumber(d->disp); x = 0; /* default to opening window in upper left */ y = 0; w = d->win_width; h = d->win_height; border = BORDER; hint.x = x; hint.y = y; hint.width = w; hint.height = h; hint.min_width = w; hint.min_height = h; hint.max_width = w; hint.max_height = h; hint.flags = PPosition | PSize | USPosition | USSize; d->wind = XCreateSimpleWindow (d->disp, DefaultRootWindow (d->disp), x, y, w, h, border, WhitePixel (d->disp, DefaultScreen (d->disp)), BlackPixel (d->disp, DefaultScreen (d->disp))); XSetStandardProperties (d->disp, d->wind, d->title, d->title, None, NULL, 0, &hint); XSelectInput(d->disp, d->wind, ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask); /* * Now get the pixel values for the colormaps and create the GCs */ val.background = BlackPixel (d->disp, DefaultScreen (d->disp)); flags = GCForeground | GCBackground; colors = DefaultColormap (d->disp, DefaultScreen (d->disp)); d->gc = XCreateGC (d->disp, d->wind, flags, &val); XAllocNamedColor (d->disp, colors, COLOR_ALLOC, &shade, &exact); color_alloc = (ubyte) shade.pixel; XAllocNamedColor (d->disp, colors, COLOR_SMALLOC, &shade, &exact); color_smallalloc = (ubyte) shade.pixel; XAllocNamedColor (d->disp, colors, COLOR_FREE, &shade, &exact); color_free = (ubyte) shade.pixel; XAllocNamedColor (d->disp, colors, COLOR_TRACE, &shade, &exact); color_trace = (ubyte) shade.pixel; XAllocNamedColor (d->disp, colors, COLOR_EXTRA, &shade, &exact); color_extra = (ubyte) shade.pixel; d->memory_pixel = (ubyte *) DXAllocate(w * h); memset (d->memory_pixel, color_free, w * h); d->memory_image = XCreateImage (d->disp, XDefaultVisual (d->disp, XDefaultScreen (d->disp)), 8, ZPixmap, 0, (char *) d->memory_pixel, w, h, 8, 0); XSetErrorHandler(error_handler); /* refresh image once */ d->refresh = 1; if (!handler_script(d->fd, d)) goto error; /* arrange for it to appear, and appear on top */ XMapRaised(d->disp, d->wind); XFlush(d->disp); /* register with executive to get X events */ DXRegisterInputHandlerWithCheckProc( (Handler)handler_script, (Checker)XChecker, d->fd, (Pointer)d); if (xerror) goto error; return OK; error: xerror = 0; return ERROR; }
static void trap_errors() { xerror = 0; old_handler = XSetErrorHandler(xmerrhandler); }
//======================================== // main... //---------------------------------------- int main (int argc, char*argv[]) { XF86MiscMouseSettings mseinfo; Display* dpy; int c; int DEBUG = False; int show = False; int Version = False; int apply = False; int enable = False; int disable = False; int major = 0; int minor = 0; char link [256] = ""; char mydisp [256] = ""; char option [256] = ""; char left [256] = ""; struct mouse *pointer; struct devnode *dev; struct stat *linkstatus = NULL; pointer = (struct mouse*) malloc(sizeof(struct mouse)); dev = (struct devnode*) malloc(sizeof(struct devnode)); // get commandline options... //----------------------------- while (1) { int option_index = 0; static struct option long_options[] = { {"show" , 0 , 0 , 's'}, {"apply" , 1 , 0 , 'a'}, {"display" , 1 , 0 , 'd'}, {"help" , 0 , 0 , 'h'}, {"link" , 1 , 0 , 'l'}, {"enable" , 0 , 0 , 'E'}, {"disable" , 0 , 0 , 'D'}, {"version" , 0 , 0 , 'v'}, {"config" , 0 , 0 , 'c'}, {0 , 0 , 0 , 0 } }; c = getopt_long (argc, argv, "hsa:d:l:EDvc",long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (DEBUG) { fprintf (stderr,"option %s", long_options[option_index].name); if (optarg) fprintf (stderr," with arg %s", optarg); fprintf (stderr,"\n"); } break; case 'h': usage(); break; case 'c': showConfig(); break; case 's': show = True; break; case 'v': Version = True; break; case 'a': if (! IsRoot()) { fprintf(stderr,"xmset: only root can do this\n"); exit(1); } apply = True; strcpy(option,optarg); break; case 'l': // no longer used because we will get the // the device name (which may be a link) from the X-Server // and check if it is realy a link to the pointer device. // If not, no symlink is created after apply // --- // strcpy(link,optarg); break; case 'd': strcpy(mydisp,optarg); break; case 'E': if (! IsRoot()) { fprintf(stderr,"xmset: only root can do this\n"); exit(1); } enable = True; break; case 'D': if (! IsRoot()) { fprintf(stderr,"xmset: only root can do this\n"); exit(1); } disable = True; break; default: exit(1); } } // ... // open display... // --- if (strcmp(mydisp,"") == 0) { strcpy(mydisp,"null"); } dpy = XOpen(mydisp); if (dpy == NULL) { if (Version) { printf("0:6\n"); } else { fprintf(stderr,"xmset: could not open display\n"); } exit(1); } if (Version) { if (XF86MiscQueryVersion(dpy,&major,&minor)) { printf("%d:%d\n",major,minor); exit (0); } } // ... // store link name if the device specification // of the current configuration is a link // --- if (!XF86MiscGetMouseSettings(dpy, &mseinfo)) { fprintf(stderr,"xmset: could not get mouse settings\n"); exit(1); } if (apply == True) { linkstatus = (struct stat*)malloc(sizeof(struct stat)); lstat (mseinfo.device,linkstatus); if (S_ISLNK (linkstatus->st_mode)) { strcpy (link,mseinfo.device); } } //================================= // enable mouse //--------------------------------- if (enable == True) { XF86MiscMouseSettings mseinfo; if (!XF86MiscGetMouseSettings(dpy, &mseinfo)) { exit(1); } mseinfo.flags |= MF_REOPEN; XSetErrorHandler (catchErrors); XF86MiscSetMouseSettings(dpy, &mseinfo); XSync(dpy, False); exit(0); } //================================= // disable mouse //--------------------------------- if (disable == True) { XF86MiscMouseSettings mseinfo; if (!XF86MiscGetMouseSettings(dpy, &mseinfo)) { exit(1); } mseinfo.flags |= MF_REOPEN; mseinfo.device = "/dev/unused"; XSetErrorHandler (catchErrors); XF86MiscSetMouseSettings(dpy, &mseinfo); XSync(dpy, False); exit(0); } //================================== // apply mouse settings //---------------------------------- if (apply == True) { XF86MiscMouseSettings mseinfo; strsplit (option,':',left,option); strcpy (pointer->device,left); strsplit (option,':',left,option); strcpy (pointer->type,left); strsplit (option,':',left,option); pointer->baudrate = atoi(left); strsplit (option,':',left,option); pointer->samplerate = atoi(left); strsplit (option,':',left,option); pointer->resolution = atoi(left); strsplit (option,':',left,option); pointer->buttons = atoi(left); strsplit (option,':',left,option); if (strcmp(left,"on") == 0) { strcpy(pointer->emu3button,"on"); } else { strcpy(pointer->emu3button,"off"); } strsplit(option,':',left,option); pointer->emu3timeout = atoi(left); strsplit(option,':',left,option); if (strcmp(left,"on") == 0) { strcpy(pointer->chordmiddle,"on"); } else { strcpy(pointer->chordmiddle,"off"); } strsplit (option,':',left,option); strcpy (pointer->flag,left); // ... // relink the /dev/sax link if the configuration // use a device link to point to the input device // --- if (S_ISLNK (linkstatus->st_mode)) { remove (link); symlink (pointer->device,link); } // ... // remove mouse from currently // accessed device // --- if (!XF86MiscGetMouseSettings(dpy, &mseinfo)) { exit(1); } mseinfo.flags |= MF_REOPEN; sprintf(mseinfo.device,"disabled"); XSetErrorHandler (catchErrors); XF86MiscSetMouseSettings(dpy, &mseinfo); XSync(dpy, False); // ... // set new mouse parameters... // --- usleep (1000); SetMouse (dpy,pointer); } //================================== // show current mouse settings //---------------------------------- if (show == True) { GetMouse(dpy); } return(0); }
int fbx_init(fbx_struct *fb, fbx_wh wh, int width_, int height_, int useShm) { int width, height; int rmask, gmask, bmask, ps, i; #ifdef _WIN32 BMINFO bminfo; HBITMAP hmembmp=0; RECT rect; HDC hdc=NULL; #else XWindowAttributes xwa; int shmok=1, alphaFirst, pixmap=0; #endif if(!fb) _throw("Invalid argument"); #ifdef _WIN32 if(!wh) _throw("Invalid argument"); _w32(GetClientRect(wh, &rect)); if(width_>0) width=width_; else { width=rect.right-rect.left; if(width<=0) width=MINWIDTH; } if(height_>0) height=height_; else { height=rect.bottom-rect.top; if(height<=0) height=MINHEIGHT; } if(fb->wh==wh) { if(width==fb->width && height==fb->height && fb->hmdc && fb->hdib && fb->bits) return 0; else if(fbx_term(fb)==-1) return -1; } memset(fb, 0, sizeof(fbx_struct)); fb->wh=wh; _w32(hdc=GetDC(fb->wh)); _w32(fb->hmdc=CreateCompatibleDC(hdc)); _w32(hmembmp=CreateCompatibleBitmap(hdc, width, height)); _w32(GetDeviceCaps(hdc, RASTERCAPS)&RC_BITBLT); _w32(GetDeviceCaps(fb->hmdc, RASTERCAPS)&RC_DI_BITMAP); bminfo.bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bminfo.bmi.bmiHeader.biBitCount=0; _w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS)); _w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS)); _w32(DeleteObject(hmembmp)); hmembmp=0; /* (we only needed it to get the screen properties) */ ps=bminfo.bmi.bmiHeader.biBitCount/8; if(width>0) bminfo.bmi.bmiHeader.biWidth=width; if(height>0) bminfo.bmi.bmiHeader.biHeight=height; fb->width=bminfo.bmi.bmiHeader.biWidth; fb->height=bminfo.bmi.bmiHeader.biHeight; if(ps<3) { /* Make the buffer BGRA */ bminfo.bmi.bmiHeader.biCompression=BI_BITFIELDS; bminfo.bmi.bmiHeader.biBitCount=32; ps=4; (*(DWORD *)&bminfo.bmi.bmiColors[0])=0xFF0000; (*(DWORD *)&bminfo.bmi.bmiColors[1])=0xFF00; (*(DWORD *)&bminfo.bmi.bmiColors[2])=0xFF; } fb->pitch=BMPPAD(fb->width*ps); /* Windoze bitmaps are always padded */ if(bminfo.bmi.bmiHeader.biCompression==BI_BITFIELDS) { rmask=(*(DWORD *)&bminfo.bmi.bmiColors[0]); gmask=(*(DWORD *)&bminfo.bmi.bmiColors[1]); bmask=(*(DWORD *)&bminfo.bmi.bmiColors[2]); } else { rmask=0xFF0000; gmask=0xFF00; bmask=0xFF; } fb->format=-1; for(i=0; i<FBX_FORMATS; i++) if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i] && ps==fbx_ps[i] && fbx_alphafirst[i]==0) fb->format=i; if(fb->format==-1) _throw("Display has unsupported pixel format"); bminfo.bmi.bmiHeader.biHeight=-bminfo.bmi.bmiHeader.biHeight; /* (our convention is top-down) */ _w32(fb->hdib=CreateDIBSection(hdc, &bminfo.bmi, DIB_RGB_COLORS, (void **)&fb->bits, NULL, 0)); _w32(SelectObject(fb->hmdc, fb->hdib)); ReleaseDC(fb->wh, hdc); return 0; finally: if(hmembmp) DeleteObject(hmembmp); if(hdc) ReleaseDC(fb->wh, hdc); #else if(!wh.dpy || !wh.d) _throw("Invalid argument"); if(wh.v) { _x11(XGetGeometry(wh.dpy, wh.d, &xwa.root, &xwa.x, &xwa.y, (unsigned int *)&xwa.width, (unsigned int *)&xwa.height, (unsigned int *)&xwa.border_width, (unsigned int *)&xwa.depth)); xwa.visual=wh.v; useShm=0; pixmap=1; } else { _x11(XGetWindowAttributes(wh.dpy, wh.d, &xwa)); } if(width_>0) width=width_; else width=xwa.width; if(height_>0) height=height_; else height=xwa.height; if(fb->wh.dpy==wh.dpy && fb->wh.d==wh.d) { if(width==fb->width && height==fb->height && fb->xi && fb->xgc && fb->bits) return 0; else if(fbx_term(fb)==-1) return -1; } memset(fb, 0, sizeof(fbx_struct)); fb->wh.dpy=wh.dpy; fb->wh.d=wh.d; #ifdef USESHM if(!useShm) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] Disabling shared memory blitting\n"); alreadyWarned=1; } } if(useShm && XShmQueryExtension(fb->wh.dpy)) { static int alreadyWarned=0; fb->shminfo.shmid=-1; if(!(fb->xi=XShmCreateImage(fb->wh.dpy, xwa.visual, xwa.depth, ZPixmap, NULL, &fb->shminfo, width, height))) { useShm=0; goto noshm; } if((fb->shminfo.shmid=shmget(IPC_PRIVATE, fb->xi->bytes_per_line*fb->xi->height+1, IPC_CREAT|0777))==-1) { useShm=0; XDestroyImage(fb->xi); goto noshm; } if((fb->shminfo.shmaddr=fb->xi->data =(char *)shmat(fb->shminfo.shmid, 0, 0))==(char *)-1) { useShm=0; XDestroyImage(fb->xi); shmctl(fb->shminfo.shmid, IPC_RMID, 0); goto noshm; } fb->shminfo.readOnly=False; XLockDisplay(fb->wh.dpy); XSync(fb->wh.dpy, False); prevHandler=XSetErrorHandler(xhandler); extok=1; serial=NextRequest(fb->wh.dpy); XShmAttach(fb->wh.dpy, &fb->shminfo); XSync(fb->wh.dpy, False); XSetErrorHandler(prevHandler); shmok=extok; if(!alreadyWarned && !shmok && warningFile) { fprintf(warningFile, "[FBX] WARNING: MIT-SHM extension failed to initialize (this is normal on a\n"); fprintf(warningFile, "[FBX] remote connection.) Will use X Pixmap drawing instead.\n"); alreadyWarned=1; } XUnlockDisplay(fb->wh.dpy); if(shmok) { char *env=getenv("FBX_USESHMPIXMAPS"); if(env && !strcmp(env, "1")) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] Using MIT-SHM pixmaps\n"); alreadyWarned=1; } fb->pm=XShmCreatePixmap(fb->wh.dpy, fb->wh.d, fb->shminfo.shmaddr, &fb->shminfo, width, height, xwa.depth); if(!fb->pm) shmok=0; } } shmctl(fb->shminfo.shmid, IPC_RMID, 0); if(!shmok) { useShm=0; XDestroyImage(fb->xi); shmdt(fb->shminfo.shmaddr); shmctl(fb->shminfo.shmid, IPC_RMID, 0); goto noshm; } fb->xattach=1; fb->shm=1; } else if(useShm) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] WARNING: MIT-SHM extension not available. Will use X pixmap\n"); fprintf(warningFile, "[FBX] drawing instead.\n"); alreadyWarned=1; } useShm=0; } noshm: if(!useShm) #endif { if(!pixmap) _x11(fb->pm=XCreatePixmap(fb->wh.dpy, fb->wh.d, width, height, xwa.depth)); _x11(fb->xi=XCreateImage(fb->wh.dpy, xwa.visual, xwa.depth, ZPixmap, 0, NULL, width, height, 8, 0)); if((fb->xi->data=(char *)malloc(fb->xi->bytes_per_line*fb->xi->height+1)) ==NULL) _throw("Memory allocation error"); } ps=fb->xi->bits_per_pixel/8; fb->width=fb->xi->width; fb->height=fb->xi->height; fb->pitch=fb->xi->bytes_per_line; if(fb->width!=width || fb->height!=height) _throw("Bitmap returned does not match requested size"); rmask=fb->xi->red_mask; gmask=fb->xi->green_mask; bmask=fb->xi->blue_mask; alphaFirst=0; if(fb->xi->byte_order==MSBFirst) { if(ps<4) { rmask=fb->xi->blue_mask; gmask=fb->xi->green_mask; bmask=fb->xi->red_mask; } else alphaFirst=1; } fb->format=-1; for(i=0; i<FBX_FORMATS; i++) if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i] && ps==fbx_ps[i] && fbx_alphafirst[i]==alphaFirst) fb->format=i; if(fb->format==-1) _throw("Display has unsupported pixel format"); fb->bits=fb->xi->data; fb->pixmap=pixmap; _x11(fb->xgc=XCreateGC(fb->wh.dpy, fb->pm? fb->pm:fb->wh.d, 0, NULL)); return 0; finally: #endif fbx_term(fb); return -1; }
const GrGLInterface* SkNativeGLContext::createGLContext() { fDisplay = XOpenDisplay(0); if (!fDisplay) { SkDebugf("Failed to open X display.\n"); this->destroyGLContext(); return NULL; } // Get a matching FB config static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, None }; #ifdef GLX_1_3 //SkDebugf("Getting matching framebuffer configs.\n"); int fbcount; GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), visual_attribs, &fbcount); if (!fbc) { SkDebugf("Failed to retrieve a framebuffer config.\n"); this->destroyGLContext(); return NULL; } //SkDebugf("Found %d matching FB configs.\n", fbcount); // Pick the FB config/visual with the most samples per pixel //SkDebugf("Getting XVisualInfos.\n"); int best_fbc = -1, best_num_samp = -1; int i; for (i = 0; i < fbcount; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); if (vi) { int samp_buf, samples; glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples); //SkDebugf(" Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," // " SAMPLES = %d\n", // i, (unsigned int)vi->visualid, samp_buf, samples); if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) best_fbc = i, best_num_samp = samples; } XFree(vi); } GLXFBConfig bestFbc = fbc[best_fbc]; // Be sure to free the FBConfig list allocated by glXChooseFBConfig() XFree(fbc); // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); #else int numVisuals; XVisualInfo visTemplate, *visReturn; visReturn = XGetVisualInfo(fDisplay, VisualNoMask, &visTemplate, &numVisuals); if (NULL == visReturn) { SkDebugf("Failed to get visual information.\n"); this->destroyGLContext(); return NULL; } int best = -1, best_num_samp = -1; for (int i = 0; i < numVisuals; ++i) { int samp_buf, samples; glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLE_BUFFERS, &samp_buf); glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLES, &samples); if (best < 0 || (samp_buf && samples > best_num_samp)) best = i, best_num_samp = samples; } XVisualInfo temp = visReturn[best]; XVisualInfo *vi = &temp; XFree(visReturn); #endif fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); if (!fPixmap) { SkDebugf("Failed to create pixmap.\n"); this->destroyGLContext(); return NULL; } fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); #ifdef GLX_1_3 // Done with the visual info data XFree(vi); #endif // Create the context // Install an X error handler so the application won't exit if GL 3.0 // context allocation fails. // // Note this error handler is global. // All display connections in all threads of a process use the same // error handler, so be sure to guard against other threads issuing // X commands while this code is running. ctxErrorOccurred = false; int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); // Get the default screen's GLX extension list const char *glxExts = glXQueryExtensionsString( fDisplay, DefaultScreen(fDisplay) ); // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. if (!gluCheckExtension( reinterpret_cast<const GLubyte*>("GLX_ARB_create_context") , reinterpret_cast<const GLubyte*>(glxExts))) { //SkDebugf("GLX_ARB_create_context not found." // " Using old-style GLX context.\n"); #ifdef GLX_1_3 fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); #else fContext = glXCreateContext(fDisplay, vi, 0, True); #endif } #ifdef GLX_1_3 else { //SkDebugf("Creating context.\n"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB"); int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; fContext = glXCreateContextAttribsARB( fDisplay, bestFbc, 0, True, context_attribs ); // Sync to ensure any errors generated are processed. XSync(fDisplay, False); if (!ctxErrorOccurred && fContext) { //SkDebugf( "Created GL 3.0 context.\n" ); } else { // Couldn't create GL 3.0 context. // Fall back to old-style 2.x context. // When a context version below 3.0 is requested, // implementations will return the newest context version compatible // with OpenGL versions less than version 3.0. // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 context_attribs[1] = 1; // GLX_CONTEXT_MINOR_VERSION_ARB = 0 context_attribs[3] = 0; ctxErrorOccurred = false; //SkDebugf("Failed to create GL 3.0 context." // " Using old-style GLX context.\n"); fContext = glXCreateContextAttribsARB( fDisplay, bestFbc, 0, True, context_attribs ); } } #endif // Sync to ensure any errors generated are processed. XSync(fDisplay, False); // Restore the original error handler XSetErrorHandler(oldHandler); if (ctxErrorOccurred || !fContext) { SkDebugf("Failed to create an OpenGL context.\n"); this->destroyGLContext(); return NULL; } // Verify that context is a direct context if (!glXIsDirect(fDisplay, fContext)) { //SkDebugf("Indirect GLX rendering context obtained.\n"); } else { //SkDebugf("Direct GLX rendering context obtained.\n"); } //SkDebugf("Making context current.\n"); if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { SkDebugf("Could not set the context.\n"); this->destroyGLContext(); return NULL; } const GrGLInterface* interface = GrGLCreateNativeInterface(); if (!interface) { SkDebugf("Failed to create gl interface"); this->destroyGLContext(); return NULL; } return interface; }