Merge branch 'master' into master
commit
b12b500bfc
|
@ -20,7 +20,7 @@ class Workspaces : public AModule, public sigc::trackable {
|
|||
auto update() -> void;
|
||||
|
||||
private:
|
||||
static inline const std::string workspace_switch_cmd_ = "workspace --no-auto-back-and-forth \"{}\"";
|
||||
static inline const std::string workspace_switch_cmd_ = "workspace {} \"{}\"";
|
||||
|
||||
static int convertWorkspaceNameToNum(std::string name);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
// calculate column width of ustring
|
||||
int ustring_clen(const Glib::ustring &str);
|
|
@ -24,6 +24,14 @@ The *backlight* module displays the current backlight level.
|
|||
typeof: integer ++
|
||||
The maximum length in characters the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*rotate*: ++
|
||||
typeof: integer ++
|
||||
Positive value to rotate the text label.
|
||||
|
|
|
@ -55,6 +55,14 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||
typeof: integer++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*rotate*: ++
|
||||
typeof: integer++
|
||||
Positive value to rotate the text label.
|
||||
|
|
|
@ -35,6 +35,14 @@ Addressed by *bluetooth*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -45,6 +45,14 @@ The *clock* module displays the current date and time.
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*rotate*: ++
|
||||
typeof: integer ++
|
||||
Positive value to rotate the text label.
|
||||
|
|
|
@ -24,6 +24,14 @@ The *cpu* module displays the current cpu utilization.
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*rotate*: ++
|
||||
typeof: integer ++
|
||||
Positive value to rotate the text label.
|
||||
|
|
|
@ -67,6 +67,14 @@ Addressed by *custom/<name>*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -39,6 +39,14 @@ Addressed by *disk*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -27,6 +27,14 @@ screensaving, also known as "presentation mode".
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module. A click also toggles the state
|
||||
|
|
|
@ -34,6 +34,14 @@ Addressed by *memory*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -97,6 +97,14 @@ Addressed by *mpd*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -64,6 +64,14 @@ Addressed by *network*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -50,6 +50,14 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*scroll-step*: ++
|
||||
typeof: float ++
|
||||
default: 1.0 ++
|
||||
|
|
|
@ -26,6 +26,14 @@ cursor is over the module, and clicking on the module toggles mute.
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*scroll-step*: ++
|
||||
typeof: int ++
|
||||
default: 5 ++
|
||||
|
|
|
@ -25,6 +25,14 @@ Addressed by *sway/language*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -25,6 +25,14 @@ Addressed by *sway/mode*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -25,6 +25,14 @@ Addressed by *sway/window*
|
|||
typeof: integer ++
|
||||
The maximum length in character the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when clicked on the module.
|
||||
|
|
|
@ -73,6 +73,10 @@ Addressed by *sway/workspaces*
|
|||
typeof: bool ++
|
||||
Whether to put workspaces starting with numbers before workspaces that do not start with a number.
|
||||
|
||||
*disable-auto-back-and-forth*: ++
|
||||
typeof: bool ++
|
||||
Whether to disable *workspace_auto_back_and_forth* when clicking on workspaces. If this is set to *true*, clicking on a workspace you are already on won't do anything, even if *workspace_auto_back_and_forth* is enabled in the Sway configuration.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{value}*: Name of the workspace, as defined by sway.
|
||||
|
|
|
@ -63,6 +63,14 @@ Addressed by *temperature*
|
|||
typeof: integer ++
|
||||
The maximum length in characters the module should display.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you clicked on the module.
|
||||
|
|
|
@ -147,6 +147,7 @@ src_files = files(
|
|||
'src/main.cpp',
|
||||
'src/bar.cpp',
|
||||
'src/client.cpp',
|
||||
'src/util/ustring_clen.cpp'
|
||||
)
|
||||
|
||||
if is_linux
|
||||
|
|
|
@ -20,7 +20,7 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
|||
}
|
||||
event_box_.add(label_);
|
||||
if (config_["max-length"].isUInt()) {
|
||||
label_.set_max_width_chars(config_["max-length"].asUInt());
|
||||
label_.set_max_width_chars(config_["max-length"].asInt());
|
||||
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
|
||||
label_.set_single_line_mode(true);
|
||||
} else if (ellipsize && label_.get_max_width_chars() == -1) {
|
||||
|
@ -28,9 +28,28 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
|||
label_.set_single_line_mode(true);
|
||||
}
|
||||
|
||||
if (config_["rotate"].isUInt()) {
|
||||
label_.set_angle(config["rotate"].asUInt());
|
||||
if (config_["min-length"].isUInt()) {
|
||||
label_.set_width_chars(config_["min-length"].asUInt());
|
||||
}
|
||||
|
||||
uint rotate = 0;
|
||||
|
||||
if (config_["rotate"].isUInt()) {
|
||||
rotate = config["rotate"].asUInt();
|
||||
label_.set_angle(rotate);
|
||||
}
|
||||
|
||||
if (config_["align"].isDouble()) {
|
||||
auto align = config_["align"].asFloat();
|
||||
if (rotate == 90 || rotate == 270) {
|
||||
label_.set_yalign(align);
|
||||
} else {
|
||||
label_.set_xalign(align);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
auto ALabel::update() -> void {
|
||||
|
|
|
@ -120,17 +120,26 @@ void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_
|
|||
auto client = waybar::Client::inst();
|
||||
try {
|
||||
auto &output = client->getOutput(data);
|
||||
/**
|
||||
* Multiple .done events may arrive in batch. In this case libwayland would queue
|
||||
* xdg_output.destroy and dispatch all pending events, triggering this callback several times
|
||||
* for the same output. .done events can also arrive after that for a scale or position changes.
|
||||
* We wouldn't want to draw a duplicate bar for each such event either.
|
||||
*
|
||||
* All the properties we care about are immutable so it's safe to delete the xdg_output object
|
||||
* on the first event and use the ptr value to check that the callback was already invoked.
|
||||
*/
|
||||
if (output.xdg_output) {
|
||||
output.xdg_output.reset();
|
||||
spdlog::debug("Output detection done: {} ({})", output.name, output.identifier);
|
||||
|
||||
auto configs = client->getOutputConfigs(output);
|
||||
if (!configs.empty()) {
|
||||
wl_display_roundtrip(client->wl_display);
|
||||
for (const auto &config : configs) {
|
||||
client->bars.emplace_back(std::make_unique<Bar>(&output, config));
|
||||
}
|
||||
}
|
||||
// unsubscribe
|
||||
output.xdg_output.reset();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include "util/ustring_clen.hpp"
|
||||
#ifdef HAVE_LANGINFO_1STDAY
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
|
@ -154,12 +155,14 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std
|
|||
do {
|
||||
if (wd != first_dow) os << ' ';
|
||||
Glib::ustring wd_ustring(date::format(locale_, "%a", wd));
|
||||
auto clen = ustring_clen(wd_ustring);
|
||||
auto wd_len = wd_ustring.length();
|
||||
if (wd_len > 2) {
|
||||
wd_ustring = wd_ustring.substr(0, 2);
|
||||
wd_len = 2;
|
||||
while (clen > 2) {
|
||||
wd_ustring = wd_ustring.substr(0, wd_len-1);
|
||||
wd_len--;
|
||||
clen = ustring_clen(wd_ustring);
|
||||
}
|
||||
const std::string pad(2 - wd_len, ' ');
|
||||
const std::string pad(2 - clen, ' ');
|
||||
os << pad << wd_ustring;
|
||||
} while (++wd != first_dow);
|
||||
os << "\n";
|
||||
|
|
|
@ -12,6 +12,10 @@ waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar&
|
|||
bar_(bar),
|
||||
idle_inhibitor_(nullptr),
|
||||
pid_(-1) {
|
||||
if (waybar::Client::inst()->idle_inhibit_manager == nullptr) {
|
||||
throw std::runtime_error("idle-inhibit not available");
|
||||
}
|
||||
|
||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||
event_box_.signal_button_press_event().connect(
|
||||
sigc::mem_fun(*this, &IdleInhibitor::handleToggle));
|
||||
|
|
|
@ -56,7 +56,8 @@ auto Window::update() -> void {
|
|||
bar_.window.get_style_context()->remove_class("solo");
|
||||
bar_.window.get_style_context()->remove_class("empty");
|
||||
}
|
||||
label_.set_markup(fmt::format(format_, window_));
|
||||
label_.set_markup(fmt::format(format_, fmt::arg("title", window_),
|
||||
fmt::arg("app_id", app_id_)));
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(window_);
|
||||
}
|
||||
|
|
|
@ -257,11 +257,19 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) {
|
|||
ipc_.sendCmd(
|
||||
IPC_COMMAND,
|
||||
fmt::format(workspace_switch_cmd_ + "; move workspace to output \"{}\"; " + workspace_switch_cmd_,
|
||||
"--no-auto-back-and-forth",
|
||||
node["name"].asString(),
|
||||
node["target_output"].asString(),
|
||||
"--no-auto-back-and-forth",
|
||||
node["name"].asString()));
|
||||
} else {
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format(workspace_switch_cmd_, node["name"].asString()));
|
||||
ipc_.sendCmd(
|
||||
IPC_COMMAND,
|
||||
fmt::format("workspace {} \"{}\"",
|
||||
config_["disable-auto-back-and-forth"].asBool()
|
||||
? "--no-auto-back-and-forth"
|
||||
: "",
|
||||
node["name"].asString()));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
|
@ -322,7 +330,9 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
|||
}
|
||||
}
|
||||
try {
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format(workspace_switch_cmd_, name));
|
||||
ipc_.sendCmd(
|
||||
IPC_COMMAND,
|
||||
fmt::format(workspace_switch_cmd_, "--no-auto-back-and-forth", name));
|
||||
} catch (const std::exception &e) {
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "modules/wlr/taskbar.hpp"
|
||||
|
||||
#include "glibmm/error.h"
|
||||
#include "glibmm/fileutils.h"
|
||||
#include "glibmm/refptr.h"
|
||||
#include "util/format.hpp"
|
||||
|
||||
|
@ -15,6 +17,7 @@
|
|||
#include <gtkmm/icontheme.h>
|
||||
|
||||
#include <giomm/desktopappinfo.h>
|
||||
#include <gio/gdesktopappinfo.h>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
|
@ -64,12 +67,25 @@ static std::vector<std::string> search_prefix()
|
|||
} while(end != std::string::npos);
|
||||
}
|
||||
|
||||
std::string home_dir = std::getenv("HOME");
|
||||
prefixes.push_back(home_dir + "/.local/share/");
|
||||
|
||||
for (auto& p : prefixes)
|
||||
spdlog::debug("Using 'desktop' search path prefix: {}", p);
|
||||
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string icon_path, int size)
|
||||
{
|
||||
try {
|
||||
auto pb = Gdk::Pixbuf::create_from_file(icon_path, size, size);
|
||||
return pb;
|
||||
} catch(...) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/* Method 1 - get the correct icon name from the desktop file */
|
||||
static std::string get_from_desktop_app_info(const std::string &app_id)
|
||||
{
|
||||
|
@ -111,6 +127,33 @@ static std::string get_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_
|
|||
return "";
|
||||
}
|
||||
|
||||
/* Method 3 - as last resort perform a search for most appropriate desktop info file */
|
||||
static std::string get_from_desktop_app_info_search(const std::string &app_id)
|
||||
{
|
||||
std::string desktop_file = "";
|
||||
|
||||
gchar*** desktop_list = g_desktop_app_info_search(app_id.c_str());
|
||||
if (desktop_list != nullptr && desktop_list[0] != nullptr) {
|
||||
for (size_t i=0; desktop_list[0][i]; i++) {
|
||||
if (desktop_file == "") {
|
||||
desktop_file = desktop_list[0][i];
|
||||
} else {
|
||||
auto tmp_info = Gio::DesktopAppInfo::create(desktop_list[0][i]);
|
||||
auto startup_class = tmp_info->get_startup_wm_class();
|
||||
|
||||
if (startup_class == app_id) {
|
||||
desktop_file = desktop_list[0][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_strfreev(desktop_list[0]);
|
||||
}
|
||||
g_free(desktop_list);
|
||||
|
||||
return get_from_desktop_app_info(desktop_file);
|
||||
}
|
||||
|
||||
static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||
const std::string &app_id_list, int size)
|
||||
{
|
||||
|
@ -142,11 +185,23 @@ static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme
|
|||
icon_name = get_from_desktop_app_info(lower_app_id);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info(app_name);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info_search(app_id);
|
||||
|
||||
if (icon_name.empty())
|
||||
continue;
|
||||
icon_name = "unknown";
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
|
||||
try {
|
||||
pixbuf = icon_theme->load_icon(icon_name, size, Gtk::ICON_LOOKUP_FORCE_SIZE);
|
||||
} catch(...) {
|
||||
if (Glib::file_test(icon_name, Glib::FILE_TEST_EXISTS))
|
||||
pixbuf = load_icon_from_file(icon_name, size);
|
||||
else
|
||||
pixbuf = {};
|
||||
}
|
||||
|
||||
auto pixbuf = icon_theme->load_icon(icon_name, size, Gtk::ICON_LOOKUP_FORCE_SIZE);
|
||||
if (pixbuf) {
|
||||
image.set(pixbuf);
|
||||
found = true;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#include "util/ustring_clen.hpp"
|
||||
|
||||
int ustring_clen(const Glib::ustring &str){
|
||||
int total = 0;
|
||||
for (auto i = str.begin(); i != str.end(); ++i) {
|
||||
total += g_unichar_iswide(*i) + 1;
|
||||
}
|
||||
return total;
|
||||
}
|
Loading…
Reference in New Issue