mirror of
https://github.com/Raymo111/i3lock-color.git
synced 2024-12-02 14:05:43 -05:00
Respect Xft.dpi for determining the unlock indicator’s scale factor
fixes #184
This commit is contained in:
parent
ae72b675ca
commit
f9c30db62b
6 changed files with 144 additions and 14 deletions
|
@ -19,6 +19,7 @@ i3lock_CFLAGS = \
|
|||
$(XCB_CFLAGS) \
|
||||
$(XCB_IMAGE_CFLAGS) \
|
||||
$(XCB_UTIL_CFLAGS) \
|
||||
$(XCB_UTIL_XRM_CFLAGS) \
|
||||
$(XKBCOMMON_CFLAGS) \
|
||||
$(CAIRO_CFLAGS) \
|
||||
$(CODE_COVERAGE_CFLAGS)
|
||||
|
@ -31,12 +32,15 @@ i3lock_LDADD = \
|
|||
$(XCB_LIBS) \
|
||||
$(XCB_IMAGE_LIBS) \
|
||||
$(XCB_UTIL_LIBS) \
|
||||
$(XCB_UTIL_XRM_LIBS) \
|
||||
$(XKBCOMMON_LIBS) \
|
||||
$(CAIRO_LIBS) \
|
||||
$(CODE_COVERAGE_LDFLAGS)
|
||||
|
||||
i3lock_SOURCES = \
|
||||
cursors.h \
|
||||
dpi.c \
|
||||
dpi.h \
|
||||
i3lock.c \
|
||||
i3lock.h \
|
||||
randr.c \
|
||||
|
|
|
@ -93,6 +93,7 @@ dnl downloaded in a newer version and would like to overwrite.
|
|||
PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr])
|
||||
PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image])
|
||||
PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom])
|
||||
PKG_CHECK_MODULES([XCB_UTIL_XRM], [xcb-xrm])
|
||||
PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11])
|
||||
PKG_CHECK_MODULES([CAIRO], [cairo])
|
||||
|
||||
|
|
109
dpi.c
Normal file
109
dpi.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* vim:ts=4:sw=4:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
*
|
||||
*/
|
||||
#include "dpi.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <xcb/xcb_xrm.h>
|
||||
#include "xcb.h"
|
||||
#include "i3lock.h"
|
||||
|
||||
extern bool debug_mode;
|
||||
|
||||
static long dpi;
|
||||
|
||||
extern xcb_screen_t *screen;
|
||||
|
||||
static long init_dpi_fallback(void) {
|
||||
return (double)screen->height_in_pixels * 25.4 / (double)screen->height_in_millimeters;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the DPI setting.
|
||||
* This will use the 'Xft.dpi' X resource if available and fall back to
|
||||
* guessing the correct value otherwise.
|
||||
*/
|
||||
void init_dpi(void) {
|
||||
xcb_xrm_database_t *database = NULL;
|
||||
char *resource = NULL;
|
||||
|
||||
if (conn == NULL) {
|
||||
goto init_dpi_end;
|
||||
}
|
||||
|
||||
database = xcb_xrm_database_from_default(conn);
|
||||
if (database == NULL) {
|
||||
DEBUG("Failed to open the resource database.\n");
|
||||
goto init_dpi_end;
|
||||
}
|
||||
|
||||
xcb_xrm_resource_get_string(database, "Xft.dpi", NULL, &resource);
|
||||
if (resource == NULL) {
|
||||
DEBUG("Resource Xft.dpi not specified, skipping.\n");
|
||||
goto init_dpi_end;
|
||||
}
|
||||
|
||||
char *endptr;
|
||||
double in_dpi = strtod(resource, &endptr);
|
||||
if (in_dpi == HUGE_VAL || dpi < 0 || *endptr != '\0' || endptr == resource) {
|
||||
DEBUG("Xft.dpi = %s is an invalid number and couldn't be parsed.\n", resource);
|
||||
dpi = 0;
|
||||
goto init_dpi_end;
|
||||
}
|
||||
dpi = (long)round(in_dpi);
|
||||
|
||||
DEBUG("Found Xft.dpi = %ld.\n", dpi);
|
||||
|
||||
init_dpi_end:
|
||||
if (resource != NULL) {
|
||||
free(resource);
|
||||
}
|
||||
|
||||
if (database != NULL) {
|
||||
xcb_xrm_database_free(database);
|
||||
}
|
||||
|
||||
if (dpi == 0) {
|
||||
DEBUG("Using fallback for calculating DPI.\n");
|
||||
dpi = init_dpi_fallback();
|
||||
DEBUG("Using dpi = %ld\n", dpi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the value of the DPI setting.
|
||||
*
|
||||
*/
|
||||
long get_dpi_value(void) {
|
||||
return dpi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI
|
||||
* screen) to a corresponding amount of physical pixels on a standard or retina
|
||||
* screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen.
|
||||
*
|
||||
*/
|
||||
int logical_px(const int logical) {
|
||||
if (screen == NULL) {
|
||||
/* Dpi info may not be available when parsing a config without an X
|
||||
* server, such as for config file validation. */
|
||||
return logical;
|
||||
}
|
||||
|
||||
/* There are many misconfigurations out there, i.e. systems with screens
|
||||
* whose dpi is in fact higher than 96 dpi, but not significantly higher,
|
||||
* so software was never adapted. We could tell people to reconfigure their
|
||||
* systems to 96 dpi in order to get the behavior they expect/are used to,
|
||||
* but since we can easily detect this case in code, let’s do it for them.
|
||||
*/
|
||||
if ((dpi / 96.0) < 1.25)
|
||||
return logical;
|
||||
return ceil((dpi / 96.0) * logical);
|
||||
}
|
22
dpi.h
Normal file
22
dpi.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* Initialize the DPI setting.
|
||||
* This will use the 'Xft.dpi' X resource if available and fall back to
|
||||
* guessing the correct value otherwise.
|
||||
*/
|
||||
void init_dpi(void);
|
||||
|
||||
/**
|
||||
* This function returns the value of the DPI setting.
|
||||
*
|
||||
*/
|
||||
long get_dpi_value(void);
|
||||
|
||||
/**
|
||||
* Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI
|
||||
* screen) to a corresponding amount of physical pixels on a standard or retina
|
||||
* screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen.
|
||||
*
|
||||
*/
|
||||
int logical_px(const int logical);
|
3
i3lock.c
3
i3lock.c
|
@ -46,6 +46,7 @@
|
|||
#include "cursors.h"
|
||||
#include "unlock_indicator.h"
|
||||
#include "randr.h"
|
||||
#include "dpi.h"
|
||||
|
||||
#define TSTAMP_N_SECS(n) (n * 1.0)
|
||||
#define TSTAMP_N_MINS(n) (60 * TSTAMP_N_SECS(n))
|
||||
|
@ -1033,6 +1034,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
||||
|
||||
init_dpi();
|
||||
|
||||
randr_init(&randr_base, screen->root);
|
||||
randr_query(screen->root);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "xcb.h"
|
||||
#include "unlock_indicator.h"
|
||||
#include "randr.h"
|
||||
#include "dpi.h"
|
||||
|
||||
#define BUTTON_RADIUS 90
|
||||
#define BUTTON_SPACE (BUTTON_RADIUS + 5)
|
||||
|
@ -80,17 +81,6 @@ static xcb_visualtype_t *vistype;
|
|||
unlock_state_t unlock_state;
|
||||
auth_state_t auth_state;
|
||||
|
||||
/*
|
||||
* Returns the scaling factor of the current screen. E.g., on a 227 DPI MacBook
|
||||
* Pro 13" Retina screen, the scaling factor is 227/96 = 2.36.
|
||||
*
|
||||
*/
|
||||
static double scaling_factor(void) {
|
||||
const int dpi = (double)screen->height_in_pixels * 25.4 /
|
||||
(double)screen->height_in_millimeters;
|
||||
return (dpi / 96.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws global image with fill color onto a pixmap with the given
|
||||
* resolution and returns it.
|
||||
|
@ -98,9 +88,10 @@ static double scaling_factor(void) {
|
|||
*/
|
||||
xcb_pixmap_t draw_image(uint32_t *resolution) {
|
||||
xcb_pixmap_t bg_pixmap = XCB_NONE;
|
||||
int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER);
|
||||
const double scaling_factor = get_dpi_value() / 96.0;
|
||||
int button_diameter_physical = ceil(scaling_factor * BUTTON_DIAMETER);
|
||||
DEBUG("scaling_factor is %.f, physical diameter is %d px\n",
|
||||
scaling_factor(), button_diameter_physical);
|
||||
scaling_factor, button_diameter_physical);
|
||||
|
||||
if (!vistype)
|
||||
vistype = get_root_visual_type(screen);
|
||||
|
@ -142,7 +133,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
|
|||
|
||||
if (unlock_indicator &&
|
||||
(unlock_state >= STATE_KEY_PRESSED || auth_state > STATE_AUTH_IDLE)) {
|
||||
cairo_scale(ctx, scaling_factor(), scaling_factor());
|
||||
cairo_scale(ctx, scaling_factor, scaling_factor);
|
||||
/* Draw a (centered) circle with transparent background. */
|
||||
cairo_set_line_width(ctx, 10.0);
|
||||
cairo_arc(ctx,
|
||||
|
|
Loading…
Reference in a new issue