sawfish r4211 - trunk/src



Author: jkozicki
Date: Sat Jan 19 12:03:08 2008
New Revision: 4211
URL: http://svn.gnome.org/viewvc/sawfish?rev=4211&view=rev

Log:
Net wm properties by Rodrigo Gallardo

This patch makes sawfish use the _NET_WM_NAME properties for window names, as
mandated by the EWMH spec
(http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html)

This patch is a bit more invasive that it seems requiered, because, to make it
work properly in my system I had to make sawfish assume all strings are UTF8
encoded (see the pieces of the patch touching fonts.c)

Please test it and tell me what breaks. If there are no objections to the
substance of the patch, I'd still like some feedback on what to do with text
rendering with "normal" xlfd fonts. 


GSR-FR comment:
Probably the sanest solution, just next release will have to be marked with a
huge "Reencode strings in utf-8".
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^



Modified:
   trunk/src/display.c
   trunk/src/events.c
   trunk/src/fonts.c
   trunk/src/sawmill.h
   trunk/src/sawmill_subrs.h
   trunk/src/windows.c

Modified: trunk/src/display.c
==============================================================================
--- trunk/src/display.c	(original)
+++ trunk/src/display.c	Sat Jan 19 12:03:08 2008
@@ -55,7 +55,8 @@
 
 /* some atoms that may be useful.. */
 Atom xa_wm_state, xa_wm_change_state, xa_wm_protocols, xa_wm_delete_window,
-    xa_wm_colormap_windows, xa_wm_take_focus, xa_compound_text;
+  xa_wm_colormap_windows, xa_wm_take_focus, xa_compound_text,
+  xa_wm_net_name, xa_wm_net_icon_name, xa_utf8_string;
 
 DEFSYM(display_name, "display-name");
 DEFSYM(canonical_display_name, "canonical-display-name");
@@ -335,6 +336,9 @@
 	    xa_wm_colormap_windows = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False);
 	    xa_wm_take_focus = XInternAtom (dpy, "WM_TAKE_FOCUS", False);
 	    xa_compound_text = XInternAtom (dpy, "COMPOUND_TEXT", False);
+	    xa_wm_net_name = XInternAtom (dpy, "_NET_WM_NAME", False);
+	    xa_wm_net_icon_name = XInternAtom (dpy, "_NET_WM_ICON_NAME", False);
+	    xa_utf8_string = XInternAtom (dpy, "UTF8_STRING", False);
 
 	    if (!XShapeQueryExtension (dpy, &shape_event_base,
 				       &shape_error_base))

Modified: trunk/src/events.c
==============================================================================
--- trunk/src/events.c	(original)
+++ trunk/src/events.c	Sat Jan 19 12:03:08 2008
@@ -476,6 +476,111 @@
        a motion event is actually evaluated) */
 }
 
+
+static bool
+update_window_name(Lisp_Window * w, XPropertyEvent xproperty) {
+  u_char *prop;
+  Atom actual;
+  int format;
+  long nitems, bytes_after;
+  char **text_list;
+  XTextProperty tprop;
+  int count;
+  repv str = Qnil;
+  int convert_status;
+
+  if (xproperty.state != PropertyNewValue
+      || XGetWindowProperty (dpy, w->id, xproperty.atom,
+			     0, 200, False, AnyPropertyType, &actual,
+			     &format, &nitems,
+			     &bytes_after, &prop) != Success
+      || actual == None)
+    return FALSE;
+
+  if (format != 8 || WINDOW_IS_GONE_P (w))
+    return FALSE;
+
+  tprop.value = prop;
+  tprop.encoding = actual;
+  tprop.format = format;
+  tprop.nitems = strlen (prop);
+
+  if (actual == xa_compound_text || actual == XA_STRING) 
+    {
+      convert_status = XmbTextPropertyToTextList (dpy, &tprop, &text_list, &count);
+      if (convert_status >= Success && count > 0) 
+	{
+	  char * utf8str = g_locale_to_utf8(text_list[0], -1, NULL, NULL, NULL);
+	  if (utf8str)
+	    str = rep_string_dup (utf8str);
+	}
+      XFreeStringList(text_list);
+    }
+
+#ifdef X_HAVE_UTF8_STRING
+  if (actual == xa_utf8_string) 
+    {
+      convert_status = Xutf8TextPropertyToTextList (dpy, &tprop, &text_list, &count);
+      if (convert_status >= Success && count > 0)
+	str = rep_string_dup (text_list[0]);
+      XFreeStringList(text_list);
+    }
+#endif
+
+  XFree (prop);
+  
+  if (str == Qnil)
+    return FALSE;
+
+  if (xproperty.atom == xa_wm_net_name)
+    {
+      if ( str != Qnil && Fequal (w->net_name, str) == Qnil)
+	{
+	  w->net_name = str;
+	  return TRUE;
+	}
+    }
+  
+  if (xproperty.atom == xa_wm_net_icon_name) 
+    {
+      if ( str != Qnil && Fequal (w->net_icon_name, str) == Qnil)
+	{
+	  w->net_icon_name = str;
+	  return TRUE;
+	}
+    }
+  
+  /* No point in updating the rest if we have the _NET ones. They won't
+     be used anyways. */
+  if (w->net_name != Qnil)
+    return FALSE;
+  
+  if (xproperty.atom == XA_WM_NAME)
+    {
+      if (str == Qnil)
+	str = rep_null_string ();
+      if (Fequal (w->name, str) == Qnil
+	  || Fequal (w->full_name, str) == Qnil)
+	{
+	  w->full_name = w->name = str;
+	  return TRUE;
+	}
+    }
+  
+  if (xproperty.atom == XA_WM_ICON_NAME)
+    {
+      if (str == Qnil)
+	str = rep_null_string ();
+      if (Fequal (w->icon_name, str) == Qnil)
+	{
+	  w->icon_name = str;
+	  return TRUE;
+	}
+    }	  
+
+  return FALSE;
+}
+
 static void
 property_notify (XEvent *ev)
 {
@@ -489,72 +594,9 @@
 
 	switch (ev->xproperty.atom)
 	{
-	    u_char *prop;
-	    Atom actual;
-	    int format;
-	    long nitems, bytes_after;
 	    long supplied;
 	    bool old_urgency, new_urgency;
 
-	case XA_WM_NAME:
-	case XA_WM_ICON_NAME:
-	    if (ev->xproperty.state == PropertyNewValue
-		&& XGetWindowProperty (dpy, w->id, ev->xproperty.atom,
-				       0, 200, False, AnyPropertyType, &actual,
-				       &format, &nitems,
-				       &bytes_after, &prop) == Success
-		&& actual != None)
-	    {
-		if (format == 8 && !WINDOW_IS_GONE_P (w))
-		{
-		    repv str = Qnil;
-		    if (actual == xa_compound_text || actual == XA_STRING)
-		    {
-			char **text_list;
-			XTextProperty tprop;
-			int count;
-			tprop.value = prop;
-			tprop.encoding = actual;
-			tprop.format = format;
-			tprop.nitems = strlen (prop);
-			if (XmbTextPropertyToTextList (dpy, &tprop,
-						       &text_list, &count)
-			    >= Success)
-			{
-			    if (count > 0)
-			    	str = rep_string_dup (text_list[0]);
-			    XFreeStringList(text_list);
-			}
-		    }
-		    if (str == Qnil)
-			str = rep_null_string ();
-
-		    if (ev->xproperty.atom == XA_WM_NAME)
-		    {
-			if (Fequal (w->name, str) == Qnil
-			    || Fequal (w->full_name, str) == Qnil)
-			{
-			    w->full_name = w->name = str;
-			    need_refresh = TRUE;
-			}
-			else
-			    changed = FALSE;
-		    }
-		    else
-		    {
-			if (Fequal (w->icon_name, str) == Qnil)
-			{
-			    w->icon_name = str;
-			    need_refresh = TRUE;
-			}
-			else
-			    changed = FALSE;
-		    }
-		}
-		XFree (prop);
-	    }
-	    break;
-
 	case XA_WM_HINTS:
 	    old_urgency = w->wmhints != 0 && w->wmhints->flags & XUrgencyHint;
 	    if (w->wmhints != 0)
@@ -572,7 +614,16 @@
 	    break;
 
 	default:
-	    if (ev->xproperty.atom == xa_wm_colormap_windows)
+
+	    if (ev->xproperty.atom == XA_WM_NAME ||
+		ev->xproperty.atom == XA_WM_ICON_NAME ||
+		ev->xproperty.atom == xa_wm_net_name ||
+		ev->xproperty.atom == xa_wm_net_icon_name ) 
+	    {
+	      need_refresh = changed = 
+		update_window_name(w, ev->xproperty);
+	    }
+	    else if (ev->xproperty.atom == xa_wm_colormap_windows)
 	    {
 		if (w->n_cmap_windows > 0)
 		    XFree (w->cmap_windows);

Modified: trunk/src/fonts.c
==============================================================================
--- trunk/src/fonts.c	(original)
+++ trunk/src/fonts.c	Sat Jan 19 12:03:08 2008
@@ -311,7 +311,11 @@
 static int
 fontset_measure (Lisp_Font *f, u_char *string, size_t length)
 {
+#ifdef X_HAVE_UTF8_STRING
+    return Xutf8TextEscapement (f->font, string, length);
+#else
     return XmbTextEscapement (f->font, string, length);
+#endif
 }
 
 static void
@@ -322,8 +326,11 @@
 
     gcv.foreground = fg->pixel;
     XChangeGC (dpy, gc, GCForeground, &gcv);
-
+#ifdef X_HAVE_UTF8_STRING
+    Xutf8DrawString (dpy, id, f->font, gc, x, y, string, length);
+#else
     XmbDrawString (dpy, id, f->font, gc, x, y, string, length);
+#endif
 }
 
 static const Lisp_Font_Class fontset_class = {
@@ -365,7 +372,7 @@
 {
     XGlyphInfo info;
 
-    XftTextExtents8 (dpy, f->font, string, length, &info);
+    XftTextExtentsUtf8 (dpy, f->font, string, length, &info);
 
     return info.xOff; 
 }
@@ -389,7 +396,7 @@
     xft_color.color.blue = fg->blue;
     xft_color.color.alpha = fg->alpha;
 
-    XftDrawString8 (draw, &xft_color, f->font,
+    XftDrawStringUtf8 (draw, &xft_color, f->font,
 		    x, y, string, length);
 }
 
@@ -475,24 +482,14 @@
 static int
 pango_measure (Lisp_Font *f, u_char *string, size_t length)
 {
-    gsize r, w;
-    u_char *utf8str;
     PangoLayout *layout;
     PangoRectangle rect;
 
-    utf8str = g_locale_to_utf8 (string, length, &r, &w, NULL);
-    if (utf8str != NULL)
-    {
-	string = utf8str;
-	length = w;
-    }
-
     layout = pango_layout_new (pango_context);
     pango_layout_set_text (layout, string, length);
 
     pango_layout_get_extents (layout, NULL, &rect);
 
-    g_free (utf8str);
     g_object_unref (layout);
  
     return rect.width / PANGO_SCALE;
@@ -529,8 +526,6 @@
 {
     static XftDraw *draw;
     XftColor xft_color;
-    gsize r, w;
-    u_char *utf8str;
     PangoLayout *layout;
     PangoLayoutIter *iter;
 
@@ -545,13 +540,6 @@
     xft_color.color.blue = fg->blue;
     xft_color.color.alpha = fg->alpha;
 
-    utf8str = g_locale_to_utf8 (string, length, &r, &w, NULL);
-    if (utf8str != NULL)
-    {
-	string = utf8str;
-	length = w;
-    }
-
     layout = pango_layout_new (pango_context);
     pango_layout_set_text (layout, string, length);
     iter = pango_layout_get_iter (layout);
@@ -565,7 +553,6 @@
 			 line, x + rect.x / PANGO_SCALE, y);
     } while (pango_layout_iter_next_line (iter));
 
-    g_free (utf8str);
     g_object_unref (layout);
     pango_layout_iter_free (iter);
 }

Modified: trunk/src/sawmill.h
==============================================================================
--- trunk/src/sawmill.h	(original)
+++ trunk/src/sawmill.h	Sat Jan 19 12:03:08 2008
@@ -147,6 +147,7 @@
     Window *cmap_windows;
     int n_cmap_windows;
     repv full_name, name, icon_name;
+    repv net_name, net_icon_name;
     int frame_vis;
     repv icon_image;
 

Modified: trunk/src/sawmill_subrs.h
==============================================================================
--- trunk/src/sawmill_subrs.h	(original)
+++ trunk/src/sawmill_subrs.h	Sat Jan 19 12:03:08 2008
@@ -57,7 +57,7 @@
 extern Window root_window, no_focus_window;
 extern Atom xa_wm_state, xa_wm_change_state, xa_wm_protocols,
     xa_wm_delete_window, xa_wm_colormap_windows, xa_wm_take_focus,
-    xa_compound_text;
+  xa_compound_text, xa_wm_net_name, xa_wm_net_icon_name, xa_utf8_string;
 extern int shape_event_base, shape_error_base;
 extern repv Qdisplay_name, Qcanonical_display_name;
 extern bool sys_init (char *program_name);

Modified: trunk/src/windows.c
==============================================================================
--- trunk/src/windows.c	(original)
+++ trunk/src/windows.c	Sat Jan 19 12:03:08 2008
@@ -356,6 +356,85 @@
     }
 }
 
+/* Queries X properties to get the window {icon,}name */
+static void
+get_window_name(Lisp_Window * w)
+{
+  char *tem;
+  XTextProperty prop;
+
+  /* We only try to use the utf8 properties if our xlib supports them */
+#ifdef X_HAVE_UTF8_STRING
+  if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_name) && prop.value) {
+    if (prop.nitems > 0)
+      {
+        char **list;
+	int count;
+	prop.nitems = strlen(prop.value);
+	if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count)
+	    >= Success)
+	  {
+	    if (count > 0)
+	      w->net_name = rep_string_dup (list[0]);
+	    XFreeStringList (list);
+	  }
+      }
+  }
+
+  if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_icon_name) && prop.value) {
+    if (prop.nitems > 0)
+      {
+        char **list;
+	int count;
+	prop.nitems = strlen(prop.value);
+	if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count)
+	    >= Success)
+	  {
+	    if (count > 0)
+	      w->net_icon_name = rep_string_dup (list[0]);
+	    XFreeStringList (list);
+	  }
+      }
+  }
+
+  /* If we got the _NET names, there's no point in querying the others, 
+     as they won't be used anyways. */
+  if (w->net_name != Qnil)
+    return;
+
+#endif
+
+  if (XGetWMName (dpy, w->id, &prop) && prop.value)
+    {
+      if (prop.nitems > 0)
+	{
+	  char **list;
+	  int count;
+	  prop.nitems = strlen(prop.value);
+	  if (XmbTextPropertyToTextList (dpy, &prop, &list, &count)
+	      >= Success)
+	    {
+	      if (count > 0)
+		w->name = rep_string_dup (g_locale_to_utf8(list[0],
+							   -1, NULL, NULL, NULL));
+	      XFreeStringList (list);
+	    }
+	}
+      XFree (prop.value);
+    }
+  w->full_name = w->name;
+  
+  if (XGetIconName (dpy, w->id, &tem))
+    {
+      w->icon_name = rep_string_dup (g_locale_to_utf8(tem,
+						      -1, NULL, NULL, NULL));
+      XFree (tem);
+    }
+  else
+    w->icon_name = w->name;
+
+}
+
 /* Add the top-level window ID to the manager's data structures */
 Lisp_Window *
 add_window (Window id)
@@ -369,7 +448,6 @@
 	XWindowChanges xwc;
 	u_int xwcm;
 	long supplied;
-	XTextProperty prop;
 
 	DB(("add_window (%lx)\n", id));
 
@@ -389,6 +467,8 @@
 	w->frame_style = Qnil;;
 	w->icon_image = rep_NULL;
 	w->name = rep_null_string ();
+	w->net_name = Qnil;
+	w->net_icon_name = Qnil;
 
 	/* have to put it somewhere until it finds the right place */
 	insert_in_stacking_list_above_all (w);
@@ -401,31 +481,7 @@
 	DB(("  orig: width=%d height=%d x=%d y=%d\n",
 	    w->attr.width, w->attr.height, w->attr.x, w->attr.y));
 
-	if (XGetWMName (dpy, id, &prop) && prop.value)
-	{
-	    if (prop.nitems > 0)
-	    {
-		char **list;
-		int count;
-		prop.nitems = strlen(prop.value);
-		if (XmbTextPropertyToTextList (dpy, &prop, &list, &count)
-		    >= Success)
-		{
-		    if (count > 0)
-			w->name = rep_string_dup (list[0]);
-		    XFreeStringList (list);
-		}
-	    }
-	    XFree (prop.value);
-	}
-	w->full_name = w->name;
-	if (XGetIconName (dpy, id, &tem))
-	{
-	    w->icon_name = rep_string_dup (tem);
-	    XFree (tem);
-	}
-	else
-	    w->icon_name = w->name;
+	get_window_name(w);
 
 	w->wmhints = XGetWMHints (dpy, id);
 	if (!XGetWMNormalHints (dpy, w->id, &w->hints, &supplied))
@@ -700,8 +756,10 @@
 Return the name of window object WINDOW.
 ::end:: */
 {
+    Lisp_Window * w;
     rep_DECLARE1(win, WINDOWP);
-    return VWIN(win)->name;
+    w = VWIN(win);
+    return w->net_name != Qnil ? w->net_name : w->name;
 }
 
 DEFUN("window-full-name", Fwindow_full_name, Swindow_full_name,
@@ -724,8 +782,10 @@
 Return the name of window object WINDOW's icon.
 ::end:: */
 {
+    Lisp_Window * w;
     rep_DECLARE1(win, WINDOWP);
-    return VWIN(win)->icon_name;
+    w = VWIN(win);
+    return w->net_icon_name != Qnil ? w->net_icon_name : w->icon_name;
 }
 
 DEFUN("window-mapped-p", Fwindow_mapped_p, Swindow_mapped_p,
@@ -1420,6 +1480,8 @@
     rep_MARKVAL(VWIN(win)->name);
     rep_MARKVAL(VWIN(win)->full_name);
     rep_MARKVAL(VWIN(win)->icon_name);
+    rep_MARKVAL(VWIN(win)->net_name);
+    rep_MARKVAL(VWIN(win)->net_icon_name);
     rep_MARKVAL(VWIN(win)->icon_image);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]