spelling typo fixed
[wmaker-crm.git] / src / winspector.c
blob1aa528b88ab4ca8d53d3f13a5199423e5c986c6c
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"
50 #include <proplist.h>
58 typedef struct InspectorPanel {
59 struct InspectorPanel *nextPtr;
61 WWindow *frame;
63 WWindow *inspected; /* the window that's being inspected */
65 WMWindow *win;
67 Window parent;
69 /* common stuff */
70 WMButton *revertBtn;
71 WMButton *applyBtn;
72 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
84 WMButton *selWinB;
86 WMLabel *specLbl;
88 /* second page. attributes */
90 WMFrame *attrFrm;
91 WMButton *attrChk[11];
93 /* 3rd page. more attributes */
94 WMFrame *moreFrm;
95 #ifdef XKB_BUTTON_HINT
96 WMButton *moreChk[9];
97 #else
98 WMButton *moreChk[8];
99 #endif
101 /* 4th page. icon and workspace */
102 WMFrame *iconFrm;
103 WMLabel *iconLbl;
104 WMLabel *fileLbl;
105 WMTextField *fileText;
106 WMButton *alwChk;
108 WMButton *updateIconBtn;
110 WMButton *browseIconBtn;
112 WMFrame *wsFrm;
113 WMPopUpButton *wsP;
115 /* 5th page. application wide attributes */
116 WMFrame *appFrm;
117 WMButton *appChk[3];
119 unsigned int done:1;
120 unsigned int destroyed:1;
121 unsigned int choosingIcon:1;
122 } InspectorPanel;
127 extern Cursor wCursor[WCUR_LAST];
129 extern WDDomain *WDWindowAttributes;
131 static InspectorPanel *panelList=NULL;
133 extern WPreferences wPreferences;
135 static proplist_t ANoTitlebar = NULL;
136 static proplist_t ANoResizebar;
137 static proplist_t ANoMiniaturizeButton;
138 static proplist_t ANoCloseButton;
139 static proplist_t ANoBorder;
140 static proplist_t ANoHideOthers;
141 static proplist_t ANoMouseBindings;
142 static proplist_t ANoKeyBindings;
143 static proplist_t ANoAppIcon;
144 static proplist_t AKeepOnTop;
145 static proplist_t AKeepOnBottom;
146 static proplist_t AOmnipresent;
147 static proplist_t ASkipWindowList;
148 static proplist_t AKeepInsideScreen;
149 static proplist_t AUnfocusable;
150 static proplist_t AAlwaysUserIcon;
151 static proplist_t AStartMiniaturized;
152 static proplist_t AStartMaximized;
153 static proplist_t ADontSaveSession;
154 static proplist_t AEmulateAppIcon;
155 static proplist_t AFullMaximize;
156 static proplist_t ACollapseAppIcons;
157 #ifdef XKB_BUTTON_HINT
158 static proplist_t ANoLanguageButton;
159 #endif
161 static proplist_t AStartWorkspace;
163 static proplist_t AIcon;
165 /* application wide options */
166 static proplist_t AStartHidden;
169 static proplist_t AnyWindow;
170 static proplist_t EmptyString;
171 static proplist_t Yes, No;
174 #define PWIDTH 270
175 #define PHEIGHT 350
179 static char *spec_text;
182 static void applySettings(WMButton *button, InspectorPanel *panel);
187 #define UNDEFINED_POS 0xffffff
189 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
190 int xpos, int ypos,
191 Bool showSelectPanel);
195 static void
196 make_keys()
198 if (ANoTitlebar!=NULL)
199 return;
201 AIcon = PLMakeString("Icon");
202 ANoTitlebar = PLMakeString("NoTitlebar");
203 ANoResizebar = PLMakeString("NoResizebar");
204 ANoMiniaturizeButton = PLMakeString("NoMiniaturizeButton");
205 ANoCloseButton = PLMakeString("NoCloseButton");
206 ANoBorder = PLMakeString("NoBorder");
207 ANoHideOthers = PLMakeString("NoHideOthers");
208 ANoMouseBindings = PLMakeString("NoMouseBindings");
209 ANoKeyBindings = PLMakeString("NoKeyBindings");
210 ANoAppIcon = PLMakeString("NoAppIcon");
211 AKeepOnTop = PLMakeString("KeepOnTop");
212 AKeepOnBottom = PLMakeString("KeepOnBottom");
213 AOmnipresent = PLMakeString("Omnipresent");
214 ASkipWindowList = PLMakeString("SkipWindowList");
215 AKeepInsideScreen = PLMakeString("KeepInsideScreen");
216 AUnfocusable = PLMakeString("Unfocusable");
217 AAlwaysUserIcon = PLMakeString("AlwaysUserIcon");
218 AStartMiniaturized = PLMakeString("StartMiniaturized");
219 AStartMaximized = PLMakeString("StartMaximized");
220 AStartHidden = PLMakeString("StartHidden");
221 ADontSaveSession = PLMakeString("DontSaveSession");
222 AEmulateAppIcon = PLMakeString("EmulateAppIcon");
223 AFullMaximize = PLMakeString("FullMaximize");
224 ACollapseAppIcons = PLMakeString("CollapseAppIcons");
225 #ifdef XKB_BUTTON_HINT
226 ANoLanguageButton = PLMakeString("NoLanguageButton");
227 #endif
229 AStartWorkspace = PLMakeString("StartWorkspace");
231 AnyWindow = PLMakeString("*");
232 EmptyString = PLMakeString("");
233 Yes = PLMakeString("Yes");
234 No = PLMakeString("No");
239 static void
240 freeInspector(InspectorPanel *panel)
242 panel->destroyed = 1;
243 if (panel->choosingIcon)
244 return;
246 WMDestroyWidget(panel->win);
248 XDestroyWindow(dpy, panel->parent);
250 wfree(panel);
254 static void
255 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
257 InspectorPanel *panel;
258 InspectorPanel *tmp;
260 panel = panelList;
261 while (panel->frame!=data)
262 panel = panel->nextPtr;
264 if (panelList == panel)
265 panelList = panel->nextPtr;
266 else {
267 tmp = panelList;
268 while (tmp->nextPtr!=panel) {
269 tmp = tmp->nextPtr;
271 tmp->nextPtr = panel->nextPtr;
273 panel->inspected->flags.inspector_open = 0;
274 panel->inspected->inspector = NULL;
276 WMRemoveNotificationObserver(panel);
278 wWindowUnmap(panel->frame);
279 wUnmanageWindow(panel->frame, True, False);
281 freeInspector(panel);
286 void
287 wDestroyInspectorPanels()
289 InspectorPanel *panel;
291 while (panelList != NULL) {
292 panel = panelList;
293 panelList = panelList->nextPtr;
294 wUnmanageWindow(panel->frame, False, False);
295 WMDestroyWidget(panel->win);
297 panel->inspected->flags.inspector_open = 0;
298 panel->inspected->inspector = NULL;
300 wfree(panel);
305 static void
306 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
308 int page;
310 page = WMGetPopUpButtonSelectedItem(bPtr);
312 if (page == 0) {
313 WMMapWidget(panel->specFrm);
314 WMMapWidget(panel->specLbl);
315 } else if (page == 1) {
316 WMMapWidget(panel->attrFrm);
317 } else if (page == 2) {
318 WMMapWidget(panel->moreFrm);
319 } else if (page == 3) {
320 WMMapWidget(panel->iconFrm);
321 WMMapWidget(panel->wsFrm);
322 } else {
323 WMMapWidget(panel->appFrm);
326 if (page != 0) {
327 WMUnmapWidget(panel->specFrm);
328 WMUnmapWidget(panel->specLbl);
330 if (page != 1)
331 WMUnmapWidget(panel->attrFrm);
332 if (page != 2)
333 WMUnmapWidget(panel->moreFrm);
334 if (page != 3) {
335 WMUnmapWidget(panel->iconFrm);
336 WMUnmapWidget(panel->wsFrm);
338 if (page != 4 && panel->appFrm)
339 WMUnmapWidget(panel->appFrm);
343 #define USE_TEXT_FIELD 1
344 #define UPDATE_TEXT_FIELD 2
345 #define REVERT_TO_DEFAULT 4
348 static int
349 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
350 char *wm_instance, char *wm_class, int flags)
352 WMPixmap *pixmap = (WMPixmap*) NULL;
353 char *file=NULL, *path=NULL;
354 char *db_icon=NULL;
356 if ((flags & USE_TEXT_FIELD) != 0) {
357 file = WMGetTextFieldText(panel->fileText);
358 if (file && file[0] == 0) {
359 wfree(file);
360 file = NULL;
362 } else {
363 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
364 wm_instance, wm_class, False);
365 if(db_icon != NULL)
366 file = wstrdup(db_icon);
368 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
369 if (file)
370 file = wstrdup(db_icon);
371 flags |= UPDATE_TEXT_FIELD;
374 if ((flags & UPDATE_TEXT_FIELD) != 0) {
375 WMSetTextFieldText(panel->fileText, file);
378 if (file) {
379 path = FindImage(wPreferences.icon_path, file);
381 if (!path) {
382 char *buf;
384 buf = wmalloc(strlen(file)+80);
385 sprintf(buf, _("Could not find icon \"%s\" specified for this window"),
386 file);
387 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
388 _("OK"), NULL, NULL);
389 wfree(buf);
390 wfree(file);
391 return -1;
394 pixmap = WMCreatePixmapFromFile(scrPtr, path);
395 wfree(path);
397 if (!pixmap) {
398 char *buf;
400 buf = wmalloc(strlen(file)+80);
401 sprintf(buf, _("Could not open specified icon \"%s\":%s"),
402 file, RMessageForError(RErrorCode));
403 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
404 _("OK"), NULL, NULL);
405 wfree(buf);
406 wfree(file);
407 return -1;
409 wfree(file);
412 WMSetLabelImage(panel->iconLbl, pixmap);
413 if (pixmap)
414 WMReleasePixmap(pixmap);
416 return 0;
419 #if 0
420 static void
421 updateIcon(WMButton *button, InspectorPanel *panel)
423 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
425 #endif
427 static int
428 getBool(proplist_t value)
430 char *val;
432 if (!PLIsString(value)) {
433 return 0;
435 if (!(val = PLGetString(value))) {
436 return 0;
439 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
440 || val[0]=='t' || val[0]=='1'))
441 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
443 return 1;
444 } else if ((val[1]=='\0'
445 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
446 || val[0]=='f' || val[0]=='0'))
447 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
449 return 0;
450 } else {
451 wwarning(_("can't convert \"%s\" to boolean"), val);
452 return 0;
457 #define UPDATE_DEFAULTS 1
458 #define IS_BOOLEAN 2
462 * Will insert the attribute = value; pair in window's list,
463 * if it's different from the defaults.
464 * Defaults means either defaults database, or attributes saved
465 * for the default window "*". This is to let one revert options that are
466 * global because they were saved for all windows ("*").
471 static int
472 insertAttribute(proplist_t dict, proplist_t window, proplist_t attr,
473 proplist_t value, int flags)
475 proplist_t def_win, def_value=NULL;
476 int update = 0;
477 int modified = 0;
479 if (!(flags & UPDATE_DEFAULTS) && dict) {
480 if ((def_win = PLGetDictionaryEntry(dict, AnyWindow)) != NULL) {
481 def_value = PLGetDictionaryEntry(def_win, attr);
485 /* If we could not find defaults in database, fall to hardcoded values.
486 * Also this is true if we save defaults for all windows
488 if (!def_value)
489 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
491 if ((flags & IS_BOOLEAN))
492 update = (getBool(value) != getBool(def_value));
493 else {
494 update = !PLIsEqual(value, def_value);
497 if (update) {
498 PLInsertDictionaryEntry(window, attr, value);
499 modified = 1;
502 return modified;
506 static void
507 saveSettings(WMButton *button, InspectorPanel *panel)
509 WWindow *wwin = panel->inspected;
510 WDDomain *db = WDWindowAttributes;
511 proplist_t dict = db->dictionary;
512 proplist_t winDic, value, key;
513 char *icon_file;
514 int flags = 0;
515 int different = 0;
517 /* Save will apply the changes and save them */
518 applySettings(panel->applyBtn, panel);
520 if (WMGetButtonSelected(panel->instRb) != 0)
521 key = PLMakeString(wwin->wm_instance);
522 else if (WMGetButtonSelected(panel->clsRb) != 0)
523 key = PLMakeString(wwin->wm_class);
524 else if (WMGetButtonSelected(panel->bothRb) != 0) {
525 char *buffer;
527 buffer = wmalloc(strlen(wwin->wm_instance)+strlen(wwin->wm_class)+4);
528 strcat(strcat(strcpy(buffer, wwin->wm_instance), "."), wwin->wm_class);
529 key = PLMakeString(buffer);
530 wfree(buffer);
531 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
532 key = PLRetain(AnyWindow);
533 flags = UPDATE_DEFAULTS;
534 } else
535 key = NULL;
537 if (!key)
538 return;
540 if (!dict) {
541 dict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
542 if (dict) {
543 db->dictionary = dict;
544 value = PLMakeString(db->path);
545 PLSetFilename(dict, value);
546 PLRelease(value);
548 else {
549 PLRelease(key);
550 return;
554 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
555 USE_TEXT_FIELD) < 0)
556 return;
558 PLSetStringCmpHook(NULL);
560 winDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
562 /* Update icon for window */
563 icon_file = WMGetTextFieldText(panel->fileText);
564 if (icon_file) {
565 if (icon_file[0] != 0) {
566 value = PLMakeString(icon_file);
567 different |= insertAttribute(dict, winDic, AIcon, value, flags);
568 PLRelease(value);
570 wfree(icon_file);
574 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
576 i--;
578 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
579 value = PLMakeString(panel->frame->screen_ptr->workspaces[i]->name);
580 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
581 flags);
582 PLRelease(value);
586 flags |= IS_BOOLEAN;
588 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
589 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
591 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
594 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
595 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
597 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
598 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
600 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
601 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
603 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
604 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
606 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
607 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
609 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
610 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
612 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
613 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
615 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
616 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
618 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
619 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
621 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
622 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
625 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
626 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
628 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
629 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
631 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
632 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
634 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
635 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
637 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
638 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
640 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
641 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
643 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
644 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
646 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
647 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
649 #ifdef XKB_BUTTON_HINT
650 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
651 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
652 #endif
654 /* application wide settings for when */
655 /* the window is the leader, save the attribute with the others */
656 if (panel->inspected->main_window == panel->inspected->client_win) {
658 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
659 different |= insertAttribute(dict, winDic, AStartHidden, value, flags);
661 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
662 different |= insertAttribute(dict, winDic, ANoAppIcon, value, flags);
664 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
665 different |= insertAttribute(dict, winDic, ACollapseAppIcons, value, flags);
668 PLRemoveDictionaryEntry(dict, key);
669 if (different) {
670 PLInsertDictionaryEntry(dict, key, winDic);
673 PLRelease(key);
674 PLRelease(winDic);
676 different = 0;
678 /* application wide settings */
679 if (panel->inspected->main_window != panel->inspected->client_win
680 && !(flags & UPDATE_DEFAULTS)) {
681 WApplication *wapp;
682 proplist_t appDic;
684 wapp = wApplicationOf(panel->inspected->main_window);
685 if (wapp) {
686 char *iconFile;
687 char *buffer;
689 appDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
691 assert(wapp->main_window_desc->wm_instance!=NULL);
692 assert(wapp->main_window_desc->wm_class!=NULL);
694 buffer = wmalloc(strlen(wapp->main_window_desc->wm_instance)
695 +strlen(wapp->main_window_desc->wm_class)+4);
696 strcat(strcpy(buffer, wapp->main_window_desc->wm_instance), ".");
697 strcat(buffer, wapp->main_window_desc->wm_class);
698 key = PLMakeString(buffer);
699 wfree(buffer);
701 iconFile = wDefaultGetIconFile(wwin->screen_ptr,
702 wapp->main_window_desc->wm_instance,
703 wapp->main_window_desc->wm_class,
704 False);
706 if (iconFile && iconFile[0]!=0) {
707 value = PLMakeString(iconFile);
708 different |= insertAttribute(dict, appDic, AIcon, value,
709 flags&~IS_BOOLEAN);
710 PLRelease(value);
713 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
714 different |= insertAttribute(dict, appDic, AStartHidden, value,
715 flags);
717 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
718 different |= insertAttribute(dict, appDic, ANoAppIcon, value,
719 flags);
721 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
722 different |= insertAttribute(dict, appDic, ACollapseAppIcons, value,
723 flags);
725 PLRemoveDictionaryEntry(dict, key);
726 if (different) {
727 PLInsertDictionaryEntry(dict, key, appDic);
729 PLRelease(key);
730 PLRelease(appDic);
734 PLSave(dict, YES);
736 /* clean up */
737 PLSetStringCmpHook(StringCompareHook);
741 static void
742 makeAppIconFor(WApplication *wapp)
744 WScreen *scr = wapp->main_window_desc->screen_ptr;
746 if (wapp->app_icon)
747 return;
749 if (!WFLAGP(wapp->main_window_desc, no_appicon))
750 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
751 else
752 wapp->app_icon = NULL;
754 if (wapp->app_icon) {
755 WIcon *icon = wapp->app_icon->icon;
756 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
757 int x=0, y=0;
759 wapp->app_icon->main_window = wapp->main_window;
761 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
762 wapp->app_icon->attracted = 1;
763 if (!wapp->app_icon->icon->shadowed) {
764 wapp->app_icon->icon->shadowed = 1;
765 wapp->app_icon->icon->force_paint = 1;
767 wDockAttachIcon(clip, wapp->app_icon, x, y);
768 } else {
769 PlaceIcon(scr, &x, &y);
770 wAppIconMove(wapp->app_icon, x, y);
772 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
773 XMapWindow(dpy, icon->core->window);
775 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
776 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
781 static void
782 removeAppIconFor(WApplication *wapp)
784 if (!wapp->app_icon)
785 return;
787 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
788 wapp->app_icon->running = 0;
789 /* since we keep it, we don't care if it was attracted or not */
790 wapp->app_icon->attracted = 0;
791 wapp->app_icon->icon->shadowed = 0;
792 wapp->app_icon->main_window = None;
793 wapp->app_icon->pid = 0;
794 wapp->app_icon->icon->owner = NULL;
795 wapp->app_icon->icon->icon_win = None;
796 wapp->app_icon->icon->force_paint = 1;
797 wAppIconPaint(wapp->app_icon);
798 } else if (wapp->app_icon->docked) {
799 wapp->app_icon->running = 0;
800 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
801 } else {
802 wAppIconDestroy(wapp->app_icon);
804 wapp->app_icon = NULL;
805 if (wPreferences.auto_arrange_icons)
806 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
810 static void
811 applySettings(WMButton *button, InspectorPanel *panel)
813 WWindow *wwin = panel->inspected;
814 WApplication *wapp = wApplicationOf(wwin->main_window);
815 int floating, sunken, skip_window_list;
816 int old_omnipresent;
817 int old_no_bind_keys;
818 int old_no_bind_mouse;
820 old_omnipresent = WFLAGP(wwin, omnipresent);
821 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
822 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
824 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
826 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
827 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
828 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
829 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
830 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
831 floating = WMGetButtonSelected(panel->attrChk[5]);
832 sunken = WMGetButtonSelected(panel->attrChk[6]);
833 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
834 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
835 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
836 skip_window_list = WMGetButtonSelected(panel->attrChk[10]);
838 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[0]));
839 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[1]));
840 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[2]));
841 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[3]));
842 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
843 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[5]));
844 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[6]));
845 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->moreChk[7]));
846 #ifdef XKB_BUTTON_HINT
847 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
848 #endif
849 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
851 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
852 wUnshadeWindow(wwin);
854 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
856 if (floating) {
857 if (!WFLAGP(wwin, floating))
858 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
859 } else if (sunken) {
860 if (!WFLAGP(wwin, sunken))
861 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
862 } else {
863 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
864 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
867 WSETUFLAG(wwin, sunken, sunken);
868 WSETUFLAG(wwin, floating, floating);
869 wwin->flags.omnipresent = 0;
871 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
872 WSETUFLAG(wwin, skip_window_list, skip_window_list);
873 UpdateSwitchMenu(wwin->screen_ptr, wwin,
874 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
875 } else {
876 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
877 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
881 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
882 if (WFLAGP(wwin, no_bind_keys)) {
883 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
884 } else {
885 wWindowSetKeyGrabs(wwin);
889 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
890 wWindowResetMouseGrabs(wwin);
893 wwin->frame->flags.need_texture_change = 1;
894 wWindowConfigureBorders(wwin);
895 wFrameWindowPaint(wwin->frame);
898 * Can't apply emulate_appicon because it will probably cause problems.
901 if (wapp) {
902 /* do application wide stuff */
903 WSETUFLAG(wapp->main_window_desc, start_hidden,
904 WMGetButtonSelected(panel->appChk[0]));
906 WSETUFLAG(wapp->main_window_desc, no_appicon,
907 WMGetButtonSelected(panel->appChk[1]));
909 WSETUFLAG(wapp->main_window_desc, collapse_appicons,
910 WMGetButtonSelected(panel->appChk[2]));
912 if (WFLAGP(wapp->main_window_desc, no_appicon))
913 removeAppIconFor(wapp);
914 else
915 makeAppIconFor(wapp);
917 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
918 char *file = WMGetTextFieldText(panel->fileText);
920 if (file[0] == 0) {
921 wfree(file);
922 file = NULL;
924 wIconChangeImageFile(wapp->app_icon->icon, file);
925 if (file)
926 wfree(file);
927 wAppIconPaint(wapp->app_icon);
935 static void
936 revertSettings(WMButton *button, InspectorPanel *panel)
938 WWindow *wwin = panel->inspected;
939 WApplication *wapp = wApplicationOf(wwin->main_window);
940 int i, n;
941 char *wm_instance = NULL;
942 char *wm_class = NULL;
943 int workspace, level;
945 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
946 wm_instance = wwin->wm_instance;
947 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
948 wm_class = wwin->wm_class;
949 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
950 wm_instance = wwin->wm_instance;
951 wm_class = wwin->wm_class;
953 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
954 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
955 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
957 wWindowSetupInitialAttributes(wwin, &level, &workspace);
959 for (i=0; i < 11; i++) {
960 int flag = 0;
962 switch (i) {
963 case 0:
964 flag = WFLAGP(wwin, no_titlebar);
965 break;
966 case 1:
967 flag = WFLAGP(wwin, no_resizebar);
968 break;
969 case 2:
970 flag = WFLAGP(wwin, no_close_button);
971 break;
972 case 3:
973 flag = WFLAGP(wwin, no_miniaturize_button);
974 break;
975 case 4:
976 flag = WFLAGP(wwin, no_border);
977 break;
978 case 5:
979 flag = WFLAGP(wwin, floating);
980 break;
981 case 6:
982 flag = WFLAGP(wwin, sunken);
983 break;
984 case 7:
985 flag = WFLAGP(wwin, omnipresent);
986 break;
987 case 8:
988 flag = WFLAGP(wwin, start_miniaturized);
989 break;
990 case 9:
991 flag = WFLAGP(wwin, start_maximized!=0);
992 break;
993 case 10:
994 flag = WFLAGP(wwin, skip_window_list);
995 break;
997 WMSetButtonSelected(panel->attrChk[i], flag);
999 for (i=0; i < 8; i++) {
1000 int flag = 0;
1002 switch (i) {
1003 case 0:
1004 flag = WFLAGP(wwin, no_hide_others);
1005 break;
1006 case 1:
1007 flag = WFLAGP(wwin, no_bind_keys);
1008 break;
1009 case 2:
1010 flag = WFLAGP(wwin, no_bind_mouse);
1011 break;
1012 case 3:
1013 flag = WFLAGP(wwin, dont_move_off);
1014 break;
1015 case 4:
1016 flag = WFLAGP(wwin, no_focusable);
1017 break;
1018 case 5:
1019 flag = WFLAGP(wwin, dont_save_session);
1020 break;
1021 case 6:
1022 flag = WFLAGP(wwin, emulate_appicon);
1023 break;
1024 case 7:
1025 flag = WFLAGP(wwin, full_maximize);
1026 break;
1027 #ifdef XKB_BUTTON_HINT
1028 case 8:
1029 flag = WFLAGP(wwin, no_language_button);
1030 break;
1031 #endif
1033 WMSetButtonSelected(panel->moreChk[i], flag);
1035 if (panel->appFrm && wapp) {
1036 for (i=0; i < 2; i++) {
1037 int flag = 0;
1039 switch (i) {
1040 case 0:
1041 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1042 break;
1043 case 1:
1044 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1045 break;
1046 case 2:
1047 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1048 break;
1050 WMSetButtonSelected(panel->appChk[i], flag);
1053 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1055 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1056 REVERT_TO_DEFAULT);
1058 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1060 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1061 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1062 } else {
1063 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1066 /* must auto apply, so that there wno't be internal
1067 * inconsistencies between the state in the flags and
1068 * the actual state of the window */
1069 applySettings(panel->applyBtn, panel);
1073 static void
1074 chooseIconCallback(WMWidget *self, void *clientData)
1076 char *file;
1077 InspectorPanel *panel = (InspectorPanel*)clientData;
1078 int result;
1080 panel->choosingIcon = 1;
1082 WMSetButtonEnabled(panel->browseIconBtn, False);
1084 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1085 panel->inspected->wm_instance,
1086 panel->inspected->wm_class);
1088 panel->choosingIcon = 0;
1090 if (!panel->destroyed) { /* kluge */
1091 if (result) {
1092 WMSetTextFieldText(panel->fileText, file);
1093 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1094 USE_TEXT_FIELD);
1095 wfree(file);
1097 WMSetButtonEnabled(panel->browseIconBtn, True);
1098 } else {
1099 freeInspector(panel);
1104 static void
1105 textEditedObserver(void *observerData, WMNotification *notification)
1107 InspectorPanel *panel = (InspectorPanel*)observerData;
1109 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1110 return;
1112 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1113 USE_TEXT_FIELD);
1115 WMPerformButtonClick(panel->updateIconBtn);
1120 static void
1121 selectSpecification(WMWidget *bPtr, void *data)
1123 InspectorPanel *panel = (InspectorPanel*)data;
1124 char *str;
1125 WWindow *wwin = panel->inspected;
1128 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1129 WMSetButtonEnabled(panel->applyBtn, False);
1130 } else {
1131 WMSetButtonEnabled(panel->applyBtn, True);
1134 str = wmalloc(16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1135 + strlen(wwin->wm_class ? wwin->wm_class : "?"));
1137 sprintf(str, _("Inspecting %s.%s"),
1138 wwin->wm_instance ? wwin->wm_instance : "?",
1139 wwin->wm_class ? wwin->wm_class : "?");
1141 wFrameWindowChangeTitle(panel->frame->frame, str);
1143 wfree(str);
1147 static void
1148 selectWindow(WMWidget *bPtr, void *data)
1150 InspectorPanel *panel = (InspectorPanel*)data;
1151 WWindow *wwin = panel->inspected;
1152 WScreen *scr = wwin->screen_ptr;
1153 XEvent event;
1154 WWindow *iwin;
1156 if (XGrabPointer(dpy, scr->root_win, True,
1157 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1158 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1159 wwarning("could not grab mouse pointer");
1160 return;
1163 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1165 WMMaskEvent(dpy, ButtonPressMask, &event);
1167 XUngrabPointer(dpy, CurrentTime);
1169 iwin = wWindowFor(event.xbutton.subwindow);
1171 if (iwin && !iwin->flags.internal_window && iwin != wwin
1172 && !iwin->flags.inspector_open) {
1174 iwin->flags.inspector_open = 1;
1175 iwin->inspector = createInspectorForWindow(iwin,
1176 panel->frame->frame_x,
1177 panel->frame->frame_y,
1178 True);
1179 wCloseInspectorForWindow(wwin);
1180 } else {
1181 WMSetLabelText(panel->specLbl, spec_text);
1187 static InspectorPanel*
1188 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1189 Bool showSelectPanel)
1191 WScreen *scr = wwin->screen_ptr;
1192 InspectorPanel *panel;
1193 Window parent;
1194 int i;
1195 int x, y;
1196 int btn_width, frame_width;
1197 WMButton *selectedBtn = NULL;
1198 #ifdef wrong_behaviour
1199 WMPixmap *pixmap;
1200 #endif
1202 spec_text = _("The configuration will apply to all\n"
1203 "windows that have their WM_CLASS\n"
1204 "property set to the above selected\n"
1205 "name, when saved.");
1207 panel = wmalloc(sizeof(InspectorPanel));
1208 memset(panel, 0, sizeof(InspectorPanel));
1210 panel->destroyed = 0;
1213 panel->inspected = wwin;
1215 panel->nextPtr = panelList;
1216 panelList = panel;
1219 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1220 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1223 /**** create common stuff ****/
1225 /* command buttons */
1226 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1227 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1228 panel->saveBtn = WMCreateCommandButton(panel->win);
1229 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1230 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1231 WMSetButtonText(panel->saveBtn, _("Save"));
1232 WMResizeWidget(panel->saveBtn, btn_width, 28);
1233 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1234 WMSetButtonEnabled(panel->saveBtn, False);
1236 panel->applyBtn = WMCreateCommandButton(panel->win);
1237 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1238 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1239 WMSetButtonText(panel->applyBtn, _("Apply"));
1240 WMResizeWidget(panel->applyBtn, btn_width, 28);
1242 panel->revertBtn = WMCreateCommandButton(panel->win);
1243 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1244 WMMoveWidget(panel->revertBtn, 15, 310);
1245 WMSetButtonText(panel->revertBtn, _("Reload"));
1246 WMResizeWidget(panel->revertBtn, btn_width, 28);
1248 /* page selection popup button */
1249 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1250 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1251 WMMoveWidget(panel->pagePopUp, 25, 15);
1252 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1254 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1255 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1256 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1257 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1258 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1260 /**** window spec ****/
1261 frame_width = PWIDTH - (2 * 15);
1263 panel->specFrm = WMCreateFrame(panel->win);
1264 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1265 WMMoveWidget(panel->specFrm, 15, 65);
1266 WMResizeWidget(panel->specFrm, frame_width, 145);
1269 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1270 WMMoveWidget(panel->defaultRb, 10, 78);
1271 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1272 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1273 WMSetButtonSelected(panel->defaultRb, False);
1274 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1276 if (wwin->wm_class && wwin->wm_instance) {
1277 char *str, *tmp;
1279 tmp = wstrconcat(wwin->wm_instance, ".");
1280 str = wstrconcat(tmp, wwin->wm_class);
1282 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1283 WMMoveWidget(panel->bothRb, 10, 18);
1284 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1285 WMSetButtonText(panel->bothRb, str);
1286 wfree(tmp);
1287 wfree(str);
1288 WMGroupButtons(panel->defaultRb, panel->bothRb);
1290 if (!selectedBtn)
1291 selectedBtn = panel->bothRb;
1293 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1296 if (wwin->wm_instance) {
1297 panel->instRb = WMCreateRadioButton(panel->specFrm);
1298 WMMoveWidget(panel->instRb, 10, 38);
1299 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1300 WMSetButtonText(panel->instRb, wwin->wm_instance);
1301 WMGroupButtons(panel->defaultRb, panel->instRb);
1303 if (!selectedBtn)
1304 selectedBtn = panel->instRb;
1306 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1309 if (wwin->wm_class) {
1310 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1311 WMMoveWidget(panel->clsRb, 10, 58);
1312 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1313 WMSetButtonText(panel->clsRb, wwin->wm_class);
1314 WMGroupButtons(panel->defaultRb, panel->clsRb);
1316 if (!selectedBtn)
1317 selectedBtn = panel->clsRb;
1319 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1323 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1324 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1325 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1326 WMSetButtonText(panel->selWinB, _("Select Window"));
1327 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1330 panel->specLbl = WMCreateLabel(panel->win);
1331 WMMoveWidget(panel->specLbl, 15, 210);
1332 WMResizeWidget(panel->specLbl, frame_width, 100);
1333 WMSetLabelText(panel->specLbl, spec_text);
1334 WMSetLabelWraps(panel->specLbl, True);
1336 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1338 /**** attributes ****/
1339 panel->attrFrm = WMCreateFrame(panel->win);
1340 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1341 WMMoveWidget(panel->attrFrm, 15, 45);
1342 WMResizeWidget(panel->attrFrm, frame_width, 250);
1344 for (i=0; i < 11; i++) {
1345 char *caption = NULL;
1346 int flag = 0;
1347 char *descr = NULL;
1349 switch (i) {
1350 case 0:
1351 caption = _("Disable Titlebar");
1352 flag = WFLAGP(wwin, no_titlebar);
1353 descr = _("Remove the titlebar of this window.\n"
1354 "To access the window commands menu of a window\n"
1355 "without it's titlebar, press Control+Esc (or the\n"
1356 "equivalent shortcut, if you changed the default\n"
1357 "settings).");
1358 break;
1359 case 1:
1360 caption = _("Disable Resizebar");
1361 flag = WFLAGP(wwin, no_resizebar);
1362 descr = _("Remove the resizebar of this window.");
1363 break;
1364 case 2:
1365 caption = _("Disable Close Button");
1366 flag = WFLAGP(wwin, no_close_button);
1367 descr = _("Remove the `close window' button of this window.");
1368 break;
1369 case 3:
1370 caption = _("Disable Miniaturize Button");
1371 flag = WFLAGP(wwin, no_miniaturize_button);
1372 descr = _("Remove the `miniaturize window' button of the window.");
1373 break;
1374 case 4:
1375 caption = _("Disable Border");
1376 flag = WFLAGP(wwin, no_border);
1377 descr = _("Remove the 1 pixel black border around the window.");
1378 break;
1379 case 5:
1380 caption = _("Keep on Top / Floating");
1381 flag = WFLAGP(wwin, floating);
1382 descr = _("Keep the window over other windows, not allowing\n"
1383 "them to cover it.");
1384 break;
1385 case 6:
1386 caption = _("Keep at Bottom / Sunken");
1387 flag = WFLAGP(wwin, sunken);
1388 descr = _("Keep the window under all other windows.");
1389 break;
1390 case 7:
1391 caption = _("Omnipresent");
1392 flag = WFLAGP(wwin, omnipresent);
1393 descr = _("Make window occupy all workspaces.");
1394 break;
1395 case 8:
1396 caption = _("Start Miniaturized");
1397 flag = WFLAGP(wwin, start_miniaturized);
1398 descr = _("Make the window be automatically miniaturized when it's\n"
1399 "first shown.");
1400 break;
1401 case 9:
1402 caption = _("Start Maximized");
1403 flag = WFLAGP(wwin, start_maximized!=0);
1404 descr = _("Make the window be automatically maximized when it's\n"
1405 "first shown.");
1406 break;
1407 case 10:
1408 caption = _("Skip Window List");
1409 flag = WFLAGP(wwin, skip_window_list);
1410 descr = _("Do not list the window in the window list menu.");
1411 break;
1413 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1414 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1415 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1416 WMSetButtonSelected(panel->attrChk[i], flag);
1417 WMSetButtonText(panel->attrChk[i], caption);
1419 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1423 /**** more attributes ****/
1424 panel->moreFrm = WMCreateFrame(panel->win);
1425 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1426 WMMoveWidget(panel->moreFrm, 15, 45);
1427 WMResizeWidget(panel->moreFrm, frame_width, 250);
1429 for (i=0;
1430 #ifdef XKB_BUTTON_HINT
1431 i < 9;
1432 #else
1433 i < 8;
1434 #endif
1435 i++) {
1436 char *caption = NULL;
1437 int flag = 0;
1438 char *descr = NULL;
1440 switch (i) {
1441 case 0:
1442 caption = _("Ignore HideOthers");
1443 flag = WFLAGP(wwin, no_hide_others);
1444 descr = _("Do not hide the window when issuing the\n"
1445 "`HideOthers' command.");
1446 break;
1447 case 1:
1448 caption = _("Don't Bind Keyboard Shortcuts");
1449 flag = WFLAGP(wwin, no_bind_keys);
1450 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1451 "when this window is focused. This will allow the\n"
1452 "window to receive all key combinations regardless\n"
1453 "of your shortcut configuration.");
1454 break;
1455 case 2:
1456 caption = _("Don't Bind Mouse Clicks");
1457 flag = WFLAGP(wwin, no_bind_mouse);
1458 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1459 "in the window (when alt is the modifier you have"
1460 "configured).");
1461 break;
1462 case 3:
1463 caption = _("Keep Inside Screen");
1464 flag = WFLAGP(wwin, dont_move_off);
1465 descr = _("Do not allow the window to move itself completely\n"
1466 "outside the screen. For bug compatibility.\n");
1467 break;
1468 case 4:
1469 caption = _("Don't 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 5:
1475 caption = _("Don't Save Session");
1476 flag = WFLAGP(wwin, dont_save_session);
1477 descr = _("Do not save the associated application in the\n"
1478 "session's state, so that it won't be restarted\n"
1479 "together with other applications when Window Maker\n"
1480 "starts.");
1481 break;
1482 case 6:
1483 caption = _("Emulate Application Icon");
1484 flag = WFLAGP(wwin, emulate_appicon);
1485 descr = _("Make this window act as an application that provides\n"
1486 "enough information to Window Maker for a dockable\n"
1487 "application icon to be created.");
1488 break;
1489 case 7:
1490 caption = _("Full Screen Maximization");
1491 flag = WFLAGP(wwin, full_maximize);
1492 descr = _("Make the window use the whole screen space when it's\n"
1493 "maximized. The titlebar and resizebar will be moved\n"
1494 "to outside the screen.");
1495 break;
1496 #ifdef XKB_BUTTON_HINT
1497 case 8:
1498 caption = _("Disable Language Button");
1499 flag = WFLAGP(wwin, no_language_button);
1500 descr = _("Remove the `toggle language' button of the window.");
1501 break;
1502 #endif
1504 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1505 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1506 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1507 WMSetButtonSelected(panel->moreChk[i], flag);
1508 WMSetButtonText(panel->moreChk[i], caption);
1510 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1513 /* miniwindow/workspace */
1514 panel->iconFrm = WMCreateFrame(panel->win);
1515 WMMoveWidget(panel->iconFrm, 15, 50);
1516 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1517 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1519 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1520 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1521 WMResizeWidget(panel->iconLbl, 64, 64);
1522 WMSetLabelRelief(panel->iconLbl, WRGroove);
1523 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1525 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1526 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1527 WMMoveWidget(panel->browseIconBtn, 22, 32);
1528 WMResizeWidget(panel->browseIconBtn, 120, 26);
1529 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1531 #ifdef wrong_behaviour
1532 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1533 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1534 WMSetButtonImage(panel->updateIconBtn, pixmap);
1535 WMReleasePixmap(pixmap);
1536 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1537 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1538 WMReleasePixmap(pixmap);
1539 #endif
1541 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1542 WMMoveWidget(panel->fileLbl, 20, 85);
1543 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1544 WMSetLabelText(panel->fileLbl, _("Icon File Name:"));
1546 panel->fileText = WMCreateTextField(panel->iconFrm);
1547 WMMoveWidget(panel->fileText, 20, 105);
1548 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1549 WMSetTextFieldText(panel->fileText, NULL);
1550 WMAddNotificationObserver(textEditedObserver, panel,
1551 WMTextDidEndEditingNotification,
1552 panel->fileText);
1554 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1555 WMMoveWidget(panel->alwChk, 20, 130);
1556 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1557 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1558 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1561 panel->wsFrm = WMCreateFrame(panel->win);
1562 WMMoveWidget(panel->wsFrm, 15, 225);
1563 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1564 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1566 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1567 "first shown."), WMWidgetView(panel->wsFrm));
1569 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1570 WMMoveWidget(panel->wsP, 20, 30);
1571 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1572 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1573 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1574 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1577 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1578 wwin->wm_class);
1579 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1580 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1581 } else {
1582 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1585 /* application wide attributes */
1586 if (wwin->main_window != None) {
1587 WApplication *wapp = wApplicationOf(wwin->main_window);
1589 panel->appFrm = WMCreateFrame(panel->win);
1590 WMSetFrameTitle(panel->appFrm, _("Application Wide"));
1591 WMMoveWidget(panel->appFrm, 15, 50);
1592 WMResizeWidget(panel->appFrm, frame_width, 240);
1594 for (i=0; i < 3; i++) {
1595 char *caption = NULL;
1596 int flag = 0;
1597 char *descr = NULL;
1599 switch (i) {
1600 case 0:
1601 caption = _("Start Hidden");
1602 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1603 descr = _("Automatically hide application when it's started.");
1604 break;
1605 case 1:
1606 caption = _("No Application Icon");
1607 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1608 descr = _("Disable the application icon for the application.\n"
1609 "Note that you won't be able to dock it anymore,\n"
1610 "and any icons that are already docked will stop\n"
1611 "working correctly.");
1612 break;
1613 case 2:
1614 caption = _("Collapse Application Icons");
1615 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1616 descr = _("Collapse application icons from other instances\n"
1617 "of this application into one.\n");
1618 break;
1620 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1621 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1622 WMResizeWidget(panel->appChk[i], 205, 20);
1623 WMSetButtonSelected(panel->appChk[i], flag);
1624 WMSetButtonText(panel->appChk[i], caption);
1626 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1629 if (WFLAGP(wwin, emulate_appicon)) {
1630 WMSetButtonEnabled(panel->appChk[1], False);
1631 WMSetButtonEnabled(panel->moreChk[6], True);
1632 } else {
1633 WMSetButtonEnabled(panel->appChk[1], True);
1634 WMSetButtonEnabled(panel->moreChk[6], False);
1636 } else {
1637 int tmp;
1639 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1640 || !wwin->wm_class || !wwin->wm_instance)
1641 tmp = False;
1642 else
1643 tmp = True;
1644 WMSetButtonEnabled(panel->moreChk[6], tmp);
1646 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1647 panel->appFrm = NULL;
1650 /* if the window is a transient, don't let it have a miniaturize
1651 * button */
1652 if (wWindowFor(wwin->transient_for)!=NULL)
1653 WMSetButtonEnabled(panel->attrChk[3], False);
1654 else
1655 WMSetButtonEnabled(panel->attrChk[3], True);
1658 if (!wwin->wm_class && !wwin->wm_instance) {
1659 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1663 WMRealizeWidget(panel->win);
1665 WMMapSubwidgets(panel->win);
1666 WMMapSubwidgets(panel->specFrm);
1667 WMMapSubwidgets(panel->attrFrm);
1668 WMMapSubwidgets(panel->moreFrm);
1669 WMMapSubwidgets(panel->iconFrm);
1670 WMMapSubwidgets(panel->wsFrm);
1671 if (panel->appFrm)
1672 WMMapSubwidgets(panel->appFrm);
1674 if (showSelectPanel) {
1675 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1676 changePage(panel->pagePopUp, panel);
1677 } else {
1678 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1679 changePage(panel->pagePopUp, panel);
1683 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1684 0, 0, 0);
1685 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1686 panel->parent = parent;
1687 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1689 WMMapWidget(panel->win);
1691 XSetTransientForHint(dpy, parent, wwin->client_win);
1693 if (xpos == UNDEFINED_POS) {
1694 x = wwin->frame_x+wwin->frame->core->width/2;
1695 y = wwin->frame_y+wwin->frame->top_width*2;
1696 if (y + PHEIGHT > scr->scr_height)
1697 y = scr->scr_height - PHEIGHT - 30;
1698 if (x + PWIDTH > scr->scr_width)
1699 x = scr->scr_width - PWIDTH;
1700 } else {
1701 x = xpos;
1702 y = ypos;
1705 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1706 "Inspector", x, y, PWIDTH, PHEIGHT);
1708 if (!selectedBtn)
1709 selectedBtn = panel->defaultRb;
1711 WMSetButtonSelected(selectedBtn, True);
1713 selectSpecification(selectedBtn, panel);
1715 /* kluge to know who should get the key events */
1716 panel->frame->client_leader = WMWidgetXID(panel->win);
1718 WSETUFLAG(panel->frame, no_closable, 0);
1719 WSETUFLAG(panel->frame, no_close_button, 0);
1720 wWindowUpdateButtonImages(panel->frame);
1721 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1722 panel->frame->frame->on_click_right = destroyInspector;
1724 wWindowMap(panel->frame);
1726 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1727 wwin->wm_class, UPDATE_TEXT_FIELD);
1729 return panel;
1733 void
1734 wShowInspectorForWindow(WWindow *wwin)
1736 if (wwin->flags.inspector_open)
1737 return;
1739 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1741 make_keys();
1742 wwin->flags.inspector_open = 1;
1743 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1744 UNDEFINED_POS, False);
1750 void
1751 wHideInspectorForWindow(WWindow *wwin)
1753 WWindow *pwin = wwin->inspector->frame;
1755 wWindowUnmap(pwin);
1756 pwin->flags.hidden = 1;
1758 wClientSetState(pwin, IconicState, None);
1763 void
1764 wUnhideInspectorForWindow(WWindow *wwin)
1766 WWindow *pwin = wwin->inspector->frame;
1768 pwin->flags.hidden = 0;
1769 pwin->flags.mapped = 1;
1770 XMapWindow(dpy, pwin->client_win);
1771 XMapWindow(dpy, pwin->frame->core->window);
1772 wClientSetState(pwin, NormalState, None);
1777 WWindow*
1778 wGetWindowOfInspectorForWindow(WWindow *wwin)
1780 if (wwin->inspector) {
1781 assert(wwin->flags.inspector_open != 0);
1783 return wwin->inspector->frame;
1784 } else
1785 return NULL;
1789 void
1790 wCloseInspectorForWindow(WWindow *wwin)
1792 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1794 (*pwin->frame->on_click_right)(NULL, pwin, NULL);