#include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "alloc.h" #include "drawinfo.h" #include "prefs.h" #include "screen.h" #include "client.h" #include "icon.h" #include "version.h" #define ABOUT_STRING(LF) \ " " LF "version "VERSION LF "by Marcus Comstedt" LF \ "" LF " " LF \ "Contributions by Scott Lawrence" LF "" LF \ "and Nicolas Sipieter " LF "" LF " " LF \ "Some small contributions by redsPL" LF "" LF " " LF #ifdef AMIGAOS #include extern struct Library *XLibBase; #endif #ifdef AMIGAOS #define BIN_PREFIX AMIWM_HOME #else #define BIN_PREFIX AMIWM_HOME"/" #endif #define CHECKIT 1 #define CHECKED 2 #define DISABLED 4 char battery_status[128]; extern Display *dpy; extern Cursor wm_curs; extern XContext screen_context, client_context; extern Client *activeclient; extern void select_all_icons(Scrn *i); extern void mod_menuselect(struct module *, int, int, int); extern void setfocus(Window); extern void flushmodules(); extern void wberror(Scrn *, char *); Scrn *mbdclick=NULL, *mbdscr=NULL; static struct ToolItem { struct ToolItem *next; const char *name, *cmd; char hotkey; int level; struct Menu *submenu; } *firsttoolitem=NULL, *lasttoolitem=NULL; static struct Item { struct Item *next; Window win; const char *text; int textlen; char hotkey, flags; struct Menu *menu, *sub; struct module *owner; struct Item *mod_chain; } *activeitem=NULL, *activesubitem=NULL; static struct Menu { struct Menu *next; struct Item *item; Window win, parent; const char *title; int titlelen; int width, height; char flags; struct Item *firstitem, *lastitem; } *activemenu=NULL, *activesubmenu=NULL; #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) { extern char *x_server; #ifdef HAVE_ALLOCA char *line=alloca(strlen(x_server)+strlen(cmd)+28); #else char *line=malloc(strlen(x_server)+strlen(cmd)+28); if(line) { #endif char *dot; sprintf(line, "DISPLAY='%s", x_server); if(!(dot=strrchr(line, '.')) || strchr(dot, ':')) dot=line+strlen(line); sprintf(dot, ".%d' %s &", scr->number, 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 void add_toolitem(const char *n, const char *c, const char *k, int l) { struct ToolItem *ti; if((ti=malloc(sizeof(struct ToolItem)))) { ti->name=n; ti->cmd=c; if(k) ti->hotkey=k[0]; else ti->hotkey=0; ti->level=l; ti->next=NULL; if(lasttoolitem) lasttoolitem->next=ti; else firsttoolitem=ti; lasttoolitem=ti; } } static void menu_layout(struct Menu *menu) { XSetWindowAttributes attr; XWindowAttributes attr2; int w, x, y; struct Item *item; if(menu->win) { XGetWindowAttributes(dpy, menu->win, &attr2); x=attr2.x; y=scr->bh-2; } else { XGetWindowAttributes(dpy, menu->item->win, &attr2); x=attr2.x+attr2.width-scr->hotkeyspace+9; y=attr2.y-2; XGetWindowAttributes(dpy, menu->item->menu->parent, &attr2); x+=attr2.x; y+=attr2.y; } menu->width=menu->height=0; for(item=menu->firstitem; item; item=item->next) { if(item->text) menu->height+=scr->dri.dri_Ascent+scr->dri.dri_Descent+1; else menu->height+=6; #ifdef USE_FONTSETS w=XmbTextEscapement(scr->dri.dri_FontSet, item->text, item->textlen)+2; #else w=XTextWidth(scr->dri.dri_Font, item->text, item->textlen)+2; #endif if(item->hotkey) w+=scr->hotkeyspace; if(item->flags&CHECKIT) w+=scr->checkmarkspace; if(item->sub) w+=scr->subspace; if(w>menu->width) menu->width=w; } menu->width+=6; menu->height+=2; attr.override_redirect=True; attr.background_pixel=scr->dri.dri_Pens[BARBLOCKPEN]; attr.border_pixel=scr->dri.dri_Pens[BARDETAILPEN]; menu->parent=XCreateWindow(dpy, scr->back, x, y, menu->width, menu->height, 1, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel|CWBorderPixel, &attr); XSaveContext(dpy, menu->parent, screen_context, (XPointer)scr); XSelectInput(dpy, menu->parent, ExposureMask); w=1; for(item=menu->firstitem; item; item=item->next) { int h=(item->text? scr->dri.dri_Ascent+scr->dri.dri_Descent+1:6); item->win=XCreateWindow(dpy, menu->parent, 3, w, menu->width-6, h, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr); XSaveContext(dpy, item->win, screen_context, (XPointer)scr); w+=h; XSelectInput(dpy, item->win, ExposureMask|ButtonReleaseMask| EnterWindowMask|LeaveWindowMask); } XMapSubwindows(dpy, menu->parent); } static struct Menu *add_menu(const char *name, char flags) { struct Menu *menu=calloc(1, sizeof(struct Menu)); XSetWindowAttributes attr; int w; if(menu) { attr.override_redirect=True; attr.background_pixel=scr->dri.dri_Pens[BARBLOCKPEN]; #ifdef USE_FONTSETS w=XmbTextEscapement(scr->dri.dri_FontSet, name, menu->titlelen=strlen(name))+8; #else w=XTextWidth(scr->dri.dri_Font, name, menu->titlelen=strlen(name))+8; #endif menu->win=XCreateWindow(dpy, scr->menubarparent, scr->menuleft, 0, w, scr->bh-1, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr); XSaveContext(dpy, menu->win, screen_context, (XPointer)scr); XMapWindow(dpy, menu->win); XSelectInput(dpy, menu->win, ExposureMask|EnterWindowMask|LeaveWindowMask); scr->menuleft+=w+6; menu->flags=flags; menu->title=name; menu->item=NULL; menu->firstitem=menu->lastitem=NULL; menu->next=scr->firstmenu; scr->firstmenu=menu; } return menu; } static struct Item *add_item(struct Menu *m, const char *name, char key, char flags) { struct Item *item=calloc(1, sizeof(struct Item)); if(item) { if(name) { item->text=name; item->textlen=strlen(name); } else item->text=NULL; item->hotkey=key; item->flags=flags; item->menu=m; item->sub=NULL; item->next=NULL; if(m->lastitem) m->lastitem->next=item; else m->firstitem=item; m->lastitem=item; } return item; } static struct Menu *sub_menu(struct Item *i, char flags) { struct Menu *menu=calloc(1, sizeof(struct Menu)); if(menu) { menu->flags=flags; menu->title=NULL; menu->firstitem=menu->lastitem=NULL; menu->next=NULL; menu->item=i; i->sub=menu; } return menu; } void redraw_menu(struct Menu *m, Window w) { int active=(m==activemenu && !(m->flags & DISABLED)); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[active?BARBLOCKPEN: BARDETAILPEN]); XSetBackground(dpy, scr->menubargc, scr->dri.dri_Pens[active?BARDETAILPEN: BARBLOCKPEN]); #ifdef USE_FONTSETS XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, 4, 1+scr->dri.dri_Ascent, m->title, m->titlelen); #else XDrawImageString(dpy, w, scr->menubargc, 4, 1+scr->dri.dri_Ascent, m->title, m->titlelen); #endif } void redraw_item(struct Item *i, Window w) { struct Menu *m=i->menu; int s=scr->dri.dri_Ascent>>1; if((i==activeitem || i==activesubitem) && !(i->flags&DISABLED)) { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARBLOCKPEN]); XSetBackground(dpy, scr->menubargc, scr->dri.dri_Pens[BARDETAILPEN]); } else { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARDETAILPEN]); XSetBackground(dpy, scr->menubargc, scr->dri.dri_Pens[BARBLOCKPEN]); } if(i->text) { #ifdef USE_FONTSETS XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, (i->flags&CHECKIT)?1+scr->checkmarkspace:1, scr->dri.dri_Ascent+1, i->text, i->textlen); #else XDrawImageString(dpy, w, scr->menubargc, (i->flags&CHECKIT)?1+scr->checkmarkspace:1, scr->dri.dri_Ascent+1, i->text, i->textlen); #endif } else { XFillRectangle(dpy, w, scr->menubargc, 2, 2, m->width-10, 2); } if(i->sub) { int x=m->width-6-scr->hotkeyspace-1+8; #ifdef USE_FONTSETS #ifdef HAVE_XUTF8DRAWIMAGESTRING Xutf8DrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, x+scr->dri.dri_Ascent+1, 1+scr->dri.dri_Ascent, "\302\273", 2); #else XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, x+scr->dri.dri_Ascent+1, 1+scr->dri.dri_Ascent, "»", 1); #endif #else XDrawImageString(dpy, w, scr->menubargc, x+scr->dri.dri_Ascent+1, 1+scr->dri.dri_Ascent, "»", 1); #endif } else if(i->hotkey) { int x=m->width-6-scr->hotkeyspace-1+8; XDrawLine(dpy, w, scr->menubargc, x, 1+s, x+s, 1); XDrawLine(dpy, w, scr->menubargc, x+s, 1, x+s+s, 1+s); XDrawLine(dpy, w, scr->menubargc, x+s+s, 1+s, x+s, 1+s+s); XDrawLine(dpy, w, scr->menubargc, x+s, 1+s+s, x, 1+s); #ifdef USE_FONTSETS XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, x+scr->dri.dri_Ascent+1, 1+scr->dri.dri_Ascent, &i->hotkey, 1); #else XDrawImageString(dpy, w, scr->menubargc, x+scr->dri.dri_Ascent+1, 1+scr->dri.dri_Ascent, &i->hotkey, 1); #endif } if(i->flags&CHECKED) { XDrawLine(dpy, w, scr->menubargc, 0, s, s, scr->dri.dri_Ascent); XDrawLine(dpy, w, scr->menubargc, s, scr->dri.dri_Ascent, s+s, 0); } if(i->flags&DISABLED) { XSetStipple(dpy, scr->menubargc, scr->disabled_stipple); XSetFillStyle(dpy, scr->menubargc, FillStippled); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARBLOCKPEN]); XFillRectangle(dpy, w, scr->menubargc, 0, 0, m->width-6, scr->dri.dri_Ascent+scr->dri.dri_Descent+1); XSetFillStyle(dpy, scr->menubargc, FillSolid); } } void createmenubar() { XSetWindowAttributes attr; struct Menu *m, *sm1; // struct Menu *sm2, *sm3; struct ToolItem *ti; GC gc; scr->firstmenu = NULL; attr.override_redirect=True; if (scr->deftitle) { attr.background_pixel=scr->dri.dri_Pens[BARBLOCKPEN]; scr->menubar=XCreateWindow(dpy, scr->back, 0, 0, scr->width, scr->bh, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr); scr->menubarparent=XCreateWindow(dpy, scr->menubar, 0, 0, scr->width, scr->bh-1, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr); attr.background_pixel=scr->dri.dri_Pens[BACKGROUNDPEN]; scr->menubardepth=XCreateWindow(dpy, scr->menubar, scr->width-23, 0, 23, scr->bh, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr); } else { scr->menubar=XCreateWindow(dpy, scr->back, 0, 0, scr->width, scr->bh, 0, 0, InputOnly, CopyFromParent, CWOverrideRedirect, &attr); scr->menubarparent=None; scr->menubardepth=XCreateWindow(dpy, scr->menubar, scr->width-23, 0, 23, scr->bh, 0, 0, InputOnly, CopyFromParent, CWOverrideRedirect, &attr); } XSaveContext(dpy, scr->menubar, screen_context, (XPointer)scr); if (scr->menubarparent) XSaveContext(dpy, scr->menubarparent, screen_context, (XPointer)scr); XSaveContext(dpy, scr->menubardepth, screen_context, (XPointer)scr); scr->disabled_stipple=XCreatePixmap(dpy, scr->back, 6, 2, 1); gc=XCreateGC(dpy, scr->disabled_stipple, 0, NULL); XSetForeground(dpy, gc, 0); XFillRectangle(dpy, scr->disabled_stipple, gc, 0, 0, 6, 2); XSetForeground(dpy, gc, 1); XDrawPoint(dpy, scr->disabled_stipple, gc, 0, 0); XDrawPoint(dpy, scr->disabled_stipple, gc, 3, 1); XFreeGC(dpy, gc); if (scr->deftitle) { scr->menubargc=XCreateGC(dpy, scr->menubar, 0, NULL); #ifndef USE_FONTSETS XSetFont(dpy, scr->menubargc, scr->dri.dri_Font->fid); #endif XSetBackground(dpy, scr->menubargc, scr->dri.dri_Pens[BARBLOCKPEN]); } else { scr->menubargc = NULL; } XSelectInput(dpy, scr->menubar, ExposureMask|ButtonPressMask|ButtonReleaseMask); XSelectInput(dpy, scr->menubardepth, ExposureMask|ButtonPressMask| ButtonReleaseMask|EnterWindowMask|LeaveWindowMask); XMapWindow(dpy, scr->menubardepth); XMapWindow(dpy, scr->menubar); scr->hotkeyspace=8+1+scr->dri.dri_MaxBoundsWidth+ scr->dri.dri_Ascent; scr->checkmarkspace=4+scr->dri.dri_Ascent; scr->subspace=scr->hotkeyspace-scr->dri.dri_Ascent; scr->menuleft=4; if (!scr->menubarparent) return; m=add_menu("Workbench", 0); //add_item(m,"Backdrop",'B',CHECKIT|CHECKED|DISABLED); add_item(m,"Execute Command...",'E',0); add_item(m,"Configuration",'C',0); add_item(m,"Redraw All",0,0); //add_item(m,"Update All",0,DISABLED); //add_item(m,"Last Message",0,DISABLED); add_item(m,NULL,0,DISABLED); add_item(m,"About...",'?',0); add_item(m,"Quit...",'Q',0); menu_layout(m); /*m=add_menu("Window", 0); add_item(m,"New Drawer",'N',DISABLED); add_item(m,"Open Parent",0,DISABLED); add_item(m,"Close",'K',DISABLED); add_item(m,"Update",0,DISABLED); add_item(m,"Select Contents",'A',0); add_item(m,"Clean Up",'.',0); sm1=sub_menu(add_item(m,"Snapshot",0,DISABLED),0); add_item(sm1, "Window",0,DISABLED); add_item(sm1, "All",0,DISABLED); sm2=sub_menu(add_item(m,"Show",0,DISABLED),0); add_item(sm2, "Only Icons",0,CHECKIT|CHECKED|DISABLED); add_item(sm2, "All Files",'V',CHECKIT|DISABLED); sm3=sub_menu(add_item(m,"View By",0,DISABLED),0); add_item(sm3, "Icon",0,CHECKIT|CHECKED|DISABLED); add_item(sm3, "Name",0,CHECKIT|DISABLED); add_item(sm3, "Date",0,CHECKIT|DISABLED); add_item(sm3, "Size",0,CHECKIT|DISABLED); menu_layout(m); menu_layout(sm1); menu_layout(sm2); menu_layout(sm3);*/ /*m=add_menu("Icons", DISABLED); add_item(m,"Open",'O',DISABLED); add_item(m,"Copy",'C',DISABLED); add_item(m,"Rename...",'R',DISABLED); add_item(m,"Information...",'I',DISABLED); add_item(m,"Snapshot",'S',DISABLED); add_item(m,"UnSnapshot",'U',DISABLED); add_item(m,"Leave Out",'L',DISABLED); add_item(m,"Put Away",'P',DISABLED); add_item(m,NULL,0,DISABLED); add_item(m,"Delete...",'D',DISABLED); add_item(m,"Format Disk...",0,DISABLED); add_item(m,"Empty Trash",0,DISABLED); menu_layout(m);*/ m=add_menu("Tools", 0); #ifdef AMIGAOS add_item(m,"ResetWB",0,DISABLED); #else add_item(m,"ResetWB",0,0); #endif for(ti=firsttoolitem; ti; ti=ti->next) if(ti->level<0) ti->submenu=sm1=sub_menu(add_item(m,ti->name,ti->hotkey,0),0); else { ti->submenu=NULL; add_item((ti->level? sm1:m), ti->name,ti->hotkey,(ti->cmd? 0:DISABLED)); } menu_layout(m); for(ti=firsttoolitem; ti; ti=ti->next) if(ti->submenu) { menu_layout(ti->submenu); ti->submenu=NULL; } if(prefs.screenmenu) { m=add_menu("Screens",0); add_item(m,"New Screen",0,0); add_item(m,"Delete Screen",0,0); menu_layout(m); } } /* * Redraw the menu bar and its components. * * This takes in the target window, which may be the basic menubar, * a clicked-on menu, or the depth widget. */ void redrawmenubar(Scrn *scr, Window w) { static const char defaultTimeFormat[] = "%c"; int widget_rhs; struct Menu *m; struct Item *item; if(!w || !scr->menubargc) return; if(w==scr->menubar) { /* Menubar itself */ XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARDETAILPEN]); XSetBackground(dpy, scr->menubargc, scr->dri.dri_Pens[BARBLOCKPEN]); #ifdef USE_FONTSETS XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, 4, 1+scr->dri.dri_Ascent, scr->title, strlen(scr->title)); #else XDrawImageString(dpy, w, scr->menubargc, 4, 1+scr->dri.dri_Ascent, scr->title, strlen(scr->title)); #endif XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARTRIMPEN]); XDrawLine(dpy, w, scr->menubargc, 0, scr->bh-1, scr->width-1, scr->bh-1); /* Widgets start here and move to the left */ widget_rhs = (scr->width - 30); /* * Update the title bar clock if it's enabled. */ if( prefs.titlebarclock ) { char clockbuf[512]; const char * fmt = defaultTimeFormat; time_t the_time; int l; if( prefs.titleclockformat ) fmt = prefs.titleclockformat; time( &the_time ); strftime( clockbuf, 512, fmt, localtime( &the_time ) ); #ifdef USE_FONTSETS l = XmbTextEscapement(scr->dri.dri_FontSet, clockbuf, strlen(clockbuf)); XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, widget_rhs - l, 1+scr->dri.dri_Ascent, clockbuf, strlen(clockbuf)); #else l = XTextWidth(scr->dri.dri_Font, clockbuf, strlen(clockbuf)); XDrawImageString( dpy, w, scr->menubargc, widget_rhs - l, 1+scr->dri.dri_Ascent, clockbuf, strlen(clockbuf)); #endif widget_rhs = widget_rhs - l - 8; // 8 = padding } /* * Update the battery indicator if it's enabled. */ if (prefs.battery_info) { char battery_buf[512]; int l; sprintf(battery_buf, "| %s |", battery_status); #ifdef USE_FONTSETS l = XmbTextEscapement(scr->dri.dri_FontSet, battery_buf, strlen(battery_buf)); XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->menubargc, widget_rhs - l, 1+scr->dri.dri_Ascent, battery_buf, strlen(battery_buf)); #else l = XTextWidth(scr->dri.dri_Font, battery_buf, strlen(battery_buf)); XDrawImageString( dpy, w, scr->menubargc, widget_rhs - l, 1+scr->dri.dri_Ascent, battery_buf, strlen(battery_buf)); #endif widget_rhs = widget_rhs - l - 8; // 8 = padding } } else if(w==scr->menubardepth) { /* Menubar depth widget */ if(!mbdclick) { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); } XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHINEPEN]); XFillRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XDrawRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4); if(mbdclick) XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?SHADOWPEN:SHINEPEN]); XDrawLine(dpy, w, scr->menubargc, 0, 0, 22, 0); XDrawLine(dpy, w, scr->menubargc, 0, 0, 0, scr->bh-2); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?SHINEPEN:SHADOWPEN]); XDrawLine(dpy, w, scr->menubargc, 0, scr->bh-1, 22, scr->bh-1); XDrawLine(dpy, w, scr->menubargc, 22, 0, 22, scr->bh-1); } else { /* One of the menus is being displayed */ for(m=scr->firstmenu; m; m=m->next) if(m->win==w) redraw_menu(m, w); if(activemenu) { for(item=activemenu->firstitem; item; item=item->next) if(item->win==w) redraw_item(item, w); if(w==activemenu->parent) { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARDETAILPEN]); XDrawLine(dpy, w, scr->menubargc, 0, 0, 0, activemenu->height-1); XDrawLine(dpy, w, scr->menubargc, activemenu->width-1, 0, activemenu->width-1, activemenu->height-1); } } if(activesubmenu) { for(item=activesubmenu->firstitem; item; item=item->next) if(item->win==w) redraw_item(item, w); if(w==activesubmenu->parent) { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[BARDETAILPEN]); XDrawLine(dpy, w, scr->menubargc, 0, 0, 0, activesubmenu->height-1); XDrawLine(dpy, w, scr->menubargc, activesubmenu->width-1, 0, activesubmenu->width-1, activesubmenu->height-1); } } } } static void leave_item(struct Item *i, Window w) { if(i==activesubitem) activesubitem=NULL; if(i==activeitem) { if(activesubmenu && i->sub==activesubmenu) { return; } else { activeitem=NULL; } } XSetWindowBackground(dpy, i->win, scr->dri.dri_Pens[BARBLOCKPEN]); XClearWindow(dpy, i->win); redraw_item(i, i->win); } static void enter_item(struct Item *i, Window w) { if(activesubitem) leave_item(activesubitem, activesubitem->win); if(activesubmenu!=i->sub && i->menu!=activesubmenu) { if(activesubmenu) XUnmapWindow(dpy, activesubmenu->parent); if(i->sub) XMapRaised(dpy, i->sub->parent); activesubmenu=i->sub; } if(activeitem && !(activeitem->sub && i->menu==activeitem->sub)) leave_item(activeitem, activeitem->win); if(!(i->flags&DISABLED)) { if(activeitem) activesubitem=i; else activeitem=i; XSetWindowBackground(dpy, i->win, scr->dri.dri_Pens[BARDETAILPEN]); XClearWindow(dpy, i->win); redraw_item(i, i->win); } } static void enter_menu(struct Menu *m, Window w) { if(m!=activemenu) { struct Menu *oa=activemenu; if(activesubitem) leave_item(activeitem, activesubitem->win); if(activesubmenu) { XUnmapWindow(dpy, activesubmenu->parent); activesubmenu=NULL; } if(activeitem) leave_item(activeitem, activeitem->win); if(!(m->flags & DISABLED)) XSetWindowBackground(dpy, w, scr->dri.dri_Pens[BARDETAILPEN]); XClearWindow(dpy, w); redraw_menu(activemenu=m, w); if(m->parent) XMapRaised(dpy, m->parent); if(oa) { if(oa->parent) XUnmapWindow(dpy, oa->parent); XSetWindowBackground(dpy, oa->win, scr->dri.dri_Pens[BARBLOCKPEN]); XClearWindow(dpy, oa->win); redraw_menu(oa, oa->win); } } } void menubar_enter(Window w) { struct Menu *m; struct Item *i; for(m=scr->firstmenu; m; m=m->next) if(m->win==w) { enter_menu(m, w); return; } if((m=activemenu)) for(i=m->firstitem; i; i=i->next) if(w==i->win) { enter_item(i, w); return; } if((m=activesubmenu)) for(i=m->firstitem; i; i=i->next) if(w==i->win) { enter_item(i, w); return; } } void menubar_leave(Window w) { if(activesubitem && activesubitem->win==w) leave_item(activesubitem, w); if(activeitem && activeitem->win==w) leave_item(activeitem, w); } void menu_on() { Window r, c; int rx, ry, x, y; unsigned int m; if(scr->menubarparent) { XMapRaised(dpy, scr->menubarparent); XRaiseWindow(dpy, scr->menubar); XGrabPointer(dpy, scr->back, True, ButtonPressMask|ButtonReleaseMask| EnterWindowMask|LeaveWindowMask, GrabModeAsync, GrabModeAsync, scr->back, wm_curs, CurrentTime); XSetInputFocus(dpy, scr->menubar, RevertToParent, CurrentTime); if(XQueryPointer(dpy, scr->menubarparent, &r, &c, &rx, &ry, &x, &y, &m)) menubar_enter(c); } } void menuaction(struct Item *i, struct Item *si) { extern void restart_amiwm(void); extern int screen_has_clients(void); struct Menu *m; struct Item *mi; struct ToolItem *ti; int menu=0, item=0, sub=0; for(m=i->menu->next; m; m=m->next) menu++; for(mi=i->menu->firstitem; mi&&mi!=i; mi=mi->next) item++; if(i->sub) { for(mi=i->sub->firstitem; mi&&mi!=si; mi=mi->next) sub++; if(!mi) sub=-1; } else --sub; mi=(sub>=0? si:i); if(mi->flags & DISABLED) return; if(mi->owner) { mod_menuselect(mi->owner, menu, item, sub); return; } switch(menu) { case 0: /* Workbench */ switch(item) { case 0: spawn(BIN_PREFIX"executecmd"); break; case 1: spawn(BIN_PREFIX"config_util"); case 2: { XSetWindowAttributes xswa; unsigned long mask; Window win; xswa.background_pixmap = None; xswa.override_redirect = True; xswa.backing_store = NotUseful; xswa.save_under = False; mask = CWBackPixmap|CWOverrideRedirect|CWBackingStore|CWSaveUnder; win = XCreateWindow(dpy, scr->back, 0, 0, scr->width, scr->height, 0, scr->depth, InputOutput, scr->visual, mask, &xswa); XMapWindow(dpy, win); XDestroyWindow(dpy, win); } break; case 4: #ifdef AMIGAOS spawn(BIN_PREFIX"requestchoice >NIL: amiwm \"" ABOUT_STRING("*N") "\" Ok"); #else spawn(BIN_PREFIX"requestchoice >/dev/null amiwm '" ABOUT_STRING("\n") "' Ok"); #endif break; case 5: #ifndef AMIGAOS if(prefs.fastquit) { #endif exit(0); #ifndef AMIGAOS } else { #ifdef HAVE_ALLOCA char *buf=alloca(256); #else char buf[256]; #endif sprintf(buf, "; export DISPLAY; ( if [ `"BIN_PREFIX"requestchoice " "Workbench 'Do you really want\nto quit workbench?' Ok Cancel`" " = 1 ]; then kill %d; fi; )", (int)getpid()); spawn(buf); } #endif break; } break; /* case 1: // Window switch(item) { case 4: select_all_icons(scr); break; case 5: cleanupicons(); break; } break; */ // case 2: /* Icons */ // break; case 1: /* Tools */ #ifndef AMIGAOS if(item==0) restart_amiwm(); #endif if(item>0) { int it=0, si=-1; for(ti=firsttoolitem; ti; ti=ti->next) { if(ti->level>0) si++; else { it++; si=-1; } if(it==item && si==sub) break; } if(ti && ti->cmd) spawn(ti->cmd); } break; case 2: /* Screens */ if(item==0) { openscreen("New Screen", DefaultRootWindow(dpy)); realizescreens(); scr = get_front_scr()->upfront; screentoback(); } if(item==1) { if(scr->behind == scr) wberror(scr,"Cannot close last Screen"); else if(screen_has_clients()) wberror(scr,"Can't close a screen with running programs on it"); else closescreen(); } break; } } void menu_off() { struct Menu *oa; struct Item *oi, *osi; if(scr->menubarparent) { Window r,p,*children; unsigned int nchildren; XUngrabPointer(dpy, CurrentTime); setfocus((activeclient && activeclient->state==NormalState? activeclient->window:None)); XUnmapWindow(dpy, scr->menubarparent); if(XQueryTree(dpy, scr->back, &r, &p, &children, &nchildren)) { int n; Client *c2; for(n=0; nparent) break; if(nmenubar; XRestackWindows(dpy, ws, 2); } if(children) XFree(children); } } if((osi=activesubitem)) leave_item(osi, osi->win); if((oi=activeitem)) leave_item(oi, oi->win); if((oa=activesubmenu)) { activesubmenu=NULL; if(oa->parent) XUnmapWindow(dpy, oa->parent); } if((oa=activemenu)) { activemenu=NULL; if(oa->parent) XUnmapWindow(dpy, oa->parent); XSetWindowBackground(dpy, oa->win, scr->dri.dri_Pens[BARBLOCKPEN]); XClearWindow(dpy, oa->win); redraw_menu(oa, oa->win); } if(oi) { XSync(dpy, False); menuaction(oi, osi); } } struct Item *getitembyhotkey(KeySym key) { struct Menu *m; struct Item *i; if(key) { if(key>='a' && key<='z') key-=0x20; for(m=scr->firstmenu; m; m=m->next) for(i=m->firstitem; i; i=i->next) if(i->hotkey==key) return i; } return NULL; } static struct Item *own_item(struct module *m, struct Item *i, struct Item *c) { if(i->owner) return NULL; i->owner = m; i->mod_chain = c; i->flags &= ~DISABLED; redraw_item(i, i->win); return i; } void disown_item_chain(struct module *m, struct Item *i) { while(i) if(i->owner == m) { struct Item *c = i->mod_chain; i->owner = NULL; i->mod_chain = NULL; i->flags |= DISABLED; redraw_item(i, i->win); i = c; } else i=i->mod_chain; } struct Item *own_items(struct module *m, Scrn *s, int menu, int item, int sub, struct Item *c) { struct Item *cl, *chain = NULL, *endlink = NULL; int m0, m1, mn; struct Menu *mm; if(!s) return NULL; if(menu<0) { m0 = 0; m1 = 65535; } else m0 = m1 = menu; for(mn=0, mm=s->firstmenu; mm && mn <= m1; mm=mm->next, mn++) if(mn>=m0) { int i0, i1, in; struct Item *ii; if(item<0) { i0 = 0; i1 = 65535; } else i0 = i1 = item; for(in=0, ii=mm->firstitem; ii && in <= i1; ii=ii->next, in++) if(in>=i0) { int s0, s1, sn; struct Item *ss; if(!(cl=own_item(m, ii, chain))) { disown_item_chain(m, chain); return NULL; } else chain=cl; if(!endlink) endlink=chain; if(ii->sub) { if(sub<0) { s0 = 0; s1 = 65535; } else s0 = s1 = sub; for(sn=0, ss=ii->sub->firstitem; ss && sn <= i1; ss=ss->next, sn++) if(sn>=s0) { if(!(cl=own_item(m, ss, chain))) { disown_item_chain(m, chain); return NULL; } else chain=cl; } } } } if(endlink) endlink->next = c; return chain; }