mirror of
https://github.com/amiwm/amiwm.git
synced 2026-03-24 01:24:15 +00:00
250 lines
5.3 KiB
C
250 lines
5.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include "libami.h"
|
|
#include "drawinfo.h"
|
|
|
|
char *progname;
|
|
|
|
Display *dpy;
|
|
XContext launchercontext;
|
|
struct DrawInfo dri;
|
|
Atom appiconmsg;
|
|
char *icondir;
|
|
|
|
struct launcher {
|
|
struct ColorStore colorstore1, colorstore2;
|
|
char cmdline[1];
|
|
};
|
|
|
|
#ifdef AMIGAOS
|
|
void spawn(const char *cmd)
|
|
{
|
|
char *line=malloc(strlen(cmd)+12);
|
|
if(line) {
|
|
sprintf(line, "RUN <>NIL: %s", cmd);
|
|
system(line);
|
|
free(line);
|
|
}
|
|
}
|
|
#else
|
|
void spawn(const char *cmd)
|
|
{
|
|
#ifdef HAVE_ALLOCA
|
|
char *line=alloca(strlen(cmd)+4);
|
|
#else
|
|
char *line=malloc(strlen(cmd)+4);
|
|
if(line) {
|
|
#endif
|
|
sprintf(line, "%s &", cmd);
|
|
#ifdef __ultrix
|
|
{
|
|
int pid, status;
|
|
if ((pid = fork ()) == 0) {
|
|
(void) setsid();
|
|
execl ("/bin/sh", "sh", "-c", line, 0);
|
|
} else
|
|
waitpid (pid, &status, 0);
|
|
}
|
|
#else
|
|
system(line);
|
|
#endif
|
|
#ifndef HAVE_ALLOCA
|
|
free(line);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
static void broker_cb(XEvent *evt, unsigned long mask)
|
|
{
|
|
XPointer ret;
|
|
|
|
if(evt->type != ClientMessage || evt->xclient.message_type != appiconmsg)
|
|
return;
|
|
|
|
if(!XFindContext(dpy, evt->xclient.window, launchercontext, &ret)) {
|
|
struct launcher *l = (struct launcher*)ret;
|
|
spawn(l->cmdline);
|
|
}
|
|
}
|
|
|
|
static void create_broker()
|
|
{
|
|
cx_broker(0, broker_cb);
|
|
}
|
|
|
|
static void create_launcher(char *label, char *icon, char *cmdline)
|
|
{
|
|
struct DiskObject *icon_do = NULL;
|
|
Pixmap icon_icon1, icon_icon2;
|
|
Window win;
|
|
|
|
struct launcher *l = malloc(sizeof(struct launcher)+strlen(cmdline));
|
|
if (l == NULL) {
|
|
fprintf(stderr, "%s: out of memory!\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
memset(l, 0, sizeof(*l));
|
|
strcpy(l->cmdline, cmdline);
|
|
|
|
if (icon != NULL && *icon != 0) {
|
|
#ifdef AMIGAOS
|
|
char fn[256];
|
|
strncpy(fn, icondir, sizeof(fn)-1);
|
|
fn[sizeof(fn)-1]='\0';
|
|
AddPart(fn,icon,sizeof(fn));
|
|
#else
|
|
int rl=strlen(icon)+strlen(icondir)+2;
|
|
#ifdef HAVE_ALLOCA
|
|
char *fn=alloca(rl);
|
|
#else
|
|
char fn[1024];
|
|
#endif
|
|
sprintf(fn, "%s/%s", icondir, icon);
|
|
#endif
|
|
fn[strlen(fn)-5]=0;
|
|
icon_do = GetDiskObject(fn);
|
|
}
|
|
|
|
if(icon_do == NULL)
|
|
icon_do = GetDefDiskObject(3/*WBTOOL*/);
|
|
|
|
if(icon_do == NULL) {
|
|
md_errormsg(md_root, "Failed to load icon");
|
|
md_exit(0);
|
|
}
|
|
|
|
icon_icon1 =
|
|
md_image_to_pixmap(md_root, dri.dri_Pens[BACKGROUNDPEN],
|
|
(struct Image *)icon_do->do_Gadget.GadgetRender,
|
|
icon_do->do_Gadget.Width, icon_do->do_Gadget.Height,
|
|
&l->colorstore1);
|
|
|
|
icon_icon2 =
|
|
md_image_to_pixmap(md_root, dri.dri_Pens[BACKGROUNDPEN],
|
|
(struct Image *)icon_do->do_Gadget.SelectRender,
|
|
icon_do->do_Gadget.Width, icon_do->do_Gadget.Height,
|
|
&l->colorstore2);
|
|
|
|
FreeDiskObject(icon_do);
|
|
XSync(dpy, False);
|
|
win = md_create_appicon(md_root, 0x80000000, 0x80000000,
|
|
label, icon_icon1, icon_icon2, None);
|
|
XSaveContext(dpy, win, launchercontext, (XPointer)l);
|
|
}
|
|
|
|
static int skip_ws(char *arg, int len)
|
|
{
|
|
int n = 0;
|
|
while(len > 0 && isspace(*(unsigned char *)arg)) { n++; arg++; --len; }
|
|
return n;
|
|
}
|
|
|
|
static int get_string(char *arg, int len, int lineno)
|
|
{
|
|
int n;
|
|
if (len < 1 || *arg != '(') {
|
|
fprintf(stderr, "%s: missing '(' on line %d\n", progname, lineno);
|
|
return 0;
|
|
}
|
|
for (n=1; n<len; n++)
|
|
if (arg[n] == ')')
|
|
break;
|
|
if (n >= len) {
|
|
fprintf(stderr, "%s: missing ')' on line %d\n", progname, lineno);
|
|
return 0;
|
|
}
|
|
return n+1;
|
|
}
|
|
|
|
static char *create_string(char *arg, int l)
|
|
{
|
|
char *p = malloc(l+1);
|
|
if (!p) {
|
|
fprintf(stderr, "%s: out of memory!\n", progname);
|
|
exit(1);
|
|
}
|
|
if(l>0) memcpy(p, arg, l);
|
|
p[l] = 0;
|
|
return p;
|
|
}
|
|
|
|
static void create_appicons_line(char *arg, int len, int lineno)
|
|
{
|
|
int l;
|
|
char *label, *icon, *cmdline;
|
|
if (*arg == '#')
|
|
return;
|
|
l = skip_ws(arg, len);
|
|
arg += l; len -= l;
|
|
if (!len) return;
|
|
l = get_string(arg, len, lineno);
|
|
if (!l) return;
|
|
label = create_string(arg+1, l-2);
|
|
arg += l; len -= l;
|
|
l = skip_ws(arg, len);
|
|
arg += l; len -= l;
|
|
l = get_string(arg, len, lineno);
|
|
if (!l) { free(label); return; }
|
|
icon = create_string(arg+1, l-2);
|
|
arg += l; len -= l;
|
|
l = skip_ws(arg, len);
|
|
arg += l; len -= l;
|
|
l = get_string(arg, len, lineno);
|
|
if (!l) { free(icon); free(label); return; }
|
|
cmdline = create_string(arg+1, l-2);
|
|
arg += l; len -= l;
|
|
l = skip_ws(arg, len);
|
|
arg += l; len -= l;
|
|
if (len) fprintf(stderr, "%s: junk at end of line %d\n", progname, lineno);
|
|
create_launcher(label, icon, cmdline);
|
|
free(cmdline);
|
|
free(icon);
|
|
free(label);
|
|
}
|
|
|
|
static void create_appicons(char *arg)
|
|
{
|
|
char *p;
|
|
int l = 1;
|
|
while((p = strchr(arg, '\n'))) {
|
|
create_appicons_line(arg, p-arg, l++);
|
|
arg = p+1;
|
|
}
|
|
create_appicons_line(arg, strlen(arg), l);
|
|
}
|
|
|
|
static void setup()
|
|
{
|
|
XWindowAttributes attr;
|
|
launchercontext = XUniqueContext();
|
|
XGetWindowAttributes(dpy, md_root, &attr);
|
|
init_dri(&dri, dpy, md_root, attr.colormap, False);
|
|
appiconmsg = XInternAtom(dpy, "AMIWM_APPICONMSG", False);
|
|
icondir = get_current_icondir();
|
|
if(!icondir) icondir="";
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *arg=md_init(argc, argv);
|
|
progname=argv[0];
|
|
|
|
if(!(dpy = md_display())) {
|
|
fprintf(stderr, "%s: cannot connect to X server %s\n", progname,
|
|
XDisplayName(NULL));
|
|
exit(1);
|
|
}
|
|
if(arg) {
|
|
setup();
|
|
create_broker();
|
|
create_appicons(arg);
|
|
md_main_loop();
|
|
}
|
|
return 0;
|
|
}
|