/* * $Id$ * * ede-desktop, desktop and icon manager * Part of Equinox Desktop Environment (EDE). * Copyright (c) 2006-2008 EDE Authors. * * This program is licensed under terms of the * GNU General Public License version 2 or newer. * See COPYING for details. */ #include // strrchr, strncpy, strlen #include // CARD32 #include #include #include "Utils.h" 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; static int overlay_x = 0; static int overlay_y = 0; static int overlay_w = 0; static int overlay_h = 0; static Fl_Window* overlay_drawable = NULL; static 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); } 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; } #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') { E_DEBUG("%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 = (char*)strrchr(path, '/'); if(p) return (p + 1); return (char*)path; } bool is_temp_filename(const char* path) { int len; if(!path || path[0] == '\0' || path[0] == '.') return true; len = strlen(path); if(path[len - 1] == '~') return true; return false; }