From f58b1a91b37e5ad758b3d0a3d9be950e8feb5d0c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 16 Jun 2014 11:39:32 +0000 Subject: [PATCH] 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 --- FL/Fl_Window.H | 30 +++- FL/mac.H | 3 + FL/win32.H | 3 + FL/x.H | 2 + src/Fl.cxx | 4 + src/Fl_Window.cxx | 118 +++++++++++++++- src/Fl_win32.cxx | 324 ++++++++++++++++++++++++++++++++++---------- src/Fl_x.cxx | 95 ++++++++++++- test/CMakeLists.txt | 1 + test/Makefile | 4 + test/icon.cxx | 51 +++++++ 11 files changed, 553 insertions(+), 82 deletions(-) create mode 100644 test/icon.cxx 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 +#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 #include #include +#include #include #include #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. */ -const void *Fl_Window::icon() const { - return icon_; +/** 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 current icon window target dependent data. */ +/** 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_->legacy_icon; +} + +/** 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,6 +2055,254 @@ void Fl_Window::label(const char *name,const char *iname) { //////////////////////////////////////////////////////////////// +static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, + int hotx, int hoty) { + BITMAPV5HEADER bi; + HBITMAP bitmap, mask; + DWORD *bits; + HICON icon; + + if (!is_icon) { + if ((hotx < 0) || (hotx >= image->w())) + return NULL; + if ((hoty < 0) || (hoty >= image->h())) + return NULL; + } + + memset(&bi, 0, sizeof(BITMAPV5HEADER)); + + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = image->w(); + bi.bV5Height = -image->h(); // Negative for top-down + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + HDC hdc; + + hdc = GetDC(NULL); + bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ReleaseDC(NULL, hdc); + + if (bits == NULL) + return NULL; + + const uchar *i = (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: + *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 2: + *bits = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 3: + *bits = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + case 4: + *bits = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + } + i += image->d(); + bits++; + } + i += image->ld(); + } + + // A mask bitmap is still needed even though it isn't used + mask = CreateBitmap(image->w(),image->h(),1,1,NULL); + if (mask == NULL) { + DeleteObject(bitmap); + return NULL; + } + + ICONINFO ii; + + ii.fIcon = is_icon; + ii.xHotspot = hotx; + ii.yHotspot = hoty; + ii.hbmMask = mask; + ii.hbmColor = bitmap; + + 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 @@ -2109,81 +2359,9 @@ int Fl_X::set_cursor(Fl_Cursor c) { } int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { - BITMAPV5HEADER bi; - HBITMAP bitmap, mask; - DWORD *bits; HCURSOR new_cursor; - if ((hotx < 0) || (hotx >= image->w())) - return 0; - if ((hoty < 0) || (hoty >= image->h())) - return 0; - - memset(&bi, 0, sizeof(BITMAPV5HEADER)); - - bi.bV5Size = sizeof(BITMAPV5HEADER); - bi.bV5Width = image->w(); - bi.bV5Height = -image->h(); // Negative for top-down - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5RedMask = 0x00FF0000; - bi.bV5GreenMask = 0x0000FF00; - bi.bV5BlueMask = 0x000000FF; - bi.bV5AlphaMask = 0xFF000000; - - HDC hdc; - - hdc = GetDC(NULL); - bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); - ReleaseDC(NULL, hdc); - - if (bits == NULL) - return 0; - - const uchar *i = (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: - *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; - break; - case 2: - *bits = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; - break; - case 3: - *bits = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; - break; - case 4: - *bits = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; - break; - } - i += image->d(); - bits++; - } - i += image->ld(); - } - - // A mask bitmap is still needed even though it isn't used - mask = CreateBitmap(image->w(),image->h(),1,1,NULL); - if (mask == NULL) { - DeleteObject(bitmap); - return 0; - } - - ICONINFO ii; - - ii.fIcon = FALSE; - ii.xHotspot = hotx; - ii.yHotspot = hoty; - ii.hbmMask = mask; - ii.hbmColor = bitmap; - - new_cursor = CreateIconIndirect(&ii); - - DeleteObject(bitmap); - DeleteObject(mask); - + 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 +#include +#include +#include + +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(); +}