added snprintf.c to be linked in WINGs
[wmaker-crm.git] / src / winspector.c
blobb4bd90ae6e940ff04cdeecefb9d21553118757b6
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 * Copyright (c) 1998 Dan Pascu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "funcs.h"
39 #include "defaults.h"
40 #include "dialog.h"
41 #include "icon.h"
42 #include "stacking.h"
43 #include "application.h"
44 #include "appicon.h"
45 #include "actions.h"
46 #include "winspector.h"
47 #include "dock.h"
48 #include "client.h"
51 #include <proplist.h>
59 typedef struct InspectorPanel {
60 struct InspectorPanel *nextPtr;
62 WWindow *frame;
64 WWindow *inspected; /* the window that's being inspected */
66 WMWindow *win;
68 Window parent;
70 /* common stuff */
71 WMButton *revertBtn;
72 WMButton *applyBtn;
73 WMButton *saveBtn;
75 WMPopUpButton *pagePopUp;
77 /* first page. general stuff */
79 WMFrame *specFrm;
80 WMButton *instRb;
81 WMButton *clsRb;
82 WMButton *bothRb;
83 WMButton *defaultRb;
85 WMButton *selWinB;
87 WMLabel *specLbl;
89 /* second page. attributes */
91 WMFrame *attrFrm;
92 WMButton *attrChk[11];
94 /* 3rd page. more attributes */
95 WMFrame *moreFrm;
96 #ifdef XKB_BUTTON_HINT
97 WMButton *moreChk[9];
98 #else
99 WMButton *moreChk[8];
100 #endif
102 /* 4th page. icon and workspace */
103 WMFrame *iconFrm;
104 WMLabel *iconLbl;
105 WMLabel *fileLbl;
106 WMTextField *fileText;
107 WMButton *alwChk;
109 WMButton *updateIconBtn;
111 WMButton *browseIconBtn;
113 WMFrame *wsFrm;
114 WMPopUpButton *wsP;
116 /* 5th page. application wide attributes */
117 WMFrame *appFrm;
118 WMButton *appChk[3];
120 unsigned int done:1;
121 unsigned int destroyed:1;
122 unsigned int choosingIcon:1;
123 } InspectorPanel;
128 extern Cursor wCursor[WCUR_LAST];
130 extern WDDomain *WDWindowAttributes;
132 static InspectorPanel *panelList=NULL;
134 extern WPreferences wPreferences;
136 static proplist_t ANoTitlebar = NULL;
137 static proplist_t ANoResizebar;
138 static proplist_t ANoMiniaturizeButton;
139 static proplist_t ANoCloseButton;
140 static proplist_t ANoBorder;
141 static proplist_t ANoHideOthers;
142 static proplist_t ANoMouseBindings;
143 static proplist_t ANoKeyBindings;
144 static proplist_t ANoAppIcon;
145 static proplist_t AKeepOnTop;
146 static proplist_t AKeepOnBottom;
147 static proplist_t AOmnipresent;
148 static proplist_t ASkipWindowList;
149 static proplist_t AKeepInsideScreen;
150 static proplist_t AUnfocusable;
151 static proplist_t AAlwaysUserIcon;
152 static proplist_t AStartMiniaturized;
153 static proplist_t AStartMaximized;
154 static proplist_t ADontSaveSession;
155 static proplist_t AEmulateAppIcon;
156 static proplist_t AFullMaximize;
157 static proplist_t ACollapseAppIcons;
158 #ifdef XKB_BUTTON_HINT
159 static proplist_t ANoLanguageButton;
160 #endif
162 static proplist_t AStartWorkspace;
164 static proplist_t AIcon;
166 /* application wide options */
167 static proplist_t AStartHidden;
170 static proplist_t AnyWindow;
171 static proplist_t EmptyString;
172 static proplist_t Yes, No;
175 #define PWIDTH 270
176 #define PHEIGHT 350
180 static char *spec_text;
183 static void applySettings(WMButton *button, InspectorPanel *panel);
188 #define UNDEFINED_POS 0xffffff
190 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
191 int xpos, int ypos,
192 Bool showSelectPanel);
196 static void
197 make_keys()
199 if (ANoTitlebar!=NULL)
200 return;
202 AIcon = PLMakeString("Icon");
203 ANoTitlebar = PLMakeString("NoTitlebar");
204 ANoResizebar = PLMakeString("NoResizebar");
205 ANoMiniaturizeButton = PLMakeString("NoMiniaturizeButton");
206 ANoCloseButton = PLMakeString("NoCloseButton");
207 ANoBorder = PLMakeString("NoBorder");
208 ANoHideOthers = PLMakeString("NoHideOthers");
209 ANoMouseBindings = PLMakeString("NoMouseBindings");
210 ANoKeyBindings = PLMakeString("NoKeyBindings");
211 ANoAppIcon = PLMakeString("NoAppIcon");
212 AKeepOnTop = PLMakeString("KeepOnTop");
213 AKeepOnBottom = PLMakeString("KeepOnBottom");
214 AOmnipresent = PLMakeString("Omnipresent");
215 ASkipWindowList = PLMakeString("SkipWindowList");
216 AKeepInsideScreen = PLMakeString("KeepInsideScreen");
217 AUnfocusable = PLMakeString("Unfocusable");
218 AAlwaysUserIcon = PLMakeString("AlwaysUserIcon");
219 AStartMiniaturized = PLMakeString("StartMiniaturized");
220 AStartMaximized = PLMakeString("StartMaximized");
221 AStartHidden = PLMakeString("StartHidden");
222 ADontSaveSession = PLMakeString("DontSaveSession");
223 AEmulateAppIcon = PLMakeString("EmulateAppIcon");
224 AFullMaximize = PLMakeString("FullMaximize");
225 ACollapseAppIcons = PLMakeString("CollapseAppIcons");
226 #ifdef XKB_BUTTON_HINT
227 ANoLanguageButton = PLMakeString("NoLanguageButton");
228 #endif
230 AStartWorkspace = PLMakeString("StartWorkspace");
232 AnyWindow = PLMakeString("*");
233 EmptyString = PLMakeString("");
234 Yes = PLMakeString("Yes");
235 No = PLMakeString("No");
240 static void
241 freeInspector(InspectorPanel *panel)
243 panel->destroyed = 1;
244 if (panel->choosingIcon)
245 return;
247 WMDestroyWidget(panel->win);
249 XDestroyWindow(dpy, panel->parent);
251 wfree(panel);
255 static void
256 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
258 InspectorPanel *panel;
259 InspectorPanel *tmp;
261 panel = panelList;
262 while (panel->frame!=data)
263 panel = panel->nextPtr;
265 if (panelList == panel)
266 panelList = panel->nextPtr;
267 else {
268 tmp = panelList;
269 while (tmp->nextPtr!=panel) {
270 tmp = tmp->nextPtr;
272 tmp->nextPtr = panel->nextPtr;
274 panel->inspected->flags.inspector_open = 0;
275 panel->inspected->inspector = NULL;
277 WMRemoveNotificationObserver(panel);
279 wWindowUnmap(panel->frame);
280 wUnmanageWindow(panel->frame, True, False);
282 freeInspector(panel);
287 void
288 wDestroyInspectorPanels()
290 InspectorPanel *panel;
292 while (panelList != NULL) {
293 panel = panelList;
294 panelList = panelList->nextPtr;
295 wUnmanageWindow(panel->frame, False, False);
296 WMDestroyWidget(panel->win);
298 panel->inspected->flags.inspector_open = 0;
299 panel->inspected->inspector = NULL;
301 wfree(panel);
306 static void
307 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
309 int page;
311 page = WMGetPopUpButtonSelectedItem(bPtr);
313 if (page == 0) {
314 WMMapWidget(panel->specFrm);
315 WMMapWidget(panel->specLbl);
316 } else if (page == 1) {
317 WMMapWidget(panel->attrFrm);
318 } else if (page == 2) {
319 WMMapWidget(panel->moreFrm);
320 } else if (page == 3) {
321 WMMapWidget(panel->iconFrm);
322 WMMapWidget(panel->wsFrm);
323 } else {
324 WMMapWidget(panel->appFrm);
327 if (page != 0) {
328 WMUnmapWidget(panel->specFrm);
329 WMUnmapWidget(panel->specLbl);
331 if (page != 1)
332 WMUnmapWidget(panel->attrFrm);
333 if (page != 2)
334 WMUnmapWidget(panel->moreFrm);
335 if (page != 3) {
336 WMUnmapWidget(panel->iconFrm);
337 WMUnmapWidget(panel->wsFrm);
339 if (page != 4 && panel->appFrm)
340 WMUnmapWidget(panel->appFrm);
344 #define USE_TEXT_FIELD 1
345 #define UPDATE_TEXT_FIELD 2
346 #define REVERT_TO_DEFAULT 4
349 static int
350 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
351 char *wm_instance, char *wm_class, int flags)
353 WMPixmap *pixmap = (WMPixmap*) NULL;
354 char *file=NULL, *path=NULL;
355 char *db_icon=NULL;
357 if ((flags & USE_TEXT_FIELD) != 0) {
358 file = WMGetTextFieldText(panel->fileText);
359 if (file && file[0] == 0) {
360 wfree(file);
361 file = NULL;
363 } else {
364 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
365 wm_instance, wm_class, False);
366 if(db_icon != NULL)
367 file = wstrdup(db_icon);
369 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
370 if (file)
371 file = wstrdup(db_icon);
372 flags |= UPDATE_TEXT_FIELD;
375 if ((flags & UPDATE_TEXT_FIELD) != 0) {
376 WMSetTextFieldText(panel->fileText, file);
379 if (file) {
380 path = FindImage(wPreferences.icon_path, file);
382 if (!path) {
383 char *buf;
384 int len = strlen(file)+80;
386 buf = wmalloc(len);
387 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"),
388 file);
389 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
390 _("OK"), NULL, NULL);
391 wfree(buf);
392 wfree(file);
393 return -1;
396 pixmap = WMCreatePixmapFromFile(scrPtr, path);
397 wfree(path);
399 if (!pixmap) {
400 char *buf;
401 int len = strlen(file)+80;
403 buf = wmalloc(len);
404 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
405 file, RMessageForError(RErrorCode));
406 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
407 _("OK"), NULL, NULL);
408 wfree(buf);
409 wfree(file);
410 return -1;
412 wfree(file);
415 WMSetLabelImage(panel->iconLbl, pixmap);
416 if (pixmap)
417 WMReleasePixmap(pixmap);
419 return 0;
422 #if 0
423 static void
424 updateIcon(WMButton *button, InspectorPanel *panel)
426 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
428 #endif
430 static int
431 getBool(proplist_t value)
433 char *val;
435 if (!PLIsString(value)) {
436 return 0;
438 if (!(val = PLGetString(value))) {
439 return 0;
442 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
443 || val[0]=='t' || val[0]=='1'))
444 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
446 return 1;
447 } else if ((val[1]=='\0'
448 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
449 || val[0]=='f' || val[0]=='0'))
450 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
452 return 0;
453 } else {
454 wwarning(_("can't convert \"%s\" to boolean"), val);
455 return 0;
460 #define UPDATE_DEFAULTS 1
461 #define IS_BOOLEAN 2
465 * Will insert the attribute = value; pair in window's list,
466 * if it's different from the defaults.
467 * Defaults means either defaults database, or attributes saved
468 * for the default window "*". This is to let one revert options that are
469 * global because they were saved for all windows ("*").
474 static int
475 insertAttribute(proplist_t dict, proplist_t window, proplist_t attr,
476 proplist_t value, int flags)
478 proplist_t def_win, def_value=NULL;
479 int update = 0;
480 int modified = 0;
482 if (!(flags & UPDATE_DEFAULTS) && dict) {
483 if ((def_win = PLGetDictionaryEntry(dict, AnyWindow)) != NULL) {
484 def_value = PLGetDictionaryEntry(def_win, attr);
488 /* If we could not find defaults in database, fall to hardcoded values.
489 * Also this is true if we save defaults for all windows
491 if (!def_value)
492 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
494 if ((flags & IS_BOOLEAN))
495 update = (getBool(value) != getBool(def_value));
496 else {
497 update = !PLIsEqual(value, def_value);
500 if (update) {
501 PLInsertDictionaryEntry(window, attr, value);
502 modified = 1;
505 return modified;
509 static void
510 saveSettings(WMButton *button, InspectorPanel *panel)
512 WWindow *wwin = panel->inspected;
513 WDDomain *db = WDWindowAttributes;
514 proplist_t dict = db->dictionary;
515 proplist_t winDic, value, key;
516 char *icon_file;
517 int flags = 0;
518 int different = 0;
520 /* Save will apply the changes and save them */
521 applySettings(panel->applyBtn, panel);
523 if (WMGetButtonSelected(panel->instRb) != 0)
524 key = PLMakeString(wwin->wm_instance);
525 else if (WMGetButtonSelected(panel->clsRb) != 0)
526 key = PLMakeString(wwin->wm_class);
527 else if (WMGetButtonSelected(panel->bothRb) != 0) {
528 char *buffer;
530 buffer = wmalloc(strlen(wwin->wm_instance)+strlen(wwin->wm_class)+4);
531 strcat(strcat(strcpy(buffer, wwin->wm_instance), "."), wwin->wm_class);
532 key = PLMakeString(buffer);
533 wfree(buffer);
534 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
535 key = PLRetain(AnyWindow);
536 flags = UPDATE_DEFAULTS;
537 } else
538 key = NULL;
540 if (!key)
541 return;
543 if (!dict) {
544 dict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
545 if (dict) {
546 db->dictionary = dict;
547 value = PLMakeString(db->path);
548 PLSetFilename(dict, value);
549 PLRelease(value);
551 else {
552 PLRelease(key);
553 return;
557 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
558 USE_TEXT_FIELD) < 0)
559 return;
561 PLSetStringCmpHook(NULL);
563 winDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
565 /* Update icon for window */
566 icon_file = WMGetTextFieldText(panel->fileText);
567 if (icon_file) {
568 if (icon_file[0] != 0) {
569 value = PLMakeString(icon_file);
570 different |= insertAttribute(dict, winDic, AIcon, value, flags);
571 PLRelease(value);
573 wfree(icon_file);
577 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
579 i--;
581 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
582 value = PLMakeString(panel->frame->screen_ptr->workspaces[i]->name);
583 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
584 flags);
585 PLRelease(value);
589 flags |= IS_BOOLEAN;
591 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
594 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
595 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
597 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
598 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
600 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
601 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
603 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
604 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
606 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
607 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
609 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
610 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
612 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
613 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
615 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
616 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
618 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
619 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
621 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
622 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
624 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
625 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
628 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
629 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
631 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
632 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
634 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
635 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
637 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
638 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
640 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
641 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
643 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
644 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
646 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
647 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
649 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
650 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
652 #ifdef XKB_BUTTON_HINT
653 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
654 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
655 #endif
657 /* application wide settings for when */
658 /* the window is the leader, save the attribute with the others */
659 if (panel->inspected->main_window == panel->inspected->client_win) {
661 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
662 different |= insertAttribute(dict, winDic, AStartHidden, value, flags);
664 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
665 different |= insertAttribute(dict, winDic, ANoAppIcon, value, flags);
667 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
668 different |= insertAttribute(dict, winDic, ACollapseAppIcons, value, flags);
671 PLRemoveDictionaryEntry(dict, key);
672 if (different) {
673 PLInsertDictionaryEntry(dict, key, winDic);
676 PLRelease(key);
677 PLRelease(winDic);
679 different = 0;
681 /* application wide settings */
682 if (panel->inspected->main_window != panel->inspected->client_win
683 && !(flags & UPDATE_DEFAULTS)) {
684 WApplication *wapp;
685 proplist_t appDic;
687 wapp = wApplicationOf(panel->inspected->main_window);
688 if (wapp) {
689 char *iconFile;
690 char *buffer;
692 appDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
694 assert(wapp->main_window_desc->wm_instance!=NULL);
695 assert(wapp->main_window_desc->wm_class!=NULL);
697 buffer = wmalloc(strlen(wapp->main_window_desc->wm_instance)
698 +strlen(wapp->main_window_desc->wm_class)+4);
699 strcat(strcpy(buffer, wapp->main_window_desc->wm_instance), ".");
700 strcat(buffer, wapp->main_window_desc->wm_class);
701 key = PLMakeString(buffer);
702 wfree(buffer);
704 iconFile = wDefaultGetIconFile(wwin->screen_ptr,
705 wapp->main_window_desc->wm_instance,
706 wapp->main_window_desc->wm_class,
707 False);
709 if (iconFile && iconFile[0]!=0) {
710 value = PLMakeString(iconFile);
711 different |= insertAttribute(dict, appDic, AIcon, value,
712 flags&~IS_BOOLEAN);
713 PLRelease(value);
716 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
717 different |= insertAttribute(dict, appDic, AStartHidden, value,
718 flags);
720 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
721 different |= insertAttribute(dict, appDic, ANoAppIcon, value,
722 flags);
724 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
725 different |= insertAttribute(dict, appDic, ACollapseAppIcons, value,
726 flags);
728 PLRemoveDictionaryEntry(dict, key);
729 if (different) {
730 PLInsertDictionaryEntry(dict, key, appDic);
732 PLRelease(key);
733 PLRelease(appDic);
737 PLSave(dict, YES);
739 /* clean up */
740 PLSetStringCmpHook(StringCompareHook);
744 static void
745 makeAppIconFor(WApplication *wapp)
747 WScreen *scr = wapp->main_window_desc->screen_ptr;
749 if (wapp->app_icon)
750 return;
752 if (!WFLAGP(wapp->main_window_desc, no_appicon))
753 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
754 else
755 wapp->app_icon = NULL;
757 if (wapp->app_icon) {
758 WIcon *icon = wapp->app_icon->icon;
759 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
760 int x=0, y=0;
762 wapp->app_icon->main_window = wapp->main_window;
764 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
765 wapp->app_icon->attracted = 1;
766 if (!wapp->app_icon->icon->shadowed) {
767 wapp->app_icon->icon->shadowed = 1;
768 wapp->app_icon->icon->force_paint = 1;
770 wDockAttachIcon(clip, wapp->app_icon, x, y);
771 } else {
772 PlaceIcon(scr, &x, &y);
773 wAppIconMove(wapp->app_icon, x, y);
775 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
776 XMapWindow(dpy, icon->core->window);
778 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
779 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
784 static void
785 removeAppIconFor(WApplication *wapp)
787 if (!wapp->app_icon)
788 return;
790 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
791 wapp->app_icon->running = 0;
792 /* since we keep it, we don't care if it was attracted or not */
793 wapp->app_icon->attracted = 0;
794 wapp->app_icon->icon->shadowed = 0;
795 wapp->app_icon->main_window = None;
796 wapp->app_icon->pid = 0;
797 wapp->app_icon->icon->owner = NULL;
798 wapp->app_icon->icon->icon_win = None;
799 wapp->app_icon->icon->force_paint = 1;
800 wAppIconPaint(wapp->app_icon);
801 } else if (wapp->app_icon->docked) {
802 wapp->app_icon->running = 0;
803 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
804 } else {
805 wAppIconDestroy(wapp->app_icon);
807 wapp->app_icon = NULL;
808 if (wPreferences.auto_arrange_icons)
809 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
813 static void
814 applySettings(WMButton *button, InspectorPanel *panel)
816 WWindow *wwin = panel->inspected;
817 WApplication *wapp = wApplicationOf(wwin->main_window);
818 int floating, sunken, skip_window_list;
819 int old_omnipresent;
820 int old_no_bind_keys;
821 int old_no_bind_mouse;
823 old_omnipresent = WFLAGP(wwin, omnipresent);
824 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
825 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
827 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
829 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
830 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
831 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
832 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
833 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
834 floating = WMGetButtonSelected(panel->attrChk[5]);
835 sunken = WMGetButtonSelected(panel->attrChk[6]);
836 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
837 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
838 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
839 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
841 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
842 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
843 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
844 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
845 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
846 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
847 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
848 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
849 #ifdef XKB_BUTTON_HINT
850 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
851 #endif
852 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
854 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
855 wUnshadeWindow(wwin);
857 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
859 if (floating) {
860 if (!WFLAGP(wwin, floating))
861 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
862 } else if (sunken) {
863 if (!WFLAGP(wwin, sunken))
864 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
865 } else {
866 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
867 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
870 WSETUFLAG(wwin, sunken, sunken);
871 WSETUFLAG(wwin, floating, floating);
872 wwin->flags.omnipresent = 0;
874 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
875 WSETUFLAG(wwin, skip_window_list, skip_window_list);
876 UpdateSwitchMenu(wwin->screen_ptr, wwin,
877 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
878 } else {
879 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
880 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
884 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
885 if (WFLAGP(wwin, no_bind_keys)) {
886 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
887 } else {
888 wWindowSetKeyGrabs(wwin);
892 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
893 wWindowResetMouseGrabs(wwin);
896 wwin->frame->flags.need_texture_change = 1;
897 wWindowConfigureBorders(wwin);
898 wFrameWindowPaint(wwin->frame);
901 * Can't apply emulate_appicon because it will probably cause problems.
904 if (wapp) {
905 /* do application wide stuff */
906 WSETUFLAG(wapp->main_window_desc, start_hidden,
907 WMGetButtonSelected(panel->appChk[0]));
909 WSETUFLAG(wapp->main_window_desc, no_appicon,
910 WMGetButtonSelected(panel->appChk[1]));
912 WSETUFLAG(wapp->main_window_desc, collapse_appicons,
913 WMGetButtonSelected(panel->appChk[2]));
915 if (WFLAGP(wapp->main_window_desc, no_appicon))
916 removeAppIconFor(wapp);
917 else
918 makeAppIconFor(wapp);
920 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
921 char *file = WMGetTextFieldText(panel->fileText);
923 if (file[0] == 0) {
924 wfree(file);
925 file = NULL;
927 wIconChangeImageFile(wapp->app_icon->icon, file);
928 if (file)
929 wfree(file);
930 wAppIconPaint(wapp->app_icon);
938 static void
939 revertSettings(WMButton *button, InspectorPanel *panel)
941 WWindow *wwin = panel->inspected;
942 WApplication *wapp = wApplicationOf(wwin->main_window);
943 int i, n;
944 char *wm_instance = NULL;
945 char *wm_class = NULL;
946 int workspace, level;
948 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
949 wm_instance = wwin->wm_instance;
950 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
951 wm_class = wwin->wm_class;
952 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
953 wm_instance = wwin->wm_instance;
954 wm_class = wwin->wm_class;
956 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
957 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
958 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
960 wWindowSetupInitialAttributes(wwin, &level, &workspace);
962 for (i=0; i < 11; i++) {
963 int flag = 0;
965 switch (i) {
966 case 0:
967 flag = WFLAGP(wwin, no_titlebar);
968 break;
969 case 1:
970 flag = WFLAGP(wwin, no_resizebar);
971 break;
972 case 2:
973 flag = WFLAGP(wwin, no_close_button);
974 break;
975 case 3:
976 flag = WFLAGP(wwin, no_miniaturize_button);
977 break;
978 case 4:
979 flag = WFLAGP(wwin, no_border);
980 break;
981 case 5:
982 flag = WFLAGP(wwin, floating);
983 break;
984 case 6:
985 flag = WFLAGP(wwin, sunken);
986 break;
987 case 7:
988 flag = WFLAGP(wwin, omnipresent);
989 break;
990 case 8:
991 flag = WFLAGP(wwin, start_miniaturized);
992 break;
993 case 9:
994 flag = WFLAGP(wwin, start_maximized!=0);
995 break;
996 case 10:
997 flag = WFLAGP(wwin, full_maximize);
998 break;
1000 WMSetButtonSelected(panel->attrChk[i], flag);
1002 for (i=0; i < 8; i++) {
1003 int flag = 0;
1005 switch (i) {
1006 case 0:
1007 flag = WFLAGP(wwin, no_bind_keys);
1008 break;
1009 case 1:
1010 flag = WFLAGP(wwin, no_bind_mouse);
1011 break;
1012 case 2:
1013 flag = WFLAGP(wwin, skip_window_list);
1014 break;
1015 case 3:
1016 flag = WFLAGP(wwin, no_focusable);
1017 break;
1018 case 4:
1019 flag = WFLAGP(wwin, dont_move_off);
1020 break;
1021 case 5:
1022 flag = WFLAGP(wwin, no_hide_others);
1023 break;
1024 case 6:
1025 flag = WFLAGP(wwin, dont_save_session);
1026 break;
1027 case 7:
1028 flag = WFLAGP(wwin, emulate_appicon);
1029 break;
1030 #ifdef XKB_BUTTON_HINT
1031 case 8:
1032 flag = WFLAGP(wwin, no_language_button);
1033 break;
1034 #endif
1036 WMSetButtonSelected(panel->moreChk[i], flag);
1038 if (panel->appFrm && wapp) {
1039 for (i=0; i < 2; i++) {
1040 int flag = 0;
1042 switch (i) {
1043 case 0:
1044 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1045 break;
1046 case 1:
1047 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1048 break;
1049 case 2:
1050 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1051 break;
1053 WMSetButtonSelected(panel->appChk[i], flag);
1056 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1058 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1059 REVERT_TO_DEFAULT);
1061 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1063 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1064 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1065 } else {
1066 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1069 /* must auto apply, so that there wno't be internal
1070 * inconsistencies between the state in the flags and
1071 * the actual state of the window */
1072 applySettings(panel->applyBtn, panel);
1076 static void
1077 chooseIconCallback(WMWidget *self, void *clientData)
1079 char *file;
1080 InspectorPanel *panel = (InspectorPanel*)clientData;
1081 int result;
1083 panel->choosingIcon = 1;
1085 WMSetButtonEnabled(panel->browseIconBtn, False);
1087 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1088 panel->inspected->wm_instance,
1089 panel->inspected->wm_class);
1091 panel->choosingIcon = 0;
1093 if (!panel->destroyed) { /* kluge */
1094 if (result) {
1095 WMSetTextFieldText(panel->fileText, file);
1096 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1097 USE_TEXT_FIELD);
1098 wfree(file);
1100 WMSetButtonEnabled(panel->browseIconBtn, True);
1101 } else {
1102 freeInspector(panel);
1107 static void
1108 textEditedObserver(void *observerData, WMNotification *notification)
1110 InspectorPanel *panel = (InspectorPanel*)observerData;
1112 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1113 return;
1115 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1116 USE_TEXT_FIELD);
1118 WMPerformButtonClick(panel->updateIconBtn);
1123 static void
1124 selectSpecification(WMWidget *bPtr, void *data)
1126 InspectorPanel *panel = (InspectorPanel*)data;
1127 char *str;
1128 WWindow *wwin = panel->inspected;
1129 int len;
1131 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1132 WMSetButtonEnabled(panel->applyBtn, False);
1133 } else {
1134 WMSetButtonEnabled(panel->applyBtn, True);
1137 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1138 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1140 str = wmalloc(len);
1142 snprintf(str, len, _("Inspecting %s.%s"),
1143 wwin->wm_instance ? wwin->wm_instance : "?",
1144 wwin->wm_class ? wwin->wm_class : "?");
1146 wFrameWindowChangeTitle(panel->frame->frame, str);
1148 wfree(str);
1152 static void
1153 selectWindow(WMWidget *bPtr, void *data)
1155 InspectorPanel *panel = (InspectorPanel*)data;
1156 WWindow *wwin = panel->inspected;
1157 WScreen *scr = wwin->screen_ptr;
1158 XEvent event;
1159 WWindow *iwin;
1161 if (XGrabPointer(dpy, scr->root_win, True,
1162 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1163 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1164 wwarning("could not grab mouse pointer");
1165 return;
1168 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1170 WMMaskEvent(dpy, ButtonPressMask, &event);
1172 XUngrabPointer(dpy, CurrentTime);
1174 iwin = wWindowFor(event.xbutton.subwindow);
1176 if (iwin && !iwin->flags.internal_window && iwin != wwin
1177 && !iwin->flags.inspector_open) {
1179 iwin->flags.inspector_open = 1;
1180 iwin->inspector = createInspectorForWindow(iwin,
1181 panel->frame->frame_x,
1182 panel->frame->frame_y,
1183 True);
1184 wCloseInspectorForWindow(wwin);
1185 } else {
1186 WMSetLabelText(panel->specLbl, spec_text);
1192 static InspectorPanel*
1193 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1194 Bool showSelectPanel)
1196 WScreen *scr = wwin->screen_ptr;
1197 InspectorPanel *panel;
1198 Window parent;
1199 int i;
1200 int x, y;
1201 int btn_width, frame_width;
1202 WMButton *selectedBtn = NULL;
1203 #ifdef wrong_behaviour
1204 WMPixmap *pixmap;
1205 #endif
1207 spec_text = _("The configuration will apply to all\n"
1208 "windows that have their WM_CLASS\n"
1209 "property set to the above selected\n"
1210 "name, when saved.");
1212 panel = wmalloc(sizeof(InspectorPanel));
1213 memset(panel, 0, sizeof(InspectorPanel));
1215 panel->destroyed = 0;
1218 panel->inspected = wwin;
1220 panel->nextPtr = panelList;
1221 panelList = panel;
1224 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1225 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1228 /**** create common stuff ****/
1230 /* command buttons */
1231 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1232 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1233 panel->saveBtn = WMCreateCommandButton(panel->win);
1234 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1235 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1236 WMSetButtonText(panel->saveBtn, _("Save"));
1237 WMResizeWidget(panel->saveBtn, btn_width, 28);
1238 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1239 WMSetButtonEnabled(panel->saveBtn, False);
1241 panel->applyBtn = WMCreateCommandButton(panel->win);
1242 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1243 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1244 WMSetButtonText(panel->applyBtn, _("Apply"));
1245 WMResizeWidget(panel->applyBtn, btn_width, 28);
1247 panel->revertBtn = WMCreateCommandButton(panel->win);
1248 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1249 WMMoveWidget(panel->revertBtn, 15, 310);
1250 WMSetButtonText(panel->revertBtn, _("Reload"));
1251 WMResizeWidget(panel->revertBtn, btn_width, 28);
1253 /* page selection popup button */
1254 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1255 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1256 WMMoveWidget(panel->pagePopUp, 25, 15);
1257 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1259 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1260 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1261 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1262 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1263 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1265 /**** window spec ****/
1266 frame_width = PWIDTH - (2 * 15);
1268 panel->specFrm = WMCreateFrame(panel->win);
1269 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1270 WMMoveWidget(panel->specFrm, 15, 65);
1271 WMResizeWidget(panel->specFrm, frame_width, 145);
1274 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1275 WMMoveWidget(panel->defaultRb, 10, 78);
1276 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1277 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1278 WMSetButtonSelected(panel->defaultRb, False);
1279 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1281 if (wwin->wm_class && wwin->wm_instance) {
1282 char *str, *tmp;
1284 tmp = wstrconcat(wwin->wm_instance, ".");
1285 str = wstrconcat(tmp, wwin->wm_class);
1287 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1288 WMMoveWidget(panel->bothRb, 10, 18);
1289 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1290 WMSetButtonText(panel->bothRb, str);
1291 wfree(tmp);
1292 wfree(str);
1293 WMGroupButtons(panel->defaultRb, panel->bothRb);
1295 if (!selectedBtn)
1296 selectedBtn = panel->bothRb;
1298 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1301 if (wwin->wm_instance) {
1302 panel->instRb = WMCreateRadioButton(panel->specFrm);
1303 WMMoveWidget(panel->instRb, 10, 38);
1304 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1305 WMSetButtonText(panel->instRb, wwin->wm_instance);
1306 WMGroupButtons(panel->defaultRb, panel->instRb);
1308 if (!selectedBtn)
1309 selectedBtn = panel->instRb;
1311 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1314 if (wwin->wm_class) {
1315 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1316 WMMoveWidget(panel->clsRb, 10, 58);
1317 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1318 WMSetButtonText(panel->clsRb, wwin->wm_class);
1319 WMGroupButtons(panel->defaultRb, panel->clsRb);
1321 if (!selectedBtn)
1322 selectedBtn = panel->clsRb;
1324 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1328 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1329 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1330 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1331 WMSetButtonText(panel->selWinB, _("Select window"));
1332 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1335 panel->specLbl = WMCreateLabel(panel->win);
1336 WMMoveWidget(panel->specLbl, 15, 210);
1337 WMResizeWidget(panel->specLbl, frame_width, 100);
1338 WMSetLabelText(panel->specLbl, spec_text);
1339 WMSetLabelWraps(panel->specLbl, True);
1341 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1343 /**** attributes ****/
1344 panel->attrFrm = WMCreateFrame(panel->win);
1345 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1346 WMMoveWidget(panel->attrFrm, 15, 45);
1347 WMResizeWidget(panel->attrFrm, frame_width, 250);
1349 for (i=0; i < 11; i++) {
1350 char *caption = NULL;
1351 int flag = 0;
1352 char *descr = NULL;
1354 switch (i) {
1355 case 0:
1356 caption = _("Disable titlebar");
1357 flag = WFLAGP(wwin, no_titlebar);
1358 descr = _("Remove the titlebar of this window.\n"
1359 "To access the window commands menu of a window\n"
1360 "without it's titlebar, press Control+Esc (or the\n"
1361 "equivalent shortcut, if you changed the default\n"
1362 "settings).");
1363 break;
1364 case 1:
1365 caption = _("Disable resizebar");
1366 flag = WFLAGP(wwin, no_resizebar);
1367 descr = _("Remove the resizebar of this window.");
1368 break;
1369 case 2:
1370 caption = _("Disable close button");
1371 flag = WFLAGP(wwin, no_close_button);
1372 descr = _("Remove the `close window' button of this window.");
1373 break;
1374 case 3:
1375 caption = _("Disable miniaturize button");
1376 flag = WFLAGP(wwin, no_miniaturize_button);
1377 descr = _("Remove the `miniaturize window' button of the window.");
1378 break;
1379 case 4:
1380 caption = _("Disable border");
1381 flag = WFLAGP(wwin, no_border);
1382 descr = _("Remove the 1 pixel black border around the window.");
1383 break;
1384 case 5:
1385 caption = _("Keep on top (floating)");
1386 flag = WFLAGP(wwin, floating);
1387 descr = _("Keep the window over other windows, not allowing\n"
1388 "them to cover it.");
1389 break;
1390 case 6:
1391 caption = _("Keep at bottom (sunken)");
1392 flag = WFLAGP(wwin, sunken);
1393 descr = _("Keep the window under all other windows.");
1394 break;
1395 case 7:
1396 caption = _("Omnipresent");
1397 flag = WFLAGP(wwin, omnipresent);
1398 descr = _("Make window present in all workspaces.");
1399 break;
1400 case 8:
1401 caption = _("Start miniaturized");
1402 flag = WFLAGP(wwin, start_miniaturized);
1403 descr = _("Make the window be automatically miniaturized when it's\n"
1404 "first shown.");
1405 break;
1406 case 9:
1407 caption = _("Start maximized");
1408 flag = WFLAGP(wwin, start_maximized!=0);
1409 descr = _("Make the window be automatically maximized when it's\n"
1410 "first shown.");
1411 break;
1412 case 10:
1413 caption = _("Full screen maximization");
1414 flag = WFLAGP(wwin, full_maximize);
1415 descr = _("Make the window use the whole screen space when it's\n"
1416 "maximized. The titlebar and resizebar will be moved\n"
1417 "to outside the screen.");
1418 break;
1420 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1421 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1422 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1423 WMSetButtonSelected(panel->attrChk[i], flag);
1424 WMSetButtonText(panel->attrChk[i], caption);
1426 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1430 /**** more attributes ****/
1431 panel->moreFrm = WMCreateFrame(panel->win);
1432 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1433 WMMoveWidget(panel->moreFrm, 15, 45);
1434 WMResizeWidget(panel->moreFrm, frame_width, 250);
1436 for (i=0;
1437 #ifdef XKB_BUTTON_HINT
1438 i < 9;
1439 #else
1440 i < 8;
1441 #endif
1442 i++) {
1443 char *caption = NULL;
1444 int flag = 0;
1445 char *descr = NULL;
1447 switch (i) {
1448 case 0:
1449 caption = _("Do not bind keyboard shortcuts");
1450 flag = WFLAGP(wwin, no_bind_keys);
1451 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1452 "when this window is focused. This will allow the\n"
1453 "window to receive all key combinations regardless\n"
1454 "of your shortcut configuration.");
1455 break;
1456 case 1:
1457 caption = _("Do not bind mouse clicks");
1458 flag = WFLAGP(wwin, no_bind_mouse);
1459 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1460 "in the window (when alt is the modifier you have"
1461 "configured).");
1462 break;
1463 case 2:
1464 caption = _("Do not show in the window list");
1465 flag = WFLAGP(wwin, skip_window_list);
1466 descr = _("Do not list the window in the window list menu.");
1467 break;
1468 case 3:
1469 caption = _("Do not let it take focus");
1470 flag = WFLAGP(wwin, no_focusable);
1471 descr = _("Do not let the window take keyboard focus when you\n"
1472 "click on it.");
1473 break;
1474 case 4:
1475 caption = _("Keep inside screen");
1476 flag = WFLAGP(wwin, dont_move_off);
1477 descr = _("Do not allow the window to move itself completely\n"
1478 "outside the screen. For bug compatibility.\n");
1479 break;
1480 case 5:
1481 caption = _("Ignore 'Hide Others'");
1482 flag = WFLAGP(wwin, no_hide_others);
1483 descr = _("Do not hide the window when issuing the\n"
1484 "`HideOthers' command.");
1485 break;
1486 case 6:
1487 caption = _("Ignore 'Save Session'");
1488 flag = WFLAGP(wwin, dont_save_session);
1489 descr = _("Do not save the associated application in the\n"
1490 "session's state, so that it won't be restarted\n"
1491 "together with other applications when Window Maker\n"
1492 "starts.");
1493 break;
1494 case 7:
1495 caption = _("Emulate application icon");
1496 flag = WFLAGP(wwin, emulate_appicon);
1497 descr = _("Make this window act as an application that provides\n"
1498 "enough information to Window Maker for a dockable\n"
1499 "application icon to be created.");
1500 break;
1501 #ifdef XKB_BUTTON_HINT
1502 case 8:
1503 caption = _("Disable language button");
1504 flag = WFLAGP(wwin, no_language_button);
1505 descr = _("Remove the `toggle language' button of the window.");
1506 break;
1507 #endif
1509 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1510 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1511 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1512 WMSetButtonSelected(panel->moreChk[i], flag);
1513 WMSetButtonText(panel->moreChk[i], caption);
1515 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1518 /* miniwindow/workspace */
1519 panel->iconFrm = WMCreateFrame(panel->win);
1520 WMMoveWidget(panel->iconFrm, 15, 50);
1521 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1522 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1524 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1525 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1526 WMResizeWidget(panel->iconLbl, 64, 64);
1527 WMSetLabelRelief(panel->iconLbl, WRGroove);
1528 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1530 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1531 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1532 WMMoveWidget(panel->browseIconBtn, 22, 32);
1533 WMResizeWidget(panel->browseIconBtn, 120, 26);
1534 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1536 #ifdef wrong_behaviour
1537 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1538 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1539 WMSetButtonImage(panel->updateIconBtn, pixmap);
1540 WMReleasePixmap(pixmap);
1541 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1542 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1543 WMReleasePixmap(pixmap);
1544 #endif
1546 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1547 WMMoveWidget(panel->fileLbl, 20, 85);
1548 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1549 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1551 panel->fileText = WMCreateTextField(panel->iconFrm);
1552 WMMoveWidget(panel->fileText, 20, 105);
1553 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1554 WMSetTextFieldText(panel->fileText, NULL);
1555 WMAddNotificationObserver(textEditedObserver, panel,
1556 WMTextDidEndEditingNotification,
1557 panel->fileText);
1559 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1560 WMMoveWidget(panel->alwChk, 20, 130);
1561 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1562 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1563 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1566 panel->wsFrm = WMCreateFrame(panel->win);
1567 WMMoveWidget(panel->wsFrm, 15, 225);
1568 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1569 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1571 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1572 "first shown."), WMWidgetView(panel->wsFrm));
1574 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1575 WMMoveWidget(panel->wsP, 20, 30);
1576 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1577 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1578 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1579 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1582 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1583 wwin->wm_class);
1584 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1585 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1586 } else {
1587 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1590 /* application wide attributes */
1591 if (wwin->main_window != None) {
1592 WApplication *wapp = wApplicationOf(wwin->main_window);
1594 panel->appFrm = WMCreateFrame(panel->win);
1595 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1596 WMMoveWidget(panel->appFrm, 15, 50);
1597 WMResizeWidget(panel->appFrm, frame_width, 240);
1599 for (i=0; i < 3; i++) {
1600 char *caption = NULL;
1601 int flag = 0;
1602 char *descr = NULL;
1604 switch (i) {
1605 case 0:
1606 caption = _("Start hidden");
1607 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1608 descr = _("Automatically hide application when it's started.");
1609 break;
1610 case 1:
1611 caption = _("No application icon");
1612 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1613 descr = _("Disable the application icon for the application.\n"
1614 "Note that you won't be able to dock it anymore,\n"
1615 "and any icons that are already docked will stop\n"
1616 "working correctly.");
1617 break;
1618 case 2:
1619 caption = _("Collapse application icons");
1620 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1621 descr = _("Collapse application icons from other instances\n"
1622 "of this application into one.\n");
1623 break;
1625 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1626 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1627 WMResizeWidget(panel->appChk[i], 205, 20);
1628 WMSetButtonSelected(panel->appChk[i], flag);
1629 WMSetButtonText(panel->appChk[i], caption);
1631 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1634 if (WFLAGP(wwin, emulate_appicon)) {
1635 WMSetButtonEnabled(panel->appChk[1], False);
1636 WMSetButtonEnabled(panel->moreChk[7], True);
1637 } else {
1638 WMSetButtonEnabled(panel->appChk[1], True);
1639 WMSetButtonEnabled(panel->moreChk[7], False);
1641 } else {
1642 int tmp;
1644 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1645 || !wwin->wm_class || !wwin->wm_instance)
1646 tmp = False;
1647 else
1648 tmp = True;
1649 WMSetButtonEnabled(panel->moreChk[7], tmp);
1651 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1652 panel->appFrm = NULL;
1655 /* if the window is a transient, don't let it have a miniaturize
1656 * button */
1657 if (wWindowFor(wwin->transient_for)!=NULL)
1658 WMSetButtonEnabled(panel->attrChk[3], False);
1659 else
1660 WMSetButtonEnabled(panel->attrChk[3], True);
1663 if (!wwin->wm_class && !wwin->wm_instance) {
1664 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1668 WMRealizeWidget(panel->win);
1670 WMMapSubwidgets(panel->win);
1671 WMMapSubwidgets(panel->specFrm);
1672 WMMapSubwidgets(panel->attrFrm);
1673 WMMapSubwidgets(panel->moreFrm);
1674 WMMapSubwidgets(panel->iconFrm);
1675 WMMapSubwidgets(panel->wsFrm);
1676 if (panel->appFrm)
1677 WMMapSubwidgets(panel->appFrm);
1679 if (showSelectPanel) {
1680 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1681 changePage(panel->pagePopUp, panel);
1682 } else {
1683 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1684 changePage(panel->pagePopUp, panel);
1688 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1689 0, 0, 0);
1690 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1691 panel->parent = parent;
1692 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1694 WMMapWidget(panel->win);
1696 XSetTransientForHint(dpy, parent, wwin->client_win);
1698 if (xpos == UNDEFINED_POS) {
1699 x = wwin->frame_x+wwin->frame->core->width/2;
1700 y = wwin->frame_y+wwin->frame->top_width*2;
1701 if (y + PHEIGHT > scr->scr_height)
1702 y = scr->scr_height - PHEIGHT - 30;
1703 if (x + PWIDTH > scr->scr_width)
1704 x = scr->scr_width - PWIDTH;
1705 } else {
1706 x = xpos;
1707 y = ypos;
1710 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1711 "Inspector", x, y, PWIDTH, PHEIGHT);
1713 if (!selectedBtn)
1714 selectedBtn = panel->defaultRb;
1716 WMSetButtonSelected(selectedBtn, True);
1718 selectSpecification(selectedBtn, panel);
1720 /* kluge to know who should get the key events */
1721 panel->frame->client_leader = WMWidgetXID(panel->win);
1723 WSETUFLAG(panel->frame, no_closable, 0);
1724 WSETUFLAG(panel->frame, no_close_button, 0);
1725 wWindowUpdateButtonImages(panel->frame);
1726 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1727 panel->frame->frame->on_click_right = destroyInspector;
1729 wWindowMap(panel->frame);
1731 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1732 wwin->wm_class, UPDATE_TEXT_FIELD);
1734 return panel;
1738 void
1739 wShowInspectorForWindow(WWindow *wwin)
1741 if (wwin->flags.inspector_open)
1742 return;
1744 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1746 make_keys();
1747 wwin->flags.inspector_open = 1;
1748 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1749 UNDEFINED_POS, False);
1755 void
1756 wHideInspectorForWindow(WWindow *wwin)
1758 WWindow *pwin = wwin->inspector->frame;
1760 wWindowUnmap(pwin);
1761 pwin->flags.hidden = 1;
1763 wClientSetState(pwin, IconicState, None);
1768 void
1769 wUnhideInspectorForWindow(WWindow *wwin)
1771 WWindow *pwin = wwin->inspector->frame;
1773 pwin->flags.hidden = 0;
1774 pwin->flags.mapped = 1;
1775 XMapWindow(dpy, pwin->client_win);
1776 XMapWindow(dpy, pwin->frame->core->window);
1777 wClientSetState(pwin, NormalState, None);
1782 WWindow*
1783 wGetWindowOfInspectorForWindow(WWindow *wwin)
1785 if (wwin->inspector) {
1786 assert(wwin->flags.inspector_open != 0);
1788 return wwin->inspector->frame;
1789 } else
1790 return NULL;
1794 void
1795 wCloseInspectorForWindow(WWindow *wwin)
1797 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1799 (*pwin->frame->on_click_right)(NULL, pwin, NULL);