/* Returns the physical display size as reported by X11: */ void PsychGetDisplaySize(int screenNumber, int *width, int *height) { if(screenNumber>=numDisplays) PsychErrorExitMsg(PsychError_internal, "screenNumber passed to PsychGetDisplaySize() is out of range"); *width = (int) XDisplayWidthMM(displayCGIDs[screenNumber], PsychGetXScreenIdForScreen(screenNumber)); *height = (int) XDisplayHeightMM(displayCGIDs[screenNumber], PsychGetXScreenIdForScreen(screenNumber)); }
/** * This method will expand the graphics panel already openned to the maximun of the display area scaled by the scale value supplied. * * @param scale Porcentage (0-100) of the display width to use. */ void resizemax(float scale) { Display *disp; float ax, ay; int X, Y; /* Xlib code */ disp = XOpenDisplay(NULL); if (disp == NULL) { fprintf(stderr, "No Display.\n"); exit(-1); } else { Y = XDisplayHeightMM(disp, 0); X = XDisplayWidthMM(disp, 0) / (0.9); } XCloseDisplay(disp); /* End of Xlib code */ ay = (double) Y / (double) X; ax = X / 25.4 * scale; cpgpap(ax, ay); cpgpage(); BASIC_ASPECT = ay; }
float get_DPI_scale() { Display* display = XOpenDisplay(nullptr); const int width = XDisplayWidth(display, 0); const int widthMM = XDisplayWidthMM(display, 0); XCloseDisplay(display); return width/(92*0.0393700787402f*widthMM); }
std::pair<int, int> getDPI() { Display * dpy = XOpenDisplay(nullptr); int screen = 0; //TODO: find a way to get the current screen int horizontalDPI = ((((double) XDisplayWidth(dpy, screen)) * 25.4) / ((double) XDisplayWidthMM(dpy, screen))); int verticalDPI = ((((double) XDisplayHeight(dpy, screen)) * 25.4) / ((double) XDisplayHeightMM(dpy, screen))); return std::pair<int, int>(horizontalDPI, verticalDPI); }
// INPUT display, screen n° // OUTPUT int * int (size in mm) CAMLprim value caml_xscreen_sizemm(value disp, value screen) { CAMLparam2(disp, screen); int w = XDisplayWidthMM ((Display*) disp, Int_val(screen)); int h = XDisplayHeightMM ((Display*) disp, Int_val(screen)); CAMLreturn(Int_pair(w,h)); }
int main(int argc, char* argv[]) { (void)argc; (void)argv; Display *dpy = _getXdis (); XVisualInfo *vis = _getXvis (dpy, _attr); Window win = _setXwin (dpy, vis); GLXContext ctx = _getGLXctx(dpy, vis); // bind the rendering context to the window Bool ret = glXMakeCurrent(dpy, win, ctx); if (False == ret) { printf("ERROR: glXMakeCurrent() fail\n"); exit(0); } { // init S52 lib (Screen No 0) #ifdef SET_SCREEN_SIZE int w = 1280; int h = 1024; int wmm = 376; int hmm = 307; #else int h = XDisplayHeight (dpy, 0); int hmm = XDisplayHeightMM(dpy, 0); int w = XDisplayWidth (dpy, 0); int wmm = XDisplayWidthMM (dpy, 0); #endif S52_init(w, h, wmm, hmm, NULL); } // differ from w/h S52_setViewPort(0, 0, WIDTH, HEIGHT); /* debug - use for timing rendering S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_SY); //S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_LS); S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_LC); S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_AC); S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_AP); S52_setMarinerParam(S52_CMD_WRD_FILTER, S52_CMD_WRD_FILTER_TX); //*/ // load cell from s52.cfg S52_loadCell(NULL, NULL); { // main loop XEvent event; while (True) { do { XNextEvent(dpy, &event); switch (event.type) { case ConfigureNotify: break; //case GraphicsExpose: // S52_setViewPort(0, 0, event.xconfigure.width, event.xconfigure.height); break; //case ... case KeyPress: case KeyRelease: { unsigned int keycode = ((XKeyEvent *)&event)->keycode; unsigned int keysym = XkbKeycodeToKeysym(dpy, keycode, 0, 1); // ESC - quit if (XK_Escape == keysym) { goto exit; } } } } while (XPending(dpy)); S52_draw(); S52_drawLast(); // nothing to do glXSwapBuffers(dpy, win); } } exit: XKillClient(dpy, win); S52_done(); return True; }
void X11Window::create(XVisualInfo *visual, DisplayWindowSite *new_site, const DisplayWindowDescription &desc) { site = new_site; // Reset all variables close_window(); handle.screen = visual->screen; atoms = X11Atoms(handle.display); int disp_width_px = XDisplayWidth(handle.display, handle.screen); int disp_height_px = XDisplayHeight(handle.display, handle.screen); int disp_width_mm = XDisplayWidthMM(handle.display, handle.screen); // Get DPI of screen or use 96.0f if Xlib doesn't have a value. ppi = (disp_width_mm < 24) ? 96.0f : (25.4f * static_cast<float>(disp_width_px) / static_cast<float>(disp_width_mm)); // Update pixel ratio. set_pixel_ratio(pixel_ratio); // Get X11 root window. auto _root_window = RootWindow(handle.display, handle.screen); // Get and validate initial window position and size. int win_x = desc.get_position().left * pixel_ratio; int win_y = desc.get_position().top * pixel_ratio; int win_width = desc.get_size().width * pixel_ratio; int win_height = desc.get_size().height * pixel_ratio; if (win_width <= 0) throw Exception("Invalid window width."); if (win_height <= 0) throw Exception("Invalid window height."); // Set values if fullscreen requested. if (desc.is_fullscreen()) { win_x = 0; win_y = 0; win_width = disp_width_px; win_height = disp_height_px; } // Center window if position supplied is (-1, -1) if (win_x == -1 && win_y == -1) { win_x = (disp_width_px - win_width)/2 - 1; win_y = (disp_height_px - win_height)/2 - 1; } // Set minimum and maximum size this->resize_allowed = desc.get_allow_resize() || desc.is_fullscreen(); // Fullscreen mode needs a resizable window. if (resize_allowed) { minimum_size = Size(_ResizeMinimumSize_, _ResizeMinimumSize_); maximum_size = Size(0, 0); // No maximum size by default. } else { minimum_size = Size(win_width, win_height); maximum_size = Size(win_width, win_height); } // Setup X11 size hints. this->size_hints = XAllocSizeHints(); if (size_hints == NULL) throw Exception("Failed to allocate X11 XSizeHints structure."); size_hints->flags = PMinSize | (resize_allowed ? 0 : PMaxSize); size_hints->flags |= PResizeInc | PBaseSize | PWinGravity; // x, y, width, height are obsolete. size_hints->flags |= USSize | USPosition; // See http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472522864 size_hints->min_width = minimum_size.width; size_hints->min_height = minimum_size.height; size_hints->max_width = maximum_size.width; size_hints->max_height = maximum_size.height; size_hints->width_inc = 1; size_hints->height_inc = 1; size_hints->base_width = win_width; size_hints->base_height = win_height; size_hints->win_gravity = NorthWestGravity; // Setup X11 colormap. // // The X.Org XServer implementation used on most systems requires that // a color-map be set for the window. Additionally, windows with a // different color-depth than its parent must have the border-pixel flag // set when creating them. Failure to do either will cause XCreateWindow() // to result in a BadMatch error. // // Source: stackoverflow.com/questions/3645632 color_map = XCreateColormap(handle.display, _root_window, visual->visual, AllocNone); // Static popups are unresizable captionless popup windows. // These windows should not be decorated. bool is_static_popup = desc.is_popup() && !desc.has_caption() && !desc.get_allow_resize(); // Tell X11 to perserve graphical content under small popup windows to avoid redraws. bool save_under = desc.is_popup() && ( (win_width * win_height) < (256 * 256 * pixel_ratio * pixel_ratio) ); // Setup window attributes. XSetWindowAttributes attr = XSetWindowAttributes { .background_pixmap = None, /* default */ .background_pixel = 0ul, /* default: undefined */ .border_pixmap = CopyFromParent, /* default */ .border_pixel = 0ul, /* see color_map details above */ .bit_gravity = ForgetGravity, /* default */ .win_gravity = NorthWestGravity, /* default */ .backing_store = NotUseful, /* default */ .backing_planes = -1ul, /* default */ .backing_pixel = 0ul, /* default */ .save_under = save_under ? True : False, .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask | ExposureMask // | VisibilityChangeMask | StructureNotifyMask | FocusChangeMask | PropertyChangeMask , .do_not_propagate_mask = NoEventMask, /* default */ .override_redirect = is_static_popup ? True : False, .colormap = color_map, /* see color_map details above */ .cursor = None /* default; Let X11 handle the cursor for now. */ }; this->system_cursor = XCreateFontCursor(handle.display, XC_left_ptr); // This is allowed to fail log_event("debug", "clan::X11Window::create(): Creating window..."); log_event("debug", " x%1 y%2 w%3 h%4 b%5 d%6", win_x, win_y, win_width, win_height, border_width, visual->depth); log_event("debug", " a.su%1, a.od%2", save_under, is_static_popup); // Create window handle.window = XCreateWindow( handle.display, _root_window, win_x, win_y, win_width, win_height, border_width, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap, &attr ); if (!handle.window) throw Exception("Unable to create the X11 window"); if (!desc.get_owner().is_null()) { DisplayWindow owner = desc.get_owner(); XSetTransientForHint(handle.display, handle.window, owner.get_handle().window); } // Setup the hidden cursor (Maybe this should be done only once when required) char data[64]; // 8x8 memset(data, 0, 64); XColor black_color; memset(&black_color, 0, sizeof(black_color)); cursor_bitmap = XCreateBitmapFromData(handle.display, handle.window, data, 8, 8); hidden_cursor = XCreatePixmapCursor(handle.display, cursor_bitmap, cursor_bitmap, &black_color, &black_color, 0,0); // Set title of window: set_title(desc.get_title()); { // Inform the window manager who we are, so it can kill us if we're not good for its universe. Atom atom; int32_t pid = getpid(); if (pid > 0) { atom = atoms.get_atom(handle.display, "_NET_WM_PID", False); XChangeProperty(handle.display, handle.window, atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &pid, 1); } char hostname[256]; if (gethostname(hostname, sizeof(hostname)) > -1) { hostname[255] = 0; atom = atoms.get_atom(handle.display, "WM_CLIENT_MACHINE", False); XChangeProperty(handle.display, handle.window, atom, XA_STRING, 8, PropModeReplace, (unsigned char *) hostname, strlen(hostname)); } } // Set-up window type/styling. // TODO Support more window types, broaden ClanLib window type support, etc. if (atoms["_NET_WM_WINDOW_TYPE"] != None) { Atom type = None; std::string name; if (desc.is_dialog()) { name = "_NET_WM_WINDOW_TYPE_DIALOG"; type = atoms[name]; } else if (desc.is_popup()) { if (is_static_popup) { name = "_NET_WM_WINDOW_TYPE_TOOLTIP"; type = atoms[name]; } else if (desc.has_caption()) // A pop-up with title bar -> utility { name = "_NET_WM_WINDOW_TYPE_UTILITY"; type = atoms[name]; } // else, a pop-up without a title bar -> popup-menu, combo, dropdown, tooltip, ... if (type == None) { name = "_NET_WM_WINDOW_TYPE_POPUP_MENU"; type = atoms[name]; } if (type == None) { name = "_NET_WM_WINDOW_TYPE_COMBO"; type = atoms[name]; } if (type == None) { name = "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"; type = atoms[name]; } } // else if (desc.is_normal()) // Fallback to normal window type if WM doesn't support what we want. if (type == None) { name = "_NET_WM_WINDOW_TYPE_NORMAL"; type = atoms[name]; } if (type != None) // Ensure selected type exists. { XChangeProperty(handle.display, handle.window, atoms["_NET_WM_WINDOW_TYPE"], XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); log_event("debug", "clan::X11Window::create(): Creating window of type '%1'.", name); } else { log_event("debug", "clan::X11Window::create(): Failed to find a suitable window type."); } } else { log_event("debug", "clan::X11Window::create(): _NET_WM_WINDOW_TYPE does not exist."); } // Set size hints XSetWMNormalHints(handle.display, handle.window, size_hints); { // Subscribe to WM events. Atom protocol = atoms["WM_DELETE_WINDOW"]; Status result = XSetWMProtocols(handle.display, handle.window, &protocol, 1); if (result == 0) log_event("debug", "clan::X11Window::create(): Failed to set WM_PROTOCOLS."); } { // Make auto-repeat keys detectable. Bool supports_detectable_autorepeat; XkbSetDetectableAutoRepeat(handle.display, True, &supports_detectable_autorepeat); } { // Make window full-screen if requested. if (atoms["_NET_WM_STATE"] == None && atoms["_NET_WM_STATE_FULLSCREEN"]) { fullscreen = false; log_event("debug", "clan::X11Window: Fullscreen not supported by WM."); } else { fullscreen = desc.is_fullscreen(); } if (fullscreen) { Atom state = atoms["_NET_WM_STATE_FULLSCREEN"]; XChangeProperty(handle.display, handle.window, atoms["_NET_WM_STATE"], XA_ATOM, 32, PropModeReplace, (unsigned char *)&state, 1); } } update_frame_extents(); auto new_client_area = desc.get_position_client_area() // supplied position is at ? client area : window area; ? Rect::xywh(win_x, win_y, win_width, win_height) : Rect::xywh(win_x + frame_extents.left, win_y + frame_extents.right, win_width, win_height) ; process_window_resize(new_client_area); // Set window visibility if (desc.is_visible()) { show(false); } // Setup the clipboard clipboard.setup(); // Go looking for joysticks: setup_joysticks(); } void X11Window::update_frame_extents() { frame_extents = Rect { border_width, border_width, border_width, border_width }; if (atoms["_NET_FRAME_EXTENTS"] == None) return; // Request frame extents from WM. if (atoms["_NET_REQUEST_FRAME_EXTENTS"] != None) { XEvent event; memset(&event, 0, sizeof(event)); event.type = ClientMessage; event.xclient.window = handle.window; event.xclient.format = 32; event.xclient.message_type = atoms["_NET_REQUEST_FRAME_EXTENTS"]; XSendEvent(handle.display, RootWindow(handle.display, handle.screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &event); int timer = 10; while(true) { if (timer < 0) { log_event("debug", "clan::X11Window: Your window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation."); break; } if (XCheckMaskEvent(handle.display, PropertyNotify, &event)) { break; } clan::System::sleep(5); timer--; } } unsigned long item_count; // _NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32 unsigned char *data = atoms.get_property(handle.window, "_NET_FRAME_EXTENTS", item_count); if (data == NULL) return; if (item_count >= 4) { long *cardinal = (long *)data; frame_extents.left = cardinal[0]; frame_extents.right = cardinal[1]; frame_extents.top = cardinal[2]; frame_extents.bottom = cardinal[3]; } XFree(data); }