dockapps/libdockapp/src/damain.c
Doug Torrance 24c0e4e4f2 libdockapp: Don't withdraw dockapps in windowed mode.
In Window Maker, windows with application class "DockApp" are automatically
withdrawn.  We don't want this in windowed mode. We use the application
name instead, with the usual convention of capitalizing the initial letter.
2017-04-27 11:29:10 +01:00

248 lines
6.7 KiB
C

/*
* Copyright (c) 1999-2003 Alfredo K. Kojima, Alban Hertroys
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "dockapp.h"
#include "daargs.h"
#include "dautil.h"
#include <ctype.h>
#define MIN(a, b) (a < b ? a : b)
struct DAContext *_daContext;
DARect DANoRect = {0, 0, 0, 0};
Display *DADisplay = NULL;
Window DALeader = None;
Window DAIcon = None;
Window DAWindow = None;
int DADepth = 0;
Visual *DAVisual = NULL;
unsigned long DAExpectedVersion = 0;
GC DAGC = NULL, DAClearGC = NULL;
DARect DAPreferredIconSizes = {-1, -1, 0, 0};
Atom WM_DELETE_WINDOW;
void
DAOpenDisplay(char *display, int argc, char **argv)
{
/* Open Connection to X Server */
DADisplay = XOpenDisplay(display);
if (!DADisplay) {
printf("%s: could not open display %s!\n", _daContext->programName,
XDisplayName(display));
exit(EXIT_FAILURE);
}
DADepth = DefaultDepth(DADisplay, DefaultScreen(DADisplay));
DAVisual = DefaultVisual(DADisplay, DefaultScreen(DADisplay));
DAGC = DefaultGC(DADisplay, DefaultScreen(DADisplay));
}
void
DAProposeIconSize(unsigned width, unsigned height)
{
XIconSize *iconSizes;
int nrSizes = 0;
_daContext->width = width;
_daContext->height = height;
/* Get the nearest allowed icon size if the WM specifies such */
iconSizes = XAllocIconSize();
if (XGetIconSizes(DADisplay, DefaultRootWindow(DADisplay),
&iconSizes, &nrSizes)) {
int i;
int da = -1;
int min_w = -1, min_h = -1;
int max_w = 0, max_h = 0;
for (i = 0; i < nrSizes; i++) {
int w1, h1, w, h;
if ((max_w < iconSizes[i].max_width) ||
(max_h < iconSizes[i].max_height)) {
max_w = iconSizes[i].max_width;
max_h = iconSizes[i].max_height;
}
if ((min_w > iconSizes[i].min_width) ||
(min_h > iconSizes[i].min_height) ||
(min_w == -1)) {
min_w = iconSizes[i].min_width;
min_h = iconSizes[i].min_height;
}
if ((width > iconSizes[i].max_width) ||
(width < iconSizes[i].min_width) ||
(height > iconSizes[i].max_height) ||
(height < iconSizes[i].min_height))
continue;
w1 = (iconSizes[i].max_width - width) % iconSizes[i].width_inc;
h1 = (iconSizes[i].max_height - height) % iconSizes[i].height_inc;
w = MIN(w1, iconSizes[i].width_inc - w1);
h = MIN(h1, iconSizes[i].height_inc - h1);
if ((w * h < da) || (da == -1)) {
_daContext->width = width + w;
_daContext->height = height + h;
da = w * h;
}
}
DAPreferredIconSizes.x = min_w;
DAPreferredIconSizes.y = min_h;
DAPreferredIconSizes.width = max_w;
DAPreferredIconSizes.height = max_h;
if (da == -1) /* requested size is out of bounds */
DAWarning("Requested icon-size (%d x %d) is out of the range "
"allowed by the window manager\n",
_daContext->width, _daContext->height);
}
XFree(iconSizes);
}
void
DACreateIcon(char *name, unsigned width, unsigned height, int argc, char **argv)
{
XClassHint *classHint;
XWMHints *wmHints;
XGCValues gcv;
unsigned long valueMask;
char *resourceValue;
_daContext->width = width;
_daContext->height = height;
/* Create Windows */
DALeader = XCreateSimpleWindow(DADisplay, DefaultRootWindow(DADisplay),
0, 0, width, height, 0, 0, 0);
if (!_daContext->windowed) {
DAIcon = XCreateSimpleWindow(DADisplay, DefaultRootWindow(DADisplay),
0, 0, width, height, 0, 0, 0);
DAWindow = DAIcon;
} else {
DAIcon = None;
DAWindow = DALeader;
}
/* Set ClassHint */
classHint = XAllocClassHint();
if (!classHint)
printf("%s: can't allocate memory for class hints!\n",
_daContext->programName), exit(1);
if (!_daContext->windowed) {
classHint->res_class = RES_CLASSNAME;
} else {
char class[100];
snprintf(class, 100, "%c%s", toupper(name[0]), name + 1);
classHint->res_class = class;
}
classHint->res_name = name;
XSetClassHint(DADisplay, DALeader, classHint);
XFree(classHint);
/* Set WMHints */
wmHints = XAllocWMHints();
if (!wmHints)
printf("%s: can't allocate memory for wm hints!\n",
_daContext->programName), exit(1);
wmHints->flags = WindowGroupHint;
wmHints->window_group = DALeader;
if (!_daContext->windowed) {
wmHints->flags |= IconWindowHint|StateHint;
wmHints->icon_window = DAIcon;
wmHints->initial_state = WithdrawnState;
}
XSetWMHints(DADisplay, DALeader, wmHints);
XFree(wmHints);
/* Set WMProtocols */
WM_DELETE_WINDOW = XInternAtom(DADisplay, "WM_DELETE_WINDOW", True);
XSetWMProtocols(DADisplay, DALeader, &WM_DELETE_WINDOW, 1);
/* Set Command to start the app so it can be docked properly */
XSetCommand(DADisplay, DALeader, argv, argc);
gcv.graphics_exposures = False;
valueMask = GCGraphicsExposures;
/* continue setting the foreground GC */
resourceValue = XGetDefault(DADisplay, RES_CLASSNAME, "foreground");
if (resourceValue) {
gcv.foreground = DAGetColor(resourceValue);
valueMask |= GCForeground;
}
XChangeGC(DADisplay, DAGC, valueMask, &gcv);
/* set background GC values before setting value for foreground */
resourceValue = XGetDefault(DADisplay, RES_CLASSNAME, "background");
if (resourceValue)
gcv.foreground = DAGetColor(resourceValue);
DAClearGC = XCreateGC(DADisplay, DAWindow,
GCGraphicsExposures|GCForeground, &gcv);
XFlush(DADisplay);
}
void
DAShow(void)
{
DAShowWindow(DALeader);
}
void
DAShowWindow(Window window)
{
XMapRaised(DADisplay, window);
if ((window == DALeader) && !_daContext->windowed)
XMapSubwindows(DADisplay, DAIcon);
else
XMapSubwindows(DADisplay, window);
XFlush(DADisplay);
}
/* Deprecated */
void
DAInitialize(char *display, char *name, unsigned width, unsigned height,
int argc, char **argv)
{
DAOpenDisplay(display, argc, argv);
DACreateIcon(name, width, height, argc, argv);
}