eiconman based on fltk1. Most of the stuff is

revised from scratch.
This commit is contained in:
Sanel Zukan 2007-06-18 14:18:35 +00:00
parent 95a3034827
commit 202b4ffb29
13 changed files with 563 additions and 1136 deletions

View File

@ -1,194 +0,0 @@
/*
* $Id$
*
* Eiconman, desktop and icon manager
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include "DesktopConfig.h"
#include "Utils.h"
#include "eiconman.h"
#include <edelib/Nls.h>
#include <edelib/Debug.h>
#include <fltk/Item.h>
#include <fltk/ColorChooser.h>
#include <fltk/file_chooser.h>
#include <fltk/SharedImage.h>
#include <fltk/run.h>
#include <fltk/draw.h>
#include <fltk/x11.h>
void close_cb(fltk::Widget*, void* w) {
DesktopConfig* dc = (DesktopConfig*)w;
dc->hide();
}
void ok_cb(fltk::Widget*, void* w) { }
void apply_cb(fltk::Widget*, void* w) {
DesktopConfig* dc = (DesktopConfig*)w;
//Desktop::instance()->set_bg_color(dc->bg_color());
}
void wp_use_cb(fltk::Widget*, void* w) {
DesktopConfig* dc = (DesktopConfig*)w;
dc->wp_disable();
}
void color_box_cb(fltk::Widget*, void* w) {
DesktopConfig* dc = (DesktopConfig*)w;
fltk::Color col = dc->bg_color();
if(fltk::color_chooser(_("Background color"), col))
dc->set_color(col);
}
void img_browse_cb(fltk::Widget*, void* w) {
DesktopConfig* dc = (DesktopConfig*)w;
const char* f = fltk::file_chooser(_("Choose image"), "Image files (*.{jpg,png,xpm})", 0);
if(f)
dc->set_preview_image(f);
};
PreviewBox::PreviewBox(int x, int y, int w, int h, const char* l) : fltk::InvisibleBox(x,y,w,h)
{
}
PreviewBox::~PreviewBox()
{
}
void PreviewBox::draw(void) {
draw_box();
if(image()) {
fltk::Rectangle ir(0,0,w(),h());
box()->inset(ir);
fltk::Image* im = (fltk::Image*)image();
im->draw(ir);
}
}
DesktopConfig::DesktopConfig() : fltk::Window(540, 265, _("Background settings")), img_enable(false), wp_img(NULL) {
begin();
// monitor
fltk::InvisibleBox* m1 = new fltk::InvisibleBox(75, 175, 100, 15);
m1->box(fltk::BORDER_BOX);
fltk::InvisibleBox* m2 = new fltk::InvisibleBox(20, 20, 210, 160);
m2->box(fltk::THIN_UP_BOX);
preview = new PreviewBox(30, 30, 190, 140);
preview->box(fltk::DOWN_BOX);
preview->color(56);
fltk::InvisibleBox* m4 = new fltk::InvisibleBox(50, 185, 145, 15);
m4->box(fltk::THIN_UP_BOX);
// fetch workspace names
fltk::Choice* ws_names = new fltk::Choice(310, 20, 220, 25, _("Desktop:"));
ws_names->begin();
new fltk::Item(_("All desktops"));
ws_names->end();
// rest
use_wp = new fltk::CheckButton(310, 60, 20, 20, _("Use wallpaper"));
use_wp->align(fltk::ALIGN_RIGHT);
use_wp->callback(wp_use_cb, this);
use_wp->value(1);
img_path = new fltk::Input(310, 95, 190, 25, _("Image:"));
img_browse = new fltk::Button(505, 95, 25, 25, "...");
img_browse->callback(img_browse_cb, this);
img_choice = new fltk::Choice(310, 130, 220, 25, _("Mode:"));
img_choice->begin();
new fltk::Item(_("Normal"));
new fltk::Item(_("Center"));
new fltk::Item(_("Stretch"));
new fltk::Item(_("Aspect stretch"));
new fltk::Item(_("Tile"));
img_choice->end();
color_box = new fltk::Button(310, 175, 25, 25, _("Background color"));
color_box->color((fltk::Color)0x3ca700);
color_box->align(fltk::ALIGN_RIGHT);
color_box->callback(color_box_cb, this);
fltk::Button* ok = new fltk::Button(250, 230, 90, 25, _("&OK"));
ok->callback(ok_cb, this);
fltk::Button* apply = new fltk::Button(345, 230, 90, 25, _("&Apply"));
apply->callback(apply_cb, this);
fltk::Button* close = new fltk::Button(440, 230, 90, 25, _("&Cancel"));
close->callback(close_cb, this);
end();
}
DesktopConfig::~DesktopConfig()
{
}
void DesktopConfig::run(void) {
if(!shown())
show();
while(visible())
fltk::wait();
}
void DesktopConfig::wp_disable(void) {
if(!use_wp->value()) {
img_path->deactivate();
img_browse->deactivate();
img_choice->deactivate();
} else {
img_path->activate();
img_browse->activate();
img_choice->activate();
}
img_enable = false;
preview->image(NULL);
set_color(color_box->color());
}
void DesktopConfig::set_preview_color(unsigned int c) {
if(c == preview->color())
return;
preview->color(c);
preview->redraw();
}
void DesktopConfig::set_color(unsigned int c) {
if(c != color_box->color()) {
color_box->color(c);
color_box->redraw();
}
set_preview_color(c);
}
void DesktopConfig::set_preview_image(const char* path) {
EASSERT(path != NULL);
if(wp_path == path)
return;
wp_path = path;
wp_img = fltk::SharedImage::get(wp_path.c_str());
preview->image(wp_img);
preview->redraw();
img_path->value(wp_path.c_str());
}

View File

@ -1,60 +0,0 @@
/*
* $Id$
*
* Eiconman, desktop and icon manager
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#ifndef __DESKTOPCONFIG_H__
#define __DESKTOPCONFIG_H__
#include <fltk/Window.h>
#include <fltk/Button.h>
#include <fltk/Input.h>
#include <fltk/InvisibleBox.h>
#include <fltk/Choice.h>
#include <fltk/CheckButton.h>
#include <fltk/Image.h>
#include <edelib/String.h>
class PreviewBox : public fltk::InvisibleBox {
public:
PreviewBox(int x, int y, int w, int h, const char* l = 0);
~PreviewBox();
virtual void draw(void);
};
class DesktopConfig : public fltk::Window {
private:
bool img_enable;
fltk::Image* wp_img;
fltk::Input* img_path;
fltk::Button* img_browse;
fltk::Choice* img_choice;
fltk::CheckButton* use_wp;
PreviewBox* preview;
fltk::Button* color_box;
edelib::String wp_path;
public:
DesktopConfig();
~DesktopConfig();
void run(void);
void wp_disable(void);
bool wp_enabled(void) { return img_enable; }
void set_preview_color(unsigned int c);
void set_preview_image(const char* path);
void set_color(unsigned int c);
unsigned int bg_color(void) { return color_box->color(); }
};
#endif

View File

@ -12,63 +12,50 @@
#include "DesktopIcon.h"
#include "eiconman.h"
#include "Utils.h"
#include <FL/Fl.h>
#include <FL/fl_draw.h>
#include <FL/Fl_Shared_Image.h>
#include <FL/x.h>
#include <edelib/Debug.h>
#include <edelib/IconTheme.h>
#include <edelib/Nls.h>
#include <edelib/Item.h>
#include <edelib/Ask.h>
#include <fltk/SharedImage.h>
#include <fltk/Color.h>
#include <fltk/Divider.h>
#include <fltk/draw.h>
#include <fltk/events.h>
#include <fltk/damage.h>
#include <X11/extensions/shape.h>
#include <fltk/x11.h> // Pixmap
// fuck !
#define Window XWindow
#include <X11/extensions/shape.h>
#undef Window
// default icon size
// minimal icon size
#define ICONSIZE 48
// spaces around box in case of large/small icons
#define OFFSET_W 16
#define OFFSET_H 16
void icon_delete_cb(fltk::Widget*, void* di) {
DesktopIcon* dicon = (DesktopIcon*)di;
edelib::ask(_("Delete '%s' ?"), dicon->label());
}
// label offset from icon y()+h(), so selection box can be drawn nicely
#define LABEL_OFFSET 2
DesktopIcon::DesktopIcon(GlobalIconSettings* gisett, IconSettings* isett) :
fltk::Widget(isett->x, isett->y, ICONSIZE, ICONSIZE), settings(NULL)
{
EASSERT(gisett != NULL); EASSERT(isett != NULL);
DesktopIcon::DesktopIcon(GlobalIconSettings* gs, IconSettings* is, int bg) :
Fl_Button(is->x, is->y, ICONSIZE, ICONSIZE) {
EASSERT(gs != NULL);
lwidth = lheight = 0;
focus = false;
micon = false;
image_w = image_h = ICONSIZE;
micon = NULL;
/*
* GlobalIconSettings is shared from desktop so we only
* reference it. On other hand IconSettings is not shared
* and we must construct a copy from given parameter
*/
globals = gisett;
globals = gs;
settings = new IconSettings;
settings->name = isett->name;
settings->cmd = isett->cmd;
settings->icon = isett->icon;
settings->type = isett->type;
settings->key_name= isett->key_name;
settings->name = is->name;
settings->cmd = is->cmd;
settings->icon = is->icon;
settings->type = is->type;
settings->key_name= is->key_name;
// x,y are not needed since x(), y() are filled with it
@ -77,83 +64,52 @@ DesktopIcon::DesktopIcon(GlobalIconSettings* gisett, IconSettings* isett) :
if(!settings->icon.empty()) {
const char* nn = settings->icon.c_str();
edelib::IconSizes isize = edelib::ICON_SIZE_MEDIUM;
edelib::String ipath = edelib::IconTheme::get(nn, isize);
edelib::String ipath = edelib::IconTheme::get(nn, edelib::ICON_SIZE_MEDIUM);
Fl_Image* img = Fl_Shared_Image::get(ipath.c_str());
if(img) {
int img_w = img->w();
int img_h = img->h();
/*
* Resize box according to size from IconSizes.
*
* Here is avoided image()->measure() since looks like
* that function messes up icon's alpha blending if is widget
* resizes (but not icon). This is a bug in fltk.
*/
if(isize >= ICONSIZE) {
image_w = isize;
image_h = isize;
// resize box if icon is larger
if(img_w > ICONSIZE || img_h > ICONSIZE)
size(img_w + OFFSET_W, img_h + OFFSET_H);
resize(image_w + OFFSET_W, image_h + OFFSET_H);
}
nn = ipath.c_str();
image(fltk::SharedImage::get(nn));
image(img);
} else
EDEBUG(ESTRLOC ": Unable to load %s\n", ipath.c_str());
}
/*
EDEBUG(ESTRLOC ": Got label: %s\n", label());
EDEBUG(ESTRLOC ": Got image: %s\n", settings->icon.c_str());
EDEBUG(ESTRLOC ": Got x/y : %i %i\n", x(), y());
*/
//Use desktop color as color for icon background
color(bg);
align(fltk::ALIGN_WRAP);
align(FL_ALIGN_WRAP);
update_label_size();
pmenu = new fltk::PopupMenu(0, 0, 100, 100);
pmenu->begin();
if(settings->type == ICON_TRASH) {
edelib::Item* it = new edelib::Item(_("&Open"));
it->offset_x(12, 12);
it = new edelib::Item(_("&Properties"));
it->offset_x(12, 12);
new fltk::Divider();
it = new edelib::Item(_("&Empty"));
it->offset_x(12, 12);
} else {
edelib::Item* it = new edelib::Item(_("&Open"));
it->offset_x(12, 12);
it = new edelib::Item(_("&Rename"));
it->offset_x(12, 12);
it = new edelib::Item(_("&Delete"));
it->offset_x(12, 12);
it->callback(icon_delete_cb, this);
new fltk::Divider();
it = new edelib::Item(_("&Properties"));
it->offset_x(12, 12);
}
pmenu->end();
pmenu->type(fltk::PopupMenu::POPUP3);
}
DesktopIcon::~DesktopIcon()
{
if(settings) {
EDEBUG(ESTRLOC ": IconSettings clearing from ~DesktopIcon()\n");
delete settings;
}
DesktopIcon::~DesktopIcon() {
EDEBUG("DesktopIcon::~DesktopIcon()\n");
if(settings)
delete settings;
if(micon)
delete micon;
if(pmenu)
delete pmenu;
}
void DesktopIcon::update_label_size(void) {
lwidth = globals->label_maxwidth;
lheight= 0;
// FIXME: really needed ???
fltk::setfont(labelfont(), labelsize());
/*
* make sure current font size/type is set (internaly to fltk)
* so fl_measure() can correctly calculate label width and height
*/
fl_font(labelfont(), labelsize());
//fltk::measure(label(), lwidth, lheight, fltk::ALIGN_WRAP);
fltk::measure(label(), lwidth, lheight, flags());
fl_measure(label(), lwidth, lheight, align());
lwidth += 8;
lheight += 4;
@ -172,7 +128,7 @@ void DesktopIcon::drag(int x, int y, bool apply) {
if(apply) {
position(micon->x(), micon->y());
delete micon;
micon = 0;
micon = NULL;
}
}
@ -180,7 +136,7 @@ void DesktopIcon::drag(int x, int y, bool apply) {
int DesktopIcon::drag_icon_x(void) {
if(!micon)
return x();
else
else
return micon->x();
}
@ -192,130 +148,94 @@ int DesktopIcon::drag_icon_y(void) {
return micon->y();
}
void DesktopIcon::draw(void) {
if(image() && (damage() & fltk::DAMAGE_ALL)) {
fltk::Image* ii = (fltk::Image*)image();
int ix = (w()/2) - (ii->w()/2);
/*
* Make sure to pickup image's w() and h() since if fltk is compiled
* with Xrender it will be scaled to rectangle's w()/h().
*
* On other hand, if fltk is _not_ compiled with Xrender,
* scaling will not be done.
* Yuck !
*/
fltk::Rectangle ir(ix, 5, ii->w(), ii->h());
ii->draw(ir);
void DesktopIcon::fast_redraw(void) {
EASSERT(parent() != NULL && "Impossible !");
// LABEL_OFFSET + 2 include selection box line height too
parent()->damage(FL_DAMAGE_ALL, x(), y(), w(), h() + lheight + LABEL_OFFSET + 2);
}
void DesktopIcon::draw(void) {
//draw_box(FL_UP_BOX, FL_BLACK);
if(image() && (damage() & FL_DAMAGE_ALL)) {
Fl_Image* im = image();
// center image in the box
int ix = (w()/2) - (im->w()/2);
int iy = (h()/2) - (im->h()/2);
ix += x();
iy += y();
im->draw(ix, iy);
}
if(globals->label_draw && (damage() & (fltk::DAMAGE_ALL | fltk::DAMAGE_CHILD_LABEL))) {
int X = w()-(w()/2)-(lwidth/2);
int Y = h()+2;
if(globals->label_draw && (damage() & (FL_DAMAGE_ALL))) {
int X = x() + w()-(w()/2)-(lwidth/2);
int Y = y() + h() + LABEL_OFFSET;
Fl_Color old = fl_color();
if(!globals->label_transparent) {
fltk::setcolor(globals->label_background);
fltk::fillrect(X, Y, lwidth, lheight);
fl_color(globals->label_background);
fl_rectf(X, Y, lwidth, lheight);
}
Rectangle r(X, Y, lwidth, lheight);
fltk::setcolor(globals->label_foreground);
drawtext(label(), r, flags());
fl_color(globals->label_foreground);
fl_draw(label(), X, Y, lwidth, lheight, align(), 0, 0);
if(is_focused()) {
/*
* draw focused box on our way so later
* this can be used to draw customised boxes
*/
fltk::line_style(fltk::DOT);
fl_line_style(FL_DOT);
fltk::push_matrix();
fl_color(globals->label_foreground);
//fltk::setcolor(fltk::WHITE);
fltk::setcolor(globals->label_foreground);
fltk::addvertex(X,Y);
fltk::addvertex(X+lwidth,Y);
fltk::addvertex(X+lwidth,Y+lheight);
fltk::addvertex(X,Y+lheight);
fltk::addvertex(X,Y);
fltk::strokepath();
fltk::pop_matrix();
fl_push_matrix();
fl_begin_loop();
fl_vertex(X,Y);
fl_vertex(X+lwidth,Y);
fl_vertex(X+lwidth,Y+lheight);
fl_vertex(X,Y+lheight);
fl_vertex(X,Y);
fl_end_loop();
fl_pop_matrix();
// revert to default line style
fltk::line_style(0);
fl_line_style(0);
}
set_damage(damage() & ~fltk::DAMAGE_CHILD_LABEL);
// revert to old color whatever that be
fl_color(old);
}
}
int DesktopIcon::handle(int event) {
switch(event) {
case fltk::FOCUS:
case fltk::UNFOCUS:
return 1;
case fltk::ENTER:
case fltk::LEAVE:
return 1;
/*
* We have to handle fltk::MOVE too, if
* want to get only once fltk::ENTER when
* entered or fltk::LEAVE when leaved.
*/
case fltk::MOVE:
return 1;
case fltk::PUSH:
if(fltk::event_button() == 3)
pmenu->popup();
return 1;
case fltk::RELEASE:
if(fltk::event_clicks() > 0)
EDEBUG(ESTRLOC ": EXECUTE: %s\n", settings->cmd.c_str());
return 1;
case fltk::DND_ENTER:
EDEBUG("Icon DND_ENTER\n");
return 1;
case fltk::DND_DRAG:
EDEBUG("Icon DND_DRAG\n");
return 1;
case fltk::DND_LEAVE:
EDEBUG("Icon DND_LEAVE\n");
return 1;
case fltk::DND_RELEASE:
EDEBUG("Icon DND_RELEASE\n");
return 1;
case fltk::PASTE:
EDEBUG("Icon PASTE\n");
return 1;
}
return fltk::Widget::handle(event);
return Fl_Button::handle(event);
}
MovableIcon::MovableIcon(DesktopIcon* ic) : fltk::Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic) {
MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic) {
EASSERT(icon != NULL);
set_override();
create();
color(ic->color());
fltk::Image* img = icon->icon_image();
if(img)
image(img);
begin();
icon_box = new Fl_Box(0, 0, w(), h());
icon_box->image(ic->icon_image());
end();
}
MovableIcon::~MovableIcon() {
}
void MovableIcon::show(void) {
if(!shown())
Fl_X::make_xid(this);
#if 0
if(img) {
#ifdef SHAPE
Pixmap mask = create_pixmap_mask(img->width(), img->height());
XShapeCombineMask(fltk::xdisplay, fltk::xid(this), ShapeBounding, 0, 0, mask, ShapeSet);
#else
image(img);
#endif
}
Pixmap mask = create_mask((Fl_RGB_Image*)icon->icon_image());
XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet);
#endif
}
MovableIcon::~MovableIcon()
{
}

View File

@ -13,16 +13,17 @@
#ifndef __DESKTOPICON_H__
#define __DESKTOPICON_H__
#include <fltk/Widget.h>
#include <fltk/Window.h>
#include <fltk/Image.h>
#include <fltk/PopupMenu.h>
#include <FL/Fl_Widget.h>
#include <FL/Fl_Window.h>
#include <FL/Fl_Box.h>
#include <FL/Fl_Button.h>
#include <FL/Fl_Image.h>
class GlobalIconSettings;
class IconSettings;
class MovableIcon;
class DesktopIcon : public fltk::Widget {
class DesktopIcon : public Fl_Button {
private:
IconSettings* settings;
const GlobalIconSettings* globals;
@ -31,24 +32,33 @@ class DesktopIcon : public fltk::Widget {
int lheight;
bool focus;
// pseudosizes (nor real icon sizes)
int image_w;
int image_h;
fltk::PopupMenu* pmenu;
MovableIcon* micon;
void update_label_size(void);
public:
DesktopIcon(GlobalIconSettings* gisett, IconSettings* isett);
DesktopIcon(GlobalIconSettings* gisett, IconSettings* isett, int bg);
~DesktopIcon();
virtual void draw(void);
virtual int handle(int event);
void drag(int x, int y, bool apply);
int drag_icon_x(void);
int drag_icon_y(void);
/*
* This is 'enhanced' (in some sense) redraw(). Redrawing
* icon will not fully redraw label nor focus box, which laid outside
* icon box. It will use damage() on given region, but called from
* parent, so parent can redraw that region on itself (since label does
* not laid on any box)
*
* Alternative way would be to redraw whole parent, but it is pretty unneeded
* and slow.
*/
void fast_redraw(void);
/*
* Here is implemented localy focus schema avoiding
* messy fltk one. Focus/unfocus is handled from Desktop.
@ -57,19 +67,20 @@ class DesktopIcon : public fltk::Widget {
void do_unfocus(void) { focus = false; }
bool is_focused(void) { return focus; }
fltk::Image* icon_image(void) { return (fltk::Image*)image(); }
Fl_Image* icon_image(void) { return image(); }
const IconSettings* get_settings(void) const { return settings; }
};
class MovableIcon : public fltk::Window {
class MovableIcon : public Fl_Window {
private:
DesktopIcon* icon;
Fl_Box* icon_box;
public:
MovableIcon(DesktopIcon* i);
~MovableIcon();
virtual void show(void);
};
#endif

View File

@ -1,7 +1,7 @@
#LINKLIBS += -L/opt/ede/lib -ledelib -lao -lvorbis -lvorbisfile -lmad -L/usr/local/lib -lfltk2_images -lpng -lfltk2_images -ljpeg -lz -lfltk2 -L/usr/X11R6/lib -lX11 -lXi -lXinerama -lpthread -lm -lXext -lstdc++ ;
LINKLIBS += -L/opt/ede/lib -ledelib -lao -lvorbis -lvorbisfile -lmad -L/usr/local/lib -lfltk2_images -lpng -lfltk2_images -ljpeg -lz -lfltk2 -L/usr/X11R6/lib -lX11 -lXi -lXinerama -lpthread -lm -lXft -lXext -lstdc++ ;
LINKLIBS += -L/opt/ede/lib -ledelib -lao -lvorbis -lvorbisfile -lmad -L/usr/local/lib -L/usr/X11R6/lib -lfltk_images -lpng -lz -ljpeg -lfltk -ldl -lm -lXext -lX11 -lstdc++ ;
C++FLAGS += -g3 -I/opt/ede/include ;
C++FLAGS += -Wall -g3 -I/opt/ede/include ;
Main eiconman : eiconman.cpp Utils.cpp DesktopIcon.cpp DesktopConfig.cpp ;
Main eiconman : eiconman.cpp Utils.cpp Wallpaper.cpp DesktopIcon.cpp ;

View File

@ -12,9 +12,11 @@
#include "Utils.h"
#include <X11/Xproto.h> // CARD32
#include <fltk/x11.h>
#include <FL/x.h>
#include <edelib/Debug.h>
#include <string.h> // strrchr
Atom NET_WORKAREA = 0;
Atom NET_WM_WINDOW_TYPE = 0;
Atom NET_WM_WINDOW_TYPE_DESKTOP = 0;
@ -27,20 +29,22 @@ int overlay_y = 0;
int overlay_w = 0;
int overlay_h = 0;
Fl_Window* overlay_drawable = NULL;
char dash_list[] = {1};
bool net_get_workarea(int& x, int& y, int& w, int &h) {
Atom real;
if(!NET_WORKAREA)
NET_WORKAREA= XInternAtom(fltk::xdisplay, "_NET_WORKAREA", 1);
NET_WORKAREA= XInternAtom(fl_display, "_NET_WORKAREA", 1);
int format;
unsigned long n, extra;
unsigned char* prop;
x = y = w = h = 0;
int status = XGetWindowProperty(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen),
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
NET_WORKAREA, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
if(status != Success)
@ -60,18 +64,18 @@ bool net_get_workarea(int& x, int& y, int& w, int &h) {
return false;
}
void net_make_me_desktop(fltk::Window* w) {
void net_make_me_desktop(Fl_Window* w) {
if(!NET_WM_WINDOW_TYPE)
NET_WM_WINDOW_TYPE = XInternAtom(fltk::xdisplay, "_NET_WM_WINDOW_TYPE", False);
NET_WM_WINDOW_TYPE = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
if(!NET_WM_WINDOW_TYPE_DESKTOP)
NET_WM_WINDOW_TYPE_DESKTOP= XInternAtom(fltk::xdisplay, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
NET_WM_WINDOW_TYPE_DESKTOP= XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
/*
* xid() will return zero if window is not shown;
* make sure it is shown
*/
EASSERT(fltk::xid(w));
EASSERT(fl_xid(w));
/*
* Reminder for me (others possible):
@ -80,20 +84,20 @@ void net_make_me_desktop(fltk::Window* w) {
*
* I lost two hours messing with this ! (gdb is unusefull in X world)
*/
XChangeProperty(fltk::xdisplay, fltk::xid(w), NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace,
XChangeProperty(fl_display, fl_xid(w), NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace,
(unsigned char*)&NET_WM_WINDOW_TYPE_DESKTOP, sizeof(Atom));
}
int net_get_workspace_count(void) {
if(!NET_NUMBER_OF_DESKTOPS)
NET_NUMBER_OF_DESKTOPS = XInternAtom(fltk::xdisplay, "_NET_NUMBER_OF_DESKTOPS", False);
NET_NUMBER_OF_DESKTOPS = XInternAtom(fl_display, "_NET_NUMBER_OF_DESKTOPS", False);
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen),
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
NET_NUMBER_OF_DESKTOPS, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
(unsigned char**)&prop);
@ -108,13 +112,13 @@ int net_get_workspace_count(void) {
// desktops are starting from 0
int net_get_current_desktop(void) {
if(!NET_CURRENT_DESKTOP)
NET_CURRENT_DESKTOP = XInternAtom(fltk::xdisplay, "_NET_CURRENT_DESKTOP", False);
NET_CURRENT_DESKTOP = XInternAtom(fl_display, "_NET_CURRENT_DESKTOP", False);
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen),
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
NET_CURRENT_DESKTOP, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
if(status != Success && !prop)
@ -128,11 +132,11 @@ int net_get_current_desktop(void) {
// call on this XFreeStringList(names)
int net_get_workspace_names(char**& names) {
if(!NET_DESKTOP_NAMES)
NET_DESKTOP_NAMES = XInternAtom(fltk::xdisplay, "_NET_DESKTOP_NAMES", False);
NET_DESKTOP_NAMES = XInternAtom(fl_display, "_NET_DESKTOP_NAMES", False);
// FIXME: add _NET_SUPPORTING_WM_CHECK and _NET_SUPPORTED ???
XTextProperty wnames;
XGetTextProperty(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen), &wnames, NET_DESKTOP_NAMES);
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &wnames, NET_DESKTOP_NAMES);
// if wm does not understainds _NET_DESKTOP_NAMES this is not set
if(!wnames.nitems || !wnames.value)
@ -152,14 +156,14 @@ int net_get_workspace_names(char**& names) {
#if 0
int net_get_workspace_names(char** names) {
Atom nd = XInternAtom(fltk::xdisplay, "_NET_DESKTOP_NAMES", False);
Atom utf8_str = XInternAtom(fltk::xdisplay, "UTF8_STRING", False);
Atom nd = XInternAtom(fl_display, "_NET_DESKTOP_NAMES", False);
Atom utf8_str = XInternAtom(fl_display, "UTF8_STRING", False);
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen),
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
nd, 0L, 0x7fffffff, False, utf8_str, &real, &format, &n, &extra, (unsigned char**)&prop);
if(status != Success && !prop)
@ -185,16 +189,23 @@ void draw_overlay_rect(void) {
if(overlay_w <= 0 || overlay_h <= 0)
return;
XSetDashes(fltk::xdisplay, fltk::gc, 0, dash_list, 1);
XSetLineAttributes(fltk::xdisplay, fltk::gc, 1, LineOnOffDash, CapButt, JoinMiter);
XSetDashes(fl_display, fl_gc, 0, dash_list, 1);
XSetLineAttributes(fl_display, fl_gc, 1, LineOnOffDash, CapButt, JoinMiter);
XSetFunction(fltk::xdisplay, fltk::gc, GXxor);
XSetForeground(fltk::xdisplay, fltk::gc, 0xffffffff);
XDrawRectangle(fltk::xdisplay, fltk::xwindow, fltk::gc, overlay_x, overlay_y, overlay_w-1, overlay_h-1);
XSetFunction(fltk::xdisplay, fltk::gc, GXcopy);
XSetFunction(fl_display, fl_gc, GXxor);
XSetForeground(fl_display, fl_gc, 0xffffffff);
Window ow;
if(overlay_drawable)
ow = fl_xid(overlay_drawable);
else
ow = fl_window;
XDrawRectangle(fl_display, ow, fl_gc, overlay_x, overlay_y, overlay_w-1, overlay_h-1);
XSetFunction(fl_display, fl_gc, GXcopy);
// set line to 0 again
XSetLineAttributes(fltk::xdisplay, fltk::gc, 0, LineOnOffDash, CapButt, JoinMiter);
XSetLineAttributes(fl_display, fl_gc, 0, LineOnOffDash, CapButt, JoinMiter);
}
void draw_xoverlay(int x, int y, int w, int h) {
@ -230,3 +241,15 @@ void clear_xoverlay(void) {
overlay_w = 0;
}
}
void set_xoverlay_drawable(Fl_Window* win) {
overlay_drawable = win;
}
char* get_basename(const char* path) {
char* p = strrchr(path, '/');
if(p)
return (p + 1);
return (char*) path;
}

View File

@ -13,15 +13,23 @@
#ifndef __UTILS_H__
#define __UTILS_H__
#include <fltk/Window.h>
#include <FL/Fl_Window.h>
#include <FL/Fl_Image.h>
#include <X11/Xlib.h> // Pixmap
int net_get_workspace_count(void);
int net_get_current_desktop(void);
bool net_get_workarea(int& x, int& y, int& w, int &h);
void net_make_me_desktop(fltk::Window* w);
void net_make_me_desktop(Fl_Window* w);
int net_get_workspace_names(char**& names);
void draw_xoverlay(int x, int y, int w, int h);
void clear_xoverlay(void);
void set_xoverlay_drawable(Fl_Window* win);
Pixmap create_mask(Fl_RGB_Image* img);
char* get_basename(const char* path);
#endif

87
eiconman/Wallpaper.cpp Normal file
View File

@ -0,0 +1,87 @@
/*
* $Id$
*
* Eiconman, desktop and icon manager
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include "Wallpaper.h"
#include <edelib/Debug.h>
#include <FL/Fl_Shared_Image.h>
#include <FL/fl_draw.h>
Wallpaper::Wallpaper(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H, 0), img(NULL), tiled(false) {
}
Wallpaper::~Wallpaper() {
}
bool Wallpaper::set(const char* path) {
EASSERT(path != NULL);
tiled = false;
Fl_Image* i = Fl_Shared_Image::get(path);
if(!i)
return false;
img = i;
image(img);
return true;
}
bool Wallpaper::set_tiled(const char* path) {
bool ret = set(path);
if(ret)
tiled = true;
return ret;
}
void Wallpaper::draw(void) {
if(!image())
return;
int ix, iy, iw, ih;
Fl_Image* im = image();
iw = im->w();
ih = im->h();
if(iw == 0 || ih == 0)
return;
if(ih < h() || iw < w()) {
if(tiled) {
// tile image across the box
fl_push_clip(x(), y(), w(), h());
int tx = x() - (x() % iw);
int ty = y() - (y() % ih);
int tw = w() + tx;
int th = h() + ty;
for(int j = 0; j < th; j += ih)
for(int i = 0; i < tw; i += iw)
im->draw(i, j);
fl_pop_clip();
return;
} else {
// center image in the box
ix = (w()/2) - (iw/2);
iy = (h()/2) - (ih/2);
ix += x();
iy += y();
}
} else {
ix = x();
iy = y();
}
im->draw(ix, iy);
}

37
eiconman/Wallpaper.h Normal file
View File

@ -0,0 +1,37 @@
/*
* $Id$
*
* Eiconman, desktop and icon manager
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#ifndef __WALLPAPER_H__
#define __WALLPAPER_H__
#include <FL/Fl_Box.h>
#include <FL/Fl_Image.h>
/*
* Class responsible for displaying images at background
* their scaling (TODO), caching(TODO) and making coffee at spear time.
*/
class Wallpaper : public Fl_Box {
private:
Fl_Image* img;
bool tiled;
public:
Wallpaper(int X, int Y, int W, int H);
~Wallpaper();
bool set(const char* path);
bool set_tiled(const char* path);
virtual void draw(void);
};
#endif

View File

@ -1,5 +1,5 @@
[Desktop]
Color = 35
Color = 45
WallpaperUse = 0
Wallpaper = /home/foo/xxx/baz/tax

View File

@ -12,60 +12,38 @@
#include "eiconman.h"
#include "DesktopIcon.h"
#include "DesktopConfig.h"
#include "Utils.h"
#include "Wallpaper.h"
#include <edelib/Nls.h>
#include <edelib/Debug.h>
#include <edelib/Config.h>
#include <edelib/Directory.h>
#include <edelib/StrUtil.h>
#include <edelib/File.h>
#include <edelib/IconTheme.h>
#include <edelib/Item.h>
#include <edelib/Directory.h>
#include <edelib/MimeType.h>
#include <edelib/StrUtil.h>
#include <edelib/IconTheme.h>
#include <fltk/Divider.h>
#include <fltk/damage.h>
#include <fltk/Color.h>
#include <fltk/events.h>
#include <fltk/run.h>
#include <fltk/x11.h>
#include <fltk/SharedImage.h>
#include <FL/Fl.h>
#include <FL/Fl_Shared_Image.h>
#include <FL/x.h>
#include <FL/Fl_Box.h>
#include <signal.h>
#include <X11/Xproto.h> // CARD32
#include <stdlib.h> // rand, srand
#include <time.h> // time
#include <stdio.h> // snprintf
/*
* NOTE: DO NOT set 'using namespace fltk' here
* since fltk::Window will collide with Window from X11
* resulting compilation errors.
*
* This is why I hate this namespace shit !
*/
#define CONFIG_NAME "eiconman.conf"
#define CONFIG_NAME "eiconman.conf"
#define SELECTION_SINGLE (fltk::event_button() == 1)
#define SELECTION_MULTI (fltk::event_button() == 1 && \
(fltk::get_key_state(fltk::LeftShiftKey) ||\
fltk::get_key_state(fltk::RightShiftKey)))
#define SELECTION_SINGLE (Fl::event_button() == 1)
#define SELECTION_MULTI (Fl::event_button() == 1 && (Fl::event_key(FL_Shift_L) || Fl::event_key(FL_Shift_R)))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
/*
* Added since fltk DAMAGE_OVERLAY value is used in few different contexts
* and re-using it will do nothing. Yuck!
*/
#define EDAMAGE_OVERLAY 2
// which widgets Fl::belowmouse() to skip
#define NOT_SELECTABLE(widget) ((widget == this) || (widget == wallpaper))
Desktop* Desktop::pinstance = NULL;
bool running = true;
bool running = false;
inline unsigned int random_pos(int max) {
return (rand() % max);
@ -76,10 +54,10 @@ inline bool intersects(int x1, int y1, int w1, int h1, int x2, int y2, int w2, i
MAX(y1, y2) <= MIN(h1, h2));
}
// assume fl_open_display() is called before
inline void dpy_sizes(int& width, int& height) {
fltk::open_display();
width = DisplayWidth(fltk::xdisplay, fltk::xscreen);
height = DisplayHeight(fltk::xdisplay, fltk::xscreen);
width = DisplayWidth(fl_display, fl_screen);
height = DisplayHeight(fl_display, fl_screen);
}
void exit_signal(int signum) {
@ -87,103 +65,43 @@ void exit_signal(int signum) {
running = false;
}
/*
* It is used to notify desktop when _NET_CURRENT_DESKTOP is triggered.
* FIXME: _NET_WORKAREA is nice thing that could set here too :)
*
* FIXME: XInternAtom should be placed somewhere else
*/
int desktop_xmessage_handler(int e, fltk::Window*) {
Atom nd = XInternAtom(fltk::xdisplay, "_NET_CURRENT_DESKTOP", False);
if(fltk::xevent.type == PropertyNotify) {
if(fltk::xevent.xproperty.atom == nd) {
EDEBUG(ESTRLOC ": Desktop changed !!!\n");
return 1;
}
}
return 0;
void restart_signal(int signum) {
EDEBUG(ESTRLOC ": Restarting (got signal %d)\n", signum);
}
void background_cb(fltk::Widget*, void*) {
DesktopConfig dc;
dc.run();
}
int desktop_xmessage_handler(int event) { return 0; }
Desktop::Desktop() : fltk::Window(0, 0, 100, 100, "")
{
Desktop::Desktop() : Fl_Window(0, 0, 100, 100, "") {
selection_x = selection_y = 0;
moving = false;
desktops_num = 0;
curr_desktop = 0;
selbox = new SelectionOverlay;
selbox->x = selbox->y = selbox->w = selbox->h = 0;
selbox->show = false;
dsett = new DesktopSettings;
dsett->color = 0;
dsett->color = FL_GRAY;
dsett->wp_use = false;
dsett->wp_image = NULL;
// fallback if update_workarea() fails
int dw, dh;
dpy_sizes(dw, dh);
resize(dw, dh);
update_workarea();
read_config();
/*
* NOTE: order how childs are added is important. First
* non iconable ones should be added (wallpaper, menu, ...)
* then icons, so they can be drawn at top of them.
*/
begin();
pmenu = new fltk::PopupMenu(0, 0, 450, 50);
pmenu->begin();
edelib::Item* it = new edelib::Item(_("&New desktop item"));
it->offset_x(12, 12);
new fltk::Divider();
it = new edelib::Item(_("&Line up vertical"));
it->offset_x(12, 12);
it = new edelib::Item(_("&Line up horizontal"));
it->offset_x(12, 12);
it = new edelib::Item(_("&Arrange by name"));
it->offset_x(12, 12);
new fltk::Divider();
it = new edelib::Item(_("&Icon settings"));
it->offset_x(12, 12);
edelib::Item* itbg = new edelib::Item(_("&Background settings"));
itbg->offset_x(12, 12);
itbg->callback(background_cb);
pmenu->end();
pmenu->type(fltk::PopupMenu::POPUP3);
wallpaper = new Wallpaper(0, 0, w(), h());
//wallpaper->set_tiled("/home/sanel/wallpapers/katesmall.jpg");
end();
if(dsett->wp_use)
set_wallpaper(dsett->wp_path.c_str(), false);
else
set_bg_color(dsett->color, false);
read_config();
set_bg_color(dsett->color, false);
running = true;
}
Desktop::~Desktop() {
EDEBUG(ESTRLOC ": Desktop::~Desktop()\n");
Desktop::~Desktop() {
EDEBUG("Desktop::~Desktop()\n");
save_config();
if(selbox)
delete selbox;
/*
* icons member deleting is not needed, since add_icon will
* append to icons and to fltk::Group array. Desktop at the end
* will cleanup fltk::Group array.
*/
icons.clear();
if(dsett)
delete dsett;
delete dsett;
}
void Desktop::init(void) {
@ -205,49 +123,43 @@ Desktop* Desktop::instance(void) {
return Desktop::pinstance;
}
void Desktop::update_workarea(void) {
int X,Y,W,H;
if(net_get_workarea(X, Y, W, H))
resize(X,Y,W,H);
/*
* This function must be overriden so window can inform
* wm to see it as desktop. It will send data when window
* is created, but before is shown.
*/
void Desktop::show(void) {
if(!shown()) {
Fl_X::make_xid(this);
net_make_me_desktop(this);
}
}
void Desktop::set_bg_color(unsigned int c, bool do_redraw) {
EASSERT(dsett != NULL);
/*
* If someone intentionaly hide desktop
* then quit from it.
*/
void Desktop::hide(void) {
running = false;
}
void Desktop::update_workarea(void) {
int X, Y, W, H;
if(!net_get_workarea(X, Y, W, H)) {
EWARNING(ESTRLOC ": wm does not support _NET_WM_WORKAREA; using screen sizes...\n");
X = Y = 0;
dpy_sizes(W, H);
}
resize(X, Y, W, H);
}
void Desktop::set_bg_color(int c, bool do_redraw) {
if(color() == c)
return;
dsett->color = c;
color(c);
if(do_redraw)
redraw();
}
void Desktop::set_wallpaper(const char* path, bool do_redraw) {
EASSERT(path != NULL);
EASSERT(dsett != NULL);
/*
* Prevent cases 'set_wallpaper(dsett->wp_path.c_str())' since assignement
* will nullify pointers. Very hard to find bug! (believe me, after few hours)
*/
if(dsett->wp_path.c_str() != path)
dsett->wp_path = path;
dsett->wp_image = fltk::SharedImage::get(path);
/*
* SharedImage::get() will return NULL if is unable to read the image
* and that is exactly what is wanted here since draw() function will
* skip drawing image in nulled case. Blame user for this :)
*/
image(dsett->wp_image);
if(do_redraw)
redraw();
}
void Desktop::set_wallpaper(fltk::Image* im, bool do_redraw) {
if(dsett->wp_image == im)
return;
image(dsett->wp_image);
if(do_redraw)
redraw();
}
@ -255,7 +167,7 @@ void Desktop::set_wallpaper(fltk::Image* im, bool do_redraw) {
void Desktop::read_config(void) {
edelib::Config conf;
if(!conf.load(CONFIG_NAME)) {
EDEBUG(ESTRLOC ": Can't load %s, using default...\n", CONFIG_NAME);
EWARNING(ESTRLOC ": Can't load %s, using default...\n", CONFIG_NAME);
return;
}
@ -264,20 +176,17 @@ void Desktop::read_config(void) {
* Add IconArea[X,Y,W,H] so icons can live
* inside that area only (aka margins).
*/
// read Desktop section
int default_bg_color = fltk::BLUE;
int default_bg_color = FL_BLUE;
int default_wp_use = false;
char wpath[256];
// read Desktop section
conf.get("Desktop", "Color", dsett->color, default_bg_color);
if(conf.error() != edelib::CONF_ERR_SECTION) {
conf.get("Desktop", "WallpaperUse", dsett->wp_use, default_wp_use);
conf.get("Desktop", "Wallpaper", wpath, sizeof(wpath));
dsett->wp_path = wpath;
// keep path but disable wallpaper if file does not exists
if(!edelib::file_exists(wpath)) {
EDEBUG(ESTRLOC ": %s as wallpaper does not exists\n", wpath);
@ -289,15 +198,14 @@ void Desktop::read_config(void) {
}
// read Icons section
conf.get("Icons", "Label Background", gisett.label_background, 46848);
conf.get("Icons", "Label Foreground", gisett.label_foreground, fltk::WHITE);
conf.get("Icons", "Label Background", gisett.label_background, FL_BLUE);
conf.get("Icons", "Label Foreground", gisett.label_foreground, FL_WHITE);
conf.get("Icons", "Label Fontsize", gisett.label_fontsize, 12);
conf.get("Icons", "Label Maxwidth", gisett.label_maxwidth, 75);
conf.get("Icons", "Label Transparent",gisett.label_transparent, false);
conf.get("Icons", "Label Visible", gisett.label_draw, true);
conf.get("Icons", "Gridspacing", gisett.gridspacing, 16);
conf.get("Icons", "OneClickExec", gisett.one_click_exec, false);
conf.get("Icons", "AutoArrange", gisett.auto_arr, true);
conf.get("Icons", "AutoArrange", gisett.auto_arrange, true);
/*
* Now try to load icons, first looking inside ~/Desktop directory
@ -306,25 +214,17 @@ void Desktop::read_config(void) {
*
* FIXME: dir_exists() can't handle '~/Desktop' ???
*/
//load_icons("/home/sanel/Desktop", conf);
edelib::String dd = edelib::dir_home();
if(dd.empty()) {
EWARNING(ESTRLOC ": Can't read home directory; icons will not be loaded\n");
return;
}
dd += "/Desktop";
load_icons(dd.c_str(), conf);
}
#if 0
EDEBUG("----------------------------------------------------------\n");
EDEBUG("d Color : %i\n", bg_color);
EDEBUG("d WallpaperUse: %i\n", wp_use);
EDEBUG("i label bkg : %i\n", gisett.label_background);
EDEBUG("i label fg : %i\n", gisett.label_foreground);
EDEBUG("i label fsize : %i\n", gisett.label_fontsize);
EDEBUG("i label maxw : %i\n", gisett.label_maxwidth);
EDEBUG("i label trans : %i\n", gisett.label_transparent);
EDEBUG("i label vis : %i\n", gisett.label_draw);
EDEBUG("i gridspace : %i\n", gisett.gridspacing);
EDEBUG("i oneclick : %i\n", gisett.one_click_exec);
EDEBUG("i auto_arr : %i\n", gisett.auto_arr);
#endif
void Desktop::save_config(void) {
// TODO
}
void Desktop::load_icons(const char* path, edelib::Config& conf) {
@ -372,15 +272,7 @@ void Desktop::load_icons(const char* path, edelib::Config& conf) {
} else {
// then try to figure out it's mime; if fails, ignore it
if(mt.set(full_path.c_str())) {
/*
* FIXME: MimeType fails for directories
* Temp solution untill that is fixed in edelib
*/
if(edelib::dir_exists(full_path.c_str()))
is.icon = "folder";
else
is.icon = mt.icon_name();
is.icon = mt.icon_name();
// icon label is name of file
is.name = name;
is.type = ICON_FILE;
@ -402,13 +294,13 @@ void Desktop::load_icons(const char* path, edelib::Config& conf) {
is.x = icon_x;
is.y = icon_y;
DesktopIcon* dic = new DesktopIcon(&gisett, &is);
DesktopIcon* dic = new DesktopIcon(&gisett, &is, dsett->color);
add_icon(dic);
}
}
}
// reads .desktop file content
// read .desktop files
bool Desktop::read_desktop_file(const char* path, IconSettings& is) {
EASSERT(path != NULL);
@ -499,82 +391,53 @@ bool Desktop::read_desktop_file(const char* path, IconSettings& is) {
return true;
}
void Desktop::save_config(void) {
edelib::Config conf;
conf.set("Desktop", "Color", dsett->color);
conf.set("Desktop", "WallpaperUse", dsett->wp_use);
conf.set("Desktop", "Wallpaper", dsett->wp_path.c_str());
conf.set("Icons", "Label Background", gisett.label_background);
conf.set("Icons", "Label Foreground", gisett.label_foreground);
conf.set("Icons", "Label Fontsize", gisett.label_fontsize);
conf.set("Icons", "Label Maxwidth", gisett.label_maxwidth);
conf.set("Icons", "Label Transparent",gisett.label_transparent);
conf.set("Icons", "Label Visible", gisett.label_draw);
conf.set("Icons", "Gridspacing", gisett.gridspacing);
conf.set("Icons", "OneClickExec", gisett.one_click_exec);
conf.set("Icons", "AutoArrange", gisett.auto_arr);
unsigned int sz = icons.size();
const IconSettings* is = NULL;
for(unsigned int i = 0; i < sz; i++) {
is = icons[i]->get_settings();
conf.set(is->key_name.c_str(), "X", icons[i]->x());
conf.set(is->key_name.c_str(), "Y", icons[i]->y());
}
if(!conf.save(CONFIG_NAME))
EDEBUG(ESTRLOC ": Unable to save to %s\n", CONFIG_NAME);
}
void Desktop::add_icon(DesktopIcon* ic) {
EASSERT(ic != NULL);
icons.push_back(ic);
add(ic);
// FIXME: validate this
add((Fl_Widget*)ic);
}
void Desktop::move_selection(int x, int y, bool apply) {
unsigned int sz = selectionbuff.size();
if(sz == 0)
return;
int prev_x, prev_y, tmp_x, tmp_y;
for(unsigned int i = 0; i < sz; i++) {
prev_x = selectionbuff[i]->drag_icon_x();
prev_y = selectionbuff[i]->drag_icon_y();
tmp_x = x - selection_x;
tmp_y = y - selection_y;
selectionbuff[i]->drag(prev_x+tmp_x, prev_y+tmp_y, apply);
// very slow if is not checked
if(apply == true)
selectionbuff[i]->redraw();
}
selection_x = x;
selection_y = y;
}
void Desktop::unfocus_all(void) {
void Desktop::unfocus_all(void) {
unsigned int sz = icons.size();
DesktopIcon* ic;
for(unsigned int i = 0; i < sz; i++) {
if(icons[i]->is_focused()) {
icons[i]->do_unfocus();
icons[i]->redraw();
ic = icons[i];
if(ic->is_focused()) {
ic->do_unfocus();
ic->fast_redraw();
}
}
redraw();
}
bool Desktop::in_selection(const DesktopIcon* ic) {
void Desktop::select(DesktopIcon* ic) {
EASSERT(ic != NULL);
if(in_selection(ic))
return;
selectionbuff.push_back(ic);
if(!ic->is_focused()) {
ic->do_focus();
ic->fast_redraw();
}
}
void Desktop::select_only(DesktopIcon* ic) {
EASSERT(ic != NULL);
unfocus_all();
selectionbuff.clear();
selectionbuff.push_back(ic);
ic->do_focus();
ic->fast_redraw();
}
bool Desktop::in_selection(const DesktopIcon* ic) {
EASSERT(ic != NULL);
unsigned int sz = selectionbuff.size();
@ -586,94 +449,47 @@ bool Desktop::in_selection(const DesktopIcon* ic) {
return false;
}
void Desktop::select(DesktopIcon* ic) {
EASSERT(ic != NULL);
if(in_selection(ic))
void Desktop::move_selection(int x, int y, bool apply) {
unsigned int sz = selectionbuff.size();
if(sz == 0)
return;
selectionbuff.push_back(ic);
if(!ic->is_focused()) {
ic->do_focus();
ic->redraw();
}
redraw();
}
void Desktop::select_noredraw(DesktopIcon* ic) {
EASSERT(ic != NULL);
if(in_selection(ic))
return;
selectionbuff.push_back(ic);
}
void Desktop::select_only(DesktopIcon* ic) {
EASSERT(ic != NULL);
unfocus_all();
selectionbuff.clear();
selectionbuff.push_back(ic);
ic->do_focus();
ic->redraw();
redraw();
}
void Desktop::select_in_area(void) {
if(!selbox->show)
return;
int ax = selbox->x;
int ay = selbox->y;
int aw = selbox->w;
int ah = selbox->h;
if(aw < 0) {
ax += aw;
aw = -aw;
} else if(!aw)
aw = 1;
if(ah < 0) {
ay += ah;
ah = -ah;
} else if(!ah)
ah = 1;
/*
* XXX: This function can fail since icon coordinates are absolute (event_x_root)
* but selbox use relative (event_root). It will work as expected if desktop is at x=0 y=0.
* This should be checked further.
*/
unsigned int sz = icons.size();
DesktopIcon* ic = NULL;
int prev_x, prev_y, tmp_x, tmp_y;
DesktopIcon* ic;
for(unsigned int i = 0; i < sz; i++) {
ic = icons[i];
EASSERT(ic != NULL && "Impossible to happen");
ic = selectionbuff[i];
if(intersects(ax, ay, ax+aw, ay+ah, ic->x(), ic->y(), ic->w()+ic->x(), ic->h()+ic->y())) {
if(!ic->is_focused()) {
ic->do_focus();
ic->redraw();
}
} else {
if(ic->is_focused()) {
ic->do_unfocus();
ic->redraw();
}
}
prev_x = ic->drag_icon_x();
prev_y = ic->drag_icon_y();
tmp_x = x - selection_x;
tmp_y = y - selection_y;
ic->drag(prev_x + tmp_x, prev_y + tmp_y, apply);
// very slow if not checked
if(apply == true)
ic->fast_redraw();
}
selection_x = x;
selection_y = y;
/*
* Redraw whole screen so it reflects
* new icon position
*/
if(apply)
redraw();
}
#if 0
/*
* Tries to figure out icon below mouse (used for DND)
* If fails, return NULL
* Tries to figure out icon below mouse. It is alternative to
* Fl::belowmouse() since with this we hunt only icons, not other
* childs (wallpaper, menu), which can be returned by Fl::belowmouse()
* and bad things be hapened.
*/
DesktopIcon* Desktop::below_mouse(int px, int py) {
unsigned int sz = icons.size();
@ -681,129 +497,39 @@ DesktopIcon* Desktop::below_mouse(int px, int py) {
DesktopIcon* ic = NULL;
for(unsigned int i = 0; i < sz; i++) {
ic = icons[i];
EASSERT(ic != NULL && "Impossible to happen");
if(ic->x() < px && ic->y() < py && px < (ic->x() + ic->h()) && py < (ic->y() + ic->h()))
return ic;
}
return NULL;
}
// used to drop dnd context on desktop figuring out what it can be
void Desktop::drop_source(const char* src, int x, int y) {
if(!src)
return;
IconSettings is;
is.x = x;
is.y = y;
// absolute path we (for now) see as non-url
if(src[0] == '/')
is.cmd_is_url = false;
else
is.cmd_is_url = true;
is.name = "XXX";
is.cmd = "(none)";
is.type = ICON_NORMAL;
edelib::MimeType mt;
if(!mt.set(src)) {
EDEBUG("MimeType for %s failed, not dropping icon\n", src);
return;
}
is.icon = mt.icon_name();
EDEBUG("---------> %s\n", is.icon.c_str());
DesktopIcon* dic = new DesktopIcon(&gisett, &is);
add_icon(dic);
}
void Desktop::draw(void) {
#if 0
if(damage() & fltk::DAMAGE_ALL) {
fltk::Window::draw();
}
#endif
if(damage() & fltk::DAMAGE_ALL) {
clear_flag(fltk::HIGHLIGHT);
int nchild = children();
if(damage() & ~fltk::DAMAGE_CHILD) {
draw_box();
draw_label();
for(int i = 0; i < nchild; i++) {
fltk::Widget& ch = *child(i);
draw_child(ch);
draw_outside_label(ch);
}
} else {
for(int i = 0; i < nchild; i++) {
fltk::Widget& ch = *child(i);
if(ch.damage() & fltk::DAMAGE_CHILD_LABEL) {
draw_outside_label(ch);
ch.set_damage(ch.damage() & ~fltk::DAMAGE_CHILD_LABEL);
}
update_child(ch);
}
}
}
if(damage() & (fltk::DAMAGE_ALL|EDAMAGE_OVERLAY)) {
clear_xoverlay();
if(selbox->show)
draw_xoverlay(selbox->x, selbox->y, selbox->w, selbox->h);
/*
* now scan all icons and see if they needs redraw, and if do
* just update their label since it is indicator of selection
*/
for(int i = 0; i < children(); i++) {
if(child(i)->damage() == fltk::DAMAGE_ALL) {
child(i)->set_damage(fltk::DAMAGE_CHILD_LABEL);
update_child(*child(i));
}
}
}
}
int Desktop::handle(int event) {
switch(event) {
case fltk::FOCUS:
case fltk::UNFOCUS:
case FL_FOCUS:
case FL_UNFOCUS:
return 1;
case fltk::PUSH: {
case FL_PUSH: {
/*
* First check where we clicked. If we do it on desktop
* unfocus any possible focused childs, and handle
* specific clicks. Otherwise, do rest for childs.
*/
fltk::Widget* clicked = fltk::belowmouse();
EDEBUG(ESTRLOC ": %i\n", fltk::event_button());
if(clicked == this) {
unfocus_all();
Fl_Widget* clicked = Fl::belowmouse();
if(NOT_SELECTABLE(clicked)) {
EDEBUG(ESTRLOC ": DESKTOP CLICK !!!\n");
if(!selectionbuff.empty())
if(!selectionbuff.empty()) {
/*
* only focused are in selectionbuff, so this is
* fine to do; also will prevent full redraw when
* is clicked on desktop
*/
unfocus_all();
selectionbuff.clear();
if(fltk::event_button() == 3)
pmenu->popup();
// track position so moving can be deduced
if(fltk::event_button() == 1) {
selbox->x = fltk::event_x();
selbox->y = fltk::event_y();
}
return 1;
}
@ -818,15 +544,13 @@ int Desktop::handle(int event) {
return 1;
if(SELECTION_MULTI) {
fltk::event_is_click(0);
Fl::event_is_click(0);
select(tmp_icon);
return 1;
} else if (SELECTION_SINGLE) {
} else if(SELECTION_SINGLE) {
if(!in_selection(tmp_icon))
select_only(tmp_icon);
} else if (fltk::event_button() == 3)
} else if(Fl::event_button() == 3)
select_only(tmp_icon);
/*
@ -834,157 +558,79 @@ int Desktop::handle(int event) {
* Also prevent click on other mouse buttons during move.
*/
if(!moving)
tmp_icon->handle(fltk::PUSH);
tmp_icon->handle(FL_PUSH);
selection_x = fltk::event_x_root();
selection_y = fltk::event_y_root();
EDEBUG(ESTRLOC ": fltk::PUSH from desktop\n");
EDEBUG(ESTRLOC ": FL_PUSH from desktop\n");
selection_x = Fl::event_x_root();
selection_y = Fl::event_y_root();
return 1;
}
case fltk::DRAG:
case FL_DRAG:
moving = true;
if(!selectionbuff.empty()) {
EDEBUG(ESTRLOC ": DRAG icon from desktop\n");
move_selection(fltk::event_x_root(), fltk::event_y_root(), false);
move_selection(Fl::event_x_root(), Fl::event_y_root(), false);
} else {
EDEBUG(ESTRLOC ": DRAG from desktop\n");
/*
* Moving is started with pushed button.
* From this point selection box is created and is rolled until release
*/
if(selbox->x != 0 || selbox->y != 0) {
selbox->w = fltk::event_x() - selbox->x;
selbox->h = fltk::event_y() - selbox->y;
selbox->show = true;
// see if there some icons inside selection area
select_in_area();
// redraw selection box
redraw(EDAMAGE_OVERLAY);
}
}
return 1;
case fltk::RELEASE:
case FL_RELEASE:
EDEBUG(ESTRLOC ": RELEASE from desktop\n");
EDEBUG(ESTRLOC ": clicks: %i\n", fltk::event_is_click());
if(selbox->show) {
selbox->x = selbox->y = selbox->w = selbox->h = 0;
selbox->show = false;
redraw(EDAMAGE_OVERLAY);
/*
* Now pickup those who are in is_focused() state.
* Here is not used select() since it will fill selectionbuff with
* redrawing whole window each time. This is not what we want.
*
* Possible flickers due overlay will be later removed when is
* called move_selection(), which will in turn redraw icons again
* after position them.
*/
if(!selectionbuff.empty())
selectionbuff.clear();
for(unsigned int i = 0; i < icons.size(); i++) {
if(icons[i]->is_focused())
select_noredraw(icons[i]);
}
return 1;
}
EDEBUG(ESTRLOC ": clicks: %i\n", Fl::event_is_click());
if(!selectionbuff.empty() && moving)
move_selection(fltk::event_x_root(), fltk::event_y_root(), true);
move_selection(Fl::event_x_root(), Fl::event_y_root(), true);
/*
* Do not send fltk::RELEASE during move
* Do not send FL_RELEASE during move
*
* TODO: should be alowed fltk::RELEASE to multiple icons? (aka. run
* TODO: should be alowed FL_RELEASE to multiple icons? (aka. run
* command for all selected icons ?
*/
if(selectionbuff.size() == 1 && !moving)
selectionbuff[0]->handle(fltk::RELEASE);
selectionbuff[0]->handle(FL_RELEASE);
moving = false;
return 1;
case fltk::DND_ENTER:
case fltk::DND_DRAG:
case fltk::DND_LEAVE:
return 1;
case fltk::DND_RELEASE: {
// fltk::belowmouse() can't be used within DND context :)
DesktopIcon* di = below_mouse(fltk::event_x_root(), fltk::event_y_root());
if(di) {
di->handle(event);
} else {
EDEBUG("DND on DESKTOP\n");
}
return 1;
}
case fltk::PASTE: {
DesktopIcon* di = below_mouse(fltk::event_x_root(), fltk::event_y_root());
if(di) {
di->handle(event);
} else {
EDEBUG("PASTE on desktop with %s\n", fltk::event_text());
drop_source(fltk::event_text(), fltk::event_x_root(), fltk::event_y_root());
}
}
return 1;
default:
break;
}
return fltk::Window::handle(event);
}
/*
* This function is executed before desktop is actually showed
* but after is internally created so net_make_me_desktop() specific code can
* be executed correctly.
*
* Calling net_make_me_desktop() after show() will confuse many wm's which will
* in turn partialy register us as desktop type.
*/
void Desktop::create(void) {
fltk::Window::create();
net_make_me_desktop(this);
return Fl_Window::handle(event);
}
int main() {
signal(SIGTERM, exit_signal);
signal(SIGKILL, exit_signal);
signal(SIGINT, exit_signal);
signal(SIGINT, exit_signal);
signal(SIGHUP, restart_signal);
srand(time(NULL));
// TODO: init_locale_support()
// a lot of preparing code depends on this
fl_open_display();
fl_register_images();
//edelib::IconTheme::init("crystalsvg");
edelib::IconTheme::init("edeneu");
fltk::register_images();
Desktop::init();
Desktop::instance()->show();
/*
* XSelectInput will redirect PropertyNotify messages, which
* we are listen for
* are listened for
*/
XSelectInput(fltk::xdisplay, RootWindow(fltk::xdisplay, fltk::xscreen), PropertyChangeMask | StructureNotifyMask );
fltk::add_event_handler(desktop_xmessage_handler);
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), PropertyChangeMask | StructureNotifyMask );
Fl::add_handler(desktop_xmessage_handler);
while(running)
fltk::wait();
Fl::wait();
Desktop::shutdown();
edelib::IconTheme::shutdown();

View File

@ -13,18 +13,19 @@
#ifndef __EICONMAN_H__
#define __EICONMAN_H__
#include <fltk/Window.h>
#include <fltk/PopupMenu.h>
#include <fltk/Image.h>
#include <FL/Fl_Window.h>
#include <FL/Fl_Double_Window.h>
#include <FL/Fl_Image.h>
#include <edelib/String.h>
#include <edelib/Config.h>
#include <edelib/Vector.h>
#define EDAMAGE_LABEL 0x20
struct DesktopSettings {
int color; // background color
bool wp_use; // use wallpaper or not
fltk::Image* wp_image; // wallpaper image (can be NULL)
edelib::String wp_path; // wallpaper path
};
struct GlobalIconSettings {
@ -32,11 +33,10 @@ struct GlobalIconSettings {
int label_foreground;
int label_fontsize;
int label_maxwidth;
int gridspacing;
bool label_transparent;
bool label_draw;
bool one_click_exec;
bool auto_arr;
bool auto_arrange;
bool same_size;
};
@ -53,8 +53,8 @@ struct GlobalIconSettings {
* - symlink in ~/Desktop directory pointing to the real file
*/
struct IconSettings {
int x, y;
int type;
int x, y;
int type; // ICON_NORMAL, ICON_TRASH,...
bool cmd_is_url; // interpret cmd as url, like system:/,trash:/,$HOME
edelib::String name;
@ -64,79 +64,59 @@ struct IconSettings {
edelib::String key_name; // name used as key when storing positions
};
// selection overlay
struct SelectionOverlay {
int x, y, w, h;
bool show;
};
class Wallpaper;
class DesktopIcon;
typedef edelib::vector<DesktopIcon*> DesktopIconList;
class Desktop : public fltk::Window {
class Desktop : public Fl_Window {
private:
static Desktop* pinstance;
int desktops_num;
int curr_desktop;
int bg_color;
bool wp_use;
int selection_x, selection_y;
bool moving;
int selection_x;
int selection_y;
SelectionOverlay* selbox;
GlobalIconSettings gisett;
IconSettings isett;
DesktopSettings* dsett;
Wallpaper* wallpaper;
DesktopIconList icons;
DesktopIconList selectionbuff;
fltk::PopupMenu* pmenu;
void init_desktops(void);
void load_icons(const char* path, edelib::Config& conf);
bool read_desktop_file(const char* path, IconSettings& is);
void add_icon(DesktopIcon* ic);
void unfocus_all(void);
void select(DesktopIcon* ic);
void select_only(DesktopIcon* ic);
bool in_selection(const DesktopIcon* ic);
void select_in_area(void);
void select_noredraw(DesktopIcon* ic);
void move_selection(int x, int y, bool apply);
DesktopIcon* below_mouse(int x, int y);
void drop_source(const char* src, int x, int y);
//DesktopIcon* below_mouse(int px, int py);
public:
Desktop();
~Desktop();
virtual void show(void);
virtual void hide(void);
virtual int handle(int event);
static void init(void);
static void shutdown(void);
static Desktop* instance(void);
Desktop();
~Desktop();
void update_workarea(void);
void read_config(void);
void save_config(void);
void set_wallpaper(const char* path, bool do_redraw = true);
void set_wallpaper(fltk::Image* im, bool do_redraw = true);
void set_bg_color(unsigned int c, bool do_redraw = true);
void update_workarea(void);
void set_bg_color(int c, bool do_redraw = true);
void create(void);
virtual void draw(void);
virtual int handle(int event);
Fl_Window* desktop_window(void) { return this; }
};
#endif

View File

@ -1,87 +1,56 @@
# data file for the FLTK User Interface Designer (FLUID)
version 2.1000
images_dir fltk::Choice
# data file for the Fltk User Interface Designer (fluid)
version 1.0108
header_name {.h}
code_name {.cxx}
gridx 5
gridy 5
snap 1
Function {} {open selected
code_name {.cxx}
Function {} {open
} {
{fltk::Window} {} {open
xywh {363 251 540 260} resizable visible
Fl_Window {} {open selected
xywh {416 256 540 260} type Double resizable visible
} {
{fltk::InvisibleBox} {} {
Fl_Box {} {
xywh {75 173 100 15} box BORDER_BOX
}
{fltk::InvisibleBox} {} {
Fl_Box {} {
xywh {20 20 210 158} box THIN_UP_BOX
}
{fltk::InvisibleBox} {} {
xywh {30 30 190 138} box DOWN_BOX color 56
Fl_Box {} {
xywh {33 30 184 138} box DOWN_BOX color 56
code0 {/* box size is intentionaly odd so preserve aspect ratio */}
}
{fltk::InvisibleBox} {} {
Fl_Box {} {
xywh {50 183 145 14} box THIN_UP_BOX
}
{fltk::Choice} {} {
label {Desktop:} open
xywh {310 20 220 25}
} {}
{fltk::CheckButton} {} {
label {Use wallpaper}
xywh {310 60 20 19} align 8
}
{fltk::Input} {} {
Fl_Input {} {
label {Image:}
xywh {310 94 190 25}
xywh {310 55 190 25}
}
{fltk::Button} {} {
Fl_Button {} {
label {...}
xywh {505 94 25 25}
xywh {505 55 25 25}
}
{fltk::Choice} {} {
Fl_Choice {} {
label {Mode:} open
xywh {310 129 220 24}
xywh {310 91 220 24} down_box BORDER_BOX
} {}
{fltk::Button} {} {
Fl_Button {} {
label {Background color}
xywh {310 173 25 24} align 8 color 0x3ca700
xywh {310 136 25 24} color 73 align 8
}
{fltk::Button} {} {
Fl_Button {} {
label {&OK}
xywh {250 227 90 25}
}
{fltk::Button} {} {
Fl_Button {} {
label {&Apply}
xywh {345 227 90 25}
}
{fltk::Button} {} {
Fl_Button {} {
label {&Cancel}
xywh {440 227 90 25}
}
{fltk::Group} {} {open
xywh {20 210 210 40}
} {
{fltk::InvisibleBox} {} {
xywh {15 5 35 30} box THIN_DOWN_BOX color 0xffff0000
}
{fltk::Button} {} {
label {@<}
xywh {0 5 10 30} box FLAT_BOX
}
{fltk::Button} {} {
label {@>}
xywh {200 5 10 30} box FLAT_BOX
}
{fltk::InvisibleBox} {} {
xywh {55 5 35 30} box THIN_DOWN_BOX color 0x49a47d00
}
{fltk::InvisibleBox} {} {
xywh {95 5 35 30} box THIN_DOWN_BOX color 0x3a488800
}
{fltk::InvisibleBox} {} {
xywh {135 5 35 30} box THIN_DOWN_BOX color 0x808b3f00
}
Fl_Check_Button {} {
label { Use wallpaper}
xywh {310 20 220 25} down_box DOWN_BOX
}
}
}