void x11_show_mouse(Display *dpy, Window win, bool state) { if (state) XUndefineCursor(dpy, win); else x11_hide_mouse(dpy, win); }
static bool gfx_ctx_set_video_mode( 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); gfx_ctx_update_window_title(true); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_hide_mouse(g_dpy, g_win); 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); g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); if (!g_ctx) { RARCH_ERR("[GLX]: Failed to create new context.\n"); goto error; } 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_pglSwapInterval = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); if (g_pglSwapInterval) swap_func = "glXSwapIntervalMESA"; if (!g_pglSwapInterval) { g_pglSwapInterval = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI"); if (g_pglSwapInterval) swap_func = "glXSwapIntervalSGI"; } if (!g_pglSwapInterval) 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(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; 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(); return false; }
static bool gfx_ctx_set_video_mode( 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); XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; bool windowed_full = g_settings.video.windowed_fullscreen; bool true_full = false; int x_off = 0; int y_off = 0; EGLint vid; if (!eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &vid)) goto error; temp.visualid = vid; EGLint num_visuals; 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 | 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 (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("[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); // GLES 2.0. Don't use for any other API. static const EGLint egl_ctx_gles_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, }; g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, (g_api == GFX_CTX_OPENGL_ES_API) ? egl_ctx_gles_attribs : NULL); if (!g_egl_ctx) goto error; g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_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; gfx_ctx_update_window_title(true); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_hide_mouse(g_dpy, g_win); 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("[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); } XEvent event; XIfEvent(g_dpy, &event, egl_wait_notify, NULL); XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime); 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_swap_interval(g_interval); XFree(vi); g_has_focus = true; g_inited = true; 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(); return false; }