瀏覽代碼

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
tags/v1.2.90
Pierre Ossman 12 年之前
父節點
當前提交
ab8aeedefd

+ 29
- 1
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);


+ 3
- 0
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);

+ 3
- 0
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*);

+ 2
- 0
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);

+ 2
- 0
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

+ 57
- 3
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 $".

+ 199
- 65
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;


+ 93
- 2
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;

Loading…
取消
儲存