wAppIconPaint paint argument
[wmaker-crm.git] / src / winspector.c
blob808a76fcfd7bb28fb0a63c6f3be789f35301192a
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
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 along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <strings.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"
49 #include "wmspec.h"
51 #include <WINGs/WUtil.h>
53 typedef struct InspectorPanel {
54 struct InspectorPanel *nextPtr;
56 WWindow *frame;
58 WWindow *inspected; /* the window that's being inspected */
60 WMWindow *win;
62 Window parent;
64 /* common stuff */
65 WMButton *revertBtn;
66 WMButton *applyBtn;
67 WMButton *saveBtn;
69 WMPopUpButton *pagePopUp;
71 /* first page. general stuff */
73 WMFrame *specFrm;
74 WMButton *instRb;
75 WMButton *clsRb;
76 WMButton *bothRb;
77 WMButton *defaultRb;
79 WMButton *selWinB;
81 WMLabel *specLbl;
83 /* second page. attributes */
85 WMFrame *attrFrm;
86 WMButton *attrChk[11];
88 /* 3rd page. more attributes */
89 WMFrame *moreFrm;
90 #ifdef XKB_BUTTON_HINT
91 WMButton *moreChk[12];
92 #else
93 WMButton *moreChk[11];
94 #endif
96 /* 4th page. icon and workspace */
97 WMFrame *iconFrm;
98 WMLabel *iconLbl;
99 WMLabel *fileLbl;
100 WMTextField *fileText;
101 WMButton *alwChk;
103 WMButton *updateIconBtn;
105 WMButton *browseIconBtn;
107 WMFrame *wsFrm;
108 WMPopUpButton *wsP;
110 /* 5th page. application wide attributes */
111 WMFrame *appFrm;
112 WMButton *appChk[3];
114 unsigned int done:1;
115 unsigned int destroyed:1;
116 unsigned int choosingIcon:1;
117 } InspectorPanel;
119 extern Cursor wCursor[WCUR_LAST];
120 extern WDDomain *WDWindowAttributes;
121 extern WPreferences wPreferences;
123 static InspectorPanel *panelList = NULL;
124 static WMPropList *ANoTitlebar = NULL;
125 static WMPropList *ANoResizebar;
126 static WMPropList *ANoMiniaturizeButton;
127 static WMPropList *ANoCloseButton;
128 static WMPropList *ANoBorder;
129 static WMPropList *ANoHideOthers;
130 static WMPropList *ANoMouseBindings;
131 static WMPropList *ANoKeyBindings;
132 static WMPropList *ANoAppIcon;
133 static WMPropList *AKeepOnTop;
134 static WMPropList *AKeepOnBottom;
135 static WMPropList *AOmnipresent;
136 static WMPropList *ASkipWindowList;
137 static WMPropList *ASkipSwitchPanel;
138 static WMPropList *AKeepInsideScreen;
139 static WMPropList *AUnfocusable;
140 static WMPropList *AFocusAcrossWorkspace;
141 static WMPropList *AAlwaysUserIcon;
142 static WMPropList *AStartMiniaturized;
143 static WMPropList *AStartMaximized;
144 static WMPropList *ADontSaveSession;
145 static WMPropList *AEmulateAppIcon;
146 static WMPropList *AFullMaximize;
147 static WMPropList *ASharedAppIcon;
148 static WMPropList *ANoMiniaturizable;
149 #ifdef XKB_BUTTON_HINT
150 static WMPropList *ANoLanguageButton;
151 #endif
152 static WMPropList *AStartWorkspace;
153 static WMPropList *AIcon;
155 /* application wide options */
156 static WMPropList *AStartHidden;
157 static WMPropList *AnyWindow;
158 static WMPropList *EmptyString;
159 static WMPropList *Yes, *No;
161 #define PWIDTH 290
162 #define PHEIGHT 360
164 static char *spec_text;
165 static void applySettings(WMButton *button, InspectorPanel *panel);
167 #define UNDEFINED_POS 0xffffff
169 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
171 static void make_keys(void)
173 if (ANoTitlebar != NULL)
174 return;
176 AIcon = WMCreatePLString("Icon");
177 ANoTitlebar = WMCreatePLString("NoTitlebar");
178 ANoResizebar = WMCreatePLString("NoResizebar");
179 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
180 ANoCloseButton = WMCreatePLString("NoCloseButton");
181 ANoBorder = WMCreatePLString("NoBorder");
182 ANoHideOthers = WMCreatePLString("NoHideOthers");
183 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
184 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
185 ANoAppIcon = WMCreatePLString("NoAppIcon");
186 AKeepOnTop = WMCreatePLString("KeepOnTop");
187 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
188 AOmnipresent = WMCreatePLString("Omnipresent");
189 ASkipWindowList = WMCreatePLString("SkipWindowList");
190 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
191 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
192 AUnfocusable = WMCreatePLString("Unfocusable");
193 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
194 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
195 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
196 AStartMaximized = WMCreatePLString("StartMaximized");
197 AStartHidden = WMCreatePLString("StartHidden");
198 ADontSaveSession = WMCreatePLString("DontSaveSession");
199 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
200 AFullMaximize = WMCreatePLString("FullMaximize");
201 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
202 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
203 #ifdef XKB_BUTTON_HINT
204 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
205 #endif
207 AStartWorkspace = WMCreatePLString("StartWorkspace");
209 AnyWindow = WMCreatePLString("*");
210 EmptyString = WMCreatePLString("");
211 Yes = WMCreatePLString("Yes");
212 No = WMCreatePLString("No");
215 static void freeInspector(InspectorPanel *panel)
217 panel->destroyed = 1;
219 if (panel->choosingIcon)
220 return;
222 WMDestroyWidget(panel->win);
223 XDestroyWindow(dpy, panel->parent);
224 wfree(panel);
227 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
229 InspectorPanel *panel;
230 InspectorPanel *tmp;
232 panel = panelList;
233 while (panel->frame != data)
234 panel = panel->nextPtr;
236 if (panelList == panel)
237 panelList = panel->nextPtr;
238 else {
239 tmp = panelList;
240 while (tmp->nextPtr != panel) {
241 tmp = tmp->nextPtr;
243 tmp->nextPtr = panel->nextPtr;
245 panel->inspected->flags.inspector_open = 0;
246 panel->inspected->inspector = NULL;
248 WMRemoveNotificationObserver(panel);
250 wWindowUnmap(panel->frame);
251 wUnmanageWindow(panel->frame, True, False);
253 freeInspector(panel);
256 void wDestroyInspectorPanels(void)
258 InspectorPanel *panel;
260 while (panelList != NULL) {
261 panel = panelList;
262 panelList = panelList->nextPtr;
263 wUnmanageWindow(panel->frame, False, False);
264 WMDestroyWidget(panel->win);
266 panel->inspected->flags.inspector_open = 0;
267 panel->inspected->inspector = NULL;
269 wfree(panel);
273 static void changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
275 int page;
277 page = WMGetPopUpButtonSelectedItem(bPtr);
279 if (page == 0) {
280 WMMapWidget(panel->specFrm);
281 WMMapWidget(panel->specLbl);
282 } else if (page == 1) {
283 WMMapWidget(panel->attrFrm);
284 } else if (page == 2) {
285 WMMapWidget(panel->moreFrm);
286 } else if (page == 3) {
287 WMMapWidget(panel->iconFrm);
288 WMMapWidget(panel->wsFrm);
289 } else {
290 WMMapWidget(panel->appFrm);
293 if (page != 0) {
294 WMUnmapWidget(panel->specFrm);
295 WMUnmapWidget(panel->specLbl);
297 if (page != 1)
298 WMUnmapWidget(panel->attrFrm);
299 if (page != 2)
300 WMUnmapWidget(panel->moreFrm);
301 if (page != 3) {
302 WMUnmapWidget(panel->iconFrm);
303 WMUnmapWidget(panel->wsFrm);
305 if (page != 4 && panel->appFrm)
306 WMUnmapWidget(panel->appFrm);
309 #define USE_TEXT_FIELD 1
310 #define UPDATE_TEXT_FIELD 2
311 #define REVERT_TO_DEFAULT 4
313 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, char *wm_instance, char *wm_class, int flags)
315 WMPixmap *pixmap = (WMPixmap *) NULL;
316 char *file = NULL, *path = NULL;
317 char *db_icon = NULL;
319 if ((flags & USE_TEXT_FIELD) != 0) {
320 file = WMGetTextFieldText(panel->fileText);
321 if (file && file[0] == 0) {
322 wfree(file);
323 file = NULL;
325 } else {
326 /* Get the application icon, default included */
327 db_icon = wDefaultGetIconFile(wm_instance, wm_class, True);
328 if (db_icon != NULL)
329 file = wstrdup(db_icon);
331 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
332 if (file)
333 file = wstrdup(db_icon);
334 flags |= UPDATE_TEXT_FIELD;
337 if ((flags & UPDATE_TEXT_FIELD) != 0) {
338 WMSetTextFieldText(panel->fileText, file);
341 if (file) {
342 path = FindImage(wPreferences.icon_path, file);
344 if (!path) {
345 char *buf;
346 int len = strlen(file) + 80;
348 buf = wmalloc(len);
349 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
350 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
351 wfree(buf);
352 wfree(file);
353 return -1;
356 pixmap = WMCreatePixmapFromFile(scrPtr, path);
357 wfree(path);
359 if (!pixmap) {
360 char *buf;
361 int len = strlen(file) + 80;
363 buf = wmalloc(len);
364 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
365 file, RMessageForError(RErrorCode));
366 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
367 wfree(buf);
368 wfree(file);
369 return -1;
371 wfree(file);
374 WMSetLabelImage(panel->iconLbl, pixmap);
375 if (pixmap)
376 WMReleasePixmap(pixmap);
378 return 0;
381 #if 0
382 static void updateIcon(WMButton * button, InspectorPanel * panel)
384 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
386 #endif
388 static int getBool(WMPropList *value)
390 char *val;
392 if (!WMIsPLString(value)) {
393 return 0;
395 if (!(val = WMGetFromPLString(value))) {
396 return 0;
399 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
400 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
402 return 1;
403 } else if ((val[1] == '\0'
404 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
405 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
407 return 0;
408 } else {
409 wwarning(_("can't convert \"%s\" to boolean"), val);
410 return 0;
414 #define UPDATE_DEFAULTS 1
415 #define IS_BOOLEAN 2
418 * Will insert the attribute = value; pair in window's list,
419 * if it's different from the defaults.
420 * Defaults means either defaults database, or attributes saved
421 * for the default window "*". This is to let one revert options that are
422 * global because they were saved for all windows ("*").
426 static int
427 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
429 WMPropList *def_win, *def_value = NULL;
430 int update = 0;
431 int modified = 0;
433 if (!(flags & UPDATE_DEFAULTS) && dict) {
434 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
435 def_value = WMGetFromPLDictionary(def_win, attr);
439 /* If we could not find defaults in database, fall to hardcoded values.
440 * Also this is true if we save defaults for all windows
442 if (!def_value)
443 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
445 if ((flags & IS_BOOLEAN))
446 update = (getBool(value) != getBool(def_value));
447 else {
448 update = !WMIsPropListEqualTo(value, def_value);
451 if (update) {
452 WMPutInPLDictionary(window, attr, value);
453 modified = 1;
456 return modified;
459 static void saveSettings(WMButton *button, InspectorPanel *panel)
461 WWindow *wwin = panel->inspected;
462 WDDomain *db = WDWindowAttributes;
463 WMPropList *dict = db->dictionary;
464 WMPropList *winDic, *appDic, *value, *key, *key2;
465 char *icon_file;
466 int flags = 0;
467 int different = 0, different2 = 0;
469 /* Save will apply the changes and save them */
470 applySettings(panel->applyBtn, panel);
472 if (WMGetButtonSelected(panel->instRb) != 0)
473 key = WMCreatePLString(wwin->wm_instance);
474 else if (WMGetButtonSelected(panel->clsRb) != 0)
475 key = WMCreatePLString(wwin->wm_class);
476 else if (WMGetButtonSelected(panel->bothRb) != 0) {
477 char *buffer;
479 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
480 key = WMCreatePLString(buffer);
481 wfree(buffer);
482 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
483 key = WMRetainPropList(AnyWindow);
484 flags = UPDATE_DEFAULTS;
485 } else
486 key = NULL;
488 if (!key)
489 return;
491 if (!dict) {
492 dict = WMCreatePLDictionary(NULL, NULL);
493 if (dict) {
494 db->dictionary = dict;
495 } else {
496 WMReleasePropList(key);
497 return;
501 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
502 return;
504 WMPLSetCaseSensitive(True);
506 winDic = WMCreatePLDictionary(NULL, NULL);
507 appDic = WMCreatePLDictionary(NULL, NULL);
509 /* Update icon for window */
510 icon_file = WMGetTextFieldText(panel->fileText);
511 if (icon_file) {
512 if (icon_file[0] != 0) {
513 value = WMCreatePLString(icon_file);
514 different |= insertAttribute(dict, winDic, AIcon, value, flags);
515 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
516 WMReleasePropList(value);
518 wfree(icon_file);
522 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
524 i--;
526 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
527 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
528 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
529 WMReleasePropList(value);
533 flags |= IS_BOOLEAN;
535 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
536 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
538 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
539 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
541 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
544 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
547 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
550 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
553 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
556 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
559 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
562 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
565 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
568 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
569 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
571 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
572 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
574 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
575 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
577 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
578 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
580 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
581 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
583 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
584 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
586 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
587 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
589 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
590 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
592 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
593 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
595 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
596 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
598 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
599 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
601 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
602 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
604 #ifdef XKB_BUTTON_HINT
605 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
606 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
607 #endif
609 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
610 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
611 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
613 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
614 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
616 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
617 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
620 if (wwin->fake_group) {
621 key2 = WMCreatePLString(wwin->fake_group->identifier);
622 if (WMIsPropListEqualTo(key, key2)) {
623 WMMergePLDictionaries(winDic, appDic, True);
624 different |= different2;
625 } else {
626 WMRemoveFromPLDictionary(dict, key2);
627 if (different2) {
628 WMPutInPLDictionary(dict, key2, appDic);
631 WMReleasePropList(key2);
632 WMReleasePropList(appDic);
633 } else if (wwin->main_window != wwin->client_win) {
634 WApplication *wapp = wApplicationOf(wwin->main_window);
636 if (wapp) {
637 char *instance = wapp->main_window_desc->wm_instance;
638 char *class = wapp->main_window_desc->wm_class;
639 char *buffer;
641 buffer = StrConcatDot(instance, class);
642 key2 = WMCreatePLString(buffer);
643 wfree(buffer);
645 if (WMIsPropListEqualTo(key, key2)) {
646 WMMergePLDictionaries(winDic, appDic, True);
647 different |= different2;
648 } else {
649 WMRemoveFromPLDictionary(dict, key2);
650 if (different2)
651 WMPutInPLDictionary(dict, key2, appDic);
653 WMReleasePropList(key2);
654 WMReleasePropList(appDic);
656 } else {
657 WMMergePLDictionaries(winDic, appDic, True);
658 different |= different2;
659 WMReleasePropList(appDic);
662 WMRemoveFromPLDictionary(dict, key);
663 if (different) {
664 WMPutInPLDictionary(dict, key, winDic);
667 WMReleasePropList(key);
668 WMReleasePropList(winDic);
670 UpdateDomainFile(db);
672 /* clean up */
673 WMPLSetCaseSensitive(False);
676 static void applySettings(WMButton *button, InspectorPanel *panel)
678 WWindow *wwin = panel->inspected;
679 WApplication *wapp = wApplicationOf(wwin->main_window);
680 int floating, sunken, skip_window_list;
681 int old_omnipresent;
682 int old_no_bind_keys;
683 int old_no_bind_mouse;
685 old_omnipresent = WFLAGP(wwin, omnipresent);
686 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
687 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
689 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
691 /* Attributes... --> Window Attributes */
692 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
693 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
694 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
695 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
696 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
697 floating = WMGetButtonSelected(panel->attrChk[5]);
698 sunken = WMGetButtonSelected(panel->attrChk[6]);
699 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
700 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
701 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
702 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
704 /* Attributes... --> Advanced Options */
705 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
706 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
707 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
708 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
709 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
710 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
711 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
712 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
713 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
714 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
715 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
716 #ifdef XKB_BUTTON_HINT
717 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
718 #endif
719 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
721 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
722 wUnshadeWindow(wwin);
724 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
726 if (floating) {
727 if (!WFLAGP(wwin, floating))
728 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
729 } else if (sunken) {
730 if (!WFLAGP(wwin, sunken))
731 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
732 } else {
733 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
734 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
737 WSETUFLAG(wwin, sunken, sunken);
738 WSETUFLAG(wwin, floating, floating);
739 wwin->flags.omnipresent = 0;
741 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
742 WSETUFLAG(wwin, skip_window_list, skip_window_list);
743 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
744 } else {
745 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
746 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
750 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
751 if (WFLAGP(wwin, no_bind_keys)) {
752 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
753 } else {
754 wWindowSetKeyGrabs(wwin);
758 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
759 wWindowResetMouseGrabs(wwin);
762 wwin->frame->flags.need_texture_change = 1;
763 wWindowConfigureBorders(wwin);
764 wFrameWindowPaint(wwin->frame);
765 wNETWMUpdateActions(wwin, False);
768 * Can't apply emulate_appicon because it will probably cause problems.
770 if (wapp) {
771 /* do application wide stuff */
772 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
773 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
774 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
776 if (WFLAGP(wapp->main_window_desc, no_appicon))
777 unpaint_app_icon(wapp);
778 else
779 paint_app_icon(wapp);
781 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
782 char *file = WMGetTextFieldText(panel->fileText);
784 if (file[0] == 0) {
785 wfree(file);
786 file = NULL;
789 wIconChangeImageFile(wapp->app_icon->icon, file);
790 if (file)
791 wfree(file);
793 /* The image was updated in wIconChangeImageFile,
794 * so we don't need udpate it at wAppIconPaint */
795 wAppIconPaint(wapp->app_icon, False);
799 wNETFrameExtents(wwin);
802 static void revertSettings(WMButton *button, InspectorPanel *panel)
804 WWindow *wwin = panel->inspected;
805 WApplication *wapp = wApplicationOf(wwin->main_window);
806 int i, n;
807 char *wm_instance = NULL;
808 char *wm_class = NULL;
809 int workspace, level;
811 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
812 wm_instance = wwin->wm_instance;
813 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
814 wm_class = wwin->wm_class;
815 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
816 wm_instance = wwin->wm_instance;
817 wm_class = wwin->wm_class;
819 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
820 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
821 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
823 wWindowSetupInitialAttributes(wwin, &level, &workspace);
825 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
826 int flag = 0;
828 switch (i) {
829 case 0:
830 flag = WFLAGP(wwin, no_titlebar);
831 break;
832 case 1:
833 flag = WFLAGP(wwin, no_resizebar);
834 break;
835 case 2:
836 flag = WFLAGP(wwin, no_close_button);
837 break;
838 case 3:
839 flag = WFLAGP(wwin, no_miniaturize_button);
840 break;
841 case 4:
842 flag = WFLAGP(wwin, no_border);
843 break;
844 case 5:
845 flag = WFLAGP(wwin, floating);
846 break;
847 case 6:
848 flag = WFLAGP(wwin, sunken);
849 break;
850 case 7:
851 flag = WFLAGP(wwin, omnipresent);
852 break;
853 case 8:
854 flag = WFLAGP(wwin, start_miniaturized);
855 break;
856 case 9:
857 flag = WFLAGP(wwin, start_maximized != 0);
858 break;
859 case 10:
860 flag = WFLAGP(wwin, full_maximize);
861 break;
863 WMSetButtonSelected(panel->attrChk[i], flag);
865 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
866 int flag = 0;
868 switch (i) {
869 case 0:
870 flag = WFLAGP(wwin, no_bind_keys);
871 break;
872 case 1:
873 flag = WFLAGP(wwin, no_bind_mouse);
874 break;
875 case 2:
876 flag = WFLAGP(wwin, skip_window_list);
877 break;
878 case 3:
879 flag = WFLAGP(wwin, skip_switchpanel);
880 break;
881 case 4:
882 flag = WFLAGP(wwin, no_focusable);
883 break;
884 case 5:
885 flag = WFLAGP(wwin, dont_move_off);
886 break;
887 case 6:
888 flag = WFLAGP(wwin, no_hide_others);
889 break;
890 case 7:
891 flag = WFLAGP(wwin, dont_save_session);
892 break;
893 case 8:
894 flag = WFLAGP(wwin, emulate_appicon);
895 break;
896 case 9:
897 flag = WFLAGP(wwin, focus_across_wksp);
898 break;
899 case 10:
900 flag = WFLAGP(wwin, no_miniaturizable);
901 break;
902 #ifdef XKB_BUTTON_HINT
903 case 11:
904 flag = WFLAGP(wwin, no_language_button);
905 break;
906 #endif
908 WMSetButtonSelected(panel->moreChk[i], flag);
910 if (panel->appFrm && wapp) {
911 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
912 int flag = 0;
914 switch (i) {
915 case 0:
916 flag = WFLAGP(wapp->main_window_desc, start_hidden);
917 break;
918 case 1:
919 flag = WFLAGP(wapp->main_window_desc, no_appicon);
920 break;
921 case 2:
922 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
923 break;
925 WMSetButtonSelected(panel->appChk[i], flag);
928 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
930 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
932 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
934 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
935 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
936 } else {
937 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
940 /* must auto apply, so that there wno't be internal
941 * inconsistencies between the state in the flags and
942 * the actual state of the window */
943 applySettings(panel->applyBtn, panel);
946 static void chooseIconCallback(WMWidget *self, void *clientData)
948 char *file;
949 InspectorPanel *panel = (InspectorPanel *) clientData;
950 int result;
952 panel->choosingIcon = 1;
954 WMSetButtonEnabled(panel->browseIconBtn, False);
956 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
957 panel->inspected->wm_instance, panel->inspected->wm_class);
959 panel->choosingIcon = 0;
961 if (!panel->destroyed) { /* kluge */
962 if (result) {
963 WMSetTextFieldText(panel->fileText, file);
964 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
965 wfree(file);
967 WMSetButtonEnabled(panel->browseIconBtn, True);
968 } else {
969 freeInspector(panel);
973 static void textEditedObserver(void *observerData, WMNotification *notification)
975 InspectorPanel *panel = (InspectorPanel *) observerData;
977 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
978 return;
980 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
982 WMPerformButtonClick(panel->updateIconBtn);
986 static void selectSpecification(WMWidget *bPtr, void *data)
988 InspectorPanel *panel = (InspectorPanel *) data;
989 char *str;
990 WWindow *wwin = panel->inspected;
991 int len;
993 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
994 WMSetButtonEnabled(panel->applyBtn, False);
995 else
996 WMSetButtonEnabled(panel->applyBtn, True);
998 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
999 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1001 str = wmalloc(len);
1003 snprintf(str, len, _("Inspecting %s.%s"),
1004 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1006 wFrameWindowChangeTitle(panel->frame->frame, str);
1008 wfree(str);
1011 static void selectWindow(WMWidget *bPtr, void *data)
1013 InspectorPanel *panel = (InspectorPanel *) data;
1014 WWindow *wwin = panel->inspected;
1015 WScreen *scr = wwin->screen_ptr;
1016 XEvent event;
1017 WWindow *iwin;
1019 if (XGrabPointer(dpy, scr->root_win, True,
1020 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1021 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1022 wwarning("could not grab mouse pointer");
1023 return;
1026 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1028 WMMaskEvent(dpy, ButtonPressMask, &event);
1030 XUngrabPointer(dpy, CurrentTime);
1032 iwin = wWindowFor(event.xbutton.subwindow);
1034 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1036 iwin->flags.inspector_open = 1;
1037 iwin->inspector = createInspectorForWindow(iwin,
1038 panel->frame->frame_x, panel->frame->frame_y, True);
1039 wCloseInspectorForWindow(wwin);
1040 } else {
1041 WMSetLabelText(panel->specLbl, spec_text);
1045 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1047 WScreen *scr = wwin->screen_ptr;
1048 InspectorPanel *panel;
1049 Window parent;
1050 int i;
1051 int x, y;
1052 int btn_width, frame_width;
1053 WMButton *selectedBtn = NULL;
1054 #ifdef wrong_behaviour
1055 WMPixmap *pixmap;
1056 #endif
1058 spec_text = _("The configuration will apply to all\n"
1059 "windows that have their WM_CLASS\n"
1060 "property set to the above selected\n" "name, when saved.");
1062 panel = wmalloc(sizeof(InspectorPanel));
1063 memset(panel, 0, sizeof(InspectorPanel));
1065 panel->destroyed = 0;
1067 panel->inspected = wwin;
1069 panel->nextPtr = panelList;
1070 panelList = panel;
1072 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1073 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1075 /**** create common stuff ****/
1077 /* command buttons */
1078 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1079 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1080 panel->saveBtn = WMCreateCommandButton(panel->win);
1081 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1082 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1083 WMSetButtonText(panel->saveBtn, _("Save"));
1084 WMResizeWidget(panel->saveBtn, btn_width, 28);
1085 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1086 WMSetButtonEnabled(panel->saveBtn, False);
1088 panel->applyBtn = WMCreateCommandButton(panel->win);
1089 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1090 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1091 WMSetButtonText(panel->applyBtn, _("Apply"));
1092 WMResizeWidget(panel->applyBtn, btn_width, 28);
1094 panel->revertBtn = WMCreateCommandButton(panel->win);
1095 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1096 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1097 WMSetButtonText(panel->revertBtn, _("Reload"));
1098 WMResizeWidget(panel->revertBtn, btn_width, 28);
1100 /* page selection popup button */
1101 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1102 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1103 WMMoveWidget(panel->pagePopUp, 25, 15);
1104 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1106 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1107 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1108 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1109 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1110 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1112 /**** window spec ****/
1113 frame_width = PWIDTH - (2 * 15);
1115 panel->specFrm = WMCreateFrame(panel->win);
1116 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1117 WMMoveWidget(panel->specFrm, 15, 65);
1118 WMResizeWidget(panel->specFrm, frame_width, 145);
1120 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1121 WMMoveWidget(panel->defaultRb, 10, 78);
1122 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1123 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1124 WMSetButtonSelected(panel->defaultRb, False);
1125 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1127 if (wwin->wm_class && wwin->wm_instance) {
1128 char *str, *tmp;
1130 tmp = wstrconcat(wwin->wm_instance, ".");
1131 str = wstrconcat(tmp, wwin->wm_class);
1133 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1134 WMMoveWidget(panel->bothRb, 10, 18);
1135 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1136 WMSetButtonText(panel->bothRb, str);
1137 wfree(tmp);
1138 wfree(str);
1139 WMGroupButtons(panel->defaultRb, panel->bothRb);
1141 if (!selectedBtn)
1142 selectedBtn = panel->bothRb;
1144 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1147 if (wwin->wm_instance) {
1148 panel->instRb = WMCreateRadioButton(panel->specFrm);
1149 WMMoveWidget(panel->instRb, 10, 38);
1150 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1151 WMSetButtonText(panel->instRb, wwin->wm_instance);
1152 WMGroupButtons(panel->defaultRb, panel->instRb);
1154 if (!selectedBtn)
1155 selectedBtn = panel->instRb;
1157 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1160 if (wwin->wm_class) {
1161 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1162 WMMoveWidget(panel->clsRb, 10, 58);
1163 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1164 WMSetButtonText(panel->clsRb, wwin->wm_class);
1165 WMGroupButtons(panel->defaultRb, panel->clsRb);
1167 if (!selectedBtn)
1168 selectedBtn = panel->clsRb;
1170 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1173 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1174 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1175 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1176 WMSetButtonText(panel->selWinB, _("Select window"));
1177 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1179 panel->specLbl = WMCreateLabel(panel->win);
1180 WMMoveWidget(panel->specLbl, 15, 210);
1181 WMResizeWidget(panel->specLbl, frame_width, 100);
1182 WMSetLabelText(panel->specLbl, spec_text);
1183 WMSetLabelWraps(panel->specLbl, True);
1185 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1187 /**** attributes ****/
1188 panel->attrFrm = WMCreateFrame(panel->win);
1189 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1190 WMMoveWidget(panel->attrFrm, 15, 45);
1191 WMResizeWidget(panel->attrFrm, frame_width, 250);
1193 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1194 char *caption = NULL;
1195 int flag = 0;
1196 char *descr = NULL;
1198 switch (i) {
1199 case 0:
1200 caption = _("Disable titlebar");
1201 flag = WFLAGP(wwin, no_titlebar);
1202 descr = _("Remove the titlebar of this window.\n"
1203 "To access the window commands menu of a window\n"
1204 "without it's titlebar, press Control+Esc (or the\n"
1205 "equivalent shortcut, if you changed the default\n" "settings).");
1206 break;
1207 case 1:
1208 caption = _("Disable resizebar");
1209 flag = WFLAGP(wwin, no_resizebar);
1210 descr = _("Remove the resizebar of this window.");
1211 break;
1212 case 2:
1213 caption = _("Disable close button");
1214 flag = WFLAGP(wwin, no_close_button);
1215 descr = _("Remove the `close window' button of this window.");
1216 break;
1217 case 3:
1218 caption = _("Disable miniaturize button");
1219 flag = WFLAGP(wwin, no_miniaturize_button);
1220 descr = _("Remove the `miniaturize window' button of the window.");
1221 break;
1222 case 4:
1223 caption = _("Disable border");
1224 flag = WFLAGP(wwin, no_border);
1225 descr = _("Remove the 1 pixel black border around the window.");
1226 break;
1227 case 5:
1228 caption = _("Keep on top (floating)");
1229 flag = WFLAGP(wwin, floating);
1230 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1231 break;
1232 case 6:
1233 caption = _("Keep at bottom (sunken)");
1234 flag = WFLAGP(wwin, sunken);
1235 descr = _("Keep the window under all other windows.");
1236 break;
1237 case 7:
1238 caption = _("Omnipresent");
1239 flag = WFLAGP(wwin, omnipresent);
1240 descr = _("Make window present in all workspaces.");
1241 break;
1242 case 8:
1243 caption = _("Start miniaturized");
1244 flag = WFLAGP(wwin, start_miniaturized);
1245 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1246 break;
1247 case 9:
1248 caption = _("Start maximized");
1249 flag = WFLAGP(wwin, start_maximized != 0);
1250 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1251 break;
1252 case 10:
1253 caption = _("Full screen maximization");
1254 flag = WFLAGP(wwin, full_maximize);
1255 descr = _("Make the window use the whole screen space when it's\n"
1256 "maximized. The titlebar and resizebar will be moved\n"
1257 "to outside the screen.");
1258 break;
1260 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1261 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1262 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1263 WMSetButtonSelected(panel->attrChk[i], flag);
1264 WMSetButtonText(panel->attrChk[i], caption);
1266 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1269 /**** more attributes ****/
1270 panel->moreFrm = WMCreateFrame(panel->win);
1271 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1272 WMMoveWidget(panel->moreFrm, 15, 45);
1273 WMResizeWidget(panel->moreFrm, frame_width, 265);
1275 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1276 char *caption = NULL;
1277 int flag = 0;
1278 char *descr = NULL;
1280 switch (i) {
1281 case 0:
1282 caption = _("Do not bind keyboard shortcuts");
1283 flag = WFLAGP(wwin, no_bind_keys);
1284 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1285 "when this window is focused. This will allow the\n"
1286 "window to receive all key combinations regardless\n"
1287 "of your shortcut configuration.");
1288 break;
1289 case 1:
1290 caption = _("Do not bind mouse clicks");
1291 flag = WFLAGP(wwin, no_bind_mouse);
1292 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1293 "in the window (when alt is the modifier you have\n" "configured).");
1294 break;
1295 case 2:
1296 caption = _("Do not show in the window list");
1297 flag = WFLAGP(wwin, skip_window_list);
1298 descr = _("Do not list the window in the window list menu.");
1299 break;
1300 case 3:
1301 caption = _("Do not show in the switch panel");
1302 flag = WFLAGP(wwin, skip_switchpanel);
1303 descr = _("Do not include in switchpanel while alternating windows.");
1304 break;
1305 case 4:
1306 caption = _("Do not let it take focus");
1307 flag = WFLAGP(wwin, no_focusable);
1308 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1309 break;
1310 case 5:
1311 caption = _("Keep inside screen");
1312 flag = WFLAGP(wwin, dont_move_off);
1313 descr = _("Do not allow the window to move itself completely\n"
1314 "outside the screen. For bug compatibility.\n");
1315 break;
1316 case 6:
1317 caption = _("Ignore 'Hide Others'");
1318 flag = WFLAGP(wwin, no_hide_others);
1319 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1320 break;
1321 case 7:
1322 caption = _("Ignore 'Save Session'");
1323 flag = WFLAGP(wwin, dont_save_session);
1324 descr = _("Do not save the associated application in the\n"
1325 "session's state, so that it won't be restarted\n"
1326 "together with other applications when Window Maker\n" "starts.");
1327 break;
1328 case 8:
1329 caption = _("Emulate application icon");
1330 flag = WFLAGP(wwin, emulate_appicon);
1331 descr = _("Make this window act as an application that provides\n"
1332 "enough information to Window Maker for a dockable\n"
1333 "application icon to be created.");
1334 break;
1335 case 9:
1336 caption = _("Focus across workspaces");
1337 flag = WFLAGP(wwin, focus_across_wksp);
1338 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1339 "a focus request (annoying).");
1340 break;
1341 case 10:
1342 caption = _("Do not let it be minimized");
1343 flag = WFLAGP(wwin, no_miniaturizable);
1344 descr = _("Do not let the window of this application be\n"
1345 "minimized.\n");
1346 break;
1347 #ifdef XKB_BUTTON_HINT
1348 case 11:
1349 caption = _("Disable language button");
1350 flag = WFLAGP(wwin, no_language_button);
1351 descr = _("Remove the `toggle language' button of the window.");
1352 break;
1353 #endif
1355 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1356 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1357 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1358 WMSetButtonSelected(panel->moreChk[i], flag);
1359 WMSetButtonText(panel->moreChk[i], caption);
1361 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1364 /* miniwindow/workspace */
1365 panel->iconFrm = WMCreateFrame(panel->win);
1366 WMMoveWidget(panel->iconFrm, 15, 50);
1367 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1368 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1370 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1371 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1372 WMResizeWidget(panel->iconLbl, 64, 64);
1373 WMSetLabelRelief(panel->iconLbl, WRGroove);
1374 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1376 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1377 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1378 WMMoveWidget(panel->browseIconBtn, 22, 32);
1379 WMResizeWidget(panel->browseIconBtn, 120, 26);
1380 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1382 #ifdef wrong_behaviour
1383 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1384 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1385 WMSetButtonImage(panel->updateIconBtn, pixmap);
1386 WMReleasePixmap(pixmap);
1387 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1388 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1389 WMReleasePixmap(pixmap);
1390 #endif
1392 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1393 WMMoveWidget(panel->fileLbl, 20, 85);
1394 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1395 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1397 panel->fileText = WMCreateTextField(panel->iconFrm);
1398 WMMoveWidget(panel->fileText, 20, 105);
1399 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1400 WMSetTextFieldText(panel->fileText, NULL);
1401 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1403 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1404 WMMoveWidget(panel->alwChk, 20, 130);
1405 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1406 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1407 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1409 panel->wsFrm = WMCreateFrame(panel->win);
1410 WMMoveWidget(panel->wsFrm, 15, 225);
1411 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1412 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1414 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1415 "first shown."), WMWidgetView(panel->wsFrm));
1417 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1418 WMMoveWidget(panel->wsP, 20, 30);
1419 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1420 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1422 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1423 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1425 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1426 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1427 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1428 else
1429 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1431 /* application wide attributes */
1432 if (wwin->main_window != None) {
1433 WApplication *wapp = wApplicationOf(wwin->main_window);
1435 panel->appFrm = WMCreateFrame(panel->win);
1436 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1437 WMMoveWidget(panel->appFrm, 15, 50);
1438 WMResizeWidget(panel->appFrm, frame_width, 240);
1440 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1441 char *caption = NULL;
1442 int flag = 0;
1443 char *descr = NULL;
1445 switch (i) {
1446 case 0:
1447 caption = _("Start hidden");
1448 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1449 descr = _("Automatically hide application when it's started.");
1450 break;
1451 case 1:
1452 caption = _("No application icon");
1453 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1454 descr = _("Disable the application icon for the application.\n"
1455 "Note that you won't be able to dock it anymore,\n"
1456 "and any icons that are already docked will stop\n"
1457 "working correctly.");
1458 break;
1459 case 2:
1460 caption = _("Shared application icon");
1461 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1462 descr = _("Use a single shared application icon for all of\n"
1463 "the instances of this application.\n");
1464 break;
1466 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1467 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1468 WMResizeWidget(panel->appChk[i], 205, 20);
1469 WMSetButtonSelected(panel->appChk[i], flag);
1470 WMSetButtonText(panel->appChk[i], caption);
1471 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1474 if (WFLAGP(wwin, emulate_appicon)) {
1475 WMSetButtonEnabled(panel->appChk[1], False);
1476 WMSetButtonEnabled(panel->moreChk[7], True);
1477 } else {
1478 WMSetButtonEnabled(panel->appChk[1], True);
1479 WMSetButtonEnabled(panel->moreChk[7], False);
1481 } else {
1482 int tmp;
1484 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1485 || !wwin->wm_class || !wwin->wm_instance)
1486 tmp = False;
1487 else
1488 tmp = True;
1489 WMSetButtonEnabled(panel->moreChk[7], tmp);
1491 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1492 panel->appFrm = NULL;
1495 /* if the window is a transient, don't let it have a miniaturize
1496 * button */
1497 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1498 WMSetButtonEnabled(panel->attrChk[3], False);
1499 else
1500 WMSetButtonEnabled(panel->attrChk[3], True);
1502 if (!wwin->wm_class && !wwin->wm_instance) {
1503 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1506 WMRealizeWidget(panel->win);
1508 WMMapSubwidgets(panel->win);
1509 WMMapSubwidgets(panel->specFrm);
1510 WMMapSubwidgets(panel->attrFrm);
1511 WMMapSubwidgets(panel->moreFrm);
1512 WMMapSubwidgets(panel->iconFrm);
1513 WMMapSubwidgets(panel->wsFrm);
1514 if (panel->appFrm)
1515 WMMapSubwidgets(panel->appFrm);
1517 if (showSelectPanel) {
1518 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1519 changePage(panel->pagePopUp, panel);
1520 } else {
1521 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1522 changePage(panel->pagePopUp, panel);
1525 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1526 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1527 panel->parent = parent;
1528 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1530 WMMapWidget(panel->win);
1532 XSetTransientForHint(dpy, parent, wwin->client_win);
1534 if (xpos == UNDEFINED_POS) {
1535 x = wwin->frame_x + wwin->frame->core->width / 2;
1536 y = wwin->frame_y + wwin->frame->top_width * 2;
1537 if (y + PHEIGHT > scr->scr_height)
1538 y = scr->scr_height - PHEIGHT - 30;
1539 if (x + PWIDTH > scr->scr_width)
1540 x = scr->scr_width - PWIDTH;
1541 } else {
1542 x = xpos;
1543 y = ypos;
1546 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1548 if (!selectedBtn)
1549 selectedBtn = panel->defaultRb;
1551 WMSetButtonSelected(selectedBtn, True);
1553 selectSpecification(selectedBtn, panel);
1555 /* kluge to know who should get the key events */
1556 panel->frame->client_leader = WMWidgetXID(panel->win);
1558 WSETUFLAG(panel->frame, no_closable, 0);
1559 WSETUFLAG(panel->frame, no_close_button, 0);
1560 wWindowUpdateButtonImages(panel->frame);
1561 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1562 panel->frame->frame->on_click_right = destroyInspector;
1564 wWindowMap(panel->frame);
1566 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1568 return panel;
1571 void wShowInspectorForWindow(WWindow *wwin)
1573 if (wwin->flags.inspector_open)
1574 return;
1576 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1578 make_keys();
1579 wwin->flags.inspector_open = 1;
1580 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1583 void wHideInspectorForWindow(WWindow *wwin)
1585 WWindow *pwin = wwin->inspector->frame;
1587 wWindowUnmap(pwin);
1588 pwin->flags.hidden = 1;
1590 wClientSetState(pwin, IconicState, None);
1593 void wUnhideInspectorForWindow(WWindow *wwin)
1595 WWindow *pwin = wwin->inspector->frame;
1597 pwin->flags.hidden = 0;
1598 pwin->flags.mapped = 1;
1599 XMapWindow(dpy, pwin->client_win);
1600 XMapWindow(dpy, pwin->frame->core->window);
1601 wClientSetState(pwin, NormalState, None);
1604 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1606 if (wwin->inspector) {
1607 assert(wwin->flags.inspector_open != 0);
1609 return wwin->inspector->frame;
1610 } else
1611 return NULL;
1614 void wCloseInspectorForWindow(WWindow *wwin)
1616 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1618 (*pwin->frame->on_click_right) (NULL, pwin, NULL);