211 lines
5.1 KiB
C
211 lines
5.1 KiB
C
/*
|
|
* Window Maker window manager
|
|
*
|
|
* Copyright (c) 1997-2003 Alfredo K. Kojima
|
|
*
|
|
* 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 "wconfig.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "WindowMaker.h"
|
|
#include "window.h"
|
|
#include "GNUstep.h"
|
|
#include "properties.h"
|
|
|
|
|
|
int PropGetWMClass(Window window, char **wm_class, char **wm_instance)
|
|
{
|
|
return wm_backend->prop_get_wm_class((WNativeWindow)window,
|
|
wm_class, wm_instance);
|
|
}
|
|
|
|
void PropGetProtocols(Window window, WProtocols * prots)
|
|
{
|
|
Atom *protocols;
|
|
int count, i;
|
|
|
|
memset(prots, 0, sizeof(WProtocols));
|
|
if (!dpy) {
|
|
/* Phase 63: all XDG toplevels support close (wlr_xdg_toplevel_send_close).
|
|
* Advertise DELETE_WINDOW so wManageWindow sets kill_close=0 and the
|
|
* close menu item is enabled. */
|
|
prots->DELETE_WINDOW = 1;
|
|
return;
|
|
}
|
|
if (!XGetWMProtocols(dpy, window, &protocols, &count)) {
|
|
return;
|
|
}
|
|
for (i = 0; i < count; i++) {
|
|
if (protocols[i] == w_global.atom.wm.take_focus)
|
|
prots->TAKE_FOCUS = 1;
|
|
else if (protocols[i] == w_global.atom.wm.delete_window)
|
|
prots->DELETE_WINDOW = 1;
|
|
else if (protocols[i] == w_global.atom.wm.save_yourself)
|
|
prots->SAVE_YOURSELF = 1;
|
|
else if (protocols[i] == w_global.atom.gnustep.wm_miniaturize_window)
|
|
prots->MINIATURIZE_WINDOW = 1;
|
|
}
|
|
XFree(protocols);
|
|
}
|
|
|
|
unsigned char *PropGetCheckProperty(Window window, Atom hint, Atom type, int format, int count, int *retCount)
|
|
{
|
|
Atom type_ret;
|
|
|
|
if (!dpy)
|
|
return NULL; /* Wayland: no X11 property store */
|
|
int fmt_ret;
|
|
unsigned long nitems_ret;
|
|
unsigned long bytes_after_ret;
|
|
unsigned char *data;
|
|
int tmp;
|
|
|
|
if (count <= 0)
|
|
tmp = 0xffffff;
|
|
else
|
|
tmp = count;
|
|
|
|
if (XGetWindowProperty(dpy, window, hint, 0, tmp, False, type,
|
|
&type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
|
|
(unsigned char **)&data) != Success || !data)
|
|
return NULL;
|
|
|
|
if ((type != AnyPropertyType && type != type_ret)
|
|
|| (count > 0 && nitems_ret != count)
|
|
|| (format != 0 && format != fmt_ret)) {
|
|
XFree(data);
|
|
return NULL;
|
|
}
|
|
|
|
if (retCount)
|
|
*retCount = nitems_ret;
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
void PropSetWMakerProtocols(Window root)
|
|
{
|
|
Atom protocols[3];
|
|
int count = 0;
|
|
|
|
if (!dpy) return; /* Wayland: no X11 root-window WMaker protocols */
|
|
|
|
protocols[count++] = w_global.atom.wmaker.menu;
|
|
protocols[count++] = w_global.atom.wmaker.wm_function;
|
|
protocols[count++] = w_global.atom.wmaker.noticeboard;
|
|
|
|
XChangeProperty(dpy, root, w_global.atom.wmaker.wm_protocols, WA_ATOM,
|
|
32, PropModeReplace, (unsigned char *)protocols, count);
|
|
}
|
|
|
|
void PropSetIconTileHint(WScreen * scr, RImage * image)
|
|
{
|
|
static Atom imageAtom = 0;
|
|
unsigned char *tmp;
|
|
int x, y;
|
|
|
|
if (!dpy) return; /* Wayland: no X11 icon tile hint */
|
|
|
|
if (scr->info_window == None)
|
|
return;
|
|
|
|
if (!imageAtom) {
|
|
/*
|
|
* WIDTH, HEIGHT (16 bits, MSB First)
|
|
* array of R,G,B,A bytes
|
|
*/
|
|
imageAtom = XInternAtom(dpy, "_RGBA_IMAGE", False);
|
|
}
|
|
|
|
tmp = malloc(image->width * image->height * 4 + 4);
|
|
if (!tmp) {
|
|
wwarning("could not allocate memory to set _WINDOWMAKER_ICON_TILE hint");
|
|
return;
|
|
}
|
|
|
|
tmp[0] = image->width >> 8;
|
|
tmp[1] = image->width & 0xff;
|
|
tmp[2] = image->height >> 8;
|
|
tmp[3] = image->height & 0xff;
|
|
|
|
if (image->format == RRGBAFormat) {
|
|
memcpy(&tmp[4], image->data, image->width * image->height * 4);
|
|
} else {
|
|
char *ptr = (char *)(tmp + 4);
|
|
char *src = (char *)image->data;
|
|
|
|
for (y = 0; y < image->height; y++) {
|
|
for (x = 0; x < image->width; x++) {
|
|
*ptr++ = *src++;
|
|
*ptr++ = *src++;
|
|
*ptr++ = *src++;
|
|
*ptr++ = 255;
|
|
}
|
|
}
|
|
}
|
|
|
|
XChangeProperty(dpy, scr->info_window, w_global.atom.wmaker.icon_tile,
|
|
imageAtom, 8, PropModeReplace, tmp, image->width * image->height * 4 + 4);
|
|
wfree(tmp);
|
|
|
|
}
|
|
|
|
Window PropGetClientLeader(Window window)
|
|
{
|
|
Window *win;
|
|
Window leader;
|
|
|
|
win = (Window *) PropGetCheckProperty(window, w_global.atom.wm.client_leader, WA_WINDOW, 32, 1, NULL);
|
|
|
|
if (!win)
|
|
return None;
|
|
|
|
leader = (Window) * win;
|
|
XFree(win);
|
|
|
|
return leader;
|
|
}
|
|
|
|
int PropGetWindowState(Window window)
|
|
{
|
|
long *data;
|
|
long state;
|
|
|
|
data = (long *)PropGetCheckProperty(window, w_global.atom.wm.state,
|
|
w_global.atom.wm.state, 32, 1, NULL);
|
|
|
|
if (!data)
|
|
return -1;
|
|
|
|
state = *data;
|
|
XFree(data);
|
|
|
|
return state;
|
|
}
|
|
|
|
void PropCleanUp(Window root)
|
|
{
|
|
if (!dpy) return; /* Wayland: no X11 root-window atoms to clean up */
|
|
|
|
XDeleteProperty(dpy, root, w_global.atom.wmaker.wm_protocols);
|
|
XDeleteProperty(dpy, root, w_global.atom.wmaker.noticeboard);
|
|
XDeleteProperty(dpy, root, WA_WM_ICON_SIZE);
|
|
}
|