diff options
author | Pierre Ossman <ossman@cendio.se> | 2012-04-25 14:57:22 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2012-04-25 14:57:22 +0000 |
commit | ab8aeedefd03dcdef2e5f9f1aabc1bb9cd1d70f4 (patch) | |
tree | a50108ab32a76ed79b725303b49e1a66f1a59498 | |
parent | 57bbce4306410128397208dc4f1257055f9b5e82 (diff) | |
download | tigervnc-ab8aeedefd03dcdef2e5f9f1aabc1bb9cd1d70f4.tar.gz tigervnc-ab8aeedefd03dcdef2e5f9f1aabc1bb9cd1d70f4.zip |
Proper support for icons in FLTK (upstream STR 2816).
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4898 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r-- | common/fltk/FL/Fl_Window.H | 30 | ||||
-rw-r--r-- | common/fltk/FL/mac.H | 3 | ||||
-rw-r--r-- | common/fltk/FL/win32.H | 3 | ||||
-rw-r--r-- | common/fltk/FL/x.H | 2 | ||||
-rw-r--r-- | common/fltk/src/Fl.cxx | 2 | ||||
-rw-r--r-- | common/fltk/src/Fl_Window.cxx | 60 | ||||
-rw-r--r-- | common/fltk/src/Fl_win32.cxx | 264 | ||||
-rw-r--r-- | common/fltk/src/Fl_x.cxx | 95 |
8 files changed, 388 insertions, 71 deletions
diff --git a/common/fltk/FL/Fl_Window.H b/common/fltk/FL/Fl_Window.H index 02ba6884..9632895d 100644 --- a/common/fltk/FL/Fl_Window.H +++ b/common/fltk/FL/Fl_Window.H @@ -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 @@ 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; @@ -110,6 +124,8 @@ protected: */ int force_position() const { return ((flags() & FORCE_POSITION)?1:0); } + void free_icons(); + public: /** @@ -331,6 +347,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/common/fltk/FL/mac.H b/common/fltk/FL/mac.H index f23dc8ec..97eefd8d 100644 --- a/common/fltk/FL/mac.H +++ b/common/fltk/FL/mac.H @@ -141,6 +141,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/common/fltk/FL/win32.H b/common/fltk/FL/win32.H index 9297e9f7..858fe5b4 100644 --- a/common/fltk/FL/win32.H +++ b/common/fltk/FL/win32.H @@ -93,6 +93,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/common/fltk/FL/x.H b/common/fltk/FL/x.H index a5202862..c2eb46e5 100644 --- a/common/fltk/FL/x.H +++ b/common/fltk/FL/x.H @@ -163,6 +163,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/common/fltk/src/Fl.cxx b/common/fltk/src/Fl.cxx index 134e4d07..887c11fb 100644 --- a/common/fltk/src/Fl.cxx +++ b/common/fltk/src/Fl.cxx @@ -1535,6 +1535,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/common/fltk/src/Fl_Window.cxx b/common/fltk/src/Fl_Window.cxx index 1ece624c..fe872ec7 100644 --- a/common/fltk/src/Fl_Window.cxx +++ b/common/fltk/src/Fl_Window.cxx @@ -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 @@ 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; @@ -277,16 +279,68 @@ const char *Fl_Window::xclass() const } } +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 $". diff --git a/common/fltk/src/Fl_win32.cxx b/common/fltk/src/Fl_win32.cxx index 7fc639e1..eaae51da 100644 --- a/common/fltk/src/Fl_win32.cxx +++ b/common/fltk/src/Fl_win32.cxx @@ -1802,6 +1802,8 @@ Fl_X* Fl_X::make(Fl_Window* w) { ); 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 @@ 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=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 @@ 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++) { @@ -2143,22 +2093,206 @@ 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; + +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; diff --git a/common/fltk/src/Fl_x.cxx b/common/fltk/src/Fl_x.cxx index 8c72dba3..f95cf802 100644 --- a/common/fltk/src/Fl_x.cxx +++ b/common/fltk/src/Fl_x.cxx @@ -346,6 +346,7 @@ Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name 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 @@ void fl_open_display(Display* d) { 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 @@ 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) @@ -2220,6 +2224,93 @@ void Fl_Window::size_range_() { //////////////////////////////////////////////////////////////// +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; |