winspector: Don't use text input if NULL
[wmaker-crm.git] / src / winspector.c
blobcd9250dac516b71d31e746f9ab148cb68fa20b94
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 #define USE_TEXT_FIELD 1
54 #define UPDATE_TEXT_FIELD 2
55 #define REVERT_TO_DEFAULT 4
56 #define PWIDTH 290
57 #define PHEIGHT 360
58 #define UNDEFINED_POS 0xffffff
59 #define UPDATE_DEFAULTS 1
60 #define IS_BOOLEAN 2
62 typedef struct InspectorPanel {
63 struct InspectorPanel *nextPtr;
65 WWindow *frame;
66 WWindow *inspected; /* the window that's being inspected */
67 WMWindow *win;
68 Window parent;
70 /* common stuff */
71 WMButton *revertBtn;
72 WMButton *applyBtn;
73 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
77 WMFrame *specFrm;
78 WMButton *instRb;
79 WMButton *clsRb;
80 WMButton *bothRb;
81 WMButton *defaultRb;
82 WMButton *selWinB;
83 WMLabel *specLbl;
85 /* second page. attributes */
86 WMFrame *attrFrm;
87 WMButton *attrChk[11];
89 /* 3rd page. more attributes */
90 WMFrame *moreFrm;
91 #ifdef XKB_BUTTON_HINT
92 WMButton *moreChk[12];
93 #else
94 WMButton *moreChk[11];
95 #endif
97 /* 4th page. icon and workspace */
98 WMFrame *iconFrm;
99 WMLabel *iconLbl;
100 WMLabel *fileLbl;
101 WMTextField *fileText;
102 WMButton *alwChk;
103 WMButton *browseIconBtn;
104 WMFrame *wsFrm;
105 WMPopUpButton *wsP;
107 /* 5th page. application wide attributes */
108 WMFrame *appFrm;
109 WMButton *appChk[3];
111 unsigned int done:1;
112 unsigned int destroyed:1;
113 unsigned int choosingIcon:1;
114 } InspectorPanel;
116 extern Cursor wCursor[WCUR_LAST];
117 extern WDDomain *WDWindowAttributes;
118 extern WPreferences wPreferences;
120 static InspectorPanel *panelList = NULL;
121 static WMPropList *ANoTitlebar = NULL;
122 static WMPropList *ANoResizebar;
123 static WMPropList *ANoMiniaturizeButton;
124 static WMPropList *ANoCloseButton;
125 static WMPropList *ANoBorder;
126 static WMPropList *ANoHideOthers;
127 static WMPropList *ANoMouseBindings;
128 static WMPropList *ANoKeyBindings;
129 static WMPropList *ANoAppIcon;
130 static WMPropList *AKeepOnTop;
131 static WMPropList *AKeepOnBottom;
132 static WMPropList *AOmnipresent;
133 static WMPropList *ASkipWindowList;
134 static WMPropList *ASkipSwitchPanel;
135 static WMPropList *AKeepInsideScreen;
136 static WMPropList *AUnfocusable;
137 static WMPropList *AFocusAcrossWorkspace;
138 static WMPropList *AAlwaysUserIcon;
139 static WMPropList *AStartMiniaturized;
140 static WMPropList *AStartMaximized;
141 static WMPropList *ADontSaveSession;
142 static WMPropList *AEmulateAppIcon;
143 static WMPropList *AFullMaximize;
144 static WMPropList *ASharedAppIcon;
145 static WMPropList *ANoMiniaturizable;
146 #ifdef XKB_BUTTON_HINT
147 static WMPropList *ANoLanguageButton;
148 #endif
149 static WMPropList *AStartWorkspace;
150 static WMPropList *AIcon;
152 /* application wide options */
153 static WMPropList *AStartHidden;
154 static WMPropList *AnyWindow;
155 static WMPropList *EmptyString;
156 static WMPropList *Yes, *No;
158 static char *spec_text;
159 static void applySettings(WMButton *button, InspectorPanel *panel);
161 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
163 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
164 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
165 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width);
166 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
168 static void make_keys(void)
170 if (ANoTitlebar != NULL)
171 return;
173 AIcon = WMCreatePLString("Icon");
174 ANoTitlebar = WMCreatePLString("NoTitlebar");
175 ANoResizebar = WMCreatePLString("NoResizebar");
176 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
177 ANoCloseButton = WMCreatePLString("NoCloseButton");
178 ANoBorder = WMCreatePLString("NoBorder");
179 ANoHideOthers = WMCreatePLString("NoHideOthers");
180 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
181 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
182 ANoAppIcon = WMCreatePLString("NoAppIcon");
183 AKeepOnTop = WMCreatePLString("KeepOnTop");
184 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
185 AOmnipresent = WMCreatePLString("Omnipresent");
186 ASkipWindowList = WMCreatePLString("SkipWindowList");
187 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
188 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
189 AUnfocusable = WMCreatePLString("Unfocusable");
190 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
191 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
192 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
193 AStartMaximized = WMCreatePLString("StartMaximized");
194 AStartHidden = WMCreatePLString("StartHidden");
195 ADontSaveSession = WMCreatePLString("DontSaveSession");
196 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
197 AFullMaximize = WMCreatePLString("FullMaximize");
198 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
199 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
200 #ifdef XKB_BUTTON_HINT
201 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
202 #endif
204 AStartWorkspace = WMCreatePLString("StartWorkspace");
206 AnyWindow = WMCreatePLString("*");
207 EmptyString = WMCreatePLString("");
208 Yes = WMCreatePLString("Yes");
209 No = WMCreatePLString("No");
212 static void freeInspector(InspectorPanel *panel)
214 panel->destroyed = 1;
216 if (panel->choosingIcon)
217 return;
219 WMDestroyWidget(panel->win);
220 XDestroyWindow(dpy, panel->parent);
221 wfree(panel);
224 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
226 InspectorPanel *panel, *tmp;
228 panel = panelList;
229 while (panel->frame != data)
230 panel = panel->nextPtr;
232 if (panelList == panel) {
233 panelList = panel->nextPtr;
234 } else {
235 tmp = panelList;
236 while (tmp->nextPtr != panel)
237 tmp = tmp->nextPtr;
239 tmp->nextPtr = panel->nextPtr;
241 panel->inspected->flags.inspector_open = 0;
242 panel->inspected->inspector = NULL;
244 WMRemoveNotificationObserver(panel);
246 wWindowUnmap(panel->frame);
247 wUnmanageWindow(panel->frame, True, False);
249 freeInspector(panel);
252 void wDestroyInspectorPanels(void)
254 InspectorPanel *panel;
256 while (panelList != NULL) {
257 panel = panelList;
258 panelList = panelList->nextPtr;
259 wUnmanageWindow(panel->frame, False, False);
260 WMDestroyWidget(panel->win);
262 panel->inspected->flags.inspector_open = 0;
263 panel->inspected->inspector = NULL;
265 wfree(panel);
269 static void changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
271 int page;
273 page = WMGetPopUpButtonSelectedItem(bPtr);
275 if (page == 0) {
276 WMMapWidget(panel->specFrm);
277 WMMapWidget(panel->specLbl);
278 } else if (page == 1) {
279 WMMapWidget(panel->attrFrm);
280 } else if (page == 2) {
281 WMMapWidget(panel->moreFrm);
282 } else if (page == 3) {
283 WMMapWidget(panel->iconFrm);
284 WMMapWidget(panel->wsFrm);
285 } else {
286 WMMapWidget(panel->appFrm);
289 if (page != 0) {
290 WMUnmapWidget(panel->specFrm);
291 WMUnmapWidget(panel->specLbl);
293 if (page != 1)
294 WMUnmapWidget(panel->attrFrm);
295 if (page != 2)
296 WMUnmapWidget(panel->moreFrm);
297 if (page != 3) {
298 WMUnmapWidget(panel->iconFrm);
299 WMUnmapWidget(panel->wsFrm);
301 if (page != 4 && panel->appFrm)
302 WMUnmapWidget(panel->appFrm);
305 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, char *wm_instance, char *wm_class, int flags)
307 WMPixmap *pixmap = (WMPixmap *) NULL;
308 char *file = NULL, *path = NULL, *db_icon = NULL;
310 if ((flags & USE_TEXT_FIELD) != 0) {
311 file = WMGetTextFieldText(panel->fileText);
312 if (file && file[0] == 0) {
313 wfree(file);
314 file = NULL;
316 } else {
317 /* Get the application icon, default included */
318 db_icon = wDefaultGetIconFile(wm_instance, wm_class, True);
319 if (db_icon != NULL)
320 file = wstrdup(db_icon);
322 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
323 if (file)
324 file = wstrdup(db_icon);
325 flags |= UPDATE_TEXT_FIELD;
328 if ((flags & UPDATE_TEXT_FIELD) != 0)
329 WMSetTextFieldText(panel->fileText, file);
331 if (file) {
332 path = FindImage(wPreferences.icon_path, file);
334 if (!path) {
335 char *buf;
336 int len = strlen(file) + 80;
338 buf = wmalloc(len);
339 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
340 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
341 wfree(buf);
342 wfree(file);
343 return -1;
346 pixmap = WMCreatePixmapFromFile(scrPtr, path);
347 wfree(path);
349 if (!pixmap) {
350 char *buf;
351 int len = strlen(file) + 80;
353 buf = wmalloc(len);
354 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
355 file, RMessageForError(RErrorCode));
356 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
357 wfree(buf);
358 wfree(file);
359 return -1;
361 wfree(file);
364 WMSetLabelImage(panel->iconLbl, pixmap);
365 if (pixmap)
366 WMReleasePixmap(pixmap);
368 return 0;
371 static int getBool(WMPropList *value)
373 char *val;
375 if (!WMIsPLString(value))
376 return 0;
378 if (!(val = WMGetFromPLString(value)))
379 return 0;
381 if ((val[1] == '\0' &&
382 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
383 val[0] == 't' || val[0] == '1')) ||
384 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
385 return 1;
386 } else if ((val[1] == '\0' &&
387 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
388 val[0] == 'f' || val[0] == '0')) ||
389 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
390 return 0;
391 } else {
392 wwarning(_("can't convert \"%s\" to boolean"), val);
393 return 0;
397 /* Will insert the attribute = value; pair in window's list,
398 * if it's different from the defaults.
399 * Defaults means either defaults database, or attributes saved
400 * for the default window "*". This is to let one revert options that are
401 * global because they were saved for all windows ("*"). */
402 static int
403 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
405 WMPropList *def_win, *def_value = NULL;
406 int update = 0, modified = 0;
408 if (!(flags & UPDATE_DEFAULTS) && dict) {
409 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL)
410 def_value = WMGetFromPLDictionary(def_win, attr);
413 /* If we could not find defaults in database, fall to hardcoded values.
414 * Also this is true if we save defaults for all windows */
415 if (!def_value)
416 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
418 if (flags & IS_BOOLEAN)
419 update = (getBool(value) != getBool(def_value));
420 else
421 update = !WMIsPropListEqualTo(value, def_value);
423 if (update) {
424 WMPutInPLDictionary(window, attr, value);
425 modified = 1;
428 return modified;
431 static void saveSettings(WMButton *button, InspectorPanel *panel)
433 WWindow *wwin = panel->inspected;
434 WDDomain *db = WDWindowAttributes;
435 WMPropList *dict = NULL;
436 WMPropList *winDic, *appDic, *value, *key = NULL, *key2;
437 char *icon_file, *buf1, *buf2;
438 int flags = 0, i = 0, different = 0, different2 = 0;
440 /* Save will apply the changes and save them */
441 applySettings(panel->applyBtn, panel);
443 if (WMGetButtonSelected(panel->instRb) != 0) {
444 key = WMCreatePLString(wwin->wm_instance);
445 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
446 key = WMCreatePLString(wwin->wm_class);
447 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
448 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
449 key = WMCreatePLString(buf1);
450 wfree(buf1);
451 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
452 key = WMRetainPropList(AnyWindow);
453 flags = UPDATE_DEFAULTS;
456 if (!key)
457 return;
459 dict = db->dictionary;
460 if (!dict) {
461 dict = WMCreatePLDictionary(NULL, NULL);
462 if (dict) {
463 db->dictionary = dict;
464 } else {
465 WMReleasePropList(key);
466 return;
470 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
471 return;
473 WMPLSetCaseSensitive(True);
475 winDic = WMCreatePLDictionary(NULL, NULL);
476 appDic = WMCreatePLDictionary(NULL, NULL);
478 /* Update icon for window */
479 icon_file = WMGetTextFieldText(panel->fileText);
480 if (icon_file) {
481 if (icon_file[0] != 0) {
482 value = WMCreatePLString(icon_file);
483 different |= insertAttribute(dict, winDic, AIcon, value, flags);
484 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
485 WMReleasePropList(value);
487 wfree(icon_file);
490 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
491 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
492 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
493 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
494 WMReleasePropList(value);
497 flags |= IS_BOOLEAN;
499 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
500 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
502 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
503 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
505 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
506 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
508 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
509 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
511 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
512 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
514 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
515 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
517 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
518 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
520 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
521 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
523 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
524 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
526 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
527 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
529 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
530 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
532 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
533 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
535 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
536 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
538 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
539 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
541 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
544 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
547 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
550 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
553 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
556 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
559 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
562 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
565 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
568 #ifdef XKB_BUTTON_HINT
569 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
570 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
571 #endif
573 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
574 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
575 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
577 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
578 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
580 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
581 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
584 if (wwin->fake_group) {
585 key2 = WMCreatePLString(wwin->fake_group->identifier);
586 if (WMIsPropListEqualTo(key, key2)) {
587 WMMergePLDictionaries(winDic, appDic, True);
588 different |= different2;
589 } else {
590 WMRemoveFromPLDictionary(dict, key2);
591 if (different2)
592 WMPutInPLDictionary(dict, key2, appDic);
594 WMReleasePropList(key2);
595 WMReleasePropList(appDic);
596 } else if (wwin->main_window != wwin->client_win) {
597 WApplication *wapp = wApplicationOf(wwin->main_window);
599 if (wapp) {
600 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
601 wapp->main_window_desc->wm_class);
602 key2 = WMCreatePLString(buf2);
603 wfree(buf2);
605 if (WMIsPropListEqualTo(key, key2)) {
606 WMMergePLDictionaries(winDic, appDic, True);
607 different |= different2;
608 } else {
609 WMRemoveFromPLDictionary(dict, key2);
610 if (different2)
611 WMPutInPLDictionary(dict, key2, appDic);
613 WMReleasePropList(key2);
614 WMReleasePropList(appDic);
616 } else {
617 WMMergePLDictionaries(winDic, appDic, True);
618 different |= different2;
619 WMReleasePropList(appDic);
622 WMRemoveFromPLDictionary(dict, key);
623 if (different)
624 WMPutInPLDictionary(dict, key, winDic);
626 WMReleasePropList(key);
627 WMReleasePropList(winDic);
629 UpdateDomainFile(db);
631 /* clean up */
632 WMPLSetCaseSensitive(False);
635 static void applySettings(WMButton *button, InspectorPanel *panel)
637 WWindow *wwin = panel->inspected;
638 WApplication *wapp = wApplicationOf(wwin->main_window);
639 int floating, sunken, skip_window_list;
640 int old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
642 old_omnipresent = WFLAGP(wwin, omnipresent);
643 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
644 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
646 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
648 /* Attributes... --> Window Attributes */
649 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
650 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
651 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
652 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
653 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
654 floating = WMGetButtonSelected(panel->attrChk[5]);
655 sunken = WMGetButtonSelected(panel->attrChk[6]);
656 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
657 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
658 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
659 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
661 /* Attributes... --> Advanced Options */
662 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
663 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
664 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
665 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
666 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
667 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
668 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
669 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
670 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
671 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
672 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
673 #ifdef XKB_BUTTON_HINT
674 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
675 #endif
676 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
678 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
679 wUnshadeWindow(wwin);
681 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
683 if (floating) {
684 if (!WFLAGP(wwin, floating))
685 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
686 } else if (sunken) {
687 if (!WFLAGP(wwin, sunken))
688 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
689 } else {
690 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
691 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
694 WSETUFLAG(wwin, sunken, sunken);
695 WSETUFLAG(wwin, floating, floating);
696 wwin->flags.omnipresent = 0;
698 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
699 WSETUFLAG(wwin, skip_window_list, skip_window_list);
700 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
701 } else {
702 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
703 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
706 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
707 if (WFLAGP(wwin, no_bind_keys))
708 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
709 else
710 wWindowSetKeyGrabs(wwin);
713 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
714 wWindowResetMouseGrabs(wwin);
716 wwin->frame->flags.need_texture_change = 1;
717 wWindowConfigureBorders(wwin);
718 wFrameWindowPaint(wwin->frame);
719 wNETWMUpdateActions(wwin, False);
721 /* Can't apply emulate_appicon because it will probably cause problems. */
722 if (wapp) {
723 /* do application wide stuff */
724 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
725 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
726 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
728 if (WFLAGP(wapp->main_window_desc, no_appicon))
729 unpaint_app_icon(wapp);
730 else
731 paint_app_icon(wapp);
733 char *file = WMGetTextFieldText(panel->fileText);
734 if (file[0] == 0) {
735 wfree(file);
736 file = NULL;
739 /* If file is NULL, the always_user_icon doesn't matter,
740 * because we need to read the icon from the window */
741 if (file && WFLAGP(wwin, always_user_icon)) {
742 /* Change icon image if the app is minimized */
743 if (wwin->icon)
744 wIconChangeImageFile(wwin->icon, file);
746 /* Change App Icon image */
747 if (wapp->app_icon)
748 wIconChangeImageFile(wapp->app_icon->icon, file);
749 } else {
750 /* Change App Icon image */
751 if (wapp->app_icon)
752 wIconUpdate(wapp->app_icon->icon, get_rimage_icon_from_wm_hints(wapp->app_icon->icon));
754 /* Change icon image if the app is minimized */
755 if (wwin->icon)
756 wIconUpdate(wwin->icon, get_rimage_icon_from_wm_hints(wwin->icon));
759 if (file)
760 wfree(file);
763 wNETFrameExtents(wwin);
766 static void revertSettings(WMButton *button, InspectorPanel *panel)
768 WWindow *wwin = panel->inspected;
769 WApplication *wapp = wApplicationOf(wwin->main_window);
770 int i, n, workspace, level;
771 char *wm_instance = NULL, *wm_class = NULL;
773 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
774 wm_instance = wwin->wm_instance;
775 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
776 wm_class = wwin->wm_class;
777 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
778 wm_instance = wwin->wm_instance;
779 wm_class = wwin->wm_class;
782 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
783 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
784 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
786 wWindowSetupInitialAttributes(wwin, &level, &workspace);
788 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
789 int flag = 0;
791 switch (i) {
792 case 0:
793 flag = WFLAGP(wwin, no_titlebar);
794 break;
795 case 1:
796 flag = WFLAGP(wwin, no_resizebar);
797 break;
798 case 2:
799 flag = WFLAGP(wwin, no_close_button);
800 break;
801 case 3:
802 flag = WFLAGP(wwin, no_miniaturize_button);
803 break;
804 case 4:
805 flag = WFLAGP(wwin, no_border);
806 break;
807 case 5:
808 flag = WFLAGP(wwin, floating);
809 break;
810 case 6:
811 flag = WFLAGP(wwin, sunken);
812 break;
813 case 7:
814 flag = WFLAGP(wwin, omnipresent);
815 break;
816 case 8:
817 flag = WFLAGP(wwin, start_miniaturized);
818 break;
819 case 9:
820 flag = WFLAGP(wwin, start_maximized != 0);
821 break;
822 case 10:
823 flag = WFLAGP(wwin, full_maximize);
824 break;
826 WMSetButtonSelected(panel->attrChk[i], flag);
829 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
830 int flag = 0;
832 switch (i) {
833 case 0:
834 flag = WFLAGP(wwin, no_bind_keys);
835 break;
836 case 1:
837 flag = WFLAGP(wwin, no_bind_mouse);
838 break;
839 case 2:
840 flag = WFLAGP(wwin, skip_window_list);
841 break;
842 case 3:
843 flag = WFLAGP(wwin, skip_switchpanel);
844 break;
845 case 4:
846 flag = WFLAGP(wwin, no_focusable);
847 break;
848 case 5:
849 flag = WFLAGP(wwin, dont_move_off);
850 break;
851 case 6:
852 flag = WFLAGP(wwin, no_hide_others);
853 break;
854 case 7:
855 flag = WFLAGP(wwin, dont_save_session);
856 break;
857 case 8:
858 flag = WFLAGP(wwin, emulate_appicon);
859 break;
860 case 9:
861 flag = WFLAGP(wwin, focus_across_wksp);
862 break;
863 case 10:
864 flag = WFLAGP(wwin, no_miniaturizable);
865 break;
866 #ifdef XKB_BUTTON_HINT
867 case 11:
868 flag = WFLAGP(wwin, no_language_button);
869 break;
870 #endif
872 WMSetButtonSelected(panel->moreChk[i], flag);
874 if (panel->appFrm && wapp) {
875 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
876 int flag = 0;
878 switch (i) {
879 case 0:
880 flag = WFLAGP(wapp->main_window_desc, start_hidden);
881 break;
882 case 1:
883 flag = WFLAGP(wapp->main_window_desc, no_appicon);
884 break;
885 case 2:
886 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
887 break;
889 WMSetButtonSelected(panel->appChk[i], flag);
892 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
894 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
896 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
898 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
899 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
900 else
901 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
903 /* must auto apply, so that there wno't be internal
904 * inconsistencies between the state in the flags and
905 * the actual state of the window */
906 applySettings(panel->applyBtn, panel);
909 static void chooseIconCallback(WMWidget *self, void *clientData)
911 char *file;
912 InspectorPanel *panel = (InspectorPanel *) clientData;
913 int result;
915 panel->choosingIcon = 1;
917 WMSetButtonEnabled(panel->browseIconBtn, False);
919 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
920 panel->inspected->wm_instance,
921 panel->inspected->wm_class);
923 panel->choosingIcon = 0;
925 if (!panel->destroyed) { /* kluge */
926 if (result) {
927 WMSetTextFieldText(panel->fileText, file);
928 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
929 wfree(file);
931 WMSetButtonEnabled(panel->browseIconBtn, True);
932 } else {
933 freeInspector(panel);
937 static void textEditedObserver(void *observerData, WMNotification *notification)
939 InspectorPanel *panel = (InspectorPanel *) observerData;
941 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
942 return;
944 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
947 static void selectSpecification(WMWidget *bPtr, void *data)
949 InspectorPanel *panel = (InspectorPanel *) data;
950 char *str;
951 WWindow *wwin = panel->inspected;
952 int len;
954 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
955 WMSetButtonEnabled(panel->applyBtn, False);
956 else
957 WMSetButtonEnabled(panel->applyBtn, True);
959 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
960 + strlen(wwin->wm_class ? wwin->wm_class : "?");
962 str = wmalloc(len);
964 snprintf(str, len, _("Inspecting %s.%s"),
965 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
967 wFrameWindowChangeTitle(panel->frame->frame, str);
969 wfree(str);
972 static void selectWindow(WMWidget *bPtr, void *data)
974 InspectorPanel *panel = (InspectorPanel *) data;
975 WWindow *wwin = panel->inspected;
976 WScreen *scr = wwin->screen_ptr;
977 XEvent event;
978 WWindow *iwin;
980 if (XGrabPointer(dpy, scr->root_win, True,
981 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
982 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
983 wwarning("could not grab mouse pointer");
984 return;
987 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
988 WMMaskEvent(dpy, ButtonPressMask, &event);
989 XUngrabPointer(dpy, CurrentTime);
991 iwin = wWindowFor(event.xbutton.subwindow);
992 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
993 iwin->flags.inspector_open = 1;
994 iwin->inspector = createInspectorForWindow(iwin,
995 panel->frame->frame_x, panel->frame->frame_y, True);
996 wCloseInspectorForWindow(wwin);
997 } else {
998 WMSetLabelText(panel->specLbl, spec_text);
1002 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1004 WScreen *scr = wwin->screen_ptr;
1005 InspectorPanel *panel;
1006 Window parent;
1007 char *str = NULL, *tmp = NULL;
1008 int x, y, btn_width, frame_width;
1009 WMButton *selectedBtn = NULL;
1011 spec_text = _("The configuration will apply to all\n"
1012 "windows that have their WM_CLASS\n"
1013 "property set to the above selected\n" "name, when saved.");
1015 panel = wmalloc(sizeof(InspectorPanel));
1016 memset(panel, 0, sizeof(InspectorPanel));
1018 panel->destroyed = 0;
1019 panel->inspected = wwin;
1020 panel->nextPtr = panelList;
1021 panelList = panel;
1022 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1023 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1025 /**** create common stuff ****/
1026 /* command buttons */
1027 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1028 panel->saveBtn = WMCreateCommandButton(panel->win);
1029 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1030 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1031 WMSetButtonText(panel->saveBtn, _("Save"));
1032 WMResizeWidget(panel->saveBtn, btn_width, 28);
1033 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1034 WMSetButtonEnabled(panel->saveBtn, False);
1036 panel->applyBtn = WMCreateCommandButton(panel->win);
1037 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1038 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1039 WMSetButtonText(panel->applyBtn, _("Apply"));
1040 WMResizeWidget(panel->applyBtn, btn_width, 28);
1042 panel->revertBtn = WMCreateCommandButton(panel->win);
1043 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1044 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1045 WMSetButtonText(panel->revertBtn, _("Reload"));
1046 WMResizeWidget(panel->revertBtn, btn_width, 28);
1048 /* page selection popup button */
1049 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1050 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1051 WMMoveWidget(panel->pagePopUp, 25, 15);
1052 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1054 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1055 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1056 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1057 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1058 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1060 /**** window spec ****/
1061 frame_width = PWIDTH - (2 * 15);
1063 panel->specFrm = WMCreateFrame(panel->win);
1064 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1065 WMMoveWidget(panel->specFrm, 15, 65);
1066 WMResizeWidget(panel->specFrm, frame_width, 145);
1068 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1069 WMMoveWidget(panel->defaultRb, 10, 78);
1070 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1071 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1072 WMSetButtonSelected(panel->defaultRb, False);
1073 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1075 if (wwin->wm_class && wwin->wm_instance) {
1076 tmp = wstrconcat(wwin->wm_instance, ".");
1077 str = wstrconcat(tmp, wwin->wm_class);
1079 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1080 WMMoveWidget(panel->bothRb, 10, 18);
1081 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1082 WMSetButtonText(panel->bothRb, str);
1083 wfree(tmp);
1084 wfree(str);
1085 WMGroupButtons(panel->defaultRb, panel->bothRb);
1087 if (!selectedBtn)
1088 selectedBtn = panel->bothRb;
1090 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1093 if (wwin->wm_instance) {
1094 panel->instRb = WMCreateRadioButton(panel->specFrm);
1095 WMMoveWidget(panel->instRb, 10, 38);
1096 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1097 WMSetButtonText(panel->instRb, wwin->wm_instance);
1098 WMGroupButtons(panel->defaultRb, panel->instRb);
1100 if (!selectedBtn)
1101 selectedBtn = panel->instRb;
1103 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1106 if (wwin->wm_class) {
1107 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1108 WMMoveWidget(panel->clsRb, 10, 58);
1109 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1110 WMSetButtonText(panel->clsRb, wwin->wm_class);
1111 WMGroupButtons(panel->defaultRb, panel->clsRb);
1113 if (!selectedBtn)
1114 selectedBtn = panel->clsRb;
1116 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1119 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1120 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1121 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1122 WMSetButtonText(panel->selWinB, _("Select window"));
1123 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1125 panel->specLbl = WMCreateLabel(panel->win);
1126 WMMoveWidget(panel->specLbl, 15, 210);
1127 WMResizeWidget(panel->specLbl, frame_width, 100);
1128 WMSetLabelText(panel->specLbl, spec_text);
1129 WMSetLabelWraps(panel->specLbl, True);
1131 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1133 /**** attributes ****/
1134 create_tab_window_attributes(wwin, panel, frame_width);
1135 create_tab_window_advanced(wwin, panel, frame_width);
1136 create_tab_icon_workspace(wwin, panel, frame_width);
1137 create_tab_app_specific(wwin, panel, frame_width);
1139 /* if the window is a transient, don't let it have a miniaturize button */
1140 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1141 WMSetButtonEnabled(panel->attrChk[3], False);
1142 else
1143 WMSetButtonEnabled(panel->attrChk[3], True);
1145 if (!wwin->wm_class && !wwin->wm_instance)
1146 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1148 WMRealizeWidget(panel->win);
1150 WMMapSubwidgets(panel->win);
1151 WMMapSubwidgets(panel->specFrm);
1152 WMMapSubwidgets(panel->attrFrm);
1153 WMMapSubwidgets(panel->moreFrm);
1154 WMMapSubwidgets(panel->iconFrm);
1155 WMMapSubwidgets(panel->wsFrm);
1156 if (panel->appFrm)
1157 WMMapSubwidgets(panel->appFrm);
1159 if (showSelectPanel) {
1160 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1161 changePage(panel->pagePopUp, panel);
1162 } else {
1163 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1164 changePage(panel->pagePopUp, panel);
1167 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1168 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1169 panel->parent = parent;
1170 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1172 WMMapWidget(panel->win);
1174 XSetTransientForHint(dpy, parent, wwin->client_win);
1176 if (xpos == UNDEFINED_POS) {
1177 x = wwin->frame_x + wwin->frame->core->width / 2;
1178 y = wwin->frame_y + wwin->frame->top_width * 2;
1179 if (y + PHEIGHT > scr->scr_height)
1180 y = scr->scr_height - PHEIGHT - 30;
1181 if (x + PWIDTH > scr->scr_width)
1182 x = scr->scr_width - PWIDTH;
1183 } else {
1184 x = xpos;
1185 y = ypos;
1188 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1190 if (!selectedBtn)
1191 selectedBtn = panel->defaultRb;
1193 WMSetButtonSelected(selectedBtn, True);
1194 selectSpecification(selectedBtn, panel);
1196 /* kluge to know who should get the key events */
1197 panel->frame->client_leader = WMWidgetXID(panel->win);
1199 WSETUFLAG(panel->frame, no_closable, 0);
1200 WSETUFLAG(panel->frame, no_close_button, 0);
1201 wWindowUpdateButtonImages(panel->frame);
1202 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1203 panel->frame->frame->on_click_right = destroyInspector;
1205 wWindowMap(panel->frame);
1207 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1209 return panel;
1212 void wShowInspectorForWindow(WWindow *wwin)
1214 if (wwin->flags.inspector_open)
1215 return;
1217 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1219 make_keys();
1220 wwin->flags.inspector_open = 1;
1221 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1224 void wHideInspectorForWindow(WWindow *wwin)
1226 WWindow *pwin = wwin->inspector->frame;
1228 wWindowUnmap(pwin);
1229 pwin->flags.hidden = 1;
1231 wClientSetState(pwin, IconicState, None);
1234 void wUnhideInspectorForWindow(WWindow *wwin)
1236 WWindow *pwin = wwin->inspector->frame;
1238 pwin->flags.hidden = 0;
1239 pwin->flags.mapped = 1;
1240 XMapWindow(dpy, pwin->client_win);
1241 XMapWindow(dpy, pwin->frame->core->window);
1242 wClientSetState(pwin, NormalState, None);
1245 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1247 if (!wwin->inspector)
1248 return NULL;
1250 assert(wwin->flags.inspector_open != 0);
1251 return wwin->inspector->frame;
1254 void wCloseInspectorForWindow(WWindow *wwin)
1256 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1258 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1261 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1263 int i = 0;
1264 char *caption = NULL, *descr = NULL;
1265 int flag = 0;
1267 panel->attrFrm = WMCreateFrame(panel->win);
1268 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1269 WMMoveWidget(panel->attrFrm, 15, 45);
1270 WMResizeWidget(panel->attrFrm, frame_width, 250);
1272 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1273 switch (i) {
1274 case 0:
1275 caption = _("Disable titlebar");
1276 flag = WFLAGP(wwin, no_titlebar);
1277 descr = _("Remove the titlebar of this window.\n"
1278 "To access the window commands menu of a window\n"
1279 "without it's titlebar, press Control+Esc (or the\n"
1280 "equivalent shortcut, if you changed the default\n" "settings).");
1281 break;
1282 case 1:
1283 caption = _("Disable resizebar");
1284 flag = WFLAGP(wwin, no_resizebar);
1285 descr = _("Remove the resizebar of this window.");
1286 break;
1287 case 2:
1288 caption = _("Disable close button");
1289 flag = WFLAGP(wwin, no_close_button);
1290 descr = _("Remove the `close window' button of this window.");
1291 break;
1292 case 3:
1293 caption = _("Disable miniaturize button");
1294 flag = WFLAGP(wwin, no_miniaturize_button);
1295 descr = _("Remove the `miniaturize window' button of the window.");
1296 break;
1297 case 4:
1298 caption = _("Disable border");
1299 flag = WFLAGP(wwin, no_border);
1300 descr = _("Remove the 1 pixel black border around the window.");
1301 break;
1302 case 5:
1303 caption = _("Keep on top (floating)");
1304 flag = WFLAGP(wwin, floating);
1305 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1306 break;
1307 case 6:
1308 caption = _("Keep at bottom (sunken)");
1309 flag = WFLAGP(wwin, sunken);
1310 descr = _("Keep the window under all other windows.");
1311 break;
1312 case 7:
1313 caption = _("Omnipresent");
1314 flag = WFLAGP(wwin, omnipresent);
1315 descr = _("Make window present in all workspaces.");
1316 break;
1317 case 8:
1318 caption = _("Start miniaturized");
1319 flag = WFLAGP(wwin, start_miniaturized);
1320 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1321 break;
1322 case 9:
1323 caption = _("Start maximized");
1324 flag = WFLAGP(wwin, start_maximized != 0);
1325 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1326 break;
1327 case 10:
1328 caption = _("Full screen maximization");
1329 flag = WFLAGP(wwin, full_maximize);
1330 descr = _("Make the window use the whole screen space when it's\n"
1331 "maximized. The titlebar and resizebar will be moved\n"
1332 "to outside the screen.");
1333 break;
1335 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1336 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1337 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1338 WMSetButtonSelected(panel->attrChk[i], flag);
1339 WMSetButtonText(panel->attrChk[i], caption);
1341 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1345 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1347 int i = 0;
1348 char *caption = NULL, *descr = NULL;
1349 int flag = 0;
1351 panel->moreFrm = WMCreateFrame(panel->win);
1352 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1353 WMMoveWidget(panel->moreFrm, 15, 45);
1354 WMResizeWidget(panel->moreFrm, frame_width, 265);
1356 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1357 switch (i) {
1358 case 0:
1359 caption = _("Do not bind keyboard shortcuts");
1360 flag = WFLAGP(wwin, no_bind_keys);
1361 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1362 "when this window is focused. This will allow the\n"
1363 "window to receive all key combinations regardless\n"
1364 "of your shortcut configuration.");
1365 break;
1366 case 1:
1367 caption = _("Do not bind mouse clicks");
1368 flag = WFLAGP(wwin, no_bind_mouse);
1369 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1370 "in the window (when alt is the modifier you have\n" "configured).");
1371 break;
1372 case 2:
1373 caption = _("Do not show in the window list");
1374 flag = WFLAGP(wwin, skip_window_list);
1375 descr = _("Do not list the window in the window list menu.");
1376 break;
1377 case 3:
1378 caption = _("Do not show in the switch panel");
1379 flag = WFLAGP(wwin, skip_switchpanel);
1380 descr = _("Do not include in switchpanel while alternating windows.");
1381 break;
1382 case 4:
1383 caption = _("Do not let it take focus");
1384 flag = WFLAGP(wwin, no_focusable);
1385 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1386 break;
1387 case 5:
1388 caption = _("Keep inside screen");
1389 flag = WFLAGP(wwin, dont_move_off);
1390 descr = _("Do not allow the window to move itself completely\n"
1391 "outside the screen. For bug compatibility.\n");
1392 break;
1393 case 6:
1394 caption = _("Ignore 'Hide Others'");
1395 flag = WFLAGP(wwin, no_hide_others);
1396 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1397 break;
1398 case 7:
1399 caption = _("Ignore 'Save Session'");
1400 flag = WFLAGP(wwin, dont_save_session);
1401 descr = _("Do not save the associated application in the\n"
1402 "session's state, so that it won't be restarted\n"
1403 "together with other applications when Window Maker\n" "starts.");
1404 break;
1405 case 8:
1406 caption = _("Emulate application icon");
1407 flag = WFLAGP(wwin, emulate_appicon);
1408 descr = _("Make this window act as an application that provides\n"
1409 "enough information to Window Maker for a dockable\n"
1410 "application icon to be created.");
1411 break;
1412 case 9:
1413 caption = _("Focus across workspaces");
1414 flag = WFLAGP(wwin, focus_across_wksp);
1415 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1416 "a focus request (annoying).");
1417 break;
1418 case 10:
1419 caption = _("Do not let it be minimized");
1420 flag = WFLAGP(wwin, no_miniaturizable);
1421 descr = _("Do not let the window of this application be\n"
1422 "minimized.\n");
1423 break;
1424 #ifdef XKB_BUTTON_HINT
1425 case 11:
1426 caption = _("Disable language button");
1427 flag = WFLAGP(wwin, no_language_button);
1428 descr = _("Remove the `toggle language' button of the window.");
1429 break;
1430 #endif
1432 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1433 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1434 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1435 WMSetButtonSelected(panel->moreChk[i], flag);
1436 WMSetButtonText(panel->moreChk[i], caption);
1438 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1442 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1444 WScreen *scr = wwin->screen_ptr;
1445 int i = 0;
1447 /* miniwindow/workspace */
1448 panel->iconFrm = WMCreateFrame(panel->win);
1449 WMMoveWidget(panel->iconFrm, 15, 50);
1450 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1451 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1453 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1454 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1455 WMResizeWidget(panel->iconLbl, 64, 64);
1456 WMSetLabelRelief(panel->iconLbl, WRGroove);
1457 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1459 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1460 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1461 WMMoveWidget(panel->browseIconBtn, 22, 32);
1462 WMResizeWidget(panel->browseIconBtn, 120, 26);
1463 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1465 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1466 WMMoveWidget(panel->fileLbl, 20, 85);
1467 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1468 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1470 panel->fileText = WMCreateTextField(panel->iconFrm);
1471 WMMoveWidget(panel->fileText, 20, 105);
1472 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1473 WMSetTextFieldText(panel->fileText, NULL);
1474 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1476 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1477 WMMoveWidget(panel->alwChk, 20, 130);
1478 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1479 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1480 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1482 panel->wsFrm = WMCreateFrame(panel->win);
1483 WMMoveWidget(panel->wsFrm, 15, 225);
1484 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1485 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1487 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1488 "first shown."), WMWidgetView(panel->wsFrm));
1490 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1491 WMMoveWidget(panel->wsP, 20, 30);
1492 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1493 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1495 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1496 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1498 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1499 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1500 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1501 else
1502 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1505 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1507 WScreen *scr = wwin->screen_ptr;
1508 int i = 0, flag = 0, tmp;
1509 char *caption = NULL, *descr = NULL;
1512 if (wwin->main_window != None) {
1513 WApplication *wapp = wApplicationOf(wwin->main_window);
1515 panel->appFrm = WMCreateFrame(panel->win);
1516 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1517 WMMoveWidget(panel->appFrm, 15, 50);
1518 WMResizeWidget(panel->appFrm, frame_width, 240);
1520 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1521 switch (i) {
1522 case 0:
1523 caption = _("Start hidden");
1524 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1525 descr = _("Automatically hide application when it's started.");
1526 break;
1527 case 1:
1528 caption = _("No application icon");
1529 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1530 descr = _("Disable the application icon for the application.\n"
1531 "Note that you won't be able to dock it anymore,\n"
1532 "and any icons that are already docked will stop\n"
1533 "working correctly.");
1534 break;
1535 case 2:
1536 caption = _("Shared application icon");
1537 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1538 descr = _("Use a single shared application icon for all of\n"
1539 "the instances of this application.\n");
1540 break;
1542 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1543 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1544 WMResizeWidget(panel->appChk[i], 205, 20);
1545 WMSetButtonSelected(panel->appChk[i], flag);
1546 WMSetButtonText(panel->appChk[i], caption);
1547 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1550 if (WFLAGP(wwin, emulate_appicon)) {
1551 WMSetButtonEnabled(panel->appChk[1], False);
1552 WMSetButtonEnabled(panel->moreChk[7], True);
1553 } else {
1554 WMSetButtonEnabled(panel->appChk[1], True);
1555 WMSetButtonEnabled(panel->moreChk[7], False);
1557 } else {
1558 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1559 || !wwin->wm_class || !wwin->wm_instance)
1560 tmp = False;
1561 else
1562 tmp = True;
1564 WMSetButtonEnabled(panel->moreChk[7], tmp);
1566 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1567 panel->appFrm = NULL;