From faf043bef92338fe976e639e94d309764065b8b7 Mon Sep 17 00:00:00 2001
From: simonb <simonb>
Date: Sun, 7 May 2006 10:08:25 +0000
Subject: more utf8 changes, notably window titles

---
 ChangeLog                |  5 +++++
 src/Ewmh.cc              | 37 +++++++++++++++++++++++++++++++++++--
 src/Ewmh.hh              |  6 +++++-
 src/FbTk/FbString.cc     |  8 ++++++++
 src/FbTk/FbString.hh     |  4 ----
 src/FbTk/FbWindow.cc     | 30 +++++++++++++++++++++++-------
 src/Screen.cc            |  3 ++-
 src/WinClient.cc         | 18 ++++++++++++++++++
 src/WinClient.hh         |  7 +++++--
 src/WinClientUtil.cc     |  8 ++++----
 src/Workspace.cc         |  3 ++-
 src/WorkspaceNameTool.cc |  4 ++--
 src/fluxbox.cc           |  2 +-
 13 files changed, 110 insertions(+), 25 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6acabdc..4774eab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
 (Format: Year/Month/Day)
 Changes for 0.9.16:
 *06/05/07:
+   * Handle EMWH window and icon titles, plus localise workspace names (Simon)
+     - FbTk::FbWindow::textProperty now handles utf8 type, and always 
+       returns UTF-8 encoded strings (for internal use)
+     Ewmh.hh/cc Screen.cc WinClient.hh/cc WinClientUtil.cc Workspace.cc 
+     WorkspaceNameTool.cc fluxbox.cc FbTk/... FbString.hh/cc FbWindow.cc
    * Handle UTF-8 strings properly (Simon)
      - still need to integrate EWMH strings properly (they are utf8)
      - still need to fix up TextBox
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 6bcd3e6..ea23a22 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -189,6 +189,15 @@ void Ewmh::initForScreen(BScreen &screen) {
 
 void Ewmh::setupClient(WinClient &winclient) {
     updateStrut(winclient);
+
+    FbTk::FbString newtitle = winclient.textProperty(m_net_wm_name);
+    if (!newtitle.empty()) {
+        winclient.setTitle(newtitle);
+    }
+    newtitle = winclient.textProperty(m_net_wm_icon_name);
+    if (!newtitle.empty()) {
+        winclient.setIconTitle(newtitle);
+    }
 }
 
 void Ewmh::setupFrame(FluxboxWindow &win) {
@@ -268,7 +277,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
                                  &ret_type, &fmt, &nitems, &bytes_after,
                                  (unsigned char **) &data) && data) {
         unsigned int desktop = static_cast<long>(*data);
-        if (desktop == -1 && !win.isStuck())
+        if (desktop == (unsigned int)(-1) && !win.isStuck())
             win.stick();
         else
             win.setWorkspace(desktop);
@@ -433,11 +442,21 @@ void Ewmh::updateWorkspaceNames(BScreen &screen) {
         strcpy(names[i], workspacenames[i].c_str());
     }
 
+#ifdef X_HAVE_UTF8_STRING
+    Xutf8TextListToTextProperty(FbTk::App::instance()->display(),
+                                names, number_of_desks, XUTF8StringStyle, &text);
+    XSetTextProperty(FbTk::App::instance()->display(), screen.rootWindow().window(),
+                     &text, m_net_desktop_names);
+
+    XFree(text.value);
+
+#else
     if (XStringListToTextProperty(names, number_of_desks, &text)) {
         XSetTextProperty(FbTk::App::instance()->display(), screen.rootWindow().window(),
 			 &text, m_net_desktop_names);
         XFree(text.value);
     }
+#endif
 
     for (size_t i = 0; i < number_of_desks; i++)
         delete [] names[i];
@@ -810,7 +829,17 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) {
     if (the_property == m_net_wm_strut) {
         updateStrut(winclient);
         return true;
-    } 
+    } else if (the_property == m_net_wm_name) {
+        FbTk::FbString newtitle = winclient.textProperty(the_property);
+        if (!newtitle.empty())
+            winclient.setTitle(newtitle);
+        return true;
+    } else if (the_property == m_net_wm_icon_name) {
+        FbTk::FbString newtitle = winclient.textProperty(the_property);
+        if (!newtitle.empty())
+            winclient.setIconTitle(newtitle);
+        return true;
+    }
 
     return false;
 }
@@ -841,6 +870,7 @@ void Ewmh::createAtoms() {
 
     m_net_properties = XInternAtom(disp, "_NET_PROPERTIES", False);
     m_net_wm_name = XInternAtom(disp, "_NET_WM_NAME", False);
+    m_net_wm_icon_name = XInternAtom(disp, "_NET_WM_ICON_NAME", False);
     m_net_wm_desktop = XInternAtom(disp, "_NET_WM_DESKTOP", False);
 
     // type atoms
@@ -1017,6 +1047,8 @@ void Ewmh::updateStrut(WinClient &winclient) {
     }
 }
 
+
+
 void Ewmh::updateActions(FluxboxWindow &win) {
 
     /* From Extended Window Manager Hints, draft 1.3:
@@ -1151,3 +1183,4 @@ void Ewmh::clearState(FluxboxWindow &win) {
 void Ewmh::saveState(FluxboxWindow &win, WindowState *state) {
     m_savedstate[&win] = state;
 }
+
diff --git a/src/Ewmh.hh b/src/Ewmh.hh
index 497665a..5c336e5 100644
--- a/src/Ewmh.hh
+++ b/src/Ewmh.hh
@@ -22,6 +22,7 @@
 // $Id$
 
 #include "AtomHandler.hh"
+#include "FbTk/FbString.hh"
 
 #include <X11/Xatom.h>
 #include <vector>
@@ -101,7 +102,8 @@ private:
     Atom m_net_close_window, m_net_wm_moveresize;
 
     // application window properties
-    Atom m_net_properties, m_net_wm_name, m_net_wm_desktop,
+    Atom m_net_properties, m_net_wm_name, m_net_wm_icon_name,
+        m_net_wm_desktop,
         // types
         m_net_wm_window_type,
         m_net_wm_window_type_dock,
@@ -147,4 +149,6 @@ private:
     void clearState(FluxboxWindow &win);
     void saveState(FluxboxWindow &win, WindowState *state);
 
+    FbTk::FbString getUTF8Property(Atom property);
+
 };
diff --git a/src/FbTk/FbString.cc b/src/FbTk/FbString.cc
index a88b237..6c5ffbb 100644
--- a/src/FbTk/FbString.cc
+++ b/src/FbTk/FbString.cc
@@ -107,6 +107,14 @@ void shutdown() {
    @param size number of BYTES to convert
    @return the recoded string, or 0 on failure
 */
+
+/** 
+  --NOTE--
+  In the "C" locale, this will strip any high-bit characters
+  because C means 7-bit ASCII charset. If you don't want this
+  then you need to set your locale to something UTF-8, OR something
+  ISO8859-1.
+*/
 std::string recode(iconv_t cd,
              const std::string &in) {
 
diff --git a/src/FbTk/FbString.hh b/src/FbTk/FbString.hh
index 371d4e9..011d47a 100644
--- a/src/FbTk/FbString.hh
+++ b/src/FbTk/FbString.hh
@@ -49,10 +49,6 @@ std::string FbStrToX(const FbString &src);
 FbString LocaleStrToFb(const std::string &src);
 std::string FbStrToLocale(const FbString &src);
 
-// essentially NO-OP
-inline FbString UTF8StrToFb(const std::string &src) { return src; } 
-inline std::string FbStrToUTF8(const FbString &src) { return src; }
-
 bool haveUTF8();
 
 } // namespace FbStringUtil
diff --git a/src/FbTk/FbWindow.cc b/src/FbTk/FbWindow.cc
index 8f204b1..2c34fa1 100644
--- a/src/FbTk/FbWindow.cc
+++ b/src/FbTk/FbWindow.cc
@@ -23,6 +23,7 @@
 
 #include "FbWindow.hh"
 #include "FbPixmap.hh"
+#include "FbString.hh"
 
 #include "EventManager.hh"
 #include "Color.hh"
@@ -450,28 +451,43 @@ void FbWindow::reparent(const FbWindow &parent, int x, int y, bool continuing) {
 
 std::string FbWindow::textProperty(Atom property) const {
     XTextProperty text_prop;
-    char ** stringlist;
+    char ** stringlist = 0;
     int count;
     std::string ret;
 
+    static Atom m_utf8string = XInternAtom(display(), "UTF8_STRING", False);
+
     if (XGetTextProperty(display(), window(), &text_prop, property) == 0)
         return "";
 
     if (text_prop.value == 0 || text_prop.nitems == 0)
         return "";
 
-    if (text_prop.encoding != XA_STRING) {
-        // still returns a "StringList" despite the different name
-        if (XmbTextPropertyToTextList(display(), &text_prop, &stringlist, &count) == 0 || count == 0)
+    if (text_prop.encoding == XA_STRING) {
+        if (XTextPropertyToStringList(&text_prop, &stringlist, &count) == 0 || count == 0)
             return "";
-    } else {
+        ret = FbStringUtil::XStrToFb(stringlist[0]);
+    } else if (text_prop.encoding == m_utf8string && text_prop.format == 8) {
+#ifdef X_HAVE_UTF8_STRING
+        Xutf8TextPropertyToTextList(display(), &text_prop, &stringlist, &count);
+        if (count == 0)
+            return "";
+#else
         if (XTextPropertyToStringList(&text_prop, &stringlist, &count) == 0 || count == 0)
             return "";
+#endif
+        ret = stringlist[0];
+    } else {
+        // still returns a "StringList" despite the different name
+        if (XmbTextPropertyToTextList(display(), &text_prop, &stringlist, &count) == 0 || count == 0)
+            return "";
 
+        ret = FbStringUtil::LocaleStrToFb(stringlist[0]);
     }
 
-    ret = stringlist[0];
-    XFreeStringList(stringlist);
+    // they all use stringlist
+    if (stringlist) 
+        XFreeStringList(stringlist);
     return ret;
 }
 
diff --git a/src/Screen.cc b/src/Screen.cc
index 0609cd4..626b296 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -75,6 +75,7 @@
 #include "FbTk/Transparent.hh"
 #include "FbTk/Select2nd.hh"
 #include "FbTk/Compose.hh"
+#include "FbTk/FbString.hh"
 
 //use GNU extensions
 #ifndef	 _GNU_SOURCE
@@ -1459,7 +1460,7 @@ void BScreen::updateAvailableWorkspaceArea() {
 }
 
 void BScreen::addWorkspaceName(const char *name) {
-    m_workspace_names.push_back(name);
+    m_workspace_names.push_back(FbTk::FbStringUtil::LocaleStrToFb(name));
 }
 
 
diff --git a/src/WinClient.cc b/src/WinClient.cc
index 056013a..891dc26 100644
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -69,6 +69,8 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb
                      m_win_gravity(0),
                      m_title(""), m_icon_title(""),
                      m_class_name(""), m_instance_name(""),
+                     m_title_override(false),
+                     m_icon_title_override(false),
                      m_blackbox_hint(0),
                      m_mwm_hint(0),
                      m_focus_mode(F_PASSIVE),
@@ -342,10 +344,26 @@ void WinClient::updateTitle() {
     //         also influenced
     //
     // the limitation to 512 chars only avoids running in that trap
+    if (m_title_override)
+        return;
+
     m_title = string(Xutil::getWMName(window()), 0, 512);
 }
 
+void WinClient::setTitle(FbTk::FbString &title) {
+    m_title = title;
+    m_title_override = true;
+}
+
+void WinClient::setIconTitle(FbTk::FbString &icon_title) {
+    m_icon_title = icon_title;
+    m_icon_title_override = true;
+}
+
 void WinClient::updateIconTitle() {
+    if (m_icon_title_override)
+        return;
+
     XTextProperty text_prop;
     char **list = 0;
     int num = 0;
diff --git a/src/WinClient.hh b/src/WinClient.hh
index aaaf111..870de6a 100644
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -27,9 +27,9 @@
 #include "Window.hh"
 #include "Subject.hh"
 #include "FbWindow.hh"
+#include "FbTk/FbString.hh"
 
 #include <X11/Xutil.h>
-#include <string>
 
 class BScreen;
 class Strut;
@@ -64,7 +64,9 @@ public:
     void updateWMClassHint();
     void updateWMProtocols();
 
- 
+    // override the title with this
+    void setTitle(FbTk::FbString &title);
+    void setIconTitle(FbTk::FbString &icon_title);
     void updateTitle();
     void updateIconTitle();
     /// updates transient window information
@@ -198,6 +200,7 @@ private:
 
     std::string m_title, m_icon_title;
     std::string m_class_name, m_instance_name;
+    bool m_title_override, m_icon_title_override;
 
     FbTk::FbPixmap m_icon_pixmap;
     FbTk::FbPixmap m_icon_mask;
diff --git a/src/WinClientUtil.cc b/src/WinClientUtil.cc
index 112360d..a6460a2 100644
--- a/src/WinClientUtil.cc
+++ b/src/WinClientUtil.cc
@@ -9,8 +9,8 @@ void maxSize(const FluxboxWindow::ClientList &clients,
              unsigned int &max_width, unsigned int &max_height) {
     FluxboxWindow::ClientList::const_iterator it = clients.begin();
     FluxboxWindow::ClientList::const_iterator it_end = clients.end();
-    max_width = ~0; // unlimited
-    max_height = ~0; // unlimited
+    max_width = (unsigned int) ~0; // unlimited
+    max_height = (unsigned int) ~0; // unlimited
     for (; it != it_end; ++it) {
         // special case for max height/width == 0
         // 0 indicates unlimited size, so we skip them
@@ -21,9 +21,9 @@ void maxSize(const FluxboxWindow::ClientList &clients,
             max_width = std::min( (*it)->maxWidth(), max_width );
     }
 
-    if (max_width == ~0)
+    if (max_width == (unsigned int) ~0)
         max_width = 0;
-    if (max_height == ~0)
+    if (max_height == (unsigned int) ~0)
         max_height = 0;
 }
 
diff --git a/src/Workspace.cc b/src/Workspace.cc
index 343772a..c8650ca 100644
--- a/src/Workspace.cc
+++ b/src/Workspace.cc
@@ -38,6 +38,7 @@
 #include "FbTk/I18n.hh"
 #include "FbTk/MenuItem.hh"
 #include "FbTk/StringUtil.hh"
+#include "FbTk/FbString.hh"
 
 // use GNU extensions
 #ifndef  _GNU_SOURCE
@@ -376,7 +377,7 @@ void Workspace::setName(const std::string &name) {
                 _FBTEXT(Workspace, DefaultNameFormat, 
                         "Workspace %d", "Default workspace names, with a %d for the workspace number"),
                 m_id + 1); //m_id starts at 0
-        m_name = tname;
+        m_name = FbTk::FbStringUtil::LocaleStrToFb(tname);
     }
     
     screen().updateWorkspaceNamesAtom();
diff --git a/src/WorkspaceNameTool.cc b/src/WorkspaceNameTool.cc
index 99d6854..3f66298 100644
--- a/src/WorkspaceNameTool.cc
+++ b/src/WorkspaceNameTool.cc
@@ -90,7 +90,7 @@ unsigned int WorkspaceNameTool::width() const {
     BScreen::Workspaces::const_iterator it;
     for (it = workspaces.begin(); it != workspaces.end(); it++) {
         const std::string &name = (*it)->name();
-        max_size = std::max(m_theme.font().textWidth(name.c_str(), name.size()), 
+        max_size = std::max(m_theme.font().textWidth(name, name.size()), 
                             max_size);
     }
     // so align text dont cut the last character
@@ -108,7 +108,7 @@ unsigned int WorkspaceNameTool::height() const {
     BScreen::Workspaces::const_iterator it;
     for (it = workspaces.begin(); it != workspaces.end(); it++) {
         const std::string &name = (*it)->name();
-        max_size = std::max(m_theme.font().textWidth(name.c_str(), name.size()), 
+        max_size = std::max(m_theme.font().textWidth(name, name.size()), 
                             max_size);
     }
     // so align text dont cut the last character
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 48b67bf..fd50392 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -1479,7 +1479,7 @@ void Fluxbox::save_rc() {
 
         for (unsigned int workspace=0; workspace < screen->numberOfWorkspaces(); workspace++) {
             if (screen->getWorkspace(workspace)->name().size()!=0)
-                workspaces_string.append(screen->getWorkspace(workspace)->name());
+                workspaces_string.append(FbTk::FbStringUtil::FbStrToLocale(screen->getWorkspace(workspace)->name()));
             else
                 workspaces_string.append("Null");
             workspaces_string.append(",");
-- 
cgit v0.11.2