summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2014-06-16 11:39:32 +0000
committerPierre Ossman <ossman@cendio.se>2014-06-16 11:39:32 +0000
commitf58b1a91b37e5ad758b3d0a3d9be950e8feb5d0c (patch)
treeca7ebd90423d4d9267da62703e282f79a9793131
parent332dc1b7acfedbf80b71cc6f538a14f24d435df3 (diff)
Add ability to set custom icons for windows. STR #2816.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10197 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--FL/Fl_Window.H30
-rw-r--r--FL/mac.H3
-rw-r--r--FL/win32.H3
-rw-r--r--FL/x.H2
-rw-r--r--src/Fl.cxx4
-rw-r--r--src/Fl_Window.cxx116
-rw-r--r--src/Fl_win32.cxx308
-rw-r--r--src/Fl_x.cxx95
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/Makefile4
-rw-r--r--test/icon.cxx51
11 files changed, 544 insertions, 73 deletions
diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H
index c26f474d2..92e76676f 100644
--- a/FL/Fl_Window.H
+++ b/FL/Fl_Window.H
@@ -22,6 +22,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
@@ -89,9 +93,19 @@ class FL_EXPORT Fl_Window : public Fl_Group {
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;
@@ -141,6 +155,8 @@ protected:
*/
int force_position() const { return ((flags() & FORCE_POSITION)?1:0); }
+ void free_icons();
+
public:
/**
@@ -370,6 +386,18 @@ public:
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);
diff --git a/FL/mac.H b/FL/mac.H
index f02094427..e5f7fdb0e 100644
--- a/FL/mac.H
+++ b/FL/mac.H
@@ -142,6 +142,9 @@ public:
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);
diff --git a/FL/win32.H b/FL/win32.H
index 3ecdad79e..8ae8c8c8d 100644
--- a/FL/win32.H
+++ b/FL/win32.H
@@ -85,6 +85,9 @@ public:
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*);
diff --git a/FL/x.H b/FL/x.H
index 46f7108e2..91f888126 100644
--- a/FL/x.H
+++ b/FL/x.H
@@ -150,6 +150,8 @@ public:
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);
diff --git a/src/Fl.cxx b/src/Fl.cxx
index c3b935987..714c8deee 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1489,6 +1489,8 @@ void Fl_Window::hide() {
handle(FL_HIDE);
#if defined(WIN32)
+ // make sure any custom icons get freed
+ icons(NULL, 0);
// this little trick keeps the current clipboard alive, even if we are about
// to destroy the window that owns the selection.
if (GetClipboardOwner()==ip->xid)
@@ -1553,6 +1555,8 @@ Fl_Window::~Fl_Window() {
if (xclass_) {
free(xclass_);
}
+ free_icons();
+ delete icon_;
}
// FL_SHOW and FL_HIDE are called whenever the visibility of this widget
diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx
index 058de009c..6b8f167de 100644
--- a/src/Fl_Window.cxx
+++ b/src/Fl_Window.cxx
@@ -23,6 +23,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"
@@ -45,7 +46,8 @@ void Fl_Window::_Fl_Window() {
}
i = 0;
xclass_ = 0;
- icon_ = 0;
+ icon_ = new icon_data;
+ memset(icon_, 0, sizeof(*icon_));
iconlabel_ = 0;
resizable(0);
size_range_set = 0;
@@ -301,14 +303,118 @@ const char *Fl_Window::xclass() const
}
}
-/** Gets the current icon window target dependent data. */
+/** Sets a single default window icon.
+
+ \param[in] icon default icon for all windows subsequently created
+
+ \see Fl_Window::default_icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::icon(const Fl_RGB_Image *)
+ \see Fl_Window::icons(const Fl_RGB_Image *[], int)
+ */
+void Fl_Window::default_icon(const Fl_RGB_Image *icon) {
+ default_icons(&icon, 1);
+}
+
+/** Sets the default window icons.
+
+ The default icons are used for all windows that don't have their
+ own icons set before show() is called. You can change the default
+ icons whenever you want, but this only affects windows that are
+ created (and shown) after this call.
+
+ The given images in \p icons are copied. You can use a local
+ variable or free the images immediately after this call.
+
+ \param[in] icons default icons for all windows subsequently created
+ \param[in] count number of images in \p icons. set to 0 to remove
+ the current default icons
+
+ \see Fl_Window::default_icon(const Fl_RGB_Image *)
+ \see Fl_Window::icon(const Fl_RGB_Image *)
+ \see Fl_Window::icons(const Fl_RGB_Image *[], int)
+ */
+void Fl_Window::default_icons(const Fl_RGB_Image *icons[], int count) {
+ Fl_X::set_default_icons(icons, count);
+}
+
+/** Sets a single window icon.
+
+ \param[in] icon icon for this window
+
+ \see Fl_Window::default_icon(const Fl_RGB_Image *)
+ \see Fl_Window::default_icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::icons(const Fl_RGB_Image *[], int)
+ */
+void Fl_Window::icon(const Fl_RGB_Image *icon) {
+ icons(&icon, 1);
+}
+
+/** Sets the window icons.
+
+ The given images in \p icons are copied. You can use a local
+ variable or free the images immediately after this call.
+
+ \param[in] icons icons for this window
+ \param[in] count number of images in \p icons. set to 0 to remove
+ the current icons
+
+ \see Fl_Window::default_icon(const Fl_RGB_Image *)
+ \see Fl_Window::default_icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::icon(const Fl_RGB_Image *)
+ */
+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.
+ \deprecated in 1.3.3
+ */
const void *Fl_Window::icon() const {
- return icon_;
+ return icon_->legacy_icon;
}
-/** Sets the current icon window target dependent data. */
+/** Sets the current icon window target dependent data.
+ \deprecated in 1.3.3
+ */
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
}
//
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 094edb39d..79b300fb4 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1820,6 +1820,8 @@ Fl_X* Fl_X::make(Fl_Window* w) {
);
if (lab) free(lab);
+ x->set_icons();
+
if (w->fullscreen_active()) {
/* We need to make sure that the fullscreen is created on the
default monitor, ie the desktop where the shortcut is located
@@ -2053,71 +2055,19 @@ void Fl_Window::label(const char *name,const char *iname) {
////////////////////////////////////////////////////////////////
-#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,
+ int hotx, int hoty) {
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));
@@ -2139,7 +2089,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
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++) {
@@ -2168,22 +2118,250 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
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;
+
+static 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);
+
+ default_big_icon = NULL;
+ default_small_icon = NULL;
+
+ 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, true, 0, 0);
+
+ if (best_small != NULL)
+ default_small_icon = image_to_icon(best_small, true, 0, 0);
+}
+
+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);
+
+ default_big_icon = NULL;
+ default_small_icon = NULL;
+
+ 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;
+
+ // Windows doesn't copy the icons, so we have to "leak" them when
+ // setting, and clean up when we change to some other icons.
+ big_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_BIG, 0);
+ if ((big_icon != NULL) && (big_icon != default_big_icon))
+ DestroyIcon(big_icon);
+ small_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_SMALL, 0);
+ if ((small_icon != NULL) && (small_icon != default_small_icon))
+ DestroyIcon(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, true, 0, 0);
+ if (best_small != NULL)
+ small_icon = image_to_icon(best_small, true, 0, 0);
+ } else {
+ if ((w->icon_->big_icon != NULL) || (w->icon_->small_icon != NULL)) {
+ big_icon = w->icon_->big_icon;
+ small_icon = w->icon_->small_icon;
+ } else {
+ big_icon = default_big_icon;
+ small_icon = default_small_icon;
+ }
+ }
+
+ SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon);
+ SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon);
+}
+
+/** Sets the default window icons.
+
+ Convenience function to set the default icons using Windows'
+ native HICON icon handles.
+
+ The given icons are copied. You can free the icons immediately after
+ this call.
+
+ \param[in] big_icon default large icon for all windows
+ subsequently created
+ \param[in] small_icon default small icon for all windows
+ subsequently created
+
+ \see Fl_Window::default_icon(const Fl_RGB_Image *)
+ \see Fl_Window::default_icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::icon(const Fl_RGB_Image *)
+ \see Fl_Window::icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::icons(HICON, HICON)
+ */
+void Fl_Window::default_icons(HICON big_icon, HICON small_icon) {
+ Fl_X::set_default_icons(big_icon, small_icon);
+}
+
+/** Sets the window icons.
+
+ Convenience function to set this window's icons using Windows'
+ native HICON icon handles.
+
+ The given icons are copied. You can free the icons immediately after
+ this call.
+
+ \param[in] big_icon large icon for this window
+ \param[in] small_icon small icon for this windows
+
+ \see Fl_Window::default_icon(const Fl_RGB_Image *)
+ \see Fl_Window::default_icons(const Fl_RGB_Image *[], int)
+ \see Fl_Window::default_icons(HICON, HICON)
+ \see Fl_Window::icon(const Fl_RGB_Image *)
+ \see Fl_Window::icons(const Fl_RGB_Image *[], int)
+ */
+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;
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index b2b0f705a..0ee3c6482 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -352,6 +352,7 @@ Atom fl_NET_WM_STATE;
Atom fl_NET_WM_STATE_FULLSCREEN;
Atom fl_NET_WM_FULLSCREEN_MONITORS;
Atom fl_NET_WORKAREA;
+Atom fl_NET_WM_ICON;
/*
X defines 32-bit-entities to have a format value of max. 32,
@@ -662,6 +663,7 @@ void fl_open_display(Display* d) {
fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0);
fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0);
+ fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0);
if (sizeof(Atom) < 4)
atom_bits = sizeof(Atom) * 8;
@@ -2480,12 +2482,14 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
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)
@@ -2605,6 +2609,93 @@ void Fl_Window::size_range_() {
////////////////////////////////////////////////////////////////
+static unsigned long *default_net_wm_icons = 0L;
+static size_t default_net_wm_icons_size = 0;
+
+static 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;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a2cba8840..1ec27d35e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -82,6 +82,7 @@ CREATE_EXAMPLE(fonts fonts.cxx fltk)
CREATE_EXAMPLE(forms forms.cxx "fltk;fltk_forms")
CREATE_EXAMPLE(hello hello.cxx fltk)
CREATE_EXAMPLE(help help.cxx "fltk;fltk_images")
+CREATE_EXAMPLE(icon icon.cxx fltk)
CREATE_EXAMPLE(iconize iconize.cxx fltk)
CREATE_EXAMPLE(image image.cxx fltk)
CREATE_EXAMPLE(inactive inactive.fl fltk)
diff --git a/test/Makefile b/test/Makefile
index 5f4597bd8..4570df628 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -53,6 +53,7 @@ CPPFILES =\
glpuzzle.cxx \
hello.cxx \
help.cxx \
+ icon.cxx \
iconize.cxx \
image.cxx \
inactive.cxx \
@@ -121,6 +122,7 @@ ALL = \
forms$(EXEEXT) \
hello$(EXEEXT) \
help$(EXEEXT) \
+ icon$(EXEEXT) \
iconize$(EXEEXT) \
image$(EXEEXT) \
inactive$(EXEEXT) \
@@ -355,6 +357,8 @@ help$(EXEEXT): help.o $(IMGLIBNAME)
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) help.o -o $@ $(LINKFLTKIMG) $(LDLIBS)
$(OSX_ONLY) ../fltk-config --post $@
+icon$(EXEEXT): icon.o
+
iconize$(EXEEXT): iconize.o
image$(EXEEXT): image.o
diff --git a/test/icon.cxx b/test/icon.cxx
new file mode 100644
index 000000000..75c43ab39
--- /dev/null
+++ b/test/icon.cxx
@@ -0,0 +1,51 @@
+//
+// Icon test program for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2010 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_RGB_Image.H>
+
+static Fl_Double_Window *win;
+
+void choice_cb(Fl_Widget *, void *v) {
+ Fl_Color c = (Fl_Color)(fl_intptr_t)v;
+ uchar buffer[32*32*3];
+ Fl_RGB_Image icon(buffer, 32, 32, 3);
+ icon.color_average(c, 0.0);
+ win->icon(&icon);
+}
+
+Fl_Menu_Item choices[] = {
+ {"Red",0,choice_cb,(void*)FL_RED},
+ {"Green",0,choice_cb,(void*)FL_GREEN},
+ {"Blue",0,choice_cb,(void*)FL_BLUE},
+ {0}
+};
+
+int main(int argc, char **argv) {
+ Fl_Double_Window window(400,300);
+ win = &window;
+
+ Fl_Choice choice(80,100,200,25,"Colour:");
+ choice.menu(choices);
+ choice.callback(choice_cb);
+ choice.when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+
+ window.end();
+ window.show(argc,argv);
+ return Fl::run();
+}