support moving window between heads using keyboard
[wmaker-crm.git] / src / dialog.c
blob1a24fc864cb0a208dd6401b324e63b77d9ba7ce6
1 /* dialog.c - dialog windows for internal use
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
7 * Copyright (c) 2014 Window Maker Team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/keysym.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <dirent.h>
37 #include <limits.h>
38 #include <errno.h>
40 #ifdef HAVE_MALLOC_H
41 #include <malloc.h>
42 #endif
44 #include <signal.h>
45 #ifdef __FreeBSD__
46 #include <sys/signal.h>
47 #endif
49 #ifndef PATH_MAX
50 #define PATH_MAX DEFAULT_PATH_MAX
51 #endif
53 #include "WindowMaker.h"
54 #include "GNUstep.h"
55 #include "screen.h"
56 #include "window.h"
57 #include "dialog.h"
58 #include "misc.h"
59 #include "stacking.h"
60 #include "framewin.h"
61 #include "window.h"
62 #include "actions.h"
63 #include "xinerama.h"
66 static WMPoint getCenter(WScreen * scr, int width, int height)
68 return wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), width, height);
71 int wMessageDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
73 WMAlertPanel *panel;
74 Window parent;
75 WWindow *wwin;
76 int result;
77 WMPoint center;
79 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
81 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
83 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
85 center = getCenter(scr, 400, 180);
86 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
87 wwin->client_leader = WMWidgetXID(panel->win);
89 WMMapWidget(panel->win);
91 wWindowMap(wwin);
93 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
95 result = panel->result;
97 WMUnmapWidget(panel->win);
99 wUnmanageWindow(wwin, False, False);
101 WMDestroyAlertPanel(panel);
103 XDestroyWindow(dpy, parent);
105 return result;
108 static void toggleSaveSession(WMWidget *w, void *data)
110 /* Parameter not used, but tell the compiler that it is ok */
111 (void) data;
113 wPreferences.save_session_on_exit = WMGetButtonSelected((WMButton *) w);
116 int wExitDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
118 WMAlertPanel *panel;
119 WMButton *saveSessionBtn;
120 Window parent;
121 WWindow *wwin;
122 WMPoint center;
123 int result;
125 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
127 /* add save session button */
128 saveSessionBtn = WMCreateSwitchButton(panel->hbox);
129 WMSetButtonAction(saveSessionBtn, toggleSaveSession, NULL);
130 WMAddBoxSubview(panel->hbox, WMWidgetView(saveSessionBtn), False, True, 200, 0, 0);
131 WMSetButtonText(saveSessionBtn, _("Save workspace state"));
132 WMSetButtonSelected(saveSessionBtn, wPreferences.save_session_on_exit);
133 WMRealizeWidget(saveSessionBtn);
134 WMMapWidget(saveSessionBtn);
136 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
138 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
140 center = getCenter(scr, 400, 180);
141 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
143 wwin->client_leader = WMWidgetXID(panel->win);
145 WMMapWidget(panel->win);
147 wWindowMap(wwin);
149 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
151 result = panel->result;
153 WMUnmapWidget(panel->win);
155 wUnmanageWindow(wwin, False, False);
157 WMDestroyAlertPanel(panel);
159 XDestroyWindow(dpy, parent);
161 return result;
164 typedef struct _WMInputPanelWithHistory {
165 WMInputPanel *panel;
166 WMArray *history;
167 int histpos;
168 char *prefix;
169 char *suffix;
170 char *rest;
171 WMArray *variants;
172 int varpos;
173 } WMInputPanelWithHistory;
175 static char *HistoryFileName(const char *name)
177 char *filename = NULL;
179 filename = wstrdup(wusergnusteppath());
180 filename = wstrappend(filename, "/.AppInfo/WindowMaker/History");
181 if (name && strlen(name)) {
182 filename = wstrappend(filename, ".");
183 filename = wstrappend(filename, name);
185 return filename;
188 static int strmatch(const void *str1, const void *str2)
190 return !strcmp((const char *)str1, (const char *)str2);
193 static WMArray *LoadHistory(const char *filename, int max)
195 WMPropList *plhistory;
196 WMPropList *plitem;
197 WMArray *history;
198 int i, num;
199 char *str;
201 history = WMCreateArrayWithDestructor(1, wfree);
202 WMAddToArray(history, wstrdup(""));
204 plhistory = WMReadPropListFromFile(filename);
206 if (plhistory) {
207 if (WMIsPLArray(plhistory)) {
208 num = WMGetPropListItemCount(plhistory);
210 for (i = 0; i < num; ++i) {
211 plitem = WMGetFromPLArray(plhistory, i);
212 if (WMIsPLString(plitem)) {
213 str = WMGetFromPLString(plitem);
214 if (WMFindInArray(history, strmatch, str) == WANotFound) {
216 * The string here is duplicated because it will be freed
217 * automatically when the array is deleted. This is not really
218 * great because it is already an allocated string,
219 * unfortunately we cannot re-use it because it will be freed
220 * when we discard the PL (and we don't want to waste the PL's
221 * memory either)
223 WMAddToArray(history, wstrdup(str));
224 if (--max <= 0)
225 break;
230 WMReleasePropList(plhistory);
233 return history;
236 static void SaveHistory(WMArray * history, const char *filename)
238 int i;
239 WMPropList *plhistory;
241 plhistory = WMCreatePLArray(NULL);
243 for (i = 0; i < WMGetArrayItemCount(history); ++i)
244 WMAddToPLArray(plhistory, WMCreatePLString(WMGetFromArray(history, i)));
246 WMWritePropListToFile(plhistory, filename);
247 WMReleasePropList(plhistory);
250 static int pstrcmp(const char **str1, const char **str2)
252 return strcmp(*str1, *str2);
255 static void
256 ScanFiles(const char *dir, const char *prefix, unsigned acceptmask, unsigned declinemask, WMArray * result)
258 int prefixlen;
259 DIR *d;
260 struct dirent *de;
261 struct stat sb;
262 char *fullfilename, *suffix;
264 prefixlen = strlen(prefix);
265 d = opendir(dir);
266 if (d != NULL) {
267 while ((de = readdir(d)) != NULL) {
268 if (strlen(de->d_name) > prefixlen &&
269 !strncmp(prefix, de->d_name, prefixlen) &&
270 strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..")) {
271 fullfilename = wstrconcat((char *)dir, "/");
272 fullfilename = wstrappend(fullfilename, de->d_name);
274 if (stat(fullfilename, &sb) == 0 &&
275 (sb.st_mode & acceptmask) &&
276 !(sb.st_mode & declinemask) &&
277 WMFindInArray(result, (WMMatchDataProc *) strmatch,
278 de->d_name + prefixlen) == WANotFound) {
279 suffix = wstrdup(de->d_name + prefixlen);
280 if (sb.st_mode & S_IFDIR)
281 suffix = wstrappend(suffix, "/");
282 WMAddToArray(result, suffix);
284 wfree(fullfilename);
287 closedir(d);
291 static WMArray *GenerateVariants(const char *complete)
293 Bool firstWord = True;
294 WMArray *variants = NULL;
295 char *pos = NULL, *path = NULL, *tmp = NULL, *dir = NULL, *prefix = NULL;
297 variants = WMCreateArrayWithDestructor(0, wfree);
299 while (*complete == ' ')
300 ++complete;
302 pos = strrchr(complete, ' ');
303 if (pos != NULL) {
304 complete = pos + 1;
305 firstWord = False;
308 pos = strrchr(complete, '/');
309 if (pos != NULL) {
310 tmp = wstrndup((char *)complete, pos - complete + 1);
311 if (*tmp == '~' && *(tmp + 1) == '/' && getenv("HOME")) {
312 dir = wstrdup(getenv("HOME"));
313 dir = wstrappend(dir, tmp + 1);
314 wfree(tmp);
315 } else {
316 dir = tmp;
318 prefix = wstrdup(pos + 1);
319 ScanFiles(dir, prefix, (unsigned)-1, 0, variants);
320 wfree(dir);
321 wfree(prefix);
322 } else if (*complete == '~') {
323 WMAddToArray(variants, wstrdup("/"));
324 } else if (firstWord) {
325 path = getenv("PATH");
326 while (path) {
327 pos = strchr(path, ':');
328 if (pos) {
329 tmp = wstrndup(path, pos - path);
330 path = pos + 1;
331 } else if (*path != '\0') {
332 tmp = wstrdup(path);
333 path = NULL;
334 } else
335 break;
336 ScanFiles(tmp, complete, S_IXOTH | S_IXGRP | S_IXUSR, S_IFDIR, variants);
337 wfree(tmp);
341 WMSortArray(variants, (WMCompareDataProc *) pstrcmp);
342 return variants;
345 static void handleHistoryKeyPress(XEvent * event, void *clientData)
347 char *text;
348 unsigned pos;
349 WMInputPanelWithHistory *p = (WMInputPanelWithHistory *) clientData;
350 KeySym ksym;
352 ksym = XLookupKeysym(&event->xkey, 0);
354 switch (ksym) {
355 case XK_Up:
356 if (p->histpos < WMGetArrayItemCount(p->history) - 1) {
357 if (p->histpos == 0)
358 wfree(WMReplaceInArray(p->history, 0, WMGetTextFieldText(p->panel->text)));
359 p->histpos++;
360 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
362 break;
363 case XK_Down:
364 if (p->histpos > 0) {
365 p->histpos--;
366 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
368 break;
369 case XK_Tab:
370 if (!p->variants) {
371 text = WMGetTextFieldText(p->panel->text);
372 pos = WMGetTextFieldCursorPosition(p->panel->text);
373 p->prefix = wstrndup(text, pos);
374 p->suffix = wstrdup(text + pos);
375 wfree(text);
376 p->variants = GenerateVariants(p->prefix);
377 p->varpos = 0;
378 if (!p->variants) {
379 wfree(p->prefix);
380 wfree(p->suffix);
381 p->prefix = NULL;
382 p->suffix = NULL;
385 if (p->variants && p->prefix && p->suffix) {
386 p->varpos++;
387 if (p->varpos > WMGetArrayItemCount(p->variants))
388 p->varpos = 0;
389 if (p->varpos > 0)
390 text = wstrconcat(p->prefix, WMGetFromArray(p->variants, p->varpos - 1));
391 else
392 text = wstrdup(p->prefix);
393 pos = strlen(text);
394 text = wstrappend(text, p->suffix);
395 WMSetTextFieldText(p->panel->text, text);
396 WMSetTextFieldCursorPosition(p->panel->text, pos);
397 wfree(text);
399 break;
401 if (ksym != XK_Tab) {
402 if (p->prefix) {
403 wfree(p->prefix);
404 p->prefix = NULL;
406 if (p->suffix) {
407 wfree(p->suffix);
408 p->suffix = NULL;
410 if (p->variants) {
411 WMFreeArray(p->variants);
412 p->variants = NULL;
417 int wAdvancedInputDialog(WScreen *scr, const char *title, const char *message, const char *name, char **text)
419 WWindow *wwin;
420 Window parent;
421 char *result;
422 WMPoint center;
423 WMInputPanelWithHistory *p;
424 char *filename;
426 filename = HistoryFileName(name);
427 p = wmalloc(sizeof(WMInputPanelWithHistory));
428 p->panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
429 p->history = LoadHistory(filename, wPreferences.history_lines);
430 p->histpos = 0;
431 p->prefix = NULL;
432 p->suffix = NULL;
433 p->rest = NULL;
434 p->variants = NULL;
435 p->varpos = 0;
436 WMCreateEventHandler(WMWidgetView(p->panel->text), KeyPressMask, handleHistoryKeyPress, p);
438 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
439 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
441 XReparentWindow(dpy, WMWidgetXID(p->panel->win), parent, 0, 0);
443 center = getCenter(scr, 320, 160);
444 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
446 wwin->client_leader = WMWidgetXID(p->panel->win);
448 WMMapWidget(p->panel->win);
450 wWindowMap(wwin);
452 WMRunModalLoop(WMWidgetScreen(p->panel->win), WMWidgetView(p->panel->win));
454 if (p->panel->result == WAPRDefault) {
455 result = WMGetTextFieldText(p->panel->text);
456 wfree(WMReplaceInArray(p->history, 0, wstrdup(result)));
457 SaveHistory(p->history, filename);
458 } else
459 result = NULL;
461 wUnmanageWindow(wwin, False, False);
463 WMDestroyInputPanel(p->panel);
464 WMFreeArray(p->history);
465 wfree(p);
466 wfree(filename);
468 XDestroyWindow(dpy, parent);
470 if (result == NULL)
471 return False;
472 else {
473 if (*text)
474 wfree(*text);
475 *text = result;
477 return True;
481 int wInputDialog(WScreen *scr, const char *title, const char *message, char **text)
483 WWindow *wwin;
484 Window parent;
485 WMInputPanel *panel;
486 char *result;
487 WMPoint center;
489 panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
491 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
492 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
494 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
496 center = getCenter(scr, 320, 160);
497 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
499 wwin->client_leader = WMWidgetXID(panel->win);
501 WMMapWidget(panel->win);
503 wWindowMap(wwin);
505 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
507 if (panel->result == WAPRDefault)
508 result = WMGetTextFieldText(panel->text);
509 else
510 result = NULL;
512 wUnmanageWindow(wwin, False, False);
514 WMDestroyInputPanel(panel);
516 XDestroyWindow(dpy, parent);
518 if (result == NULL)
519 return False;
520 else {
521 if (*text)
522 wfree(*text);
523 *text = result;
525 return True;
530 *****************************************************************
531 * Icon Selection Panel
532 *****************************************************************
535 typedef struct IconPanel {
537 WScreen *scr;
539 WMWindow *win;
541 WMLabel *dirLabel;
542 WMLabel *iconLabel;
544 WMList *dirList;
545 WMList *iconList;
546 WMFont *normalfont;
548 WMButton *previewButton;
550 WMLabel *iconView;
552 WMLabel *fileLabel;
553 WMTextField *fileField;
555 WMButton *okButton;
556 WMButton *cancelButton;
557 #if 0
558 WMButton *chooseButton;
559 #endif
560 short done;
561 short result;
562 short preview;
563 } IconPanel;
565 static void listPixmaps(WScreen *scr, WMList *lPtr, const char *path)
567 struct dirent *dentry;
568 DIR *dir;
569 char pbuf[PATH_MAX + 16];
570 char *apath;
571 IconPanel *panel = WMGetHangedData(lPtr);
573 panel->preview = False;
575 apath = wexpandpath(path);
576 dir = opendir(apath);
578 if (!dir) {
579 wfree(apath);
580 snprintf(pbuf, sizeof(pbuf),
581 _("Could not open directory \"%s\":\n%s"),
582 path, strerror(errno));
583 wMessageDialog(scr, _("Error"), pbuf, _("OK"), NULL, NULL);
584 return;
587 /* list contents in the column */
588 while ((dentry = readdir(dir))) {
589 struct stat statb;
591 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
592 continue;
594 if (wstrlcpy(pbuf, apath, sizeof(pbuf)) >= sizeof(pbuf) ||
595 wstrlcat(pbuf, "/", sizeof(pbuf)) >= sizeof(pbuf) ||
596 wstrlcat(pbuf, dentry->d_name, sizeof(pbuf)) >= sizeof(pbuf)) {
597 wwarning(_("full path for file \"%s\" in \"%s\" is longer than %d bytes, skipped"),
598 dentry->d_name, path, (int) (sizeof(pbuf) - 1) );
599 continue;
602 if (stat(pbuf, &statb) < 0)
603 continue;
605 if (statb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)
606 && statb.st_mode & (S_IFREG | S_IFLNK)) {
607 WMAddListItem(lPtr, dentry->d_name);
610 WMSortListItems(lPtr);
612 closedir(dir);
613 wfree(apath);
614 panel->preview = True;
617 static void setViewedImage(IconPanel *panel, const char *file)
619 WMPixmap *pixmap;
620 RColor color;
622 color.red = 0xae;
623 color.green = 0xaa;
624 color.blue = 0xae;
625 color.alpha = 0;
626 pixmap = WMCreateScaledBlendedPixmapFromFile(WMWidgetScreen(panel->win), file, &color, 75, 75);
628 if (!pixmap) {
629 WMSetButtonEnabled(panel->okButton, False);
631 WMSetLabelText(panel->iconView, _("Could not load image file "));
633 WMSetLabelImage(panel->iconView, NULL);
634 } else {
635 WMSetButtonEnabled(panel->okButton, True);
637 WMSetLabelText(panel->iconView, NULL);
638 WMSetLabelImage(panel->iconView, pixmap);
639 WMReleasePixmap(pixmap);
643 static void listCallback(void *self, void *data)
645 WMList *lPtr = (WMList *) self;
646 IconPanel *panel = (IconPanel *) data;
647 char *path;
649 if (lPtr == panel->dirList) {
650 WMListItem *item = WMGetListSelectedItem(lPtr);
652 if (item == NULL)
653 return;
654 path = item->text;
656 WMSetTextFieldText(panel->fileField, path);
658 WMSetLabelImage(panel->iconView, NULL);
660 WMSetButtonEnabled(panel->okButton, False);
662 WMClearList(panel->iconList);
663 listPixmaps(panel->scr, panel->iconList, path);
664 } else {
665 char *tmp, *iconFile;
666 WMListItem *item = WMGetListSelectedItem(panel->dirList);
668 if (item == NULL)
669 return;
670 path = item->text;
672 item = WMGetListSelectedItem(panel->iconList);
673 if (item == NULL)
674 return;
675 iconFile = item->text;
677 tmp = wexpandpath(path);
678 path = wmalloc(strlen(tmp) + strlen(iconFile) + 4);
679 strcpy(path, tmp);
680 strcat(path, "/");
681 strcat(path, iconFile);
682 wfree(tmp);
683 WMSetTextFieldText(panel->fileField, path);
684 setViewedImage(panel, path);
685 wfree(path);
689 static void listIconPaths(WMList * lPtr)
691 char *paths;
692 char *path;
694 paths = wstrdup(wPreferences.icon_path);
696 path = strtok(paths, ":");
698 do {
699 char *tmp;
701 tmp = wexpandpath(path);
702 /* do not sort, because the order implies the order of
703 * directories searched */
704 if (access(tmp, X_OK) == 0)
705 WMAddListItem(lPtr, path);
706 wfree(tmp);
707 } while ((path = strtok(NULL, ":")) != NULL);
709 wfree(paths);
712 static void drawIconProc(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
714 IconPanel *panel = WMGetHangedData(lPtr);
715 WScreen *scr = panel->scr;
716 GC gc = scr->draw_gc;
717 GC copygc = scr->copy_gc;
718 char *file, *dirfile;
719 WMPixmap *pixmap;
720 WMColor *back;
721 WMSize size;
722 WMScreen *wmscr = WMWidgetScreen(panel->win);
723 RColor color;
724 int x, y, width, height, len;
726 /* Parameter not used, but tell the compiler that it is ok */
727 (void) index;
729 if (!panel->preview)
730 return;
732 x = rect->pos.x;
733 y = rect->pos.y;
734 width = rect->size.width;
735 height = rect->size.height;
737 back = (state & WLDSSelected) ? scr->white : scr->gray;
739 dirfile = wexpandpath(WMGetListSelectedItem(panel->dirList)->text);
740 len = strlen(dirfile) + strlen(text) + 4;
741 file = wmalloc(len);
742 snprintf(file, len, "%s/%s", dirfile, text);
743 wfree(dirfile);
745 color.red = WMRedComponentOfColor(back) >> 8;
746 color.green = WMGreenComponentOfColor(back) >> 8;
747 color.blue = WMBlueComponentOfColor(back) >> 8;
748 color.alpha = WMGetColorAlpha(back) >> 8;
750 pixmap = WMCreateScaledBlendedPixmapFromFile(wmscr, file, &color, width - 2, height - 2);
751 wfree(file);
753 if (!pixmap) {
754 /*WMRemoveListItem(lPtr, index); */
755 return;
758 XFillRectangle(dpy, d, WMColorGC(back), x, y, width, height);
760 XSetClipMask(dpy, gc, None);
761 /*XDrawRectangle(dpy, d, WMColorGC(white), x+5, y+5, width-10, 54); */
762 XDrawLine(dpy, d, WMColorGC(scr->white), x, y + height - 1, x + width, y + height - 1);
764 size = WMGetPixmapSize(pixmap);
766 XSetClipMask(dpy, copygc, WMGetPixmapMaskXID(pixmap));
767 XSetClipOrigin(dpy, copygc, x + (width - size.width) / 2, y + 2);
768 XCopyArea(dpy, WMGetPixmapXID(pixmap), d, copygc, 0, 0,
769 size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
770 x + (width - size.width) / 2, y + 2);
773 int i, j;
774 int fheight = WMFontHeight(panel->normalfont);
775 int tlen = strlen(text);
776 int twidth = WMWidthOfString(panel->normalfont, text, tlen);
777 int ofx, ofy;
779 ofx = x + (width - twidth) / 2;
780 ofy = y + 64 - fheight;
782 for (i = -1; i < 2; i++)
783 for (j = -1; j < 2; j++)
784 WMDrawString(wmscr, d, scr->white, panel->normalfont,
785 ofx + i, ofy + j, text, tlen);
787 WMDrawString(wmscr, d, scr->black, panel->normalfont, ofx, ofy, text, tlen);
790 WMReleasePixmap(pixmap);
791 /* I hope it is better to do not use cache / on my box it is fast nuff */
792 XFlush(dpy);
795 static void buttonCallback(void *self, void *clientData)
797 WMButton *bPtr = (WMButton *) self;
798 IconPanel *panel = (IconPanel *) clientData;
800 if (bPtr == panel->okButton) {
801 panel->done = True;
802 panel->result = True;
803 } else if (bPtr == panel->cancelButton) {
804 panel->done = True;
805 panel->result = False;
806 } else if (bPtr == panel->previewButton) {
807 /**** Previewer ****/
808 WMSetButtonEnabled(bPtr, False);
809 WMSetListUserDrawItemHeight(panel->iconList, 68);
810 WMSetListUserDrawProc(panel->iconList, drawIconProc);
811 WMRedisplayWidget(panel->iconList);
812 /* for draw proc to access screen/gc */
813 /*** end preview ***/
815 #if 0
816 else if (bPtr == panel->chooseButton) {
817 WMOpenPanel *op;
819 op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
821 if (WMRunModalFilePanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
822 char *path;
823 path = WMGetFilePanelFile(op);
824 WMSetTextFieldText(panel->fileField, path);
825 setViewedImage(panel, path);
826 wfree(path);
828 WMDestroyFilePanel(op);
830 #endif
833 static void keyPressHandler(XEvent * event, void *data)
835 IconPanel *panel = (IconPanel *) data;
836 char buffer[32];
837 KeySym ksym;
838 int iidx;
839 int didx;
840 int item = 0;
841 WMList *list = NULL;
843 if (event->type == KeyRelease)
844 return;
846 buffer[0] = 0;
847 XLookupString(&event->xkey, buffer, sizeof(buffer), &ksym, NULL);
849 iidx = WMGetListSelectedItemRow(panel->iconList);
850 didx = WMGetListSelectedItemRow(panel->dirList);
852 switch (ksym) {
853 case XK_Up:
854 if (iidx > 0)
855 item = iidx - 1;
856 else
857 item = iidx;
858 list = panel->iconList;
859 break;
860 case XK_Down:
861 if (iidx < WMGetListNumberOfRows(panel->iconList) - 1)
862 item = iidx + 1;
863 else
864 item = iidx;
865 list = panel->iconList;
866 break;
867 case XK_Home:
868 item = 0;
869 list = panel->iconList;
870 break;
871 case XK_End:
872 item = WMGetListNumberOfRows(panel->iconList) - 1;
873 list = panel->iconList;
874 break;
875 case XK_Next:
876 if (didx < WMGetListNumberOfRows(panel->dirList) - 1)
877 item = didx + 1;
878 else
879 item = didx;
880 list = panel->dirList;
881 break;
882 case XK_Prior:
883 if (didx > 0)
884 item = didx - 1;
885 else
886 item = 0;
887 list = panel->dirList;
888 break;
889 case XK_Return:
890 WMPerformButtonClick(panel->okButton);
891 break;
892 case XK_Escape:
893 WMPerformButtonClick(panel->cancelButton);
894 break;
897 if (list) {
898 WMSelectListItem(list, item);
899 WMSetListPosition(list, item - 5);
900 listCallback(list, panel);
904 Bool wIconChooserDialog(WScreen *scr, char **file, const char *instance, const char *class)
906 WWindow *wwin;
907 Window parent;
908 IconPanel *panel;
909 WMColor *color;
910 WMFont *boldFont;
911 Bool result;
913 panel = wmalloc(sizeof(IconPanel));
915 panel->scr = scr;
917 panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
918 WMResizeWidget(panel->win, 450, 280);
920 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask | KeyReleaseMask, keyPressHandler, panel);
922 boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
923 panel->normalfont = WMSystemFontOfSize(WMWidgetScreen(panel->win), 12);
925 panel->dirLabel = WMCreateLabel(panel->win);
926 WMResizeWidget(panel->dirLabel, 200, 20);
927 WMMoveWidget(panel->dirLabel, 10, 7);
928 WMSetLabelText(panel->dirLabel, _("Directories"));
929 WMSetLabelFont(panel->dirLabel, boldFont);
930 WMSetLabelTextAlignment(panel->dirLabel, WACenter);
932 WMSetLabelRelief(panel->dirLabel, WRSunken);
934 panel->iconLabel = WMCreateLabel(panel->win);
935 WMResizeWidget(panel->iconLabel, 140, 20);
936 WMMoveWidget(panel->iconLabel, 215, 7);
937 WMSetLabelText(panel->iconLabel, _("Icons"));
938 WMSetLabelFont(panel->iconLabel, boldFont);
939 WMSetLabelTextAlignment(panel->iconLabel, WACenter);
941 WMReleaseFont(boldFont);
943 color = WMWhiteColor(scr->wmscreen);
944 WMSetLabelTextColor(panel->dirLabel, color);
945 WMSetLabelTextColor(panel->iconLabel, color);
946 WMReleaseColor(color);
948 color = WMDarkGrayColor(scr->wmscreen);
949 WMSetWidgetBackgroundColor(panel->iconLabel, color);
950 WMSetWidgetBackgroundColor(panel->dirLabel, color);
951 WMReleaseColor(color);
953 WMSetLabelRelief(panel->iconLabel, WRSunken);
955 panel->dirList = WMCreateList(panel->win);
956 WMResizeWidget(panel->dirList, 200, 170);
957 WMMoveWidget(panel->dirList, 10, 30);
958 WMSetListAction(panel->dirList, listCallback, panel);
960 panel->iconList = WMCreateList(panel->win);
961 WMResizeWidget(panel->iconList, 140, 170);
962 WMMoveWidget(panel->iconList, 215, 30);
963 WMSetListAction(panel->iconList, listCallback, panel);
965 WMHangData(panel->iconList, panel);
967 panel->previewButton = WMCreateCommandButton(panel->win);
968 WMResizeWidget(panel->previewButton, 75, 26);
969 WMMoveWidget(panel->previewButton, 365, 130);
970 WMSetButtonText(panel->previewButton, _("Preview"));
971 WMSetButtonAction(panel->previewButton, buttonCallback, panel);
973 panel->iconView = WMCreateLabel(panel->win);
974 WMResizeWidget(panel->iconView, 75, 75);
975 WMMoveWidget(panel->iconView, 365, 40);
976 WMSetLabelImagePosition(panel->iconView, WIPOverlaps);
977 WMSetLabelRelief(panel->iconView, WRSunken);
978 WMSetLabelTextAlignment(panel->iconView, WACenter);
980 panel->fileLabel = WMCreateLabel(panel->win);
981 WMResizeWidget(panel->fileLabel, 80, 20);
982 WMMoveWidget(panel->fileLabel, 10, 210);
983 WMSetLabelText(panel->fileLabel, _("File Name:"));
985 panel->fileField = WMCreateTextField(panel->win);
986 WMSetViewNextResponder(WMWidgetView(panel->fileField), WMWidgetView(panel->win));
987 WMResizeWidget(panel->fileField, 345, 20);
988 WMMoveWidget(panel->fileField, 95, 210);
989 WMSetTextFieldEditable(panel->fileField, False);
991 panel->okButton = WMCreateCommandButton(panel->win);
992 WMResizeWidget(panel->okButton, 80, 26);
993 WMMoveWidget(panel->okButton, 360, 240);
994 WMSetButtonText(panel->okButton, _("OK"));
995 WMSetButtonEnabled(panel->okButton, False);
996 WMSetButtonAction(panel->okButton, buttonCallback, panel);
998 panel->cancelButton = WMCreateCommandButton(panel->win);
999 WMResizeWidget(panel->cancelButton, 80, 26);
1000 WMMoveWidget(panel->cancelButton, 270, 240);
1001 WMSetButtonText(panel->cancelButton, _("Cancel"));
1002 WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
1003 #if 0
1004 panel->chooseButton = WMCreateCommandButton(panel->win);
1005 WMResizeWidget(panel->chooseButton, 110, 26);
1006 WMMoveWidget(panel->chooseButton, 150, 240);
1007 WMSetButtonText(panel->chooseButton, _("Choose File"));
1008 WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
1009 #endif
1010 WMRealizeWidget(panel->win);
1011 WMMapSubwidgets(panel->win);
1013 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
1015 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1018 static const char *prefix = NULL;
1019 char *title;
1020 int len;
1021 WMPoint center;
1023 if (prefix == NULL)
1024 prefix = _("Icon Chooser");
1026 len = strlen(prefix)
1027 + 2 // " ["
1028 + (instance ? strlen(instance) : 0)
1029 + 1 // "."
1030 + (class ? strlen(class) : 0)
1031 + 1 // "]"
1032 + 1; // final NUL
1034 title = wmalloc(len);
1035 strcpy(title, prefix);
1037 if (instance || class) {
1038 strcat(title, " [");
1039 if (instance != NULL)
1040 strcat(title, instance);
1041 if (instance && class)
1042 strcat(title, ".");
1043 if (class != NULL)
1044 strcat(title, class);
1045 strcat(title, "]");
1048 center = getCenter(scr, 450, 280);
1050 wwin = wManageInternalWindow(scr, parent, None, title, center.x, center.y, 450, 280);
1051 wfree(title);
1054 /* put icon paths in the list */
1055 listIconPaths(panel->dirList);
1057 WMMapWidget(panel->win);
1059 wWindowMap(wwin);
1061 while (!panel->done) {
1062 XEvent event;
1064 WMNextEvent(dpy, &event);
1065 WMHandleEvent(&event);
1068 if (panel->result) {
1069 char *defaultPath, *wantedPath;
1071 /* check if the file the user selected is not the one that
1072 * would be loaded by default with the current search path */
1073 *file = WMGetListSelectedItem(panel->iconList)->text;
1074 if (**file == 0) {
1075 wfree(*file);
1076 *file = NULL;
1077 } else {
1078 defaultPath = FindImage(wPreferences.icon_path, *file);
1079 wantedPath = WMGetTextFieldText(panel->fileField);
1080 /* if the file is not the default, use full path */
1081 if (strcmp(wantedPath, defaultPath) != 0) {
1082 *file = wantedPath;
1083 } else {
1084 *file = wstrdup(*file);
1085 wfree(wantedPath);
1087 wfree(defaultPath);
1089 } else {
1090 *file = NULL;
1093 result = panel->result;
1095 WMReleaseFont(panel->normalfont);
1097 WMUnmapWidget(panel->win);
1099 WMDestroyWidget(panel->win);
1101 wUnmanageWindow(wwin, False, False);
1103 wfree(panel);
1105 XDestroyWindow(dpy, parent);
1107 return result;
1111 ***********************************************************************
1112 * Info Panel
1113 ***********************************************************************
1116 typedef struct {
1117 WScreen *scr;
1118 WWindow *wwin;
1119 WMWindow *win;
1120 WMLabel *logoL;
1121 WMLabel *name1L;
1122 WMFrame *lineF;
1123 WMLabel *name2L;
1124 WMLabel *versionL;
1125 WMLabel *infoL;
1126 WMLabel *copyrL;
1127 } InfoPanel;
1129 #define COPYRIGHT_TEXT \
1130 "Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
1131 "Copyright \xc2\xa9 1998-2006 Dan Pascu\n"\
1132 "Copyright \xc2\xa9 2013-2017 Window Maker Developers Team"
1134 static InfoPanel *infoPanel = NULL;
1136 static void destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
1138 /* Parameter not used, but tell the compiler that it is ok */
1139 (void) foo;
1140 (void) data;
1141 (void) event;
1143 WMUnmapWidget(infoPanel);
1144 wUnmanageWindow(infoPanel->wwin, False, False);
1145 WMDestroyWidget(infoPanel->win);
1146 wfree(infoPanel);
1147 infoPanel = NULL;
1150 void wShowInfoPanel(WScreen *scr)
1152 const int win_width = 382;
1153 const int win_height = 250;
1154 InfoPanel *panel;
1155 WMPixmap *logo;
1156 WMFont *font;
1157 char *name, *strbuf = NULL;
1158 const char *separator;
1159 char buffer[256];
1160 Window parent;
1161 WWindow *wwin;
1162 WMPoint center;
1163 char **strl;
1164 int i, width = 50, sepHeight;
1165 char *visuals[] = {
1166 "StaticGray",
1167 "GrayScale",
1168 "StaticColor",
1169 "PseudoColor",
1170 "TrueColor",
1171 "DirectColor"
1174 if (infoPanel) {
1175 if (infoPanel->scr == scr) {
1176 wRaiseFrame(infoPanel->wwin->frame->core);
1177 wSetFocusTo(scr, infoPanel->wwin);
1179 return;
1182 panel = wmalloc(sizeof(InfoPanel));
1184 panel->scr = scr;
1186 panel->win = WMCreateWindow(scr->wmscreen, "info");
1187 WMResizeWidget(panel->win, win_width, win_height);
1189 logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
1190 if (!logo) {
1191 logo = WMRetainPixmap(WMGetApplicationIconPixmap(scr->wmscreen));
1193 if (logo) {
1194 panel->logoL = WMCreateLabel(panel->win);
1195 WMResizeWidget(panel->logoL, 64, 64);
1196 WMMoveWidget(panel->logoL, 30, 20);
1197 WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
1198 WMSetLabelImage(panel->logoL, logo);
1199 WMReleasePixmap(logo);
1202 sepHeight = 3;
1203 panel->name1L = WMCreateLabel(panel->win);
1204 WMResizeWidget(panel->name1L, 240, 30 + 2);
1205 WMMoveWidget(panel->name1L, 100, 30 - 2 - sepHeight);
1207 name = "Lucida Sans,Comic Sans MS,URW Gothic L,Trebuchet MS" ":italic:pixelsize=28:antialias=true";
1208 font = WMCreateFont(scr->wmscreen, name);
1209 strbuf = "Window Maker";
1210 if (font) {
1211 width = WMWidthOfString(font, strbuf, strlen(strbuf));
1212 WMSetLabelFont(panel->name1L, font);
1213 WMReleaseFont(font);
1215 WMSetLabelTextAlignment(panel->name1L, WACenter);
1216 WMSetLabelText(panel->name1L, strbuf);
1218 panel->lineF = WMCreateFrame(panel->win);
1219 WMResizeWidget(panel->lineF, width, sepHeight);
1220 WMMoveWidget(panel->lineF, 100 + (240 - width) / 2, 60 - sepHeight);
1221 WMSetFrameRelief(panel->lineF, WRSimple);
1222 WMSetWidgetBackgroundColor(panel->lineF, scr->black);
1224 panel->name2L = WMCreateLabel(panel->win);
1225 WMResizeWidget(panel->name2L, 240, 24);
1226 WMMoveWidget(panel->name2L, 100, 60);
1227 name = "URW Gothic L,Nimbus Sans L:pixelsize=16:antialias=true";
1228 font = WMCreateFont(scr->wmscreen, name);
1229 if (font) {
1230 WMSetLabelFont(panel->name2L, font);
1231 WMReleaseFont(font);
1232 font = NULL;
1234 WMSetLabelTextAlignment(panel->name2L, WACenter);
1235 WMSetLabelText(panel->name2L, _("Window Manager for X"));
1237 snprintf(buffer, sizeof(buffer), _("Version %s"), VERSION);
1238 panel->versionL = WMCreateLabel(panel->win);
1239 WMResizeWidget(panel->versionL, 310, 16);
1240 WMMoveWidget(panel->versionL, 30, 95);
1241 WMSetLabelTextAlignment(panel->versionL, WARight);
1242 WMSetLabelText(panel->versionL, buffer);
1243 WMSetLabelWraps(panel->versionL, False);
1245 panel->copyrL = WMCreateLabel(panel->win);
1246 WMResizeWidget(panel->copyrL, 360, 60);
1247 WMMoveWidget(panel->copyrL, 15, 190);
1248 WMSetLabelTextAlignment(panel->copyrL, WALeft);
1249 WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
1250 font = WMSystemFontOfSize(scr->wmscreen, 11);
1251 if (font) {
1252 WMSetLabelFont(panel->copyrL, font);
1253 WMReleaseFont(font);
1254 font = NULL;
1257 strbuf = NULL;
1258 snprintf(buffer, sizeof(buffer), _("Using visual 0x%x: %s %ibpp "),
1259 (unsigned)scr->w_visual->visualid, visuals[scr->w_visual->class], scr->w_depth);
1261 strbuf = wstrappend(strbuf, buffer);
1263 switch (scr->w_depth) {
1264 case 15:
1265 strbuf = wstrappend(strbuf, _("(32 thousand colors)\n"));
1266 break;
1267 case 16:
1268 strbuf = wstrappend(strbuf, _("(64 thousand colors)\n"));
1269 break;
1270 case 24:
1271 case 32:
1272 strbuf = wstrappend(strbuf, _("(16 million colors)\n"));
1273 break;
1274 default:
1275 snprintf(buffer, sizeof(buffer), _("(%d colors)\n"), 1 << scr->w_depth);
1276 strbuf = wstrappend(strbuf, buffer);
1277 break;
1280 #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
1282 struct mallinfo ma = mallinfo();
1283 snprintf(buffer, sizeof(buffer),
1284 #ifdef DEBUG
1285 _("Total memory allocated: %i kB (in use: %i kB, %d free chunks).\n"),
1286 #else
1287 _("Total memory allocated: %i kB (in use: %i kB).\n"),
1288 #endif
1289 (ma.arena + ma.hblkhd) / 1024,
1290 (ma.uordblks + ma.hblkhd) / 1024
1291 #ifdef DEBUG
1293 * This information is representative of the memory
1294 * fragmentation. In ideal case it should be 1, but
1295 * that is never possible
1297 , ma.ordblks
1298 #endif
1301 strbuf = wstrappend(strbuf, buffer);
1303 #endif
1305 strbuf = wstrappend(strbuf, _("Image formats: "));
1306 strl = RSupportedFileFormats();
1307 separator = NULL;
1308 for (i = 0; strl[i] != NULL; i++) {
1309 if (separator != NULL)
1310 strbuf = wstrappend(strbuf, separator);
1311 strbuf = wstrappend(strbuf, strl[i]);
1312 separator = ", ";
1315 strbuf = wstrappend(strbuf, _("\nAdditional support for: "));
1316 strbuf = wstrappend(strbuf, "WMSPEC");
1318 #ifdef USE_MWM_HINTS
1319 strbuf = wstrappend(strbuf, ", MWM");
1320 #endif
1322 #ifdef USE_DOCK_XDND
1323 strbuf = wstrappend(strbuf, ", XDnD");
1324 #endif
1326 #ifdef USE_MAGICK
1327 strbuf = wstrappend(strbuf, ", ImageMagick");
1328 #endif
1330 #ifdef USE_XINERAMA
1331 strbuf = wstrappend(strbuf, _("\n"));
1332 #ifdef SOLARIS_XINERAMA
1333 strbuf = wstrappend(strbuf, _("Solaris "));
1334 #endif
1335 strbuf = wstrappend(strbuf, _("Xinerama: "));
1337 char tmp[128];
1338 snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found."), scr->xine_info.count);
1339 strbuf = wstrappend(strbuf, tmp);
1341 #endif
1343 #ifdef USE_RANDR
1344 strbuf = wstrappend(strbuf, _("\n"));
1345 strbuf = wstrappend(strbuf, "RandR: ");
1346 if (w_global.xext.randr.supported)
1347 strbuf = wstrappend(strbuf, _("supported"));
1348 else
1349 strbuf = wstrappend(strbuf, _("unsupported"));
1350 strbuf = wstrappend(strbuf, ".");
1351 #endif
1353 panel->infoL = WMCreateLabel(panel->win);
1354 WMResizeWidget(panel->infoL, 350, 80);
1355 WMMoveWidget(panel->infoL, 15, 115);
1356 WMSetLabelText(panel->infoL, strbuf);
1357 font = WMSystemFontOfSize(scr->wmscreen, 11);
1358 if (font) {
1359 WMSetLabelFont(panel->infoL, font);
1360 WMReleaseFont(font);
1361 font = NULL;
1363 wfree(strbuf);
1365 WMRealizeWidget(panel->win);
1366 WMMapSubwidgets(panel->win);
1368 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1370 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1372 WMMapWidget(panel->win);
1374 center = getCenter(scr, win_width, win_height);
1375 wwin = wManageInternalWindow(scr, parent, None, _("Info"), center.x, center.y, win_width, win_height);
1377 WSETUFLAG(wwin, no_closable, 0);
1378 WSETUFLAG(wwin, no_close_button, 0);
1379 #ifdef XKB_BUTTON_HINT
1380 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1381 #endif
1382 wWindowUpdateButtonImages(wwin);
1383 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1384 wwin->frame->on_click_right = destroyInfoPanel;
1386 wWindowMap(wwin);
1388 panel->wwin = wwin;
1389 infoPanel = panel;
1393 ***********************************************************************
1394 * Legal Panel
1395 ***********************************************************************
1398 typedef struct {
1399 WScreen *scr;
1400 WWindow *wwin;
1401 WMWindow *win;
1402 WMLabel *licenseL;
1403 } LegalPanel;
1405 static LegalPanel *legalPanel = NULL;
1407 static void destroyLegalPanel(WCoreWindow * foo, void *data, XEvent * event)
1409 /* Parameter not used, but tell the compiler that it is ok */
1410 (void) foo;
1411 (void) data;
1412 (void) event;
1414 WMUnmapWidget(legalPanel->win);
1415 WMDestroyWidget(legalPanel->win);
1416 wUnmanageWindow(legalPanel->wwin, False, False);
1417 wfree(legalPanel);
1418 legalPanel = NULL;
1421 void wShowLegalPanel(WScreen *scr)
1423 const int win_width = 420;
1424 const int win_height = 250;
1425 const int margin = 10;
1426 LegalPanel *panel;
1427 Window parent;
1428 WWindow *wwin;
1429 WMPoint center;
1431 if (legalPanel) {
1432 if (legalPanel->scr == scr) {
1433 wRaiseFrame(legalPanel->wwin->frame->core);
1434 wSetFocusTo(scr, legalPanel->wwin);
1436 return;
1439 panel = wmalloc(sizeof(LegalPanel));
1440 panel->scr = scr;
1441 panel->win = WMCreateWindow(scr->wmscreen, "legal");
1442 WMResizeWidget(panel->win, win_width, win_height);
1444 panel->licenseL = WMCreateLabel(panel->win);
1445 WMSetLabelWraps(panel->licenseL, True);
1446 WMResizeWidget(panel->licenseL, win_width - (2 * margin), win_height - (2 * margin));
1447 WMMoveWidget(panel->licenseL, margin, margin);
1448 WMSetLabelTextAlignment(panel->licenseL, WALeft);
1449 WMSetLabelText(panel->licenseL,
1450 _(" Window Maker is free software; you can redistribute it and/or "
1451 "modify it under the terms of the GNU General Public License as "
1452 "published by the Free Software Foundation; either version 2 of the "
1453 "License, or (at your option) any later version.\n\n"
1454 " Window Maker is distributed in the hope that it will be useful, "
1455 "but WITHOUT ANY WARRANTY; without even the implied warranty "
1456 "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
1457 "See the GNU General Public License for more details.\n\n"
1458 " You should have received a copy of the GNU General Public "
1459 "License along with this program; if not, write to the Free Software "
1460 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA"
1461 "02110-1301 USA."));
1462 WMSetLabelRelief(panel->licenseL, WRGroove);
1464 WMRealizeWidget(panel->win);
1465 WMMapSubwidgets(panel->win);
1467 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1468 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1469 center = getCenter(scr, win_width, win_height);
1470 wwin = wManageInternalWindow(scr, parent, None, _("Legal"), center.x, center.y, win_width, win_height);
1472 WSETUFLAG(wwin, no_closable, 0);
1473 WSETUFLAG(wwin, no_close_button, 0);
1474 wWindowUpdateButtonImages(wwin);
1475 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1476 #ifdef XKB_BUTTON_HINT
1477 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1478 #endif
1479 wwin->frame->on_click_right = destroyLegalPanel;
1480 panel->wwin = wwin;
1482 WMMapWidget(panel->win);
1483 wWindowMap(wwin);
1484 legalPanel = panel;
1488 ***********************************************************************
1489 * Crashing Dialog Panel
1490 ***********************************************************************
1493 typedef struct _CrashPanel {
1494 WMWindow *win; /* main window */
1496 WMLabel *iconL; /* application icon */
1497 WMLabel *nameL; /* title of panel */
1499 WMFrame *sepF; /* separator frame */
1501 WMLabel *noteL; /* Title of note */
1502 WMLabel *note2L; /* body of note with what happened */
1504 WMFrame *whatF; /* "what to do next" frame */
1505 WMPopUpButton *whatP; /* action selection popup button */
1507 WMButton *okB; /* ok button */
1509 Bool done; /* if finished with this dialog */
1510 int action; /* what to do after */
1512 KeyCode retKey;
1514 } CrashPanel;
1516 static void handleKeyPress(XEvent * event, void *clientData)
1518 CrashPanel *panel = (CrashPanel *) clientData;
1520 if (event->xkey.keycode == panel->retKey) {
1521 WMPerformButtonClick(panel->okB);
1525 static void okButtonCallback(void *self, void *clientData)
1527 CrashPanel *panel = (CrashPanel *) clientData;
1529 /* Parameter not used, but tell the compiler that it is ok */
1530 (void) self;
1532 panel->done = True;
1535 static void setCrashAction(void *self, void *clientData)
1537 WMPopUpButton *pop = (WMPopUpButton *) self;
1538 CrashPanel *panel = (CrashPanel *) clientData;
1540 panel->action = WMGetPopUpButtonSelectedItem(pop);
1543 /* Make this read the logo from a compiled in pixmap -Dan */
1544 static WMPixmap *getWindowMakerIconImage(WMScreen *scr)
1546 WMPixmap *pix = NULL;
1547 char *path = NULL;
1549 /* Get the Logo icon, without the default icon */
1550 path = get_icon_filename("Logo", "WMPanel", NULL, False);
1552 if (path) {
1553 RColor gray;
1555 gray.red = 0xae;
1556 gray.green = 0xaa;
1557 gray.blue = 0xae;
1558 gray.alpha = 0;
1560 pix = WMCreateBlendedPixmapFromFile(scr, path, &gray);
1561 wfree(path);
1564 return pix;
1567 #define PWIDTH 295
1568 #define PHEIGHT 345
1570 int wShowCrashingDialogPanel(int whatSig)
1572 CrashPanel *panel;
1573 WMScreen *scr;
1574 WMFont *font;
1575 WMPixmap *logo;
1576 int screen_no, scr_width, scr_height;
1577 int action;
1578 char buf[256];
1580 screen_no = DefaultScreen(dpy);
1581 scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_no));
1582 scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_no));
1584 scr = WMCreateScreen(dpy, screen_no);
1585 if (!scr) {
1586 werror(_("cannot open connection for crashing dialog panel. Aborting."));
1587 return WMAbort;
1590 panel = wmalloc(sizeof(CrashPanel));
1592 panel->retKey = XKeysymToKeycode(dpy, XK_Return);
1594 panel->win = WMCreateWindow(scr, "crashingDialog");
1595 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1596 WMMoveWidget(panel->win, (scr_width - PWIDTH) / 2, (scr_height - PHEIGHT) / 2);
1598 logo = getWindowMakerIconImage(scr);
1599 if (logo) {
1600 panel->iconL = WMCreateLabel(panel->win);
1601 WMResizeWidget(panel->iconL, 64, 64);
1602 WMMoveWidget(panel->iconL, 10, 10);
1603 WMSetLabelImagePosition(panel->iconL, WIPImageOnly);
1604 WMSetLabelImage(panel->iconL, logo);
1607 panel->nameL = WMCreateLabel(panel->win);
1608 WMResizeWidget(panel->nameL, 200, 30);
1609 WMMoveWidget(panel->nameL, 80, 25);
1610 WMSetLabelTextAlignment(panel->nameL, WALeft);
1611 font = WMBoldSystemFontOfSize(scr, 24);
1612 WMSetLabelFont(panel->nameL, font);
1613 WMReleaseFont(font);
1614 WMSetLabelText(panel->nameL, _("Fatal error"));
1616 panel->sepF = WMCreateFrame(panel->win);
1617 WMResizeWidget(panel->sepF, PWIDTH + 4, 2);
1618 WMMoveWidget(panel->sepF, -2, 80);
1620 panel->noteL = WMCreateLabel(panel->win);
1621 WMResizeWidget(panel->noteL, PWIDTH - 20, 40);
1622 WMMoveWidget(panel->noteL, 10, 90);
1623 WMSetLabelTextAlignment(panel->noteL, WAJustified);
1624 snprintf(buf, sizeof(buf), _("Window Maker received signal %i."), whatSig);
1625 WMSetLabelText(panel->noteL, buf);
1627 panel->note2L = WMCreateLabel(panel->win);
1628 WMResizeWidget(panel->note2L, PWIDTH - 20, 100);
1629 WMMoveWidget(panel->note2L, 10, 130);
1630 WMSetLabelTextAlignment(panel->note2L, WALeft);
1631 snprintf(buf, sizeof(buf), /* Comment for the PO file: the %s is an email address */
1632 _(" This fatal error occurred probably due to a bug."
1633 " Please fill the included BUGFORM and report it to %s."),
1634 PACKAGE_BUGREPORT);
1635 WMSetLabelText(panel->note2L, buf);
1636 WMSetLabelWraps(panel->note2L, True);
1638 panel->whatF = WMCreateFrame(panel->win);
1639 WMResizeWidget(panel->whatF, PWIDTH - 20, 50);
1640 WMMoveWidget(panel->whatF, 10, 240);
1641 WMSetFrameTitle(panel->whatF, _("What do you want to do now?"));
1643 panel->whatP = WMCreatePopUpButton(panel->whatF);
1644 WMResizeWidget(panel->whatP, PWIDTH - 20 - 70, 20);
1645 WMMoveWidget(panel->whatP, 35, 20);
1646 WMSetPopUpButtonPullsDown(panel->whatP, False);
1647 WMSetPopUpButtonText(panel->whatP, _("Select action"));
1648 WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file"));
1649 WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker"));
1650 WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager"));
1651 WMSetPopUpButtonAction(panel->whatP, setCrashAction, panel);
1652 WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart);
1653 panel->action = WMRestart;
1655 WMMapSubwidgets(panel->whatF);
1657 panel->okB = WMCreateCommandButton(panel->win);
1658 WMResizeWidget(panel->okB, 80, 26);
1659 WMMoveWidget(panel->okB, 205, 309);
1660 WMSetButtonText(panel->okB, _("OK"));
1661 WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow));
1662 WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow));
1663 WMSetButtonImagePosition(panel->okB, WIPRight);
1664 WMSetButtonAction(panel->okB, okButtonCallback, panel);
1666 panel->done = 0;
1668 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, handleKeyPress, panel);
1670 WMRealizeWidget(panel->win);
1671 WMMapSubwidgets(panel->win);
1673 WMMapWidget(panel->win);
1675 XSetInputFocus(dpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime);
1677 while (!panel->done) {
1678 XEvent event;
1680 WMNextEvent(dpy, &event);
1681 WMHandleEvent(&event);
1684 action = panel->action;
1686 WMUnmapWidget(panel->win);
1687 WMDestroyWidget(panel->win);
1688 wfree(panel);
1690 return action;