Revision: 4898
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4898&view=rev
Author:   ossman_
Date:     2012-04-25 14:57:22 +0000 (Wed, 25 Apr 2012)
Log Message:
-----------
Proper support for icons in FLTK (upstream STR 2816).

Modified Paths:
--------------
    trunk/common/fltk/FL/Fl_Window.H
    trunk/common/fltk/FL/mac.H
    trunk/common/fltk/FL/win32.H
    trunk/common/fltk/FL/x.H
    trunk/common/fltk/src/Fl.cxx
    trunk/common/fltk/src/Fl_Window.cxx
    trunk/common/fltk/src/Fl_win32.cxx
    trunk/common/fltk/src/Fl_x.cxx

Modified: trunk/common/fltk/FL/Fl_Window.H
===================================================================
--- trunk/common/fltk/FL/Fl_Window.H    2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/FL/Fl_Window.H    2012-04-25 14:57:22 UTC (rev 4898)
@@ -31,6 +31,10 @@
 #ifndef Fl_Window_H
 #define Fl_Window_H
 
+#ifdef WIN32
+#include <windows.h>
+#endif
+
 #include "Fl_Group.H"
 
 #define FL_WINDOW 0xF0         ///< window type id all subclasses have type() 
>= this
@@ -63,9 +67,19 @@
   friend class Fl_X;
   Fl_X *i; // points at the system-specific stuff
 
+  struct icon_data {
+    const void *legacy_icon;
+    Fl_RGB_Image **icons;
+    int count;
+#ifdef WIN32
+    HICON big_icon;
+    HICON small_icon;
+#endif
+  };
+
   const char* iconlabel_;
   char* xclass_;
-  const void* icon_;
+  struct icon_data *icon_;
   // size_range stuff:
   int minw, minh, maxw, maxh;
   int dw, dh, aspect;
@@ -110,6 +124,8 @@
   */
   int force_position() const { return ((flags() & FORCE_POSITION)?1:0); }
 
+  void free_icons();
+
 public:
 
   /**
@@ -331,6 +347,18 @@
   static const char *default_xclass();
   const char* xclass() const;
   void xclass(const char* c);
+
+  static void default_icon(const Fl_RGB_Image*);
+  static void default_icons(const Fl_RGB_Image*[], int);
+  void icon(const Fl_RGB_Image*);
+  void icons(const Fl_RGB_Image*[], int);
+
+#ifdef WIN32
+  static void default_icons(HICON big_icon, HICON small_icon);
+  void icons(HICON big_icon, HICON small_icon);
+#endif
+
+  /* for legacy compatibility */
   const void* icon() const;
   void icon(const void * ic);
 

Modified: trunk/common/fltk/FL/mac.H
===================================================================
--- trunk/common/fltk/FL/mac.H  2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/FL/mac.H  2012-04-25 14:57:22 UTC (rev 4898)
@@ -141,6 +141,9 @@
   void collapse(void);
   WindowRef window_ref(void);
   void set_key_window(void);
+  // OS X doesn't have per window icons
+  static void set_default_icons(const Fl_RGB_Image*[], int) {};
+  void set_icons() {};
   int set_cursor(Fl_Cursor);
   int set_cursor(const Fl_RGB_Image*, int, int);
   static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int 
w, int h);

Modified: trunk/common/fltk/FL/win32.H
===================================================================
--- trunk/common/fltk/FL/win32.H        2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/FL/win32.H        2012-04-25 14:57:22 UTC (rev 4898)
@@ -93,6 +93,9 @@
   void flush() {w->flush();}
   void set_minmax(LPMINMAXINFO minmax);
   void mapraise();
+  static void set_default_icons(const Fl_RGB_Image*[], int);
+  static void set_default_icons(HICON, HICON);
+  void set_icons();
   int set_cursor(Fl_Cursor);
   int set_cursor(const Fl_RGB_Image*, int, int);
   static Fl_X* make(Fl_Window*);

Modified: trunk/common/fltk/FL/x.H
===================================================================
--- trunk/common/fltk/FL/x.H    2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/FL/x.H    2012-04-25 14:57:22 UTC (rev 4898)
@@ -163,6 +163,8 @@
   static Fl_X* i(const Fl_Window* wi) {return wi->i;}
   void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
   void sendxjunk();
+  static void set_default_icons(const Fl_RGB_Image*[], int);
+  void set_icons();
   int set_cursor(Fl_Cursor);
   int set_cursor(const Fl_RGB_Image*, int, int);
   static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, 
Colormap=fl_colormap);

Modified: trunk/common/fltk/src/Fl.cxx
===================================================================
--- trunk/common/fltk/src/Fl.cxx        2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/src/Fl.cxx        2012-04-25 14:57:22 UTC (rev 4898)
@@ -1535,6 +1535,8 @@
   if (xclass_) {
     free(xclass_);
   }
+  free_icons();
+  delete icon_;
 }
 
 // FL_SHOW and FL_HIDE are called whenever the visibility of this widget

Modified: trunk/common/fltk/src/Fl_Window.cxx
===================================================================
--- trunk/common/fltk/src/Fl_Window.cxx 2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/src/Fl_Window.cxx 2012-04-25 14:57:22 UTC (rev 4898)
@@ -32,6 +32,7 @@
 #include <config.h>
 #include <FL/Fl.H>
 #include <FL/x.H>
+#include <FL/Fl_RGB_Image.H>
 #include <FL/Fl_Window.H>
 #include <stdlib.h>
 #include "flstring.h"
@@ -54,7 +55,8 @@
   }
   i = 0;
   xclass_ = 0;
-  icon_ = 0;
+  icon_ = new icon_data;
+  memset(icon_, 0, sizeof(*icon_));
   iconlabel_ = 0;
   resizable(0);
   size_range_set = 0;
@@ -277,17 +279,69 @@
   }
 }
 
+void Fl_Window::default_icon(const Fl_RGB_Image *icon) {
+  default_icons(&icon, 1);
+}
+
+void Fl_Window::default_icons(const Fl_RGB_Image **icons, int count) {
+  Fl_X::set_default_icons(icons, count);
+}
+
+void Fl_Window::icon(const Fl_RGB_Image *icon) {
+  icons(&icon, 1);
+}
+
+void Fl_Window::icons(const Fl_RGB_Image **icons, int count) {
+  free_icons();
+
+  if (count > 0) {
+    icon_->icons = new Fl_RGB_Image*[count];
+    icon_->count = count;
+    // FIXME: Fl_RGB_Image lacks const modifiers on methods
+    for (int i = 0;i < count;i++)
+      icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
+  }
+
+  if (i)
+    i->set_icons();
+}
+
 /** Gets the current icon window target dependent data. */
 const void *Fl_Window::icon() const {
-  return icon_;
+  return icon_->legacy_icon;
 }
 
 /** Sets the current icon window target dependent data. */
 void Fl_Window::icon(const void * ic) {
-  icon_ = ic;
+  free_icons();
+  icon_->legacy_icon = ic;
 }
 
+void Fl_Window::free_icons() {
+  int i;
 
+  icon_->legacy_icon = 0L;
+
+  if (icon_->icons) {
+    for (i = 0;i < icon_->count;i++)
+      delete icon_->icons[i];
+    delete [] icon_->icons;
+    icon_->icons = 0L;
+  }
+
+  icon_->count = 0;
+
+#ifdef WIN32
+  if (icon_->big_icon)
+    DestroyIcon(icon_->big_icon);
+  if (icon_->small_icon)
+    DestroyIcon(icon_->small_icon);
+
+  icon_->big_icon = NULL;
+  icon_->small_icon = NULL;
+#endif
+}
+
 //
 // End of "$Id: Fl_Window.cxx 8472 2011-02-25 08:44:47Z AlbrechtS $".
 //

Modified: trunk/common/fltk/src/Fl_win32.cxx
===================================================================
--- trunk/common/fltk/src/Fl_win32.cxx  2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/src/Fl_win32.cxx  2012-04-25 14:57:22 UTC (rev 4898)
@@ -1802,6 +1802,8 @@
   );
   if (lab) free(lab);
 
+  x->set_icons();
+
   if (w->flags() & Fl_Widget::FULLSCREEN) {
   /* We need to make sure that the fullscreen is created on the
      default monitor, ie the desktop where the shortcut is located
@@ -2028,71 +2030,19 @@
 
 ////////////////////////////////////////////////////////////////
 
-#ifndef IDC_HAND
-#  define IDC_HAND  MAKEINTRESOURCE(32649)
-#endif // !IDC_HAND
-
-int Fl_X::set_cursor(Fl_Cursor c) {
-  LPSTR n;
-  HCURSOR new_cursor;
-
-  if (c == FL_CURSOR_NONE)
-    new_cursor = NULL;
-  else {
-    switch (c) {
-    case FL_CURSOR_ARROW:   n = IDC_ARROW; break;
-    case FL_CURSOR_CROSS:   n = IDC_CROSS; break;
-    case FL_CURSOR_WAIT:    n = IDC_WAIT; break;
-    case FL_CURSOR_INSERT:  n = IDC_IBEAM; break;
-    case FL_CURSOR_HAND:    n = IDC_HAND; break;
-    case FL_CURSOR_HELP:    n = IDC_HELP; break;
-    case FL_CURSOR_MOVE:    n = IDC_SIZEALL; break;
-    case FL_CURSOR_N:
-    case FL_CURSOR_S:
-      // FIXME: Should probably have fallbacks for these instead
-    case FL_CURSOR_NS:      n = IDC_SIZENS; break;
-    case FL_CURSOR_NE:
-    case FL_CURSOR_SW:
-      // FIXME: Dito.
-    case FL_CURSOR_NESW:    n = IDC_SIZENESW; break;
-    case FL_CURSOR_E:
-    case FL_CURSOR_W:
-      // FIXME: Dito.
-    case FL_CURSOR_WE:      n = IDC_SIZEWE; break;
-    case FL_CURSOR_SE:
-    case FL_CURSOR_NW:
-      // FIXME: Dito.
-    case FL_CURSOR_NWSE:    n = IDC_SIZENWSE; break;
-    default:
-      return 0;
-    }
-
-    new_cursor = LoadCursor(NULL, n);
-    if (new_cursor == NULL)
-      return 0;
-  }
-
-  if ((cursor != NULL) && custom_cursor)
-    DestroyIcon(cursor);
-
-  cursor = new_cursor;
-  custom_cursor = 0;
-
-  SetCursor(cursor);
-
-  return 1;
-}
-
-int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
+static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon=true,
+                           int hotx = 0, int hoty = 0) {
   BITMAPV5HEADER bi;
   HBITMAP bitmap, mask;
   DWORD *bits;
-  HCURSOR new_cursor;
+  HICON icon;
 
-  if ((hotx < 0) || (hotx >= image->w()))
-    return 0;
-  if ((hoty < 0) || (hoty >= image->h()))
-    return 0;
+  if (!is_icon) {
+    if ((hotx < 0) || (hotx >= image->w()))
+      return NULL;
+    if ((hoty < 0) || (hoty >= image->h()))
+      return NULL;
+  }
 
   memset(&bi, 0, sizeof(BITMAPV5HEADER));
 
@@ -2114,7 +2064,7 @@
   ReleaseDC(NULL, hdc);
 
   if (bits == NULL)
-    return 0;
+    return NULL;
 
   const uchar *i = (const uchar*)*image->data();
   for (int y = 0;y < image->h();y++) {
@@ -2143,22 +2093,206 @@
   mask = CreateBitmap(image->w(),image->h(),1,1,NULL);
   if (mask == NULL) {
     DeleteObject(bitmap);
-    return 0;
+    return NULL;
   }
 
   ICONINFO ii;
 
-  ii.fIcon    = FALSE;
+  ii.fIcon    = is_icon;
   ii.xHotspot = hotx;
   ii.yHotspot = hoty;
   ii.hbmMask  = mask;
   ii.hbmColor = bitmap;
 
-  new_cursor = CreateIconIndirect(&ii);
+  icon = CreateIconIndirect(&ii);
 
   DeleteObject(bitmap);
   DeleteObject(mask);
 
+  if (icon == NULL)
+    return NULL;
+
+  return icon;
+}
+
+////////////////////////////////////////////////////////////////
+
+static HICON default_big_icon = NULL;
+static HICON default_small_icon = NULL;
+
+const Fl_RGB_Image *find_best_icon(int ideal_width, 
+                                   const Fl_RGB_Image *icons[], int count) {
+  const Fl_RGB_Image *best;
+
+  best = NULL;
+
+  for (int i = 0;i < count;i++) {
+    if (best == NULL)
+      best = icons[i];
+    else {
+      if (best->w() < ideal_width) {
+        if (icons[i]->w() > best->w())
+          best = icons[i];
+      } else {
+        if ((icons[i]->w() >= ideal_width) &&
+            (icons[i]->w() < best->w()))
+          best = icons[i];
+      }
+    }
+  }
+
+  return best;
+}
+
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
+  const Fl_RGB_Image *best_big, *best_small;
+
+  if (default_big_icon != NULL)
+    DestroyIcon(default_big_icon);
+  if (default_small_icon != NULL)
+    DestroyIcon(default_small_icon);
+
+  best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count);
+  best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count);
+
+  if (best_big != NULL)
+    default_big_icon = image_to_icon(best_big);
+  else
+    default_big_icon = NULL;
+
+  if (best_small != NULL)
+    default_small_icon = image_to_icon(best_small);
+  else
+    default_small_icon = NULL;
+}
+
+void Fl_X::set_default_icons(HICON big_icon, HICON small_icon) {
+  if (default_big_icon != NULL)
+    DestroyIcon(default_big_icon);
+  if (default_small_icon != NULL)
+    DestroyIcon(default_small_icon);
+
+  if (big_icon != NULL)
+    default_big_icon = CopyIcon(big_icon);
+  if (small_icon != NULL)
+    default_small_icon = CopyIcon(small_icon);
+}
+
+void Fl_X::set_icons() {
+  HICON big_icon, small_icon;
+
+  big_icon = NULL;
+  small_icon = NULL;
+
+  if (w->icon_->count) {
+    const Fl_RGB_Image *best_big, *best_small;
+
+    best_big = find_best_icon(GetSystemMetrics(SM_CXICON),
+                              (const Fl_RGB_Image **)w->icon_->icons,
+                              w->icon_->count);
+    best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON),
+                                (const Fl_RGB_Image **)w->icon_->icons,
+                                w->icon_->count);
+
+    if (best_big != NULL)
+      big_icon = image_to_icon(best_big);
+    if (best_small != NULL)
+      small_icon = image_to_icon(best_small);
+  } else {
+    big_icon = default_big_icon;
+    small_icon = default_small_icon;
+  }
+
+  if (big_icon != NULL)
+    SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon);
+  if (small_icon != NULL)
+    SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon);
+
+  if (w->icon_->count) {
+    if (big_icon != NULL)
+      DestroyIcon(big_icon);
+    if (small_icon != NULL)
+      DestroyIcon(small_icon);
+  }
+}
+
+void Fl_Window::default_icons(HICON big_icon, HICON small_icon) {
+  Fl_X::set_default_icons(big_icon, small_icon);
+}
+
+void Fl_Window::icons(HICON big_icon, HICON small_icon) {
+  free_icons();
+
+  if (big_icon != NULL)
+    icon_->big_icon = CopyIcon(big_icon);
+  if (small_icon != NULL)
+    icon_->small_icon = CopyIcon(small_icon);
+
+  if (i)
+    i->set_icons();
+}
+
+////////////////////////////////////////////////////////////////
+
+#ifndef IDC_HAND
+#  define IDC_HAND  MAKEINTRESOURCE(32649)
+#endif // !IDC_HAND
+
+int Fl_X::set_cursor(Fl_Cursor c) {
+  LPSTR n;
+  HCURSOR new_cursor;
+
+  if (c == FL_CURSOR_NONE)
+    new_cursor = NULL;
+  else {
+    switch (c) {
+    case FL_CURSOR_ARROW:   n = IDC_ARROW; break;
+    case FL_CURSOR_CROSS:   n = IDC_CROSS; break;
+    case FL_CURSOR_WAIT:    n = IDC_WAIT; break;
+    case FL_CURSOR_INSERT:  n = IDC_IBEAM; break;
+    case FL_CURSOR_HAND:    n = IDC_HAND; break;
+    case FL_CURSOR_HELP:    n = IDC_HELP; break;
+    case FL_CURSOR_MOVE:    n = IDC_SIZEALL; break;
+    case FL_CURSOR_N:
+    case FL_CURSOR_S:
+      // FIXME: Should probably have fallbacks for these instead
+    case FL_CURSOR_NS:      n = IDC_SIZENS; break;
+    case FL_CURSOR_NE:
+    case FL_CURSOR_SW:
+      // FIXME: Dito.
+    case FL_CURSOR_NESW:    n = IDC_SIZENESW; break;
+    case FL_CURSOR_E:
+    case FL_CURSOR_W:
+      // FIXME: Dito.
+    case FL_CURSOR_WE:      n = IDC_SIZEWE; break;
+    case FL_CURSOR_SE:
+    case FL_CURSOR_NW:
+      // FIXME: Dito.
+    case FL_CURSOR_NWSE:    n = IDC_SIZENWSE; break;
+    default:
+      return 0;
+    }
+
+    new_cursor = LoadCursor(NULL, n);
+    if (new_cursor == NULL)
+      return 0;
+  }
+
+  if ((cursor != NULL) && custom_cursor)
+    DestroyIcon(cursor);
+
+  cursor = new_cursor;
+  custom_cursor = 0;
+
+  SetCursor(cursor);
+
+  return 1;
+}
+
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
+  HCURSOR new_cursor;
+
+  new_cursor = image_to_icon(image, false, hotx, hoty);
   if (new_cursor == NULL)
     return 0;
 

Modified: trunk/common/fltk/src/Fl_x.cxx
===================================================================
--- trunk/common/fltk/src/Fl_x.cxx      2012-04-25 14:54:04 UTC (rev 4897)
+++ trunk/common/fltk/src/Fl_x.cxx      2012-04-25 14:57:22 UTC (rev 4898)
@@ -346,6 +346,7 @@
 Atom fl_NET_SUPPORTING_WM_CHECK;
 Atom fl_NET_WM_STATE;
 Atom fl_NET_WM_STATE_FULLSCREEN;
+Atom fl_NET_WM_ICON;
 
 /*
   X defines 32-bit-entities to have a format value of max. 32,
@@ -708,6 +709,7 @@
   fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
   fl_NET_WM_STATE       = XInternAtom(d, "_NET_WM_STATE",       0);
   fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
+  fl_NET_WM_ICON        = XInternAtom(d, "_NET_WM_ICON",        0);
 
   if (sizeof(Atom) < 4)
     atom_bits = sizeof(Atom) * 8;
@@ -2095,12 +2097,14 @@
       fl_show_iconic = 0;
       showit = 0;
     }
-    if (win->icon()) {
-      hints->icon_pixmap = (Pixmap)win->icon();
+    if (win->icon_->legacy_icon) {
+      hints->icon_pixmap = (Pixmap)win->icon_->legacy_icon;
       hints->flags       |= IconPixmapHint;
     }
     XSetWMHints(fl_display, xp->xid, hints);
     XFree(hints);
+
+    xp->set_icons();
   }
 
   // set the window type for menu and tooltip windows to avoid animations 
(compiz)
@@ -2220,6 +2224,93 @@
 
 ////////////////////////////////////////////////////////////////
 
+static unsigned long *default_net_wm_icons = 0L;
+static size_t default_net_wm_icons_size = 0;
+
+void icons_to_property(const Fl_RGB_Image *icons[], int count,
+                       unsigned long **property, size_t *len) {
+  size_t sz;
+  unsigned long *data;
+
+  sz = 0;
+  for (int i = 0;i < count;i++)
+    sz += 2 + icons[i]->w() * icons[i]->h();
+
+  // FIXME: Might want to sort the icons
+
+  *property = data = new unsigned long[sz];
+  *len = sz;
+
+  for (int i = 0;i < count;i++) {
+    const Fl_RGB_Image *image;
+
+    image = icons[i];
+
+    data[0] = image->w();
+    data[1] = image->h();
+    data += 2;
+
+    const uchar *in = (const uchar*)*image->data();
+    for (int y = 0;y < image->h();y++) {
+      for (int x = 0;x < image->w();x++) {
+        switch (image->d()) {
+        case 1:
+          *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
+          break;
+        case 2:
+          *data = (in[1]<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
+          break;
+        case 3:
+          *data = ( 0xff<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
+          break;
+        case 4:
+          *data = (in[3]<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
+          break;
+        }
+        in += image->d();
+        data++;
+      }
+      in += image->ld();
+    }
+  }
+}
+
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
+  if (default_net_wm_icons) {
+    delete [] default_net_wm_icons;
+    default_net_wm_icons = 0L;
+    default_net_wm_icons_size = 0;
+  }
+
+  if (count > 0)
+    icons_to_property(icons, count,
+                      &default_net_wm_icons, &default_net_wm_icons_size);
+}
+
+void Fl_X::set_icons() {
+  unsigned long *net_wm_icons;
+  size_t net_wm_icons_size;
+
+  if (w->icon_->count) {
+    icons_to_property((const Fl_RGB_Image **)w->icon_->icons, w->icon_->count,
+                      &net_wm_icons, &net_wm_icons_size);
+  } else {
+    net_wm_icons = default_net_wm_icons;
+    net_wm_icons_size = default_net_wm_icons_size;
+  }
+
+  XChangeProperty (fl_display, xid, fl_NET_WM_ICON, XA_CARDINAL, 32,
+      PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size);
+
+  if (w->icon_->count) {
+    delete [] net_wm_icons;
+    net_wm_icons = 0L;
+    net_wm_icons_size = 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
 int Fl_X::set_cursor(Fl_Cursor c) {
   unsigned int shape;
   Cursor xc;

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to