Bug 310924 - GTK: Try named cursors before defaulting to hardcoded glyphs. r=karlt
authorPhil Schaf <flying-sheep@web.de>
Wed, 19 Feb 2014 11:30:08 -0500
changeset 169546 068ed8d0e7c2c52840a54d24b2a668183ff549f4
parent 169545 d2c4ae312b66e83c55226805aa30c858b90a30e3
child 169547 1c5072801816bb8e5e5b076c338c44123528c60c
push id4835
push userryanvm@gmail.com
push dateWed, 19 Feb 2014 20:41:30 +0000
treeherderb2g-inbound@3762e1037b59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs310924
milestone30.0a1
Bug 310924 - GTK: Try named cursors before defaulting to hardcoded glyphs. r=karlt
widget/gtk/nsWindow.cpp
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -4899,17 +4899,22 @@ static GdkCursor *
 get_gtk_cursor(nsCursor aCursor)
 {
     GdkCursor *gdkcursor = nullptr;
     uint8_t newType = 0xff;
 
     if ((gdkcursor = gCursorCache[aCursor])) {
         return gdkcursor;
     }
-
+    
+    GdkDisplay *defaultDisplay = gdk_display_get_default();
+
+    // The strategy here is to use standard GDK cursors, and, if not available,
+    // load by standard name with gdk_cursor_new_from_name.
+    // Spec is here: http://www.freedesktop.org/wiki/Specifications/cursor-spec/
     switch (aCursor) {
     case eCursor_standard:
         gdkcursor = gdk_cursor_new(GDK_LEFT_PTR);
         break;
     case eCursor_wait:
         gdkcursor = gdk_cursor_new(GDK_WATCH);
         break;
     case eCursor_select:
@@ -4947,82 +4952,123 @@ get_gtk_cursor(nsCursor aCursor)
         break;
     case eCursor_move:
         gdkcursor = gdk_cursor_new(GDK_FLEUR);
         break;
     case eCursor_help:
         gdkcursor = gdk_cursor_new(GDK_QUESTION_ARROW);
         break;
     case eCursor_copy: // CSS3
-        newType = MOZ_CURSOR_COPY;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "copy");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_COPY;
         break;
     case eCursor_alias:
-        newType = MOZ_CURSOR_ALIAS;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "alias");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_ALIAS;
         break;
     case eCursor_context_menu:
-        newType = MOZ_CURSOR_CONTEXT_MENU;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "context-menu");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_CONTEXT_MENU;
         break;
     case eCursor_cell:
         gdkcursor = gdk_cursor_new(GDK_PLUS);
         break;
+    // Those two aren’t standardized. Trying both KDE’s and GNOME’s names
     case eCursor_grab:
-        newType = MOZ_CURSOR_HAND_GRAB;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "openhand");
+        if (!gdkcursor)
+            gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "hand1");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_HAND_GRAB;
         break;
     case eCursor_grabbing:
-        newType = MOZ_CURSOR_HAND_GRABBING;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "closedhand");
+        if (!gdkcursor)
+            gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "grabbing");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_HAND_GRABBING;
         break;
     case eCursor_spinning:
-        newType = MOZ_CURSOR_SPINNING;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "progress");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_SPINNING;
         break;
     case eCursor_zoom_in:
         newType = MOZ_CURSOR_ZOOM_IN;
         break;
     case eCursor_zoom_out:
         newType = MOZ_CURSOR_ZOOM_OUT;
         break;
     case eCursor_not_allowed:
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "not-allowed");
+        if (!gdkcursor) // nonstandard, yet common
+            gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "crossed_circle");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_NOT_ALLOWED;
+        break;
     case eCursor_no_drop:
-        newType = MOZ_CURSOR_NOT_ALLOWED;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "no-drop");
+        if (!gdkcursor) // this nonstandard sequence makes it work on KDE and GNOME
+            gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "forbidden");
+        if (!gdkcursor)
+            gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "circle");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_NOT_ALLOWED;
         break;
     case eCursor_vertical_text:
         newType = MOZ_CURSOR_VERTICAL_TEXT;
         break;
     case eCursor_all_scroll:
         gdkcursor = gdk_cursor_new(GDK_FLEUR);
         break;
     case eCursor_nesw_resize:
-        newType = MOZ_CURSOR_NESW_RESIZE;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "size_bdiag");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_NESW_RESIZE;
         break;
     case eCursor_nwse_resize:
-        newType = MOZ_CURSOR_NWSE_RESIZE;
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "size_fdiag");
+        if (!gdkcursor)
+            newType = MOZ_CURSOR_NWSE_RESIZE;
         break;
     case eCursor_ns_resize:
-    case eCursor_row_resize:
         gdkcursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
         break;
     case eCursor_ew_resize:
+        gdkcursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
+        break;
+    // Here, two better fitting cursors exist in some cursor themes. Try those first
+    case eCursor_row_resize:
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "split_v");
+        if (!gdkcursor)
+            gdkcursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
+        break;
     case eCursor_col_resize:
-        gdkcursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "split_h");
+        if (!gdkcursor)
+            gdkcursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
         break;
     case eCursor_none:
         newType = MOZ_CURSOR_NONE;
         break;
     default:
         NS_ASSERTION(aCursor, "Invalid cursor type");
         gdkcursor = gdk_cursor_new(GDK_LEFT_PTR);
         break;
     }
 
     // If by now we don't have a xcursor, this means we have to make a custom
     // one. First, we try creating a named cursor based on the hash of our
     // custom bitmap, as libXcursor has some magic to convert bitmapped cursors
     // to themed cursors
     if (newType != 0xFF && GtkCursors[newType].hash) {
-        gdkcursor = gdk_cursor_new_from_name(gdk_display_get_default(),
-                                             GtkCursors[newType].hash);
+        gdkcursor = gdk_cursor_new_from_name(defaultDisplay, GtkCursors[newType].hash);
     }
 
     // If we still don't have a xcursor, we now really create a bitmap cursor
     if (newType != 0xff && !gdkcursor) {
         GdkPixbuf * cursor_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
         if (!cursor_pixbuf)
             return nullptr;