dockapps/wmfu/dockapp.c

250 lines
6.7 KiB
C
Raw Normal View History

/*
* 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;
}