mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
adc3a8efcd
* DND now should work reasonable (still not finished DND on icons) * Added menus (icon specific, desktop) * Icon renaming works too * Some code to change icons fonts (unfinished) * Desktop main instance will be now first created and then call rest of init data. This will allow init data to re-use desktop instance and peek it's own data (area() for example). Previously, calling such functions would crash app since constructor didn't finished with creation of desktop instance.
359 lines
8.4 KiB
C++
359 lines
8.4 KiB
C++
/*
|
|
* $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 "Utils.h"
|
|
#include <X11/Xproto.h> // CARD32
|
|
#include <FL/x.h>
|
|
#include <edelib/Debug.h>
|
|
|
|
#include <string.h> // strrchr, strncpy, strlen
|
|
|
|
Atom _XA_NET_WORKAREA = 0;
|
|
Atom _XA_NET_WM_WINDOW_TYPE = 0;
|
|
Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP = 0;
|
|
Atom _XA_NET_NUMBER_OF_DESKTOPS = 0;
|
|
Atom _XA_NET_CURRENT_DESKTOP = 0;
|
|
Atom _XA_NET_DESKTOP_NAMES = 0;
|
|
Atom _XA_XROOTPMAP_ID = 0;
|
|
|
|
Atom _XA_EDE_DESKTOP_NOTIFY = 0;
|
|
Atom _XA_EDE_DESKTOP_NOTIFY_COLOR = 0;
|
|
|
|
int overlay_x = 0;
|
|
int overlay_y = 0;
|
|
int overlay_w = 0;
|
|
int overlay_h = 0;
|
|
|
|
Fl_Window* overlay_drawable = NULL;
|
|
|
|
char dash_list[] = {1};
|
|
|
|
void init_atoms(void) {
|
|
_XA_NET_WORKAREA = XInternAtom(fl_display, "_NET_WORKAREA", False);
|
|
_XA_NET_WM_WINDOW_TYPE = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
|
|
_XA_NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
|
|
_XA_NET_NUMBER_OF_DESKTOPS = XInternAtom(fl_display, "_NET_NUMBER_OF_DESKTOPS", False);
|
|
_XA_NET_CURRENT_DESKTOP = XInternAtom(fl_display, "_NET_CURRENT_DESKTOP", False);
|
|
_XA_NET_DESKTOP_NAMES = XInternAtom(fl_display, "_NET_DESKTOP_NAMES", False);
|
|
_XA_XROOTPMAP_ID = XInternAtom(fl_display, "_XROOTPMAP_ID", False);
|
|
|
|
_XA_EDE_DESKTOP_NOTIFY = XInternAtom(fl_display, "_EDE_DESKTOP_NOTIFY", False);
|
|
_XA_EDE_DESKTOP_NOTIFY_COLOR = XInternAtom(fl_display, "_EDE_DESKTOP_NOTIFY_COLOR", False);
|
|
}
|
|
|
|
bool net_get_workarea(int& x, int& y, int& w, int &h) {
|
|
Atom real;
|
|
|
|
int format;
|
|
unsigned long n, extra;
|
|
unsigned char* prop;
|
|
x = y = w = h = 0;
|
|
|
|
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
|
|
_XA_NET_WORKAREA, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
|
|
|
|
if(status != Success)
|
|
return false;
|
|
|
|
CARD32* val = (CARD32*)prop;
|
|
if(val) {
|
|
x = val[0];
|
|
y = val[1];
|
|
w = val[2];
|
|
h = val[3];
|
|
|
|
XFree((char*)val);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void net_make_me_desktop(Fl_Window* w) {
|
|
/*
|
|
* xid() will return zero if window is not shown;
|
|
* make sure it is shown
|
|
*/
|
|
EASSERT(fl_xid(w));
|
|
|
|
/*
|
|
* Reminder for me (others possible):
|
|
* note '&_XA_NET_WM_WINDOW_TYPE_DESKTOP' conversion, since gcc will not report warning/error
|
|
* if placed '_XA_NET_WM_WINDOW_TYPE_DESKTOP' only.
|
|
*
|
|
* I lost two hours messing with this ! (gdb is unusefull in X world)
|
|
*/
|
|
XChangeProperty(fl_display, fl_xid(w), _XA_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace,
|
|
(unsigned char*)&_XA_NET_WM_WINDOW_TYPE_DESKTOP, sizeof(Atom));
|
|
}
|
|
|
|
int net_get_workspace_count(void) {
|
|
Atom real;
|
|
int format;
|
|
unsigned long n, extra;
|
|
unsigned char* prop;
|
|
|
|
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
|
|
_XA_NET_NUMBER_OF_DESKTOPS, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
|
|
(unsigned char**)&prop);
|
|
|
|
if(status != Success && !prop)
|
|
return -1;
|
|
|
|
int ns = int(*(long*)prop);
|
|
XFree(prop);
|
|
return ns;
|
|
}
|
|
|
|
// desktops are starting from 0
|
|
int net_get_current_desktop(void) {
|
|
Atom real;
|
|
int format;
|
|
unsigned long n, extra;
|
|
unsigned char* prop;
|
|
|
|
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
|
|
_XA_NET_CURRENT_DESKTOP, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
|
|
(unsigned char**)&prop);
|
|
|
|
if(status != Success && !prop)
|
|
return -1;
|
|
|
|
int ns = int(*(long*)prop);
|
|
XFree(prop);
|
|
return ns;
|
|
}
|
|
|
|
// call on this XFreeStringList(names)
|
|
int net_get_workspace_names(char**& names) {
|
|
// FIXME: add _NET_SUPPORTING_WM_CHECK and _NET_SUPPORTED ???
|
|
XTextProperty wnames;
|
|
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &wnames, _XA_NET_DESKTOP_NAMES);
|
|
|
|
// if wm does not understainds _NET_DESKTOP_NAMES this is not set
|
|
if(!wnames.nitems || !wnames.value)
|
|
return 0;
|
|
|
|
int nsz;
|
|
|
|
/*
|
|
* FIXME: Here should as alternative Xutf8TextPropertyToTextList since
|
|
* many wm's set UTF8_STRING property. Below is XA_STRING and for UTF8_STRING
|
|
* will fail.
|
|
*/
|
|
if(!XTextPropertyToStringList(&wnames, &names, &nsz)) {
|
|
XFree(wnames.value);
|
|
return 0;
|
|
}
|
|
|
|
XFree(wnames.value);
|
|
return nsz;
|
|
}
|
|
|
|
bool ede_get_desktop_notify(char* txt, int txt_len) {
|
|
XTextProperty names;
|
|
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &names, _XA_EDE_DESKTOP_NOTIFY);
|
|
if(!names.nitems || !names.value)
|
|
return false;
|
|
|
|
char** vnames;
|
|
int nsz = 0;
|
|
if(!XTextPropertyToStringList(&names, &vnames, &nsz)) {
|
|
XFree(names.value);
|
|
return false;
|
|
}
|
|
|
|
strncpy(txt, vnames[0], txt_len);
|
|
XFreeStringList(vnames);
|
|
return true;
|
|
}
|
|
|
|
Fl_Color ede_get_desktop_notify_color(void) {
|
|
Atom real;
|
|
int format;
|
|
unsigned long n, extra;
|
|
unsigned char* prop;
|
|
|
|
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
|
|
_XA_EDE_DESKTOP_NOTIFY_COLOR, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
|
|
(unsigned char**)&prop);
|
|
|
|
int color = FL_WHITE;
|
|
|
|
if(status != Success && !prop)
|
|
return (Fl_Color)color;
|
|
|
|
color = int(*(long*)prop);
|
|
XFree(prop);
|
|
|
|
return (Fl_Color)color;
|
|
}
|
|
|
|
#if 0
|
|
int net_get_workspace_names(char** names) {
|
|
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(fl_display, RootWindow(fl_display, fl_screen),
|
|
nd, 0L, 0x7fffffff, False, utf8_str, &real, &format, &n, &extra, (unsigned char**)&prop);
|
|
|
|
if(status != Success && !prop)
|
|
return 0;
|
|
|
|
int alloc = 0;
|
|
if(real == utf8_str && format == 8) {
|
|
const char* p = (const char*)prop;
|
|
for(int i = 0, s = 0; i < n && alloc < MAX_DESKTOPS; i++, alloc++) {
|
|
if(p[i] == '\0') {
|
|
EDEBUG("%c ", p[i]);
|
|
names[alloc] = strndup((p + s), i - s + 1);
|
|
s = i + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return alloc;
|
|
}
|
|
#endif
|
|
|
|
void draw_overlay_rect(void) {
|
|
if(overlay_w <= 0 || overlay_h <= 0)
|
|
return;
|
|
|
|
XSetDashes(fl_display, fl_gc, 0, dash_list, 1);
|
|
XSetLineAttributes(fl_display, fl_gc, 2, LineOnOffDash, CapButt, JoinMiter);
|
|
|
|
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(fl_display, fl_gc, 0, LineOnOffDash, CapButt, JoinMiter);
|
|
}
|
|
|
|
void draw_xoverlay(int x, int y, int w, int h) {
|
|
if(w < 0) {
|
|
x += w;
|
|
w = -w;
|
|
} else if(!w)
|
|
w = 1;
|
|
|
|
if(h < 0) {
|
|
y += h;
|
|
h = -h;
|
|
} else if(!h)
|
|
h = 1;
|
|
|
|
if(overlay_w > 0) {
|
|
if(x == overlay_x && y == overlay_y && w == overlay_w && h == overlay_h)
|
|
return;
|
|
draw_overlay_rect();
|
|
}
|
|
|
|
overlay_x = x;
|
|
overlay_y = y;
|
|
overlay_w = w;
|
|
overlay_h = h;
|
|
|
|
draw_overlay_rect();
|
|
}
|
|
|
|
void clear_xoverlay(void) {
|
|
if(overlay_w > 0) {
|
|
draw_overlay_rect();
|
|
overlay_w = 0;
|
|
}
|
|
}
|
|
|
|
void set_xoverlay_drawable(Fl_Window* win) {
|
|
overlay_drawable = win;
|
|
}
|
|
|
|
Pixmap create_mask(Fl_Image* img) {
|
|
if(!img)
|
|
return 0;
|
|
|
|
// no alpha
|
|
if(img->d() != 4)
|
|
return 0;
|
|
|
|
int iw = img->w();
|
|
int ih = img->h();
|
|
|
|
unsigned char* xim_data = new unsigned char[((iw >> 3) + 8) * ih];
|
|
|
|
XImage* xim = XCreateImage(fl_display, fl_visual->visual, 1, ZPixmap, 0, (char*)xim_data, iw, ih, 8, 0);
|
|
if(!xim) {
|
|
delete [] xim_data;
|
|
return 0;
|
|
}
|
|
|
|
const char* src = img->data()[0];
|
|
unsigned char a;
|
|
|
|
for(int y = 0; y < ih; y++) {
|
|
for(int x = 0; x < iw; x++) {
|
|
// jump rgb and pick alpha
|
|
src += 3;
|
|
a = *src++;
|
|
|
|
if(a < 128) {
|
|
// these are transparent
|
|
XPutPixel(xim, x, y, 0);
|
|
}
|
|
else {
|
|
// these are opaque
|
|
XPutPixel(xim, x, y, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Window drawable = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen), 0, 0, iw,
|
|
ih, 0, 0, BlackPixel(fl_display, fl_screen));
|
|
|
|
Pixmap pix = XCreatePixmap(fl_display, drawable, iw, ih, 1);
|
|
|
|
XGCValues gcv;
|
|
gcv.graphics_exposures = False;
|
|
GC dgc = XCreateGC(fl_display, pix, GCGraphicsExposures, &gcv);
|
|
|
|
XPutImage(fl_display, pix, dgc, xim, 0, 0, 0, 0, iw, ih);
|
|
|
|
XDestroyWindow(fl_display, drawable);
|
|
XFreeGC(fl_display, dgc);
|
|
delete [] xim->data;
|
|
xim->data = 0;
|
|
XDestroyImage(xim);
|
|
|
|
return pix;
|
|
}
|
|
|
|
char* get_basename(const char* path) {
|
|
char* p = strrchr(path, '/');
|
|
if(p)
|
|
return (p + 1);
|
|
|
|
return (char*)path;
|
|
}
|