21625f40b5
I tried to get the latest versions from dockapps.org, but I haven't tested any of them. More dockapps will be added as time permits.
250 lines
6.7 KiB
C
250 lines
6.7 KiB
C
/*
|
|
* 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 <X11/Xlib.h>
|
|
#include <X11/xpm.h>
|
|
#include <X11/extensions/shape.h>
|
|
|
|
#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;
|
|
}
|