git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4898 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v1.2.90
@@ -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); | |||
@@ -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); |
@@ -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*); |
@@ -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); |
@@ -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 |
@@ -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 $". |
@@ -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; | |||
@@ -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; |