draw: remove custom markup support
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
a4d914f0e4
commit
26da80f90a
|
@ -64,7 +64,6 @@ set(AWE_SRCS
|
||||||
${SOURCE_DIR}/swindow.c
|
${SOURCE_DIR}/swindow.c
|
||||||
${SOURCE_DIR}/common/buffer.c
|
${SOURCE_DIR}/common/buffer.c
|
||||||
${SOURCE_DIR}/common/atoms.c
|
${SOURCE_DIR}/common/atoms.c
|
||||||
${SOURCE_DIR}/common/markup.c
|
|
||||||
${SOURCE_DIR}/common/socket.c
|
${SOURCE_DIR}/common/socket.c
|
||||||
${SOURCE_DIR}/common/util.c
|
${SOURCE_DIR}/common/util.c
|
||||||
${SOURCE_DIR}/common/version.c
|
${SOURCE_DIR}/common/version.c
|
||||||
|
|
1
README
1
README
|
@ -14,7 +14,6 @@ In order to build awesome itself, you need header files and libs of:
|
||||||
- cairo built with xcb support
|
- cairo built with xcb support
|
||||||
- pango and pangocairo
|
- pango and pangocairo
|
||||||
- libev
|
- libev
|
||||||
- glib
|
|
||||||
- Imlib2
|
- Imlib2
|
||||||
- dbus (optional, use -DWITH_DBUS=OFF with cmake to disable)
|
- dbus (optional, use -DWITH_DBUS=OFF with cmake to disable)
|
||||||
- gperf
|
- gperf
|
||||||
|
|
|
@ -37,22 +37,13 @@ alpha channel to `aa' and will blend the green with the color under it.
|
||||||
|
|
||||||
TEXT FORMAT
|
TEXT FORMAT
|
||||||
-----------
|
-----------
|
||||||
You can use and mix Pango markup and awesome markup in text string.
|
You can use Pango markup in text string.
|
||||||
This allows to format the text rendered in widgets.
|
This allows to format the text rendered in widgets.
|
||||||
Pango markup documentation can be found in the Pango documentation at
|
Pango markup documentation can be found in the Pango documentation at
|
||||||
http://library.gnome.org/devel/pango/stable/PangoMarkupFormat.html.
|
http://library.gnome.org/devel/pango/stable/PangoMarkupFormat.html.
|
||||||
|
|
||||||
List of *awesome* markup elements and their attributes:
|
|
||||||
|
|
||||||
* bg
|
|
||||||
- image: path to a background image
|
|
||||||
- align: background image alignment
|
|
||||||
- resize: resize background image to text size
|
|
||||||
|
|
||||||
A Pango markup example: <span weight="bold" foreground="#336699">...</span>.
|
A Pango markup example: <span weight="bold" foreground="#336699">...</span>.
|
||||||
|
|
||||||
An *awesome* markup example: <text align="right"/>.
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
awesome(1) awesome-client(1)
|
awesome(1) awesome-client(1)
|
||||||
|
|
|
@ -104,7 +104,7 @@ mymainmenu = awful.menu.new({ items = { { "awesome", myawesomemenu, beautiful.aw
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
|
mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon),
|
||||||
menu = mymainmenu })
|
menu = mymainmenu })
|
||||||
|
|
||||||
-- Create a systray
|
-- Create a systray
|
||||||
|
|
1
client.c
1
client.c
|
@ -30,7 +30,6 @@
|
||||||
#include "systray.h"
|
#include "systray.h"
|
||||||
#include "property.h"
|
#include "property.h"
|
||||||
#include "wibox.h"
|
#include "wibox.h"
|
||||||
#include "common/markup.h"
|
|
||||||
#include "common/atoms.h"
|
#include "common/atoms.h"
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
extern awesome_t globalconf;
|
||||||
|
|
182
common/markup.c
182
common/markup.c
|
@ -1,182 +0,0 @@
|
||||||
/*
|
|
||||||
* markup.c - markup functions
|
|
||||||
*
|
|
||||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
|
||||||
*
|
|
||||||
* 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 <glib.h>
|
|
||||||
|
|
||||||
#include "common/markup.h"
|
|
||||||
|
|
||||||
/** Callback to invoke when the opening tag of an element is seen.
|
|
||||||
* Here is just copies element elements we do not care about, and copies
|
|
||||||
* values we care.
|
|
||||||
* \param context the context of GMarkup
|
|
||||||
* \param element_name element name
|
|
||||||
* \param attribute_names array of attribute names
|
|
||||||
* \param attribute_values array of attribute values
|
|
||||||
* \param user_data pointer to user data, here a markup_parser_data_t pointer
|
|
||||||
* \param error a GError
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
markup_parse_start_element(GMarkupParseContext *context __attribute__ ((unused)),
|
|
||||||
const gchar *element_name,
|
|
||||||
const gchar **attribute_names,
|
|
||||||
const gchar **attribute_values,
|
|
||||||
gpointer user_data,
|
|
||||||
GError **error __attribute__ ((unused)))
|
|
||||||
{
|
|
||||||
markup_parser_data_t *p = (markup_parser_data_t *) user_data;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; p->elements[i]; i++)
|
|
||||||
if(!a_strcmp(element_name, p->elements[i])) {
|
|
||||||
(*p->on_element)(p, element_name, attribute_names,
|
|
||||||
attribute_values);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(a_strcmp(element_name, "markup"))
|
|
||||||
{
|
|
||||||
buffer_addf(&p->text, "<%s", element_name);
|
|
||||||
for(i = 0; attribute_names[i]; i++)
|
|
||||||
{
|
|
||||||
buffer_addf(&p->text, " %s=\"%s\"", attribute_names[i],
|
|
||||||
attribute_values[i]);
|
|
||||||
}
|
|
||||||
buffer_addc(&p->text, '>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Callback to invoke when the closing tag of an element is seen. Note that
|
|
||||||
* this is also called for empty tags like \<empty/\>.
|
|
||||||
* Here is just copies element elements we do not care about.
|
|
||||||
* \param context the context of GMarkup
|
|
||||||
* \param element_name element name
|
|
||||||
* \param user_data pointer to user data, here a markup_parser_data_t pointer
|
|
||||||
* \param error a GError
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
markup_parse_end_element(GMarkupParseContext *context __attribute__ ((unused)),
|
|
||||||
const gchar *element_name,
|
|
||||||
gpointer user_data,
|
|
||||||
GError **error __attribute__ ((unused)))
|
|
||||||
{
|
|
||||||
markup_parser_data_t *p = (markup_parser_data_t *) user_data;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; p->elements[i]; i++)
|
|
||||||
if(!a_strcmp(element_name, p->elements[i]))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(a_strcmp(element_name, "markup"))
|
|
||||||
buffer_addf(&p->text, "</%s>", element_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Callback to invoke when some text is seen (text is always inside an
|
|
||||||
* element). Note that the text of an element may be spread over multiple calls
|
|
||||||
* of this function. If the G_MARKUP_TREAT_CDATA_AS_TEXT flag is set, this
|
|
||||||
* function is also called for the content of CDATA marked sections.
|
|
||||||
* Here it recopies blindly the text in the text attribute of user_data.
|
|
||||||
* \param context the context of GMarkup
|
|
||||||
* \param text the text
|
|
||||||
* \param text_len the text length
|
|
||||||
* \param user_data pointer to user data, here a markup_parser_data_t pointer
|
|
||||||
* \param error a GError
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
markup_parse_text(GMarkupParseContext *context __attribute__ ((unused)),
|
|
||||||
const gchar *text,
|
|
||||||
gsize text_len,
|
|
||||||
gpointer user_data,
|
|
||||||
GError **error __attribute__ ((unused)))
|
|
||||||
{
|
|
||||||
markup_parser_data_t *p = (markup_parser_data_t *) user_data;
|
|
||||||
|
|
||||||
if (text_len) {
|
|
||||||
buffer_grow(&p->text, text_len);
|
|
||||||
buffer_add_xmlescaped(&p->text, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a markup_parser_data_t structure with elements list.
|
|
||||||
* \param a pointer to an allocated markup_parser_data_t which must be wiped
|
|
||||||
* with markup_parser_data_wipe()
|
|
||||||
*/
|
|
||||||
void markup_parser_data_init(markup_parser_data_t *p)
|
|
||||||
{
|
|
||||||
buffer_init(&p->text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wipe a markup_parser_data_t initialized with markup_parser_data_init.
|
|
||||||
* \param p markup_parser_data_t address
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
markup_parser_data_wipe(markup_parser_data_t *p)
|
|
||||||
{
|
|
||||||
buffer_wipe(&p->text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse markup defined in data on the string str.
|
|
||||||
* \param data A markup_parser_data_t allocated by markup_parser_data_new().
|
|
||||||
* \param str A string to parse markup from.
|
|
||||||
* \param slen String length.
|
|
||||||
* \return True if success, false otherwise.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
markup_parse(markup_parser_data_t *data, const char *str, ssize_t slen)
|
|
||||||
{
|
|
||||||
static GMarkupParser const parser =
|
|
||||||
{
|
|
||||||
/* start_element */
|
|
||||||
markup_parse_start_element,
|
|
||||||
/* end_element */
|
|
||||||
markup_parse_end_element,
|
|
||||||
/* text */
|
|
||||||
markup_parse_text,
|
|
||||||
/* passthrough */
|
|
||||||
NULL,
|
|
||||||
/* error */
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
GMarkupParseContext *mkp_ctx;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if(slen <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
mkp_ctx = g_markup_parse_context_new(&parser, 0, data, NULL);
|
|
||||||
|
|
||||||
if(!g_markup_parse_context_parse(mkp_ctx, "<markup>", -1, &error)
|
|
||||||
|| !g_markup_parse_context_parse(mkp_ctx, str, slen, &error)
|
|
||||||
|| !g_markup_parse_context_parse(mkp_ctx, "</markup>", -1, &error)
|
|
||||||
|| !g_markup_parse_context_end_parse(mkp_ctx, &error))
|
|
||||||
{
|
|
||||||
warn("unable to parse text \"%s\": %s", str, error ? error->message : "unknown error");
|
|
||||||
if(error)
|
|
||||||
g_error_free(error);
|
|
||||||
g_markup_parse_context_free(mkp_ctx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_markup_parse_context_free(mkp_ctx);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* markup.h - markup header
|
|
||||||
*
|
|
||||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
|
||||||
*
|
|
||||||
* 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_COMMON_MARKUP_H
|
|
||||||
#define AWESOME_COMMON_MARKUP_H
|
|
||||||
|
|
||||||
#include "common/buffer.h"
|
|
||||||
|
|
||||||
typedef struct markup_parser_data_t markup_parser_data_t;
|
|
||||||
|
|
||||||
typedef void (markup_on_elem_f)(markup_parser_data_t *, const char *,
|
|
||||||
const char **, const char **);
|
|
||||||
|
|
||||||
struct markup_parser_data_t
|
|
||||||
{
|
|
||||||
buffer_t text;
|
|
||||||
const char * const *elements;
|
|
||||||
markup_on_elem_f *on_element;
|
|
||||||
void *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
void markup_parser_data_init(markup_parser_data_t *);
|
|
||||||
void markup_parser_data_wipe(markup_parser_data_t *);
|
|
||||||
bool markup_parse(markup_parser_data_t *data, const char *, ssize_t);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
|
@ -1,8 +1,10 @@
|
||||||
1
|
|
||||||
align
|
align
|
||||||
bar_data_add
|
bar_data_add
|
||||||
bar_properties_set
|
bar_properties_set
|
||||||
bg
|
bg
|
||||||
|
bg_align
|
||||||
|
bg_image
|
||||||
|
bg_resize
|
||||||
border_color
|
border_color
|
||||||
border_padding
|
border_padding
|
||||||
border_width
|
border_width
|
||||||
|
@ -57,7 +59,6 @@ Mod5
|
||||||
mouse_enter
|
mouse_enter
|
||||||
mouse_leave
|
mouse_leave
|
||||||
name
|
name
|
||||||
on
|
|
||||||
ontop
|
ontop
|
||||||
opacity
|
opacity
|
||||||
orientation
|
orientation
|
||||||
|
@ -84,7 +85,6 @@ ticks_gap
|
||||||
titlebar
|
titlebar
|
||||||
top
|
top
|
||||||
transient_for
|
transient_for
|
||||||
true
|
|
||||||
type
|
type
|
||||||
urgent
|
urgent
|
||||||
valign
|
valign
|
||||||
|
@ -96,4 +96,3 @@ word
|
||||||
word_char
|
word_char
|
||||||
workarea
|
workarea
|
||||||
wrap
|
wrap
|
||||||
yes
|
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tokenize.h"
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
East,
|
East,
|
||||||
|
@ -313,29 +311,6 @@ a_strncat(char *dst, ssize_t n, const char *src, ssize_t l)
|
||||||
return dlen + a_strncpy(dst + dlen, n - dlen, src, l);
|
return dlen + a_strncpy(dst + dlen, n - dlen, src, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief convert a string to a boolean value.
|
|
||||||
*
|
|
||||||
* The a_strtobool() function converts a string \c s into a boolean.
|
|
||||||
* It recognizes the strings "true", "on", "yes" and "1".
|
|
||||||
*
|
|
||||||
* \param[in] s the string to convert
|
|
||||||
* \return true if the string is recognized as possibly true, false otherwise.
|
|
||||||
*/
|
|
||||||
static inline bool
|
|
||||||
a_strtobool(const char *s, ssize_t len)
|
|
||||||
{
|
|
||||||
switch(a_tokenize(s, len))
|
|
||||||
{
|
|
||||||
case A_TK_TRUE:
|
|
||||||
case A_TK_YES:
|
|
||||||
case A_TK_ON:
|
|
||||||
case A_TK_1:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define fatal(string, ...) _fatal(__LINE__, \
|
#define fatal(string, ...) _fatal(__LINE__, \
|
||||||
__FUNCTION__, \
|
__FUNCTION__, \
|
||||||
string, ## __VA_ARGS__)
|
string, ## __VA_ARGS__)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
#include "common/atoms.h"
|
#include "common/atoms.h"
|
||||||
|
#include "common/tokenize.h"
|
||||||
|
|
||||||
/** Get the string value of an atom.
|
/** Get the string value of an atom.
|
||||||
* \param conn X connection.
|
* \param conn X connection.
|
||||||
|
|
167
draw.c
167
draw.c
|
@ -32,7 +32,6 @@
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
|
||||||
#include "common/tokenize.h"
|
#include "common/tokenize.h"
|
||||||
#include "common/markup.h"
|
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
extern awesome_t globalconf;
|
||||||
|
|
||||||
|
@ -159,81 +158,28 @@ draw_font_delete(font_t **font)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/** Initialize a draw_text_context_t with text data.
|
||||||
draw_markup_on_element(markup_parser_data_t *p, const char *elem,
|
* \param data The draw text context to init.
|
||||||
const char **names, const char **values)
|
* \param str The text string to render.
|
||||||
|
* \param slen The text string length.
|
||||||
|
* \return True if everything is ok, false otherwise.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
draw_text_context_init(draw_text_context_t *data, const char *str, ssize_t slen)
|
||||||
{
|
{
|
||||||
draw_parser_data_t *data = p->priv;
|
|
||||||
|
|
||||||
/* hack: markup.c validates tags so we can avoid strcmps here */
|
|
||||||
switch (*elem) {
|
|
||||||
case 'b':
|
|
||||||
if(elem[2] == '_') /* bg_margin */
|
|
||||||
for(; *names; names++, values++)
|
|
||||||
switch(a_tokenize(*names, -1))
|
|
||||||
{
|
|
||||||
case A_TK_LEFT:
|
|
||||||
data->bg_margin.left = atoi(*values);
|
|
||||||
break;
|
|
||||||
case A_TK_TOP:
|
|
||||||
data->bg_margin.top = atoi(*values);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else /* bg */
|
|
||||||
for(; *names; names++, values++)
|
|
||||||
switch(a_tokenize(*names, -1))
|
|
||||||
{
|
|
||||||
case A_TK_IMAGE:
|
|
||||||
if(data->bg_image)
|
|
||||||
image_delete(&data->bg_image);
|
|
||||||
data->bg_image = image_new_from_file(*values);
|
|
||||||
break;
|
|
||||||
case A_TK_ALIGN:
|
|
||||||
data->bg_align = draw_align_fromstr(*values, -1);
|
|
||||||
break;
|
|
||||||
case A_TK_RESIZE:
|
|
||||||
data->bg_resize = a_strtobool(*values, -1);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
draw_text_markup_expand(draw_parser_data_t *data,
|
|
||||||
const char *str, ssize_t slen)
|
|
||||||
{
|
|
||||||
static char const * const elements[] = { "bg", "bg_margin", NULL };
|
|
||||||
markup_parser_data_t p =
|
|
||||||
{
|
|
||||||
.elements = elements,
|
|
||||||
.priv = data,
|
|
||||||
.on_element = &draw_markup_on_element,
|
|
||||||
};
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
markup_parser_data_init(&p);
|
if(!pango_parse_markup(str, slen, 0, &data->attr_list, &data->text, NULL, &error))
|
||||||
|
|
||||||
if(!markup_parse(&p, str, slen))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
if(!pango_parse_markup(p.text.s, p.text.len, 0, &data->attr_list, &data->text, NULL, &error))
|
|
||||||
{
|
{
|
||||||
warn("cannot parse pango markup: %s", error ? error->message : "unknown error");
|
warn("cannot parse pango markup: %s", error ? error->message : "unknown error");
|
||||||
if(error)
|
if(error)
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
goto bailout;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->len = a_strlen(data->text);
|
data->len = a_strlen(data->text);
|
||||||
ret = true;
|
|
||||||
|
|
||||||
bailout:
|
return true;
|
||||||
markup_parser_data_wipe(&p);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize a new draw context.
|
/** Initialize a new draw context.
|
||||||
|
@ -273,57 +219,17 @@ draw_context_init(draw_context_t *d, int phys_screen,
|
||||||
* \param align Text alignment.
|
* \param align Text alignment.
|
||||||
* \param margin Margin to respect when drawing text.
|
* \param margin Margin to respect when drawing text.
|
||||||
* \param area Area to draw to.
|
* \param area Area to draw to.
|
||||||
* \param text Text to draw.
|
* \param data Draw text context data.
|
||||||
* \param len Text to draw length.
|
|
||||||
* \param data Optional parser data.
|
|
||||||
* \param ext Text extents.
|
* \param ext Text extents.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
draw_text(draw_context_t *ctx, font_t *font, PangoEllipsizeMode ellip, PangoWrapMode wrap,
|
draw_text(draw_context_t *ctx, draw_text_context_t *data, font_t *font,
|
||||||
alignment_t align, padding_t *margin, area_t area, const char *text, ssize_t len,
|
PangoEllipsizeMode ellip, PangoWrapMode wrap,
|
||||||
draw_parser_data_t *pdata, area_t *ext)
|
alignment_t align, padding_t *margin, area_t area, area_t *ext)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
draw_parser_data_t parser_data;
|
|
||||||
|
|
||||||
if(!pdata)
|
pango_layout_set_text(ctx->layout, data->text, data->len);
|
||||||
{
|
|
||||||
draw_parser_data_init(&parser_data);
|
|
||||||
if(draw_text_markup_expand(&parser_data, text, len))
|
|
||||||
{
|
|
||||||
text = parser_data.text;
|
|
||||||
len = parser_data.len;
|
|
||||||
}
|
|
||||||
pdata = &parser_data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
text = pdata->text;
|
|
||||||
len = pdata->len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pdata->bg_image)
|
|
||||||
{
|
|
||||||
x = area.x;
|
|
||||||
y = area.y;
|
|
||||||
switch(pdata->bg_align)
|
|
||||||
{
|
|
||||||
case AlignCenter:
|
|
||||||
x += (area.width - pdata->bg_image->width) / 2;
|
|
||||||
break;
|
|
||||||
case AlignRight:
|
|
||||||
x += area.width- pdata->bg_image->width;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
draw_image(ctx,
|
|
||||||
x + pdata->bg_margin.left,
|
|
||||||
y + pdata->bg_margin.top,
|
|
||||||
pdata->bg_resize ? area.height : 0, pdata->bg_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
pango_layout_set_text(ctx->layout, pdata->text, pdata->len);
|
|
||||||
pango_layout_set_width(ctx->layout,
|
pango_layout_set_width(ctx->layout,
|
||||||
pango_units_from_double(area.width
|
pango_units_from_double(area.width
|
||||||
- (margin->left
|
- (margin->left
|
||||||
|
@ -332,7 +238,7 @@ draw_text(draw_context_t *ctx, font_t *font, PangoEllipsizeMode ellip, PangoWrap
|
||||||
- (margin->top + margin->bottom));
|
- (margin->top + margin->bottom));
|
||||||
pango_layout_set_ellipsize(ctx->layout, ellip);
|
pango_layout_set_ellipsize(ctx->layout, ellip);
|
||||||
pango_layout_set_wrap(ctx->layout, wrap);
|
pango_layout_set_wrap(ctx->layout, wrap);
|
||||||
pango_layout_set_attributes(ctx->layout, pdata->attr_list);
|
pango_layout_set_attributes(ctx->layout, data->attr_list);
|
||||||
pango_layout_set_font_description(ctx->layout, font->desc);
|
pango_layout_set_font_description(ctx->layout, font->desc);
|
||||||
|
|
||||||
x = area.x + margin->left;
|
x = area.x + margin->left;
|
||||||
|
@ -364,9 +270,6 @@ draw_text(draw_context_t *ctx, font_t *font, PangoEllipsizeMode ellip, PangoWrap
|
||||||
ctx->fg.alpha / 65535.0);
|
ctx->fg.alpha / 65535.0);
|
||||||
pango_cairo_update_layout(ctx->cr, ctx->layout);
|
pango_cairo_update_layout(ctx->cr, ctx->layout);
|
||||||
pango_cairo_show_layout(ctx->cr, ctx->layout);
|
pango_cairo_show_layout(ctx->cr, ctx->layout);
|
||||||
|
|
||||||
if (pdata == &parser_data)
|
|
||||||
draw_parser_data_wipe(&parser_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Setup color-source for cairo (gradient or mono).
|
/** Setup color-source for cairo (gradient or mono).
|
||||||
|
@ -657,14 +560,13 @@ draw_graph_line(draw_context_t *ctx, area_t rect, int *to, int cur_index,
|
||||||
* \param y Y coordinate.
|
* \param y Y coordinate.
|
||||||
* \param w Width.
|
* \param w Width.
|
||||||
* \param h Height.
|
* \param h Height.
|
||||||
* \param wanted_h Wanted height: if > 0, image will be resized.
|
* \param ratio The ratio to apply to the image.
|
||||||
* \param data The image pixels array.
|
* \param data The image pixels array.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
draw_image_from_argb_data(draw_context_t *ctx, int x, int y, int w, int h,
|
draw_image_from_argb_data(draw_context_t *ctx, int x, int y, int w, int h,
|
||||||
int wanted_h, unsigned char *data)
|
double ratio, unsigned char *data)
|
||||||
{
|
{
|
||||||
double ratio;
|
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_surface_t *source;
|
cairo_surface_t *source;
|
||||||
|
|
||||||
|
@ -675,14 +577,8 @@ draw_image_from_argb_data(draw_context_t *ctx, int x, int y, int w, int h,
|
||||||
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w));
|
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w));
|
||||||
#endif
|
#endif
|
||||||
cr = cairo_create(ctx->surface);
|
cr = cairo_create(ctx->surface);
|
||||||
if(wanted_h > 0 && h > 0)
|
cairo_scale(cr, ratio, ratio);
|
||||||
{
|
cairo_set_source_surface(cr, source, x / ratio, y / ratio);
|
||||||
ratio = (double) wanted_h / (double) h;
|
|
||||||
cairo_scale(cr, ratio, ratio);
|
|
||||||
cairo_set_source_surface(cr, source, x / ratio, y / ratio);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cairo_set_source_surface(cr, source, x, y);
|
|
||||||
|
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
|
||||||
|
@ -694,13 +590,13 @@ draw_image_from_argb_data(draw_context_t *ctx, int x, int y, int w, int h,
|
||||||
* \param ctx Draw context to draw to.
|
* \param ctx Draw context to draw to.
|
||||||
* \param x X coordinate.
|
* \param x X coordinate.
|
||||||
* \param y Y coordinate.
|
* \param y Y coordinate.
|
||||||
* \param wanted_h Wanted height: if > 0, image will be resized.
|
* \param ratio The ratio to apply to the image.
|
||||||
* \param image The image to draw.
|
* \param image The image to draw.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
draw_image(draw_context_t *ctx, int x, int y, int wanted_h, image_t *image)
|
draw_image(draw_context_t *ctx, int x, int y, double ratio, image_t *image)
|
||||||
{
|
{
|
||||||
draw_image_from_argb_data(ctx, x, y, image->width, image->height, wanted_h, image->data);
|
draw_image_from_argb_data(ctx, x, y, image->width, image->height, ratio, image->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Rotate a pixmap.
|
/** Rotate a pixmap.
|
||||||
|
@ -743,14 +639,12 @@ draw_rotate(draw_context_t *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the width and height of a text in pixel.
|
/** Return the width and height of a text in pixel.
|
||||||
|
* \param data The draw context text data.
|
||||||
* \param font Font to use.
|
* \param font Font to use.
|
||||||
* \param text The text.
|
|
||||||
* \param len The text length.
|
|
||||||
* \param pdata The parser data to fill.
|
|
||||||
* \return Text height and width.
|
* \return Text height and width.
|
||||||
*/
|
*/
|
||||||
area_t
|
area_t
|
||||||
draw_text_extents(font_t *font, const char *text, ssize_t len, draw_parser_data_t *parser_data)
|
draw_text_extents(draw_text_context_t *data, font_t *font)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
@ -759,10 +653,7 @@ draw_text_extents(font_t *font, const char *text, ssize_t len, draw_parser_data_
|
||||||
xcb_screen_t *s = xutil_screen_get(globalconf.connection, globalconf.default_screen);
|
xcb_screen_t *s = xutil_screen_get(globalconf.connection, globalconf.default_screen);
|
||||||
area_t geom = { 0, 0, 0, 0 };
|
area_t geom = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
if(!len)
|
if(data->len <= 0)
|
||||||
return geom;
|
|
||||||
|
|
||||||
if(!draw_text_markup_expand(parser_data, text, len))
|
|
||||||
return geom;
|
return geom;
|
||||||
|
|
||||||
surface = cairo_xcb_surface_create(globalconf.connection,
|
surface = cairo_xcb_surface_create(globalconf.connection,
|
||||||
|
@ -773,8 +664,8 @@ draw_text_extents(font_t *font, const char *text, ssize_t len, draw_parser_data_
|
||||||
|
|
||||||
cr = cairo_create(surface);
|
cr = cairo_create(surface);
|
||||||
layout = pango_cairo_create_layout(cr);
|
layout = pango_cairo_create_layout(cr);
|
||||||
pango_layout_set_text(layout, parser_data->text, parser_data->len);
|
pango_layout_set_text(layout, data->text, data->len);
|
||||||
pango_layout_set_attributes(layout, parser_data->attr_list);
|
pango_layout_set_attributes(layout, data->attr_list);
|
||||||
pango_layout_set_font_description(layout, font->desc);
|
pango_layout_set_font_description(layout, font->desc);
|
||||||
pango_layout_get_pixel_extents(layout, NULL, &ext);
|
pango_layout_get_pixel_extents(layout, NULL, &ext);
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
|
28
draw.h
28
draw.h
|
@ -169,16 +169,10 @@ typedef struct
|
||||||
PangoAttrList *attr_list;
|
PangoAttrList *attr_list;
|
||||||
char *text;
|
char *text;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct
|
} draw_text_context_t;
|
||||||
{
|
|
||||||
int top, left;
|
|
||||||
} bg_margin;
|
|
||||||
image_t *bg_image;
|
|
||||||
alignment_t bg_align;
|
|
||||||
bool bg_resize;
|
|
||||||
} draw_parser_data_t;
|
|
||||||
|
|
||||||
void draw_text(draw_context_t *, font_t *, PangoEllipsizeMode, PangoWrapMode, alignment_t, padding_t *, area_t, const char *, ssize_t len, draw_parser_data_t *, area_t *);
|
bool draw_text_context_init(draw_text_context_t *, const char *, ssize_t);
|
||||||
|
void draw_text(draw_context_t *, draw_text_context_t *, font_t *, PangoEllipsizeMode, PangoWrapMode, alignment_t, padding_t *, area_t, area_t *);
|
||||||
void draw_rectangle(draw_context_t *, area_t, float, bool, const xcolor_t *);
|
void draw_rectangle(draw_context_t *, area_t, float, bool, const xcolor_t *);
|
||||||
void draw_rectangle_gradient(draw_context_t *, area_t, float, bool, vector_t,
|
void draw_rectangle_gradient(draw_context_t *, area_t, float, bool, vector_t,
|
||||||
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
||||||
|
@ -188,9 +182,9 @@ void draw_graph(draw_context_t *, area_t, int *, int *, int, position_t, vector_
|
||||||
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
||||||
void draw_graph_line(draw_context_t *, area_t, int *, int, position_t, vector_t,
|
void draw_graph_line(draw_context_t *, area_t, int *, int, position_t, vector_t,
|
||||||
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
const xcolor_t *, const xcolor_t *, const xcolor_t *);
|
||||||
void draw_image(draw_context_t *, int, int, int, image_t *);
|
void draw_image(draw_context_t *, int, int, double, image_t *);
|
||||||
void draw_rotate(draw_context_t *, xcb_drawable_t, xcb_drawable_t, int, int, int, int, double, int, int);
|
void draw_rotate(draw_context_t *, xcb_drawable_t, xcb_drawable_t, int, int, int, int, double, int, int);
|
||||||
area_t draw_text_extents(font_t *, const char *, ssize_t, draw_parser_data_t *);
|
area_t draw_text_extents(draw_text_context_t *, font_t *);
|
||||||
alignment_t draw_align_fromstr(const char *, ssize_t);
|
alignment_t draw_align_fromstr(const char *, ssize_t);
|
||||||
const char *draw_align_tostr(alignment_t);
|
const char *draw_align_tostr(alignment_t);
|
||||||
|
|
||||||
|
@ -212,19 +206,13 @@ xcolor_init_request_t xcolor_init_unchecked(xcolor_t *, const char *, ssize_t);
|
||||||
bool xcolor_init_reply(xcolor_init_request_t);
|
bool xcolor_init_reply(xcolor_init_request_t);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
draw_parser_data_init(draw_parser_data_t *pdata)
|
draw_text_context_wipe(draw_text_context_t *pdata)
|
||||||
{
|
|
||||||
p_clear(pdata, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
draw_parser_data_wipe(draw_parser_data_t *pdata)
|
|
||||||
{
|
{
|
||||||
if(pdata)
|
if(pdata)
|
||||||
{
|
{
|
||||||
pango_attr_list_unref(pdata->attr_list);
|
if(pdata->attr_list)
|
||||||
|
pango_attr_list_unref(pdata->attr_list);
|
||||||
p_delete(&pdata->text);
|
p_delete(&pdata->text);
|
||||||
image_unref(&pdata->bg_image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
-- Grab environment we need
|
-- Grab environment we need
|
||||||
local math = math
|
local math = math
|
||||||
|
local image = image
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local otable = otable
|
local otable = otable
|
||||||
local capi =
|
local capi =
|
||||||
|
@ -72,13 +73,13 @@ function add(c, args)
|
||||||
local closef
|
local closef
|
||||||
if theme.titlebar_close_button_focus then
|
if theme.titlebar_close_button_focus then
|
||||||
closef = widget.button({ align = "right",
|
closef = widget.button({ align = "right",
|
||||||
image = theme.titlebar_close_button_focus })
|
image = image(theme.titlebar_close_button_focus) })
|
||||||
end
|
end
|
||||||
|
|
||||||
local close
|
local close
|
||||||
if theme.titlebar_close_button_normal then
|
if theme.titlebar_close_button_normal then
|
||||||
close = widget.button({ align = "right",
|
close = widget.button({ align = "right",
|
||||||
image = theme.titlebar_close_button_normal })
|
image = image(theme.titlebar_close_button_normal) })
|
||||||
end
|
end
|
||||||
|
|
||||||
if close or closef then
|
if close or closef then
|
||||||
|
|
|
@ -15,6 +15,7 @@ local capi =
|
||||||
client = client,
|
client = client,
|
||||||
button = button,
|
button = button,
|
||||||
widget = widget,
|
widget = widget,
|
||||||
|
image = image,
|
||||||
mouse = mouse
|
mouse = mouse
|
||||||
}
|
}
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
|
@ -51,20 +52,24 @@ local function taglist_update (screen, w, label, buttons, data)
|
||||||
end
|
end
|
||||||
-- Update widgets text
|
-- Update widgets text
|
||||||
for k, tag in ipairs(tags) do
|
for k, tag in ipairs(tags) do
|
||||||
w[k].text, w[k].bg = label(tag)
|
local text, bg, bg_image, bg_resize = label(tag)
|
||||||
if buttons then
|
w[k].text = text
|
||||||
if not data[tag] then
|
if text then
|
||||||
-- Replace press function by a new one calling with tags as
|
w[k].bg, w[k].bg_image, w[k].bg_resize = bg, bg_image, bg_resize
|
||||||
-- argument.
|
if buttons then
|
||||||
-- This is done here because order of tags can change
|
if not data[tag] then
|
||||||
data[tag] = {}
|
-- Replace press function by a new one calling with tags as
|
||||||
for kb, b in ipairs(buttons) do
|
-- argument.
|
||||||
-- Copy object
|
-- This is done here because order of tags can change
|
||||||
data[tag][kb] = capi.button(b)
|
data[tag] = {}
|
||||||
data[tag][kb].press = function () b.press(tag) end
|
for kb, b in ipairs(buttons) do
|
||||||
|
-- Copy object
|
||||||
|
data[tag][kb] = capi.button(b)
|
||||||
|
data[tag][kb].press = function () b.press(tag) end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
w[k]:buttons(data[tag])
|
||||||
end
|
end
|
||||||
w[k]:buttons(data[tag])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -112,7 +117,8 @@ end
|
||||||
-- squares_sel Optional: a user provided image for selected squares.
|
-- squares_sel Optional: a user provided image for selected squares.
|
||||||
-- squares_unsel Optional: a user provided image for unselected squares.
|
-- squares_unsel Optional: a user provided image for unselected squares.
|
||||||
-- squares_resize Optional: true or false to resize squares.
|
-- squares_resize Optional: true or false to resize squares.
|
||||||
-- @return A string to print and a background color.
|
-- @return A string to print, a background color, a background image and a
|
||||||
|
-- background resize value.
|
||||||
function taglist.label.all(t, args)
|
function taglist.label.all(t, args)
|
||||||
if not args then args = {} end
|
if not args then args = {} end
|
||||||
local theme = beautiful.get()
|
local theme = beautiful.get()
|
||||||
|
@ -124,23 +130,26 @@ function taglist.label.all(t, args)
|
||||||
local taglist_squares_unsel = args.squares_unsel or theme.taglist_squares_unsel
|
local taglist_squares_unsel = args.squares_unsel or theme.taglist_squares_unsel
|
||||||
local taglist_squares_resize = theme.taglist_squares_resize or args.squares_resize or "true"
|
local taglist_squares_resize = theme.taglist_squares_resize or args.squares_resize or "true"
|
||||||
local font = args.font or theme.taglist_font or theme.font or ""
|
local font = args.font or theme.taglist_font or theme.font or ""
|
||||||
local text = "<span font_desc='"..font.."'>"
|
local text = "<span font_desc='"..font.."'> "
|
||||||
local background = ""
|
|
||||||
local sel = capi.client.focus
|
local sel = capi.client.focus
|
||||||
local bg_color = nil
|
local bg_color = nil
|
||||||
local fg_color = nil
|
local fg_color = nil
|
||||||
|
local bg_image
|
||||||
|
local bg_resize = false
|
||||||
if t.selected then
|
if t.selected then
|
||||||
bg_color = bg_focus
|
bg_color = bg_focus
|
||||||
fg_color = fg_focus
|
fg_color = fg_focus
|
||||||
end
|
end
|
||||||
if sel and sel:tags()[t] then
|
if sel and sel:tags()[t] then
|
||||||
if taglist_squares_sel then
|
if taglist_squares_sel then
|
||||||
background = "resize=\"" .. taglist_squares_resize .. "\" image=\"" .. taglist_squares_sel .. "\""
|
bg_image = capi.image(taglist_squares_sel)
|
||||||
|
bg_resize = taglist_squares_resize == "true"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local cls = t:clients()
|
local cls = t:clients()
|
||||||
if #cls > 0 and taglist_squares_unsel then
|
if #cls > 0 and taglist_squares_unsel then
|
||||||
background = "resize=\"" .. taglist_squares_resize .. "\" image=\"" .. taglist_squares_unsel .. "\""
|
bg_image = capi.image(taglist_squares_unsel)
|
||||||
|
bg_resize = taglist_squares_resize == "true"
|
||||||
end
|
end
|
||||||
for k, c in pairs(cls) do
|
for k, c in pairs(cls) do
|
||||||
if c.urgent then
|
if c.urgent then
|
||||||
|
@ -151,12 +160,12 @@ function taglist.label.all(t, args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if fg_color then
|
if fg_color then
|
||||||
text = text .. "<bg "..background.." /> <span color='"..util.color_strip_alpha(fg_color).."'>"..util.escape(t.name).."</span> "
|
text = text .. "<span color='"..util.color_strip_alpha(fg_color).."'>"..util.escape(t.name).."</span>"
|
||||||
else
|
else
|
||||||
text = text .. " <bg "..background.." />"..util.escape(t.name).." "
|
text = text .. util.escape(t.name)
|
||||||
end
|
end
|
||||||
text = text .. "</span>"
|
text = text .. " </span>"
|
||||||
return text, bg_color
|
return text, bg_color, bg_image, bg_resize
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return labels for a taglist widget with all *non empty* tags from screen.
|
--- Return labels for a taglist widget with all *non empty* tags from screen.
|
||||||
|
@ -168,7 +177,8 @@ end
|
||||||
-- fg_focus The foreground color for selected tag.
|
-- fg_focus The foreground color for selected tag.
|
||||||
-- bg_urgent The background color for urgent tags.
|
-- bg_urgent The background color for urgent tags.
|
||||||
-- fg_urgent The foreground color for urgent tags.
|
-- fg_urgent The foreground color for urgent tags.
|
||||||
-- @return A string to print.
|
-- @return A string to print, a background color, a background image and a
|
||||||
|
-- background resize value.
|
||||||
function taglist.label.noempty(t, args)
|
function taglist.label.noempty(t, args)
|
||||||
if #t:clients() > 0 or t.selected then
|
if #t:clients() > 0 or t.selected then
|
||||||
return taglist.label.all(t, args)
|
return taglist.label.all(t, args)
|
||||||
|
@ -195,6 +205,8 @@ local function tasklist_update(w, buttons, label, data)
|
||||||
w[i] = capi.widget({ type = "imagebox", align = "flex" })
|
w[i] = capi.widget({ type = "imagebox", align = "flex" })
|
||||||
w[i + 1] = capi.widget({ type = "textbox", align = "flex" })
|
w[i + 1] = capi.widget({ type = "textbox", align = "flex" })
|
||||||
w[i + 1]:margin({ left = 2, right = 2 })
|
w[i + 1]:margin({ left = 2, right = 2 })
|
||||||
|
w[i + 1].bg_resize = true
|
||||||
|
w[i + 1].bg_align = "right"
|
||||||
end
|
end
|
||||||
-- Remove widgets
|
-- Remove widgets
|
||||||
elseif len > #clients then
|
elseif len > #clients then
|
||||||
|
@ -220,7 +232,7 @@ local function tasklist_update(w, buttons, label, data)
|
||||||
w[k]:buttons(data[c])
|
w[k]:buttons(data[c])
|
||||||
w[k + 1]:buttons(data[c])
|
w[k + 1]:buttons(data[c])
|
||||||
end
|
end
|
||||||
w[k + 1].text, w[k + 1].bg = label(clients[(k + 1) / 2])
|
w[k + 1].text, w[k + 1].bg, w[k + 1].bg_image= label(clients[(k + 1) / 2])
|
||||||
w[k].bg = w[k + 1].bg
|
w[k].bg = w[k + 1].bg
|
||||||
if w[k + 1].text then
|
if w[k + 1].text then
|
||||||
-- Set icon
|
-- Set icon
|
||||||
|
@ -275,13 +287,13 @@ local function widget_tasklist_label_common(c, args)
|
||||||
local fg_urgent = args.fg_urgent or theme.tasklist_fg_urgent or theme.fg_urgent
|
local fg_urgent = args.fg_urgent or theme.tasklist_fg_urgent or theme.fg_urgent
|
||||||
local bg_urgent = args.bg_urgent or theme.tasklist_bg_urgent or theme.bg_urgent
|
local bg_urgent = args.bg_urgent or theme.tasklist_bg_urgent or theme.bg_urgent
|
||||||
local floating_icon = args.floating_icon or theme.tasklist_floating_icon
|
local floating_icon = args.floating_icon or theme.tasklist_floating_icon
|
||||||
local floating_icon_align = args.floating_icon_align or theme.tasklist_floating_icon_align or "right"
|
|
||||||
local font = args.font or theme.tasklist_font or theme.font or ""
|
local font = args.font or theme.tasklist_font or theme.font or ""
|
||||||
local bg = nil
|
local bg = nil
|
||||||
local text = "<span font_desc='"..font.."'>"
|
local text = "<span font_desc='"..font.."'>"
|
||||||
local name
|
local name
|
||||||
|
local status_image
|
||||||
if client.floating.get(c) and floating_icon then
|
if client.floating.get(c) and floating_icon then
|
||||||
text = text.."<bg image=\"" .. floating_icon .. "\" align=\"" .. floating_icon_align .. "\"/>"
|
status_image = capi.image(floating_icon)
|
||||||
end
|
end
|
||||||
if c.minimized then
|
if c.minimized then
|
||||||
name = util.escape(c.icon_name) or ""
|
name = util.escape(c.icon_name) or ""
|
||||||
|
@ -302,7 +314,7 @@ local function widget_tasklist_label_common(c, args)
|
||||||
text = text .. name
|
text = text .. name
|
||||||
end
|
end
|
||||||
text = text .. "</span>"
|
text = text .. "</span>"
|
||||||
return text, bg
|
return text, bg, status_image
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return labels for a tasklist widget with clients from all tags and screen.
|
--- Return labels for a tasklist widget with clients from all tags and screen.
|
||||||
|
@ -316,7 +328,7 @@ end
|
||||||
-- fg_focus The foreground color for focused client.
|
-- fg_focus The foreground color for focused client.
|
||||||
-- bg_urgent The background color for urgent clients.
|
-- bg_urgent The background color for urgent clients.
|
||||||
-- fg_urgent The foreground color for urgent clients.
|
-- fg_urgent The foreground color for urgent clients.
|
||||||
-- @return A string to print and a background color.
|
-- @return A string to print, a background color and a status image.
|
||||||
function tasklist.label.allscreen(c, screen, args)
|
function tasklist.label.allscreen(c, screen, args)
|
||||||
return widget_tasklist_label_common(c, args)
|
return widget_tasklist_label_common(c, args)
|
||||||
end
|
end
|
||||||
|
@ -332,7 +344,7 @@ end
|
||||||
-- fg_focus The foreground color for focused client.
|
-- fg_focus The foreground color for focused client.
|
||||||
-- bg_urgent The background color for urgent clients.
|
-- bg_urgent The background color for urgent clients.
|
||||||
-- fg_urgent The foreground color for urgent clients.
|
-- fg_urgent The foreground color for urgent clients.
|
||||||
-- @return A string to print and a background color.
|
-- @return A string to print, a background color and a status image.
|
||||||
function tasklist.label.alltags(c, screen, args)
|
function tasklist.label.alltags(c, screen, args)
|
||||||
-- Only print client on the same screen as this widget
|
-- Only print client on the same screen as this widget
|
||||||
if c.screen ~= screen then return end
|
if c.screen ~= screen then return end
|
||||||
|
@ -350,7 +362,7 @@ end
|
||||||
-- fg_focus The foreground color for focused client.
|
-- fg_focus The foreground color for focused client.
|
||||||
-- bg_urgent The background color for urgent clients.
|
-- bg_urgent The background color for urgent clients.
|
||||||
-- fg_urgent The foreground color for urgent clients.
|
-- fg_urgent The foreground color for urgent clients.
|
||||||
-- @return A string to print and a background color.
|
-- @return A string to print, a background color and a status image.
|
||||||
function tasklist.label.currenttags(c, screen, args)
|
function tasklist.label.currenttags(c, screen, args)
|
||||||
-- Only print client on the same screen as this widget
|
-- Only print client on the same screen as this widget
|
||||||
if c.screen ~= screen then return end
|
if c.screen ~= screen then return end
|
||||||
|
@ -367,14 +379,14 @@ end
|
||||||
-- @return A textbox widget configured as a button.
|
-- @return A textbox widget configured as a button.
|
||||||
function button(args)
|
function button(args)
|
||||||
if not args or not args.image then return end
|
if not args or not args.image then return end
|
||||||
args.type = "textbox"
|
local img_release = args.image
|
||||||
|
local img_press = img_release:crop(-2, -2, img_release.width, img_release.height)
|
||||||
|
args.type = "imagebox"
|
||||||
local w = capi.widget(args)
|
local w = capi.widget(args)
|
||||||
local img_release = "<bg image=\"" .. args.image .. "\" resize=\"true\"/>"
|
w.image = img_release
|
||||||
local img_press = "<bg_margin top=\"2\" left=\"2\"/><bg image=\"" .. args.image .. "\" resize=\"true\"/>"
|
w:buttons({ capi.button({}, 1, function () w.image = img_press end, function () w.image = img_release end) })
|
||||||
w.text = img_release
|
function w.mouse_leave(s) w.image = img_release end
|
||||||
w:buttons({ capi.button({}, 1, function () w.text = img_press end, function () w.text = img_release end) })
|
function w.mouse_enter(s) if capi.mouse.coords().buttons[1] then w.image = img_press end end
|
||||||
function w.mouse_leave(s) w.text = img_release end
|
|
||||||
function w.mouse_enter(s) if capi.mouse.coords().buttons[1] then w.text = img_press end end
|
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
#include "common/xembed.h"
|
#include "common/xembed.h"
|
||||||
#include "common/refcount.h"
|
#include "common/refcount.h"
|
||||||
|
#include "common/tokenize.h"
|
||||||
|
|
||||||
/** Windows type */
|
/** Windows type */
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
|
@ -44,13 +44,15 @@ imagebox_geometry(widget_t *widget, int screen, int height, int width)
|
||||||
{
|
{
|
||||||
if(d->resize)
|
if(d->resize)
|
||||||
{
|
{
|
||||||
geometry.width = ((double) height / (double) d->image->height) * d->image->width;
|
double ratio = (double) height / d->image->height;
|
||||||
geometry.height = height;
|
geometry.width = ratio * d->image->width;
|
||||||
if(geometry.width > width)
|
if(geometry.width > width)
|
||||||
{
|
{
|
||||||
geometry.width = 0;
|
geometry.width = 0;
|
||||||
geometry.height = 0;
|
geometry.height = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
geometry.height = height;
|
||||||
}
|
}
|
||||||
else if(d->image->width <= width)
|
else if(d->image->width <= width)
|
||||||
{
|
{
|
||||||
|
@ -91,6 +93,7 @@ imagebox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
|
||||||
draw_rectangle(ctx, geometry, 1.0, true, &d->bg);
|
draw_rectangle(ctx, geometry, 1.0, true, &d->bg);
|
||||||
|
|
||||||
int y = geometry.y;
|
int y = geometry.y;
|
||||||
|
double ratio = d->resize ? (double) geometry.height / d->image->height : 1;
|
||||||
switch(d->valign)
|
switch(d->valign)
|
||||||
{
|
{
|
||||||
case AlignBottom:
|
case AlignBottom:
|
||||||
|
@ -103,7 +106,7 @@ imagebox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_image(ctx, geometry.x, y, d->resize ? ctx->height : 0, d->image);
|
draw_image(ctx, geometry.x, y, ratio, d->image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,13 @@ extern awesome_t globalconf;
|
||||||
/** The textbox private data structure */
|
/** The textbox private data structure */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/** Textbox text */
|
draw_text_context_t data;
|
||||||
char *text;
|
|
||||||
/** Textbox text length */
|
|
||||||
ssize_t len;
|
|
||||||
/** Textbox width */
|
/** Textbox width */
|
||||||
int width;
|
int width;
|
||||||
/** Extents */
|
/** Extents */
|
||||||
area_t extents;
|
area_t extents;
|
||||||
PangoEllipsizeMode ellip;
|
PangoEllipsizeMode ellip;
|
||||||
PangoWrapMode wrap;
|
PangoWrapMode wrap;
|
||||||
/** Draw parser data */
|
|
||||||
draw_parser_data_t pdata;
|
|
||||||
/** Border */
|
/** Border */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -51,6 +46,12 @@ typedef struct
|
||||||
padding_t margin;
|
padding_t margin;
|
||||||
/** Background color */
|
/** Background color */
|
||||||
xcolor_t bg;
|
xcolor_t bg;
|
||||||
|
/** Background image */
|
||||||
|
image_t *bg_image;
|
||||||
|
/** Background resize to wibox height. */
|
||||||
|
bool bg_resize;
|
||||||
|
/** Background alignment */
|
||||||
|
alignment_t bg_align;
|
||||||
} textbox_data_t;
|
} textbox_data_t;
|
||||||
|
|
||||||
static area_t
|
static area_t
|
||||||
|
@ -65,14 +66,13 @@ textbox_geometry(widget_t *widget, int screen, int height, int width)
|
||||||
geometry.width = d->width;
|
geometry.width = d->width;
|
||||||
else if(widget->align == AlignFlex)
|
else if(widget->align == AlignFlex)
|
||||||
geometry.width = width;
|
geometry.width = width;
|
||||||
else
|
else if(d->bg_image)
|
||||||
{
|
{
|
||||||
geometry.width = MIN(d->extents.width, width);
|
double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1;
|
||||||
|
geometry.width = MIN(width, MAX(d->extents.width, MAX(d->width, d->bg_image->width * ratio)));
|
||||||
if(d->pdata.bg_image)
|
|
||||||
geometry.width = MAX(geometry.width,
|
|
||||||
d->pdata.bg_resize ? ((double) d->pdata.bg_image->width / (double) d->pdata.bg_image->height) * geometry.height : d->pdata.bg_image->width);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
geometry.width = MIN(d->extents.width, width);
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
@ -95,8 +95,30 @@ textbox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
|
||||||
if(d->border.width > 0)
|
if(d->border.width > 0)
|
||||||
draw_rectangle(ctx, geometry, d->border.width, false, &d->border.color);
|
draw_rectangle(ctx, geometry, d->border.width, false, &d->border.color);
|
||||||
|
|
||||||
draw_text(ctx, globalconf.font, d->ellip, d->wrap, d->align, &d->margin,
|
if(d->bg_image)
|
||||||
geometry, d->text, d->len, &d->pdata, &d->extents);
|
{
|
||||||
|
double ratio = d->bg_resize ? (double) geometry.height / d->bg_image->height : 1;
|
||||||
|
/* check there is enough space to draw the image */
|
||||||
|
if(ratio * d->bg_image->width <= geometry.width)
|
||||||
|
{
|
||||||
|
int x = geometry.x;
|
||||||
|
int y = geometry.y;
|
||||||
|
switch(d->bg_align)
|
||||||
|
{
|
||||||
|
case AlignCenter:
|
||||||
|
x += (geometry.width - d->bg_image->width * ratio) / 2;
|
||||||
|
break;
|
||||||
|
case AlignRight:
|
||||||
|
x += geometry.width - d->bg_image->width * ratio;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
draw_image(ctx, x, y, ratio, d->bg_image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text(ctx, &d->data, globalconf.font, d->ellip, d->wrap, d->align, &d->margin, geometry, &d->extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delete a textbox widget.
|
/** Delete a textbox widget.
|
||||||
|
@ -106,8 +128,7 @@ static void
|
||||||
textbox_destructor(widget_t *w)
|
textbox_destructor(widget_t *w)
|
||||||
{
|
{
|
||||||
textbox_data_t *d = w->data;
|
textbox_data_t *d = w->data;
|
||||||
draw_parser_data_wipe(&d->pdata);
|
draw_text_context_wipe(&d->data);
|
||||||
p_delete(&d->text);
|
|
||||||
p_delete(&d);
|
p_delete(&d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +161,9 @@ luaA_textbox_margin(lua_State *L)
|
||||||
* \lfield align Text alignment, left, center or right.
|
* \lfield align Text alignment, left, center or right.
|
||||||
* \lfield margin Method to pass text margin: a table with top, left, right and bottom keys.
|
* \lfield margin Method to pass text margin: a table with top, left, right and bottom keys.
|
||||||
* \lfield bg Background color.
|
* \lfield bg Background color.
|
||||||
|
* \lfield bg_image Background image.
|
||||||
|
* \lfield bg_align Background image alignment.
|
||||||
|
* \lfield bg_resize Background resize.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
luaA_textbox_index(lua_State *L, awesome_token_t token)
|
luaA_textbox_index(lua_State *L, awesome_token_t token)
|
||||||
|
@ -149,6 +173,17 @@ luaA_textbox_index(lua_State *L, awesome_token_t token)
|
||||||
|
|
||||||
switch(token)
|
switch(token)
|
||||||
{
|
{
|
||||||
|
case A_TK_BG_RESIZE:
|
||||||
|
lua_pushboolean(L, d->bg_resize);
|
||||||
|
return 1;
|
||||||
|
case A_TK_BG_ALIGN:
|
||||||
|
lua_pushstring(L, draw_align_tostr(d->bg_align));
|
||||||
|
return 1;
|
||||||
|
case A_TK_BG_IMAGE:
|
||||||
|
if(d->bg_image)
|
||||||
|
return luaA_image_userdata_new(L, d->bg_image);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
case A_TK_BG:
|
case A_TK_BG:
|
||||||
return luaA_pushcolor(L, &d->bg);
|
return luaA_pushcolor(L, &d->bg);
|
||||||
case A_TK_MARGIN:
|
case A_TK_MARGIN:
|
||||||
|
@ -164,8 +199,12 @@ luaA_textbox_index(lua_State *L, awesome_token_t token)
|
||||||
luaA_pushcolor(L, &d->border.color);
|
luaA_pushcolor(L, &d->border.color);
|
||||||
return 1;
|
return 1;
|
||||||
case A_TK_TEXT:
|
case A_TK_TEXT:
|
||||||
lua_pushstring(L, d->text);
|
if(d->data.len > 0)
|
||||||
return 1;
|
{
|
||||||
|
lua_pushlstring(L, d->data.text, d->data.len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case A_TK_WIDTH:
|
case A_TK_WIDTH:
|
||||||
lua_pushnumber(L, d->width);
|
lua_pushnumber(L, d->width);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -214,9 +253,29 @@ luaA_textbox_newindex(lua_State *L, awesome_token_t token)
|
||||||
widget_t **widget = luaA_checkudata(L, 1, "widget");
|
widget_t **widget = luaA_checkudata(L, 1, "widget");
|
||||||
const char *buf = NULL;
|
const char *buf = NULL;
|
||||||
textbox_data_t *d = (*widget)->data;
|
textbox_data_t *d = (*widget)->data;
|
||||||
|
image_t **image = NULL;
|
||||||
|
|
||||||
switch(token)
|
switch(token)
|
||||||
{
|
{
|
||||||
|
case A_TK_BG_ALIGN:
|
||||||
|
buf = luaL_checklstring(L, 3, &len);
|
||||||
|
d->bg_align = draw_align_fromstr(buf, len);
|
||||||
|
break;
|
||||||
|
case A_TK_BG_RESIZE:
|
||||||
|
d->bg_resize = luaA_checkboolean(L, 3);
|
||||||
|
break;
|
||||||
|
case A_TK_BG_IMAGE:
|
||||||
|
if(lua_isnil(L, 3)
|
||||||
|
|| (image = luaA_checkudata(L, 3, "image")))
|
||||||
|
{
|
||||||
|
/* unref image */
|
||||||
|
image_unref(&d->bg_image);
|
||||||
|
if(image)
|
||||||
|
d->bg_image = image_ref(image);
|
||||||
|
else
|
||||||
|
d->bg_image = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case A_TK_BG:
|
case A_TK_BG:
|
||||||
if(lua_isnil(L, 3))
|
if(lua_isnil(L, 3))
|
||||||
p_clear(&d->bg, 1);
|
p_clear(&d->bg, 1);
|
||||||
|
@ -239,21 +298,26 @@ luaA_textbox_newindex(lua_State *L, awesome_token_t token)
|
||||||
|| (buf = luaL_checklstring(L, 3, &len)))
|
|| (buf = luaL_checklstring(L, 3, &len)))
|
||||||
{
|
{
|
||||||
/* delete */
|
/* delete */
|
||||||
draw_parser_data_wipe(&d->pdata);
|
draw_text_context_wipe(&d->data);
|
||||||
/* reinit since we are giving it as arg to draw_text unconditionally */
|
p_clear(&d->data, 1);
|
||||||
draw_parser_data_init(&d->pdata);
|
|
||||||
p_delete(&d->text);
|
|
||||||
|
|
||||||
if(buf)
|
if(buf)
|
||||||
{
|
{
|
||||||
a_iso2utf8(buf, len, &d->text, &d->len);
|
char *text;
|
||||||
d->extents = draw_text_extents(globalconf.font, d->text, d->len, &d->pdata);
|
ssize_t tlen;
|
||||||
|
/* if text has been converted to UTF-8 */
|
||||||
|
if(draw_iso2utf8(buf, len, &text, &tlen))
|
||||||
|
{
|
||||||
|
draw_text_context_init(&d->data, text, tlen);
|
||||||
|
p_delete(&text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
draw_text_context_init(&d->data, buf, len);
|
||||||
|
|
||||||
|
d->extents = draw_text_extents(&d->data, globalconf.font);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
d->len = 0;
|
|
||||||
p_clear(&d->extents, 1);
|
p_clear(&d->extents, 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case A_TK_WIDTH:
|
case A_TK_WIDTH:
|
||||||
|
|
Loading…
Reference in New Issue