/* * Copyright (c) 1999 Alfredo K. Kojima * Copyright (c) 2001, 2002 Seiichi SATO * Copyright (c) 2007 Daniel Borca * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "dockapp.h" #define WINDOWED_SIZE_W 64 #define WINDOWED_SIZE_H 64 #define DOCKED_SIZE_W (WINDOWED_SIZE_W - 4) #define DOCKED_SIZE_H (WINDOWED_SIZE_H - 4) int dockapp_open_window(DOCKAPP *d, const char *display_specified, char *appname, int iswindowed, int argc, char **argv) { XSizeHints sizehints; XClassHint classhint; XWMHints wmhints; XTextProperty title; Window root; int ww, wh; /* Open Connection to X Server */ d->display = XOpenDisplay(display_specified); if (d->display == NULL) { return -1; } d->x_offset = d->y_offset = 0; ww = DOCKED_SIZE_W; wh = DOCKED_SIZE_H; if (iswindowed) { d->x_offset = (WINDOWED_SIZE_W - DOCKED_SIZE_W) / 2; d->y_offset = (WINDOWED_SIZE_H - DOCKED_SIZE_H) / 2; ww = WINDOWED_SIZE_W; wh = WINDOWED_SIZE_H; } /* Create Windows */ root = DefaultRootWindow(d->display); d->icon_window = XCreateSimpleWindow(d->display, root, 0, 0, ww, wh, 0, 0, 0); d->window = XCreateSimpleWindow(d->display, root, 0, 0, 1, 1, 0, 0, 0); /* Set ClassHint */ classhint.res_class = "DockApp"; classhint.res_name = appname; XSetClassHint(d->display, d->window, &classhint); /* Set WMHints */ wmhints.flags = IconWindowHint | WindowGroupHint; if (!iswindowed) { wmhints.flags |= StateHint; wmhints.initial_state = WithdrawnState; } wmhints.window_group = d->window; wmhints.icon_window = d->icon_window; XSetWMHints(d->display, d->window, &wmhints); /* Set Size Hints */ sizehints.flags = USSize; if (!iswindowed) { sizehints.flags |= USPosition; sizehints.x = sizehints.y = 0; } else { sizehints.flags |= PMinSize | PMaxSize; sizehints.min_width = sizehints.max_width = WINDOWED_SIZE_W; sizehints.min_height = sizehints.max_height = WINDOWED_SIZE_H; } sizehints.width = ww; sizehints.height = wh; XSetWMNormalHints(d->display, d->icon_window, &sizehints); /* Set WindowTitle for AfterStep Wharf */ XStringListToTextProperty(&appname, 1, &title); XSetWMName(d->display, d->window, &title); XSetWMName(d->display, d->icon_window, &title); XFree(title.value); /* Set WM Protocols */ d->delete_win = XInternAtom(d->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(d->display, d->icon_window, &d->delete_win, 1); /* Set Command to start the app so it can be docked properly */ XSetCommand(d->display, d->window, argv, argc); d->width = DOCKED_SIZE_W; d->height = DOCKED_SIZE_H; d->iswindowed = iswindowed; d->depth = DefaultDepth(d->display, DefaultScreen(d->display)); d->gc = DefaultGC(d->display, DefaultScreen(d->display)); d->quit = False; d->pixmap = dockapp_createpixmap(d, ww, wh); XSetForeground(d->display, d->gc, dockapp_get_color(d, "rgb:ae/aa/ae")); XFillRectangle(d->display, d->pixmap, d->gc, 0, 0, ww, wh); XSetWindowBackgroundPixmap(d->display, d->icon_window, d->pixmap); XSetWindowBackgroundPixmap(d->display, d->window, d->pixmap); XClearWindow(d->display, d->icon_window); if (!d->iswindowed) { XMapRaised(d->display, d->window); } else { XMapRaised(d->display, d->icon_window); } XFlush(d->display); return 0; } void dockapp_set_eventmask(const DOCKAPP *d, long mask) { XSelectInput(d->display, d->icon_window, mask); XSelectInput(d->display, d->window, mask); } void dockapp_set_shape(const DOCKAPP *d, Pixmap mask) { XShapeCombineMask(d->display, d->icon_window, ShapeBounding, d->x_offset, d->y_offset, mask, ShapeSet); XShapeCombineMask(d->display, d->window, ShapeBounding, d->x_offset, d->y_offset, mask, ShapeSet); XFlush(d->display); } void dockapp_copy_area(const DOCKAPP *d, Pixmap src, int x_src, int y_src, int w, int h, int x_dst, int y_dst) { XCopyArea(d->display, src, d->pixmap, d->gc, x_src, y_src, w, h, x_dst + d->x_offset, y_dst + d->y_offset); } void dockapp_update(const DOCKAPP *d) { XClearWindow(d->display, d->icon_window); } Bool dockapp_xpm2pixmap(const DOCKAPP *d, char **data, Pixmap *pixmap, Pixmap *mask, XpmColorSymbol *colorSymbol, unsigned int nsymbols) { XpmAttributes xpmAttr; xpmAttr.valuemask = XpmCloseness; xpmAttr.closeness = 1 << 15; if (nsymbols) { xpmAttr.colorsymbols = colorSymbol; xpmAttr.numsymbols = nsymbols; xpmAttr.valuemask |= XpmColorSymbols; } return (XpmCreatePixmapFromData(d->display, d->icon_window, data, pixmap, mask, &xpmAttr) == 0); } Pixmap dockapp_createpixmap(const DOCKAPP *d, int width, int height) { return XCreatePixmap(d->display, d->icon_window, width, height, d->depth); } Bool dockapp_nextevent_or_timeout(DOCKAPP *d, XEvent *event, unsigned long millis) { struct timeval timeout; fd_set rset; XSync(d->display, False); if (XPending(d->display)) { XNextEvent(d->display, event); return True; } timeout.tv_sec = millis / 1000; timeout.tv_usec = (millis % 1000) * 1000; FD_ZERO(&rset); FD_SET(ConnectionNumber(d->display), &rset); if (select(ConnectionNumber(d->display) + 1, &rset, NULL, NULL, &timeout) > 0) { XNextEvent(d->display, event); if (event->type == ClientMessage) { if ((Atom)event->xclient.data.l[0] == d->delete_win) { d->quit = True; return False; } } if (d->iswindowed) { event->xbutton.x -= d->x_offset; event->xbutton.y -= d->y_offset; } return True; } return False; } unsigned long dockapp_get_color(const DOCKAPP *d, const char *color_name) { XColor color; if (!XParseColor(d->display, DefaultColormap(d->display, DefaultScreen(d->display)), color_name, &color)) { return BlackPixel(d->display, DefaultScreen(d->display)); } if (!XAllocColor(d->display, DefaultColormap(d->display, DefaultScreen(d->display)), &color)) { return BlackPixel(d->display, DefaultScreen(d->display)); } return color.pixel; }