window::window() : handle ( SDL_CreateWindow ( "Untitled window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, size.get().get_x(), size.get().get_y(), SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ), &::SDL_DestroyWindow ), graphics_context(this) { if (not handle) { throw std::runtime_error("Failed to create a window."); } set_background_color(graphics::color::coral_red); cache_backbuffer_size(); dpi = get_dpi(); }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static BOOL WINAPI device_init( INIT_ONCE *once, void *param, void **context ) { /* Initialize XRender */ xrender_funcs = X11DRV_XRender_Init(); /* Init Xcursor */ X11DRV_Xcursor_Init(); palette_size = X11DRV_PALETTE_Init(); stock_bitmap_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 1 ); /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); return TRUE; }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { device_init_done = TRUE; /* Initialize XRender */ xrender_funcs = X11DRV_XRender_Init(); /* Init Xcursor */ X11DRV_Xcursor_Init(); palette_size = X11DRV_PALETTE_Init(); stock_bitmap_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 1 ); /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); horz_size = MulDiv( screen_width, 254, log_pixels_x * 10 ); vert_size = MulDiv( screen_height, 254, log_pixels_y * 10 ); }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { device_init_done = TRUE; /* Initialize XRender */ X11DRV_XRender_Init(); /* Init Xcursor */ X11DRV_Xcursor_Init(); palette_size = X11DRV_PALETTE_Init(); X11DRV_BITMAP_Init(); /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); horz_size = MulDiv( screen_width, 254, log_pixels_x * 10 ); vert_size = MulDiv( screen_height, 254, log_pixels_y * 10 ); /* Initialize fonts and text caps */ X11DRV_FONT_Init(log_pixels_x, log_pixels_y); }
static float calcDisplayDensity() { const char *current_display = getenv("DISPLAY"); if (current_display != NULL) { Display *x11display = XOpenDisplay(current_display); if (x11display != NULL) { /* try x direct */ float dpi_height = floor(DisplayHeight(x11display, 0) / (DisplayHeightMM(x11display, 0) * 0.039370) + 0.5); float dpi_width = floor(DisplayWidth(x11display, 0) / (DisplayWidthMM(x11display, 0) * 0.039370) + 0.5); XCloseDisplay(x11display); return std::max(dpi_height,dpi_width) / 96.0; } } /* return manually specified dpi */ return get_dpi()/96.0; }
static inline REAL mm_to_pixel (REAL mm) { return mm * (get_dpi() / mm_per_inch); }
static inline REAL document_to_pixel (REAL doc) { return doc * (get_dpi() / 300.0); /* Per MSDN */ }
static inline REAL inch_to_pixel (REAL inch) { return inch * get_dpi(); }
static inline REAL point_to_pixel (REAL point) { return point * get_dpi() * inch_per_point; }
math::vector<float, 2> window::get_dpi_scale() const { return get_dpi() / graphics::get_default_dpi(); }
float getDisplayDensity() { return get_dpi()/96.0; }
float window::get_horizontal_dpi() const { return get_dpi().get_x(); }
void window::update() { input_state.advance_frame(); SDL_PumpEvents(); SDL_FilterEvents ( [] (void* userdata, SDL_Event* event) -> int { // Return 0 to remove an event from the queue, anything else to // keep the event in the queue. auto&& window = static_cast<class window*>(userdata); auto&& window_id = SDL_GetWindowID(window->handle.get()); switch (event->type) { case SDL_KEYDOWN: case SDL_KEYUP: { if (event->key.windowID != window_id) { return 1; } auto&& keycode = input::sdl_keycode_to_polygonist_keycode(event->key.keysym.sym); if (event->key.state == SDL_PRESSED) { window->input_state.key_press(keycode); } else if (event->key.state == SDL_RELEASED) { window->input_state.key_release(keycode); } break; } case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { if (event->button.windowID != window_id) { return 1; } auto&& button = input::sdl_button_to_polygonist_mouse_button(event->button.button); auto&& button_index = static_cast<size_t>(button); if (event->button.state == SDL_PRESSED) { window->input_state.mouse_press(button, event->button.clicks); } else if (event->button.state == SDL_RELEASED) { window->input_state.mouse_release(button); } break; } case SDL_MOUSEWHEEL: { if (event->wheel.windowID != window_id) { return 1; } // TODO: Use preciseX and preciseY after SDL 2.1 comes // out. https://bugzilla.libsdl.org/show_bug.cgi?id=2293 // TODO: do we need to DPI scale these values? if (event->wheel.direction == SDL_MOUSEWHEEL_FLIPPED) { window->input_state.mouse_wheel(-event->wheel.x, -event->wheel.y); } else { window->input_state.mouse_wheel(event->wheel.x, event->wheel.y); } break; } case SDL_TEXTINPUT: { if (event->text.windowID != window_id) { return 1; } window->input_state.text_input(event->text.text); break; } case SDL_TEXTEDITING: { if (event->edit.windowID != window_id) { return 1; } window->input_state.text_composition(event->edit.text, event->edit.start, event->edit.length); break; } case SDL_WINDOWEVENT: if (event->window.windowID != window_id) { return 1; } switch (event->window.event) { case SDL_WINDOWEVENT_MOVED: { auto&& x = static_cast<unsigned int>(event->window.data1); auto&& y = static_cast<unsigned int>(event->window.data2); window->move_event.fire(x, y); break; } case SDL_WINDOWEVENT_SIZE_CHANGED: { auto&& width = static_cast<unsigned int>(event->window.data1); auto&& height = static_cast<unsigned int>(event->window.data2); window->size = { width, height }; window->aspect_ratio = static_cast<float>(width) / static_cast<float>(height); window->cache_backbuffer_size(); window->resize_event.fire(width, height); break; } case SDL_WINDOWEVENT_CLOSE: window->close(); break; case SDL_WINDOWEVENT_ENTER: mouse_focus_window = window; break; case SDL_WINDOWEVENT_LEAVE: // mouse_focus_window = nullptr; break; case SDL_WINDOWEVENT_FOCUS_GAINED: keyboard_focus_window = window; break; case SDL_WINDOWEVENT_FOCUS_LOST: keyboard_focus_window = nullptr; break; } break; case SDL_SYSWMEVENT: return get_application_menu()->handle_event(event->syswm.msg); case SDL_QUIT: window->close(); // Don't remove quit events from the queue. All windows // need to handle them. return 1; } return 0; }, this ); // TODO: On Windows we can use WM_DPICHANGED to detect this. auto&& dpi = get_dpi(); if (this->dpi.get() != dpi) { this->dpi = dpi; dpi_change_event.fire(dpi.get_x(), dpi.get_y()); } mouse_focus_window = has_mouse_focus() ? this : mouse_focus_window; keyboard_focus_window = has_keyboard_focus() ? this : keyboard_focus_window; // Handles any pending deletions that must be done in the shared // graphics context and couldn't be done in the texture destructor. graphics::texture::free_textures_pending_deletion(); // We may not want to do this every frame. If it turns out that we're // freeing stuff too early, move this into some strategic places around // the code. We could do this on a timer or a memory threshold as well. asset::free_unused_assets(); }
static GtkCssValue * gtk_css_value_dimension_compute (GtkCssValue *number, guint property_id, GtkStyleProviderPrivate *provider, GtkCssStyle *style, GtkCssStyle *parent_style) { GtkBorderStyle border_style; /* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */ switch (property_id) { case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH: border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); break; case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH: border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); break; case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH: border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); break; case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH: border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); break; case GTK_CSS_PROPERTY_OUTLINE_WIDTH: border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER); break; default: break; } switch (number->unit) { default: g_assert_not_reached(); /* fall through */ case GTK_CSS_PERCENT: /* percentages for font sizes are computed, other percentages aren't */ if (property_id == GTK_CSS_PROPERTY_FONT_SIZE) return gtk_css_dimension_value_new (number->value / 100.0 * get_base_font_size (property_id, provider, style, parent_style), GTK_CSS_PX); case GTK_CSS_NUMBER: case GTK_CSS_PX: case GTK_CSS_DEG: case GTK_CSS_S: return _gtk_css_value_ref (number); case GTK_CSS_PT: return gtk_css_dimension_value_new (number->value * get_dpi (style) / 72.0, GTK_CSS_PX); case GTK_CSS_PC: return gtk_css_dimension_value_new (number->value * get_dpi (style) / 72.0 * 12.0, GTK_CSS_PX); case GTK_CSS_IN: return gtk_css_dimension_value_new (number->value * get_dpi (style), GTK_CSS_PX); case GTK_CSS_CM: return gtk_css_dimension_value_new (number->value * get_dpi (style) * 0.39370078740157477, GTK_CSS_PX); case GTK_CSS_MM: return gtk_css_dimension_value_new (number->value * get_dpi (style) * 0.039370078740157477, GTK_CSS_PX); case GTK_CSS_EM: return gtk_css_dimension_value_new (number->value * get_dpi (style) / 72.0 * get_base_font_size (property_id, provider, style, parent_style), GTK_CSS_PX); case GTK_CSS_EX: /* for now we pretend ex is half of em */ return gtk_css_dimension_value_new (number->value * 0.5 * get_dpi (style) / 72.0 * get_base_font_size (property_id, provider, style, parent_style), GTK_CSS_PX); case GTK_CSS_REM: return gtk_css_dimension_value_new (number->value * get_dpi (style) / 72.0 * _gtk_css_font_size_get_default (provider), GTK_CSS_PX); case GTK_CSS_RAD: return gtk_css_dimension_value_new (number->value * 360.0 / (2 * G_PI), GTK_CSS_DEG); case GTK_CSS_GRAD: return gtk_css_dimension_value_new (number->value * 360.0 / 400.0, GTK_CSS_DEG); case GTK_CSS_TURN: return gtk_css_dimension_value_new (number->value * 360.0, GTK_CSS_DEG); case GTK_CSS_MS: return gtk_css_dimension_value_new (number->value / 1000.0, GTK_CSS_S); } }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); CGDirectPaletteRef palette; /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); if (!log_pixels_x) { size_t width = CGDisplayPixelsWide(mainDisplay); size_t height = CGDisplayPixelsHigh(mainDisplay); log_pixels_x = MulDiv(width, 254, size_mm.width * 10); log_pixels_y = MulDiv(height, 254, size_mm.height * 10); } horz_size = size_mm.width; vert_size = size_mm.height; bits_per_pixel = 32; if (mode) { CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); horz_res = CGDisplayModeGetWidth(mode); vert_res = CGDisplayModeGetHeight(mode); if (pixelEncoding) { if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; CFRelease(pixelEncoding); } CGDisplayModeRelease(mode); } else { horz_res = CGDisplayPixelsWide(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay); } macdrv_get_desktop_rect(); desktop_horz_res = desktop_rect.size.width; desktop_vert_res = desktop_rect.size.height; palette = CGPaletteCreateWithDisplay(mainDisplay); if (palette) { palette_size = CGPaletteGetNumberOfSamples(palette); CGPaletteRelease(palette); } else palette_size = 0; device_data_valid = TRUE; }
struct rtb_window * window_impl_open(struct rutabaga *rtb, int w, int h, const char *title, intptr_t parent) { struct xcb_rutabaga *xrtb = (void *) rtb; struct xrtb_window *self; Display *dpy; xcb_connection_t *xcb_conn; int default_screen; GLXFBConfig *fb_configs, fb_config; XVisualInfo *visual; int nfb_configs; uint32_t event_mask = XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE; uint32_t value_mask = XCB_CW_BORDER_PIXEL | XCB_CW_BACK_PIXMAP | XCB_CW_BIT_GRAVITY | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; uint32_t value_list[6]; xcb_colormap_t colormap; xcb_void_cookie_t ck_window, ck_map; xcb_generic_error_t *err; assert(rtb); assert(h > 0); assert(w > 0); if (!(self = calloc(1, sizeof(*self)))) goto err_malloc; self->xrtb = xrtb; dpy = xrtb->dpy; xcb_conn = xrtb->xcb_conn; default_screen = DefaultScreen(dpy); self->screen = find_xcb_screen(xcb_conn, default_screen); if (!self->screen) { ERR("couldn't find XCB screen\n"); goto err_screen; } /** * gl configuration */ fb_configs = glXGetFBConfigs(dpy, default_screen, &nfb_configs); if (!fb_configs || !nfb_configs) { ERR("no GL configurations, bailing out\n"); goto err_gl_config; } fb_config = find_reasonable_fb_config(dpy, xcb_conn, fb_configs, nfb_configs, 0); if (!fb_config) { ERR("no reasonable GL configurations, bailing out\n"); goto err_gl_config; } visual = glXGetVisualFromFBConfig(dpy, fb_config); self->gl_ctx = new_gl_context(dpy, fb_config); if (!self->gl_ctx) { ERR("couldn't create GLX context\n"); goto err_gl_ctx; } /** * window setup */ colormap = xcb_generate_id(xcb_conn); self->xcb_win = xcb_generate_id(xcb_conn); xcb_create_colormap( xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, self->screen->root, visual->visualid); value_list[0] = 0; value_list[1] = 0; value_list[2] = XCB_GRAVITY_STATIC; value_list[3] = event_mask; value_list[4] = colormap; value_list[5] = 0; ck_window = xcb_create_window_checked( xcb_conn, visual->depth, self->xcb_win, parent ? (xcb_window_t) parent : self->screen->root, 0, 0, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visualid, value_mask, value_list); free(visual); if ((err = xcb_request_check(xcb_conn, ck_window))) { ERR("can't create XCB window: %d\n", err->error_code); goto err_xcb_win; } get_dpi(dpy, default_screen, &self->dpi.x, &self->dpi.y); self->gl_win = glXCreateWindow(dpy, fb_config, self->xcb_win, 0); if (!self->gl_win) { ERR("couldn't create GL window\n"); goto err_gl_win; } if (set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, title)) set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, "oh no"); self->gl_draw = self->gl_win; if (!glXMakeContextCurrent( dpy, self->gl_draw, self->gl_draw, self->gl_ctx)) { ERR("couldn't activate GLX context\n"); goto err_gl_make_current; } ck_map = xcb_map_window_checked(xcb_conn, self->xcb_win); if ((err = xcb_request_check(xcb_conn, ck_map))) { ERR("can't map XCB window: %d\n", err->error_code); goto err_win_map; } if (parent) raise_window(xcb_conn, self->xcb_win); else xcb_icccm_set_wm_protocols(xcb_conn, self->xcb_win, xrtb->atoms.wm_protocols, 1, &xrtb->atoms.wm_delete_window); free(fb_configs); uv_mutex_init(&self->lock); return RTB_WINDOW(self); err_win_map: err_gl_make_current: err_gl_win: xcb_destroy_window(xcb_conn, self->xcb_win); err_xcb_win: glXDestroyContext(dpy, self->gl_ctx); err_gl_ctx: err_gl_config: free(fb_configs); err_screen: free(self); err_malloc: return NULL; }
VOID DIALOG_FilePrint(VOID) { DOCINFOW di; PRINTDLGW printer; int page, dopage, copy; LOGFONTW lfFont; HFONT hTextFont, old_font = 0; DWORD size; BOOL ret = FALSE; RECT rc; LPWSTR pTemp; TEXTINFO tInfo; WCHAR cTemp[PRINT_LEN_MAX]; /* Get Current Settings */ ZeroMemory(&printer, sizeof(printer)); printer.lStructSize = sizeof(printer); printer.hwndOwner = Globals.hMainWnd; printer.hDevMode = Globals.hDevMode; printer.hDevNames = Globals.hDevNames; printer.hInstance = Globals.hInstance; /* Set some default flags */ printer.Flags = PD_RETURNDC | PD_NOSELECTION; printer.nFromPage = 0; printer.nMinPage = 1; /* we really need to calculate number of pages to set nMaxPage and nToPage */ printer.nToPage = 0; printer.nMaxPage = -1; /* Let commdlg manage copy settings */ printer.nCopies = (WORD)PD_USEDEVMODECOPIES; if (!PrintDlgW(&printer)) return; Globals.hDevMode = printer.hDevMode; Globals.hDevNames = printer.hDevNames; SetMapMode(printer.hDC, MM_TEXT); /* initialize DOCINFO */ di.cbSize = sizeof(DOCINFOW); di.lpszDocName = Globals.szFileTitle; di.lpszOutput = NULL; di.lpszDatatype = NULL; di.fwType = 0; if(printer.Flags & PD_PRINTTOFILE) { di.lpszOutput = dialog_print_to_file(printer.hwndOwner); if(!di.lpszOutput) return; } /* Get the file text */ size = GetWindowTextLengthW(Globals.hEdit) + 1; pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); if (!pTemp) { DeleteDC(printer.hDC); ShowLastError(); return; } size = GetWindowTextW(Globals.hEdit, pTemp, size); if (StartDocW(printer.hDC, &di) > 0) { /* Get the page margins in pixels. */ rc.top = MulDiv(Globals.iMarginTop, GetDeviceCaps(printer.hDC, LOGPIXELSY), 2540) - GetDeviceCaps(printer.hDC, PHYSICALOFFSETY); rc.bottom = GetDeviceCaps(printer.hDC, PHYSICALHEIGHT) - MulDiv(Globals.iMarginBottom, GetDeviceCaps(printer.hDC, LOGPIXELSY), 2540); rc.left = MulDiv(Globals.iMarginLeft, GetDeviceCaps(printer.hDC, LOGPIXELSX), 2540) - GetDeviceCaps(printer.hDC, PHYSICALOFFSETX); rc.right = GetDeviceCaps(printer.hDC, PHYSICALWIDTH) - MulDiv(Globals.iMarginRight, GetDeviceCaps(printer.hDC, LOGPIXELSX), 2540); /* Create a font for the printer resolution */ lfFont = Globals.lfFont; lfFont.lfHeight = MulDiv(lfFont.lfHeight, GetDeviceCaps(printer.hDC, LOGPIXELSY), get_dpi()); /* Make the font a bit lighter */ lfFont.lfWeight -= 100; hTextFont = CreateFontIndirectW(&lfFont); old_font = SelectObject(printer.hDC, hTextFont); for (copy = 1; copy <= printer.nCopies; copy++) { page = 1; tInfo.mptr = pTemp; tInfo.mend = pTemp + size; tInfo.lptr = cTemp; tInfo.len = 0; do { if (printer.Flags & PD_PAGENUMS) { /* a specific range of pages is selected, so * skip pages that are not to be printed */ if (page > printer.nToPage) break; else if (page >= printer.nFromPage) dopage = 1; else dopage = 0; } else dopage = 1; ret = notepad_print_page(printer.hDC, &rc, dopage, page, &tInfo); page++; } while (ret && tInfo.mptr < tInfo.mend); if (!ret) break; } EndDoc(printer.hDC); SelectObject(printer.hDC, old_font); DeleteObject(hTextFont); } DeleteDC(printer.hDC); HeapFree(GetProcessHeap(), 0, pTemp); }
float window::get_vertical_dpi() const { return get_dpi().get_y(); }