From cec04b268440bd9cdcb571254983475df3bd1f94 Mon Sep 17 00:00:00 2001 From: actionless Date: Thu, 14 May 2015 22:57:22 +0200 Subject: [PATCH] Add DPI support and 'xresources' theme This makes awesome respect DPI settings, and adds a new theme based on xrdb and xsettingsd color settings ("xresources"). Closes https://github.com/awesomeWM/awesome/pull/229 --- CMakeLists.txt | 2 + awesome.c | 13 +- awesomeConfig.cmake | 1 + globalconf.h | 5 + lib/{beautiful.lua => beautiful/init.lua} | 5 +- lib/beautiful/xresources.lua | 82 +++++++ lib/wibox/widget/textbox.lua | 1 + luaa.c | 2 + themes/xresources/theme.lua | 267 ++++++++++++++++++++++ xrdb.c | 73 ++++++ xrdb.h | 30 +++ 11 files changed, 479 insertions(+), 2 deletions(-) rename lib/{beautiful.lua => beautiful/init.lua} (96%) create mode 100644 lib/beautiful/xresources.lua create mode 100644 themes/xresources/theme.lua create mode 100644 xrdb.c create mode 100644 xrdb.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b8cc295b..a52176437 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ set(AWE_SRCS ${BUILD_DIR}/systray.c ${BUILD_DIR}/xwindow.c ${BUILD_DIR}/xkb.c + ${BUILD_DIR}/xrdb.c ${BUILD_DIR}/common/atoms.c ${BUILD_DIR}/common/backtrace.c ${BUILD_DIR}/common/buffer.c @@ -136,6 +137,7 @@ add_custom_target(generated_sources file(MAKE_DIRECTORY ${BUILD_DIR}/themes/default) file(MAKE_DIRECTORY ${BUILD_DIR}/themes/sky) file(MAKE_DIRECTORY ${BUILD_DIR}/themes/zenburn) +file(MAKE_DIRECTORY ${BUILD_DIR}/themes/xresources) add_dependencies(${PROJECT_AWE_NAME} generated_sources) # }}} diff --git a/awesome.c b/awesome.c index ed920e49f..4ab725866 100644 --- a/awesome.c +++ b/awesome.c @@ -53,6 +53,9 @@ #include #include +#include +#include + #include awesome_t globalconf; @@ -412,8 +415,16 @@ main(int argc, char **argv) /* We have no clue where the input focus is right now */ globalconf.focus.need_update = true; + /* XLib sucks */ + XkbIgnoreExtension(True); + /* X stuff */ - globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); + globalconf.display = XOpenDisplay(NULL); + if (globalconf.display == NULL) + fatal("Cannot open display"); + XSetEventQueueOwner(globalconf.display, XCBOwnsEventQueue); + globalconf.default_screen = XDefaultScreen(globalconf.display); + globalconf.connection = XGetXCBConnection(globalconf.display);; if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display (error %d)", xcb_connection_has_error(globalconf.connection)); diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index 5a434a16e..47ecda64b 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -130,6 +130,7 @@ pkg_check_modules(AWESOME_REQUIRED REQUIRED gdk-pixbuf-2.0 cairo x11 + x11-xcb xcb-cursor xcb-randr xcb-xtest diff --git a/globalconf.h b/globalconf.h index 5aa635f70..1ebd5533f 100644 --- a/globalconf.h +++ b/globalconf.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "objects/key.h" #include "common/xembed.h" @@ -65,6 +66,10 @@ ARRAY_TYPE(xproperty_t, xproperty) /** Main configuration structure */ typedef struct { + /** Xlib Display */ + Display *display; + /** X Resources DB */ + XrmDatabase xrmdb; /** Connection ref */ xcb_connection_t *connection; /** Default screen number */ diff --git a/lib/beautiful.lua b/lib/beautiful/init.lua similarity index 96% rename from lib/beautiful.lua rename to lib/beautiful/init.lua index cce64aa32..15c8ac25d 100644 --- a/lib/beautiful.lua +++ b/lib/beautiful/init.lua @@ -27,7 +27,9 @@ local capi = awesome = awesome } -local beautiful = { mt = {} } +local xresources = require("beautiful.xresources") + +local beautiful = { xresources = xresources, mt = {} } -- Local data local theme = {} @@ -50,6 +52,7 @@ local function load_font(name) -- Load new font local desc = Pango.FontDescription.from_string(name) local ctx = PangoCairo.font_map_get_default():create_context() + ctx:set_resolution(beautiful.xresources.get_dpi()) -- Apply default values from the context (e.g. a default font size) desc:merge(ctx:get_font_description(), false) diff --git a/lib/beautiful/xresources.lua b/lib/beautiful/xresources.lua new file mode 100644 index 000000000..e5fb4c9f0 --- /dev/null +++ b/lib/beautiful/xresources.lua @@ -0,0 +1,82 @@ +---------------------------------------------------------------------------- +--- Library for getting xrdb data. +-- +-- @author Yauhen Kirylau <yawghen@gmail.com> +-- @copyright 2015 Yauhen Kirylau +-- @release @AWESOME_VERSION@ +-- @module beautiful.xresources +---------------------------------------------------------------------------- + +-- Grab environment +local print = print +local awesome = awesome + +local xresources = {} + +local fallback = { + --black + color0 = '#000000', + color8 = '#465457', + --red + color1 = '#cb1578', + color9 = '#dc5e86', + --green + color2 = '#8ecb15', + color10 = '#9edc60', + --yellow + color3 = '#cb9a15', + color11 = '#dcb65e', + --blue + color4 = '#6f15cb', + color12 = '#7e5edc', + --purple + color5 = '#cb15c9', + color13 = '#b75edc', + --cyan + color6 = '#15b4cb', + color14 = '#5edcb4', + --white + color7 = '#888a85', + color15 = '#ffffff', + -- + background = '#0e0021', + foreground = '#bcbcbc', +} + +--- Get current base colorscheme from xrdb. +-- @treturn table Color table with keys 'background', 'foreground' and 'color0'..'color15' +function xresources.get_current_theme() + local keys = { 'background', 'foreground' } + for i=0,15 do table.insert(keys, "color"..i) end + local colors = {} + for _, key in ipairs(keys) do + colors[key] = awesome.xrdb_get_value("", key) + if not colors[key] then + print("W: beautiful: can't get colorscheme from xrdb (using fallback).") + return fallback + end + end + return colors +end + + +--- Get DPI value from xrdb. +-- @treturn number DPI value. +function xresources.get_dpi() + if not xresources.dpi then + xresources.dpi = tonumber(awesome.xrdb_get_value("", "Xft.dpi") or 96) + end + return xresources.dpi +end + + +--- Compute resulting size applying current DPI value. +-- @tparam number size Size +-- @treturn number Resulting size +function xresources.apply_dpi(size) + return size/96*xresources.get_dpi() +end + +return xresources + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index 80259d5e6..499c4d488 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -132,6 +132,7 @@ local function new(text, ignore_markup) end local ctx = PangoCairo.font_map_get_default():create_context() + ctx:set_resolution(beautiful.xresources.get_dpi()) ret._layout = Pango.Layout.new(ctx) ret:set_ellipsize("end") diff --git a/luaa.c b/luaa.c index f441e7c7d..7629b51ca 100644 --- a/luaa.c +++ b/luaa.c @@ -46,6 +46,7 @@ #include "spawn.h" #include "systray.h" #include "xkb.h" +#include "xrdb.h" #include #include @@ -366,6 +367,7 @@ luaA_init(xdgHandle* xdg) { "xkb_set_layout_group", luaA_xkb_set_layout_group}, { "xkb_get_layout_group", luaA_xkb_get_layout_group}, { "xkb_get_group_names", luaA_xkb_get_group_names}, + { "xrdb_get_value", luaA_xrdb_get_value}, { NULL, NULL } }; diff --git a/themes/xresources/theme.lua b/themes/xresources/theme.lua new file mode 100644 index 000000000..c98582a6e --- /dev/null +++ b/themes/xresources/theme.lua @@ -0,0 +1,267 @@ +--------------------------------------------- +-- Awesome theme which follows xrdb config -- +-- by Yauhen Kirylau -- +--------------------------------------------- + +local xresources = require("beautiful").xresources +local xrdb = xresources.get_current_theme() +local dpi = xresources.apply_dpi + +local theme = {} + +theme.font = "sans 8" + +theme.bg_normal = xrdb.background +theme.bg_focus = xrdb.color12 +theme.bg_urgent = xrdb.color9 +theme.bg_minimize = xrdb.color8 +theme.bg_systray = theme.bg_normal + +theme.fg_normal = xrdb.foreground +theme.fg_focus = theme.bg_normal +theme.fg_urgent = theme.bg_normal +theme.fg_minimize = theme.bg_normal + +theme.border_width = dpi(1) +theme.border_normal = xrdb.color0 +theme.border_focus = theme.bg_focus +theme.border_marked = xrdb.color10 + +-- There are other variable sets +-- overriding the default one when +-- defined, the sets are: +-- taglist_[bg|fg]_[focus|urgent|occupied|empty] +-- tasklist_[bg|fg]_[focus|urgent] +-- titlebar_[bg|fg]_[normal|focus] +-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color] +-- mouse_finder_[color|timeout|animate_timeout|radius|factor] +-- Example: +--theme.taglist_bg_focus = "#ff0000" + +-- Variables set for theming the menu: +-- menu_[bg|fg]_[normal|focus] +-- menu_[border_color|border_width] +theme.menu_submenu_icon = "@AWESOME_THEMES_PATH@/default/submenu.png" +theme.menu_height = dpi(16) +theme.menu_width = dpi(100) + +-- You can add as many variables as +-- you wish and access them by using +-- beautiful.variable in your rc.lua +--theme.bg_widget = "#cc0000" + +-- Define the image to load +theme.titlebar_close_button_normal = "@AWESOME_THEMES_PATH@/default/titlebar/close_normal.png" +theme.titlebar_close_button_focus = "@AWESOME_THEMES_PATH@/default/titlebar/close_focus.png" + +theme.titlebar_ontop_button_normal_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/ontop_normal_inactive.png" +theme.titlebar_ontop_button_focus_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/ontop_focus_inactive.png" +theme.titlebar_ontop_button_normal_active = "@AWESOME_THEMES_PATH@/default/titlebar/ontop_normal_active.png" +theme.titlebar_ontop_button_focus_active = "@AWESOME_THEMES_PATH@/default/titlebar/ontop_focus_active.png" + +theme.titlebar_sticky_button_normal_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/sticky_normal_inactive.png" +theme.titlebar_sticky_button_focus_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/sticky_focus_inactive.png" +theme.titlebar_sticky_button_normal_active = "@AWESOME_THEMES_PATH@/default/titlebar/sticky_normal_active.png" +theme.titlebar_sticky_button_focus_active = "@AWESOME_THEMES_PATH@/default/titlebar/sticky_focus_active.png" + +theme.titlebar_floating_button_normal_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/floating_normal_inactive.png" +theme.titlebar_floating_button_focus_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/floating_focus_inactive.png" +theme.titlebar_floating_button_normal_active = "@AWESOME_THEMES_PATH@/default/titlebar/floating_normal_active.png" +theme.titlebar_floating_button_focus_active = "@AWESOME_THEMES_PATH@/default/titlebar/floating_focus_active.png" + +theme.titlebar_maximized_button_normal_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/maximized_normal_inactive.png" +theme.titlebar_maximized_button_focus_inactive = "@AWESOME_THEMES_PATH@/default/titlebar/maximized_focus_inactive.png" +theme.titlebar_maximized_button_normal_active = "@AWESOME_THEMES_PATH@/default/titlebar/maximized_normal_active.png" +theme.titlebar_maximized_button_focus_active = "@AWESOME_THEMES_PATH@/default/titlebar/maximized_focus_active.png" + +-- Use 'w' postfix for dark background: +local bg_numberic_value = 0; +for s in theme.bg_normal:gmatch("[a-fA-F0-9][a-fA-F0-9]") do + bg_numberic_value = bg_numberic_value + tonumber("0x"..s); +end +local is_dark_bg = (bg_numberic_value < 383) +local pf = is_dark_bg and 'w' or '' +-- You can use your own layout icons like this: +theme.layout_fairh = "@AWESOME_THEMES_PATH@/default/layouts/fairh" .. pf .. ".png" +theme.layout_fairv = "@AWESOME_THEMES_PATH@/default/layouts/fairv" .. pf .. ".png" +theme.layout_floating = "@AWESOME_THEMES_PATH@/default/layouts/floating" .. pf .. ".png" +theme.layout_magnifier = "@AWESOME_THEMES_PATH@/default/layouts/magnifier" .. pf .. ".png" +theme.layout_max = "@AWESOME_THEMES_PATH@/default/layouts/max" .. pf .. ".png" +theme.layout_fullscreen = "@AWESOME_THEMES_PATH@/default/layouts/fullscreen" .. pf .. ".png" +theme.layout_tilebottom = "@AWESOME_THEMES_PATH@/default/layouts/tilebottom" .. pf .. ".png" +theme.layout_tileleft = "@AWESOME_THEMES_PATH@/default/layouts/tileleft" .. pf .. ".png" +theme.layout_tile = "@AWESOME_THEMES_PATH@/default/layouts/tile" .. pf .. ".png" +theme.layout_tiletop = "@AWESOME_THEMES_PATH@/default/layouts/tiletop" .. pf .. ".png" +theme.layout_spiral = "@AWESOME_THEMES_PATH@/default/layouts/spiral" .. pf .. ".png" +theme.layout_dwindle = "@AWESOME_THEMES_PATH@/default/layouts/dwindle" .. pf .. ".png" + + +-- Define the icon theme for application icons. If not set then the icons +-- from /usr/share/icons and /usr/share/icons/hicolor will be used. +theme.icon_theme = nil + + +-------------------------------------------------- +-- Generate vector assets using current colors: -- +-------------------------------------------------- +local cairo = require("lgi").cairo +local gears = require("gears") + +local function awesome_icon() + local size = theme.menu_height + local img = cairo.ImageSurface(cairo.Format.ARGB32, size, size) + local cr = cairo.Context(img) + cr:set_source(gears.color(theme.bg_focus)) + cr:paint() + cr:set_source(gears.color(theme.fg_focus)) + cr:set_line_width(size/20) + cr:move_to(0, size/3) + cr:line_to(size*2/3, size/3) + cr:move_to(size/3, size*2/3) + cr:line_to(size*2/3, size*2/3) + cr:line_to(size*2/3, size) + cr:stroke() + return img +end +theme.awesome_icon = awesome_icon() + +-- Taglist squares: +local taglist_square_size = dpi(4) + +local function taglist_squares_sel() + local size = taglist_square_size + local img = cairo.ImageSurface(cairo.Format.ARGB32, size, size) + local cr = cairo.Context(img) + cr:set_source(gears.color(theme.fg_normal)) + cr:paint() + return img +end +theme.taglist_squares_sel = taglist_squares_sel() + +local function taglist_squares_unsel() + local size = taglist_square_size + local img = cairo.ImageSurface(cairo.Format.ARGB32, size, size) + local cr = cairo.Context(img) + cr:set_source(gears.color(theme.fg_normal)) + cr:set_line_width(size/4) + cr:rectangle(0, 0, size, size) + cr:stroke() + return img +end +theme.taglist_squares_unsel = taglist_squares_unsel() + + +local function wallpaper() + local height = screen[1].workarea.height + local width = screen[1].workarea.width + local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height) + local cr = cairo.Context(img) + + local bg = xrdb.color8 + local fg = xrdb.color7 + local alt_fg = xrdb.color12 + if not is_dark_bg then + bg, fg = fg, bg + end + + local letter_size = height/10 + local letter_line = letter_size/18 + local letter_gap = letter_size/6 + local letter_start_x = width - width / 10 + local letter_start_y = height / 10 + + + local function make_letter(n, lines, color) + + local function make_line(coords) + for i, coord in ipairs(coords) do + if i == 1 then + cr:rel_move_to(coord[1], coord[2]) + else + cr:rel_line_to(coord[1], coord[2]) + end + end + cr:stroke() + end + + lines = lines or {} + color = color or fg + cr:set_source(gears.color(color)) + cr:rectangle( + letter_start_x, letter_start_y+(letter_size+letter_gap)*n, + letter_size, letter_size + ) + cr:fill() + cr:set_source(gears.color(bg)) + for _, line in ipairs(lines) do + cr:move_to(letter_start_x, letter_start_y+(letter_size+letter_gap)*n) + make_line(line) + end + end + + -- bg + cr:set_source(gears.color(bg)) + cr:paint() + cr:set_line_width(letter_line) + local ls = letter_size + -- a + make_letter(0, { { + { 0, ls/3 }, + { ls*2/3, 0 }, + }, { + { ls/3, ls*2/3 }, + { ls/3, 0 }, + { 0, ls/3 }, + } }, alt_fg) + -- w + make_letter(1, { { + { ls/3, 0 }, + { 0,ls*2/3 }, + }, { + { ls*2/3, 0 }, + { 0,ls*2/3 }, + } }) + -- e + make_letter(2, { { + { ls/3, ls/3 }, + { ls*2/3, 0 }, + }, { + { ls/3, ls*2/3 }, + { ls*2/3, 0 }, + } }) + -- s + make_letter(3, { { + { ls/3, ls/3 }, + { ls*2/3, 0 }, + }, { + { 0, ls*2/3 }, + { ls*2/3, 0 }, + } }) + -- o + make_letter(4, { { + { ls/2, ls/3 }, + { 0, ls/3 }, + } }) + -- m + make_letter(5, { { + { ls/3, ls/3 }, + { 0,ls*2/3 }, + }, { + { ls*2/3, ls/3 }, + { 0,ls*2/3 }, + } }) + -- e + make_letter(6, { { + { ls/3, ls/3 }, + { ls*2/3, 0 }, + }, { + { ls/3, ls*2/3 }, + { ls*2/3, 0 }, + } }) + + return img +end +theme.wallpaper = wallpaper() + +return theme +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/xrdb.c b/xrdb.c new file mode 100644 index 000000000..f32693c71 --- /dev/null +++ b/xrdb.c @@ -0,0 +1,73 @@ +/* + * xrdb.c - X Resources DataBase communication functions + * + * Copyright © 2015 Yauhen Kirylau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "xrdb.h" +#include "globalconf.h" + +#include + +#include + +/* \brief open X display and X Resources DB + */ +static void xrdb_init(void) { + XrmInitialize(); // @TODO: it works without it but in docs it's said what it's + // needed + if (!(globalconf.xrmdb = XrmGetDatabase(globalconf.display))) { + + /* taken from xpbiff: */ + /* >> what a hack; need to initialize dpy->db */ + (void)XGetDefault(globalconf.display, "", ""); + /**/ + + if (!(globalconf.xrmdb = XrmGetDatabase(globalconf.display))) + warn("Can't open xrdb\n"); + } +} + +/* \brief get value from X Resources DataBase + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam string xrdb class, ie "URxvt" or "" + * \lparam string xrdb name, ie "background" or "color0" + * \lreturn string xrdb value or nil if not exists. \ + */ +int luaA_xrdb_get_value(lua_State *L) { + if (!globalconf.xrmdb) + xrdb_init(); + + char *resource_type; + int resource_code; + XrmValue resource_value; + const char *resource_class = luaL_checkstring(L, 1); + const char *resource_name = luaL_checkstring(L, 2); + + resource_code = XrmGetResource(globalconf.xrmdb, resource_name, resource_class, + &resource_type, &resource_value); + if (resource_code && (strcmp(resource_type, "String") == 0)) { + lua_pushstring(L, (char *)resource_value.addr); + return 1; + } else { + luaA_warn(L, "Failed to get xrdb value"); + return 0; + } +} diff --git a/xrdb.h b/xrdb.h new file mode 100644 index 000000000..57a0083a5 --- /dev/null +++ b/xrdb.h @@ -0,0 +1,30 @@ +/* + * xrdb.h - X Resources DataBase communication functions + * + * Copyright © 2015 Yauhen Kirylau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef AWESOME_XRDB_H +#define AWESOME_XRDB_H + +#include + +int luaA_xrdb_get_value(lua_State *L); + + +#endif