Avoid icon change to default on winspector save
[wmaker-crm.git] / src / winspector.c
blob73350308fdbafaca0fa44de91b52c87acd854575
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 NOT included */
318 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
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, *value1, *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 /* If the "Ignore client suplied icon is not selected" flag was not set,
479 * then, don't save the icon filename. If saved, the application will use
480 * that icon, even the flag is not set. */
481 if (WMGetButtonSelected(panel->alwChk) != 0) {
482 /* Update icon for window */
483 icon_file = WMGetTextFieldText(panel->fileText);
484 if (icon_file) {
485 if (icon_file[0] != 0) {
486 value = WMCreatePLString(icon_file);
487 different |= insertAttribute(dict, winDic, AIcon, value, flags);
488 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
489 WMReleasePropList(value);
491 /* Set the ckeck for AAlwaysUserIcon only if icon_file exists */
492 buf1 = wmalloc(4);
493 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
494 value1 = WMCreatePLString(buf1);
495 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
496 WMReleasePropList(value1);
497 wfree(buf1);
499 wfree(icon_file);
503 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
504 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
505 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
506 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
507 WMReleasePropList(value);
510 flags |= IS_BOOLEAN;
512 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
513 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
515 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
516 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
518 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
519 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
521 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
522 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
524 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
525 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
527 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
528 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
530 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
531 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
533 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
534 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
536 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
537 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
539 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
540 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
542 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
543 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
545 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
546 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
548 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
549 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
551 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
552 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
554 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
555 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
557 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
558 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
560 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
561 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
563 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
564 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
566 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
567 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
569 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
570 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
572 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
573 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
575 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
576 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
578 #ifdef XKB_BUTTON_HINT
579 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
580 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
581 #endif
583 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
584 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
585 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
587 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
588 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
590 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
591 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
594 if (wwin->fake_group) {
595 key2 = WMCreatePLString(wwin->fake_group->identifier);
596 if (WMIsPropListEqualTo(key, key2)) {
597 WMMergePLDictionaries(winDic, appDic, True);
598 different |= different2;
599 } else {
600 WMRemoveFromPLDictionary(dict, key2);
601 if (different2)
602 WMPutInPLDictionary(dict, key2, appDic);
604 WMReleasePropList(key2);
605 WMReleasePropList(appDic);
606 } else if (wwin->main_window != wwin->client_win) {
607 WApplication *wapp = wApplicationOf(wwin->main_window);
609 if (wapp) {
610 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
611 wapp->main_window_desc->wm_class);
612 key2 = WMCreatePLString(buf2);
613 wfree(buf2);
615 if (WMIsPropListEqualTo(key, key2)) {
616 WMMergePLDictionaries(winDic, appDic, True);
617 different |= different2;
618 } else {
619 WMRemoveFromPLDictionary(dict, key2);
620 if (different2)
621 WMPutInPLDictionary(dict, key2, appDic);
623 WMReleasePropList(key2);
624 WMReleasePropList(appDic);
626 } else {
627 WMMergePLDictionaries(winDic, appDic, True);
628 different |= different2;
629 WMReleasePropList(appDic);
632 WMRemoveFromPLDictionary(dict, key);
633 if (different)
634 WMPutInPLDictionary(dict, key, winDic);
636 WMReleasePropList(key);
637 WMReleasePropList(winDic);
639 UpdateDomainFile(db);
641 /* clean up */
642 WMPLSetCaseSensitive(False);
645 static void applySettings(WMButton *button, InspectorPanel *panel)
647 WWindow *wwin = panel->inspected;
648 WApplication *wapp = wApplicationOf(wwin->main_window);
649 int floating, sunken, skip_window_list;
650 int old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
652 old_omnipresent = WFLAGP(wwin, omnipresent);
653 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
654 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
656 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
658 /* Attributes... --> Window Attributes */
659 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
660 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
661 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
662 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
663 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
664 floating = WMGetButtonSelected(panel->attrChk[5]);
665 sunken = WMGetButtonSelected(panel->attrChk[6]);
666 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
667 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
668 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
669 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
671 /* Attributes... --> Advanced Options */
672 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
673 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
674 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
675 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
676 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
677 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
678 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
679 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
680 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
681 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
682 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
683 #ifdef XKB_BUTTON_HINT
684 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
685 #endif
686 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
688 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
689 wUnshadeWindow(wwin);
691 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
693 if (floating) {
694 if (!WFLAGP(wwin, floating))
695 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
696 } else if (sunken) {
697 if (!WFLAGP(wwin, sunken))
698 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
699 } else {
700 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
701 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
704 WSETUFLAG(wwin, sunken, sunken);
705 WSETUFLAG(wwin, floating, floating);
706 wwin->flags.omnipresent = 0;
708 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
709 WSETUFLAG(wwin, skip_window_list, skip_window_list);
710 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
711 } else {
712 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
713 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
716 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
717 if (WFLAGP(wwin, no_bind_keys))
718 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
719 else
720 wWindowSetKeyGrabs(wwin);
723 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
724 wWindowResetMouseGrabs(wwin);
726 wwin->frame->flags.need_texture_change = 1;
727 wWindowConfigureBorders(wwin);
728 wFrameWindowPaint(wwin->frame);
729 wNETWMUpdateActions(wwin, False);
731 /* Can't apply emulate_appicon because it will probably cause problems. */
732 if (wapp) {
733 /* do application wide stuff */
734 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
735 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
736 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
738 if (WFLAGP(wapp->main_window_desc, no_appicon))
739 unpaint_app_icon(wapp);
740 else
741 paint_app_icon(wapp);
743 char *file = WMGetTextFieldText(panel->fileText);
744 if (file[0] == 0) {
745 wfree(file);
746 file = NULL;
749 /* If file is NULL, the always_user_icon doesn't matter,
750 * because we need to read the icon from the window */
751 if (file && WFLAGP(wwin, always_user_icon)) {
752 /* Change icon image if the app is minimized */
753 if (wwin->icon)
754 wIconChangeImageFile(wwin->icon, file);
756 /* Change App Icon image */
757 if (wapp->app_icon)
758 wIconChangeImageFile(wapp->app_icon->icon, file);
759 } else {
760 /* Change App Icon image */
761 if (wapp->app_icon)
762 wIconUpdate(wapp->app_icon->icon, get_rimage_icon_from_wm_hints(wapp->app_icon->icon));
764 /* Change icon image if the app is minimized */
765 if (wwin->icon)
766 wIconUpdate(wwin->icon, get_rimage_icon_from_wm_hints(wwin->icon));
769 if (file)
770 wfree(file);
773 wNETFrameExtents(wwin);
776 static void revertSettings(WMButton *button, InspectorPanel *panel)
778 WWindow *wwin = panel->inspected;
779 WApplication *wapp = wApplicationOf(wwin->main_window);
780 int i, n, workspace, level;
781 char *wm_instance = NULL, *wm_class = NULL;
783 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
784 wm_instance = wwin->wm_instance;
785 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
786 wm_class = wwin->wm_class;
787 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
788 wm_instance = wwin->wm_instance;
789 wm_class = wwin->wm_class;
792 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
793 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
794 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
796 wWindowSetupInitialAttributes(wwin, &level, &workspace);
798 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
799 int flag = 0;
801 switch (i) {
802 case 0:
803 flag = WFLAGP(wwin, no_titlebar);
804 break;
805 case 1:
806 flag = WFLAGP(wwin, no_resizebar);
807 break;
808 case 2:
809 flag = WFLAGP(wwin, no_close_button);
810 break;
811 case 3:
812 flag = WFLAGP(wwin, no_miniaturize_button);
813 break;
814 case 4:
815 flag = WFLAGP(wwin, no_border);
816 break;
817 case 5:
818 flag = WFLAGP(wwin, floating);
819 break;
820 case 6:
821 flag = WFLAGP(wwin, sunken);
822 break;
823 case 7:
824 flag = WFLAGP(wwin, omnipresent);
825 break;
826 case 8:
827 flag = WFLAGP(wwin, start_miniaturized);
828 break;
829 case 9:
830 flag = WFLAGP(wwin, start_maximized != 0);
831 break;
832 case 10:
833 flag = WFLAGP(wwin, full_maximize);
834 break;
836 WMSetButtonSelected(panel->attrChk[i], flag);
839 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
840 int flag = 0;
842 switch (i) {
843 case 0:
844 flag = WFLAGP(wwin, no_bind_keys);
845 break;
846 case 1:
847 flag = WFLAGP(wwin, no_bind_mouse);
848 break;
849 case 2:
850 flag = WFLAGP(wwin, skip_window_list);
851 break;
852 case 3:
853 flag = WFLAGP(wwin, skip_switchpanel);
854 break;
855 case 4:
856 flag = WFLAGP(wwin, no_focusable);
857 break;
858 case 5:
859 flag = WFLAGP(wwin, dont_move_off);
860 break;
861 case 6:
862 flag = WFLAGP(wwin, no_hide_others);
863 break;
864 case 7:
865 flag = WFLAGP(wwin, dont_save_session);
866 break;
867 case 8:
868 flag = WFLAGP(wwin, emulate_appicon);
869 break;
870 case 9:
871 flag = WFLAGP(wwin, focus_across_wksp);
872 break;
873 case 10:
874 flag = WFLAGP(wwin, no_miniaturizable);
875 break;
876 #ifdef XKB_BUTTON_HINT
877 case 11:
878 flag = WFLAGP(wwin, no_language_button);
879 break;
880 #endif
882 WMSetButtonSelected(panel->moreChk[i], flag);
884 if (panel->appFrm && wapp) {
885 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
886 int flag = 0;
888 switch (i) {
889 case 0:
890 flag = WFLAGP(wapp->main_window_desc, start_hidden);
891 break;
892 case 1:
893 flag = WFLAGP(wapp->main_window_desc, no_appicon);
894 break;
895 case 2:
896 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
897 break;
899 WMSetButtonSelected(panel->appChk[i], flag);
902 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
904 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
906 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
908 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
909 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
910 else
911 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
913 /* must auto apply, so that there wno't be internal
914 * inconsistencies between the state in the flags and
915 * the actual state of the window */
916 applySettings(panel->applyBtn, panel);
919 static void chooseIconCallback(WMWidget *self, void *clientData)
921 char *file;
922 InspectorPanel *panel = (InspectorPanel *) clientData;
923 int result;
925 panel->choosingIcon = 1;
927 WMSetButtonEnabled(panel->browseIconBtn, False);
929 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
930 panel->inspected->wm_instance,
931 panel->inspected->wm_class);
933 panel->choosingIcon = 0;
935 if (!panel->destroyed) { /* kluge */
936 if (result) {
937 WMSetTextFieldText(panel->fileText, file);
938 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
939 wfree(file);
941 WMSetButtonEnabled(panel->browseIconBtn, True);
942 } else {
943 freeInspector(panel);
947 static void textEditedObserver(void *observerData, WMNotification *notification)
949 InspectorPanel *panel = (InspectorPanel *) observerData;
951 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
952 return;
954 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
957 static void selectSpecification(WMWidget *bPtr, void *data)
959 InspectorPanel *panel = (InspectorPanel *) data;
960 char *str;
961 WWindow *wwin = panel->inspected;
962 int len;
964 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
965 WMSetButtonEnabled(panel->applyBtn, False);
966 else
967 WMSetButtonEnabled(panel->applyBtn, True);
969 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
970 + strlen(wwin->wm_class ? wwin->wm_class : "?");
972 str = wmalloc(len);
974 snprintf(str, len, _("Inspecting %s.%s"),
975 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
977 wFrameWindowChangeTitle(panel->frame->frame, str);
979 wfree(str);
982 static void selectWindow(WMWidget *bPtr, void *data)
984 InspectorPanel *panel = (InspectorPanel *) data;
985 WWindow *wwin = panel->inspected;
986 WScreen *scr = wwin->screen_ptr;
987 XEvent event;
988 WWindow *iwin;
990 if (XGrabPointer(dpy, scr->root_win, True,
991 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
992 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
993 wwarning("could not grab mouse pointer");
994 return;
997 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
998 WMMaskEvent(dpy, ButtonPressMask, &event);
999 XUngrabPointer(dpy, CurrentTime);
1001 iwin = wWindowFor(event.xbutton.subwindow);
1002 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1003 iwin->flags.inspector_open = 1;
1004 iwin->inspector = createInspectorForWindow(iwin,
1005 panel->frame->frame_x, panel->frame->frame_y, True);
1006 wCloseInspectorForWindow(wwin);
1007 } else {
1008 WMSetLabelText(panel->specLbl, spec_text);
1012 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1014 WScreen *scr = wwin->screen_ptr;
1015 InspectorPanel *panel;
1016 Window parent;
1017 char *str = NULL, *tmp = NULL;
1018 int x, y, btn_width, frame_width;
1019 WMButton *selectedBtn = NULL;
1021 spec_text = _("The configuration will apply to all\n"
1022 "windows that have their WM_CLASS\n"
1023 "property set to the above selected\n" "name, when saved.");
1025 panel = wmalloc(sizeof(InspectorPanel));
1026 memset(panel, 0, sizeof(InspectorPanel));
1028 panel->destroyed = 0;
1029 panel->inspected = wwin;
1030 panel->nextPtr = panelList;
1031 panelList = panel;
1032 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1033 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1035 /**** create common stuff ****/
1036 /* command buttons */
1037 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1038 panel->saveBtn = WMCreateCommandButton(panel->win);
1039 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1040 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1041 WMSetButtonText(panel->saveBtn, _("Save"));
1042 WMResizeWidget(panel->saveBtn, btn_width, 28);
1043 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1044 WMSetButtonEnabled(panel->saveBtn, False);
1046 panel->applyBtn = WMCreateCommandButton(panel->win);
1047 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1048 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1049 WMSetButtonText(panel->applyBtn, _("Apply"));
1050 WMResizeWidget(panel->applyBtn, btn_width, 28);
1052 panel->revertBtn = WMCreateCommandButton(panel->win);
1053 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1054 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1055 WMSetButtonText(panel->revertBtn, _("Reload"));
1056 WMResizeWidget(panel->revertBtn, btn_width, 28);
1058 /* page selection popup button */
1059 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1060 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1061 WMMoveWidget(panel->pagePopUp, 25, 15);
1062 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1064 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1065 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1066 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1067 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1068 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1070 /**** window spec ****/
1071 frame_width = PWIDTH - (2 * 15);
1073 panel->specFrm = WMCreateFrame(panel->win);
1074 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1075 WMMoveWidget(panel->specFrm, 15, 65);
1076 WMResizeWidget(panel->specFrm, frame_width, 145);
1078 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1079 WMMoveWidget(panel->defaultRb, 10, 78);
1080 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1081 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1082 WMSetButtonSelected(panel->defaultRb, False);
1083 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1085 if (wwin->wm_class && wwin->wm_instance) {
1086 tmp = wstrconcat(wwin->wm_instance, ".");
1087 str = wstrconcat(tmp, wwin->wm_class);
1089 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1090 WMMoveWidget(panel->bothRb, 10, 18);
1091 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1092 WMSetButtonText(panel->bothRb, str);
1093 wfree(tmp);
1094 wfree(str);
1095 WMGroupButtons(panel->defaultRb, panel->bothRb);
1097 if (!selectedBtn)
1098 selectedBtn = panel->bothRb;
1100 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1103 if (wwin->wm_instance) {
1104 panel->instRb = WMCreateRadioButton(panel->specFrm);
1105 WMMoveWidget(panel->instRb, 10, 38);
1106 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1107 WMSetButtonText(panel->instRb, wwin->wm_instance);
1108 WMGroupButtons(panel->defaultRb, panel->instRb);
1110 if (!selectedBtn)
1111 selectedBtn = panel->instRb;
1113 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1116 if (wwin->wm_class) {
1117 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1118 WMMoveWidget(panel->clsRb, 10, 58);
1119 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1120 WMSetButtonText(panel->clsRb, wwin->wm_class);
1121 WMGroupButtons(panel->defaultRb, panel->clsRb);
1123 if (!selectedBtn)
1124 selectedBtn = panel->clsRb;
1126 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1129 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1130 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1131 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1132 WMSetButtonText(panel->selWinB, _("Select window"));
1133 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1135 panel->specLbl = WMCreateLabel(panel->win);
1136 WMMoveWidget(panel->specLbl, 15, 210);
1137 WMResizeWidget(panel->specLbl, frame_width, 100);
1138 WMSetLabelText(panel->specLbl, spec_text);
1139 WMSetLabelWraps(panel->specLbl, True);
1141 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1143 /**** attributes ****/
1144 create_tab_window_attributes(wwin, panel, frame_width);
1145 create_tab_window_advanced(wwin, panel, frame_width);
1146 create_tab_icon_workspace(wwin, panel, frame_width);
1147 create_tab_app_specific(wwin, panel, frame_width);
1149 /* if the window is a transient, don't let it have a miniaturize button */
1150 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1151 WMSetButtonEnabled(panel->attrChk[3], False);
1152 else
1153 WMSetButtonEnabled(panel->attrChk[3], True);
1155 if (!wwin->wm_class && !wwin->wm_instance)
1156 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1158 WMRealizeWidget(panel->win);
1160 WMMapSubwidgets(panel->win);
1161 WMMapSubwidgets(panel->specFrm);
1162 WMMapSubwidgets(panel->attrFrm);
1163 WMMapSubwidgets(panel->moreFrm);
1164 WMMapSubwidgets(panel->iconFrm);
1165 WMMapSubwidgets(panel->wsFrm);
1166 if (panel->appFrm)
1167 WMMapSubwidgets(panel->appFrm);
1169 if (showSelectPanel) {
1170 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1171 changePage(panel->pagePopUp, panel);
1172 } else {
1173 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1174 changePage(panel->pagePopUp, panel);
1177 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1178 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1179 panel->parent = parent;
1180 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1182 WMMapWidget(panel->win);
1184 XSetTransientForHint(dpy, parent, wwin->client_win);
1186 if (xpos == UNDEFINED_POS) {
1187 x = wwin->frame_x + wwin->frame->core->width / 2;
1188 y = wwin->frame_y + wwin->frame->top_width * 2;
1189 if (y + PHEIGHT > scr->scr_height)
1190 y = scr->scr_height - PHEIGHT - 30;
1191 if (x + PWIDTH > scr->scr_width)
1192 x = scr->scr_width - PWIDTH;
1193 } else {
1194 x = xpos;
1195 y = ypos;
1198 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1200 if (!selectedBtn)
1201 selectedBtn = panel->defaultRb;
1203 WMSetButtonSelected(selectedBtn, True);
1204 selectSpecification(selectedBtn, panel);
1206 /* kluge to know who should get the key events */
1207 panel->frame->client_leader = WMWidgetXID(panel->win);
1209 WSETUFLAG(panel->frame, no_closable, 0);
1210 WSETUFLAG(panel->frame, no_close_button, 0);
1211 wWindowUpdateButtonImages(panel->frame);
1212 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1213 panel->frame->frame->on_click_right = destroyInspector;
1215 wWindowMap(panel->frame);
1217 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1219 return panel;
1222 void wShowInspectorForWindow(WWindow *wwin)
1224 if (wwin->flags.inspector_open)
1225 return;
1227 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1229 make_keys();
1230 wwin->flags.inspector_open = 1;
1231 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1234 void wHideInspectorForWindow(WWindow *wwin)
1236 WWindow *pwin = wwin->inspector->frame;
1238 wWindowUnmap(pwin);
1239 pwin->flags.hidden = 1;
1241 wClientSetState(pwin, IconicState, None);
1244 void wUnhideInspectorForWindow(WWindow *wwin)
1246 WWindow *pwin = wwin->inspector->frame;
1248 pwin->flags.hidden = 0;
1249 pwin->flags.mapped = 1;
1250 XMapWindow(dpy, pwin->client_win);
1251 XMapWindow(dpy, pwin->frame->core->window);
1252 wClientSetState(pwin, NormalState, None);
1255 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1257 if (!wwin->inspector)
1258 return NULL;
1260 assert(wwin->flags.inspector_open != 0);
1261 return wwin->inspector->frame;
1264 void wCloseInspectorForWindow(WWindow *wwin)
1266 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1268 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1271 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1273 int i = 0;
1274 char *caption = NULL, *descr = NULL;
1275 int flag = 0;
1277 panel->attrFrm = WMCreateFrame(panel->win);
1278 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1279 WMMoveWidget(panel->attrFrm, 15, 45);
1280 WMResizeWidget(panel->attrFrm, frame_width, 250);
1282 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1283 switch (i) {
1284 case 0:
1285 caption = _("Disable titlebar");
1286 flag = WFLAGP(wwin, no_titlebar);
1287 descr = _("Remove the titlebar of this window.\n"
1288 "To access the window commands menu of a window\n"
1289 "without it's titlebar, press Control+Esc (or the\n"
1290 "equivalent shortcut, if you changed the default\n" "settings).");
1291 break;
1292 case 1:
1293 caption = _("Disable resizebar");
1294 flag = WFLAGP(wwin, no_resizebar);
1295 descr = _("Remove the resizebar of this window.");
1296 break;
1297 case 2:
1298 caption = _("Disable close button");
1299 flag = WFLAGP(wwin, no_close_button);
1300 descr = _("Remove the `close window' button of this window.");
1301 break;
1302 case 3:
1303 caption = _("Disable miniaturize button");
1304 flag = WFLAGP(wwin, no_miniaturize_button);
1305 descr = _("Remove the `miniaturize window' button of the window.");
1306 break;
1307 case 4:
1308 caption = _("Disable border");
1309 flag = WFLAGP(wwin, no_border);
1310 descr = _("Remove the 1 pixel black border around the window.");
1311 break;
1312 case 5:
1313 caption = _("Keep on top (floating)");
1314 flag = WFLAGP(wwin, floating);
1315 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1316 break;
1317 case 6:
1318 caption = _("Keep at bottom (sunken)");
1319 flag = WFLAGP(wwin, sunken);
1320 descr = _("Keep the window under all other windows.");
1321 break;
1322 case 7:
1323 caption = _("Omnipresent");
1324 flag = WFLAGP(wwin, omnipresent);
1325 descr = _("Make window present in all workspaces.");
1326 break;
1327 case 8:
1328 caption = _("Start miniaturized");
1329 flag = WFLAGP(wwin, start_miniaturized);
1330 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1331 break;
1332 case 9:
1333 caption = _("Start maximized");
1334 flag = WFLAGP(wwin, start_maximized != 0);
1335 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1336 break;
1337 case 10:
1338 caption = _("Full screen maximization");
1339 flag = WFLAGP(wwin, full_maximize);
1340 descr = _("Make the window use the whole screen space when it's\n"
1341 "maximized. The titlebar and resizebar will be moved\n"
1342 "to outside the screen.");
1343 break;
1345 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1346 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1347 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1348 WMSetButtonSelected(panel->attrChk[i], flag);
1349 WMSetButtonText(panel->attrChk[i], caption);
1351 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1355 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1357 int i = 0;
1358 char *caption = NULL, *descr = NULL;
1359 int flag = 0;
1361 panel->moreFrm = WMCreateFrame(panel->win);
1362 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1363 WMMoveWidget(panel->moreFrm, 15, 45);
1364 WMResizeWidget(panel->moreFrm, frame_width, 265);
1366 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1367 switch (i) {
1368 case 0:
1369 caption = _("Do not bind keyboard shortcuts");
1370 flag = WFLAGP(wwin, no_bind_keys);
1371 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1372 "when this window is focused. This will allow the\n"
1373 "window to receive all key combinations regardless\n"
1374 "of your shortcut configuration.");
1375 break;
1376 case 1:
1377 caption = _("Do not bind mouse clicks");
1378 flag = WFLAGP(wwin, no_bind_mouse);
1379 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1380 "in the window (when alt is the modifier you have\n" "configured).");
1381 break;
1382 case 2:
1383 caption = _("Do not show in the window list");
1384 flag = WFLAGP(wwin, skip_window_list);
1385 descr = _("Do not list the window in the window list menu.");
1386 break;
1387 case 3:
1388 caption = _("Do not show in the switch panel");
1389 flag = WFLAGP(wwin, skip_switchpanel);
1390 descr = _("Do not include in switchpanel while alternating windows.");
1391 break;
1392 case 4:
1393 caption = _("Do not let it take focus");
1394 flag = WFLAGP(wwin, no_focusable);
1395 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1396 break;
1397 case 5:
1398 caption = _("Keep inside screen");
1399 flag = WFLAGP(wwin, dont_move_off);
1400 descr = _("Do not allow the window to move itself completely\n"
1401 "outside the screen. For bug compatibility.\n");
1402 break;
1403 case 6:
1404 caption = _("Ignore 'Hide Others'");
1405 flag = WFLAGP(wwin, no_hide_others);
1406 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1407 break;
1408 case 7:
1409 caption = _("Ignore 'Save Session'");
1410 flag = WFLAGP(wwin, dont_save_session);
1411 descr = _("Do not save the associated application in the\n"
1412 "session's state, so that it won't be restarted\n"
1413 "together with other applications when Window Maker\n" "starts.");
1414 break;
1415 case 8:
1416 caption = _("Emulate application icon");
1417 flag = WFLAGP(wwin, emulate_appicon);
1418 descr = _("Make this window act as an application that provides\n"
1419 "enough information to Window Maker for a dockable\n"
1420 "application icon to be created.");
1421 break;
1422 case 9:
1423 caption = _("Focus across workspaces");
1424 flag = WFLAGP(wwin, focus_across_wksp);
1425 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1426 "a focus request (annoying).");
1427 break;
1428 case 10:
1429 caption = _("Do not let it be minimized");
1430 flag = WFLAGP(wwin, no_miniaturizable);
1431 descr = _("Do not let the window of this application be\n"
1432 "minimized.\n");
1433 break;
1434 #ifdef XKB_BUTTON_HINT
1435 case 11:
1436 caption = _("Disable language button");
1437 flag = WFLAGP(wwin, no_language_button);
1438 descr = _("Remove the `toggle language' button of the window.");
1439 break;
1440 #endif
1442 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1443 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1444 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1445 WMSetButtonSelected(panel->moreChk[i], flag);
1446 WMSetButtonText(panel->moreChk[i], caption);
1448 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1452 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1454 WScreen *scr = wwin->screen_ptr;
1455 int i = 0;
1457 /* miniwindow/workspace */
1458 panel->iconFrm = WMCreateFrame(panel->win);
1459 WMMoveWidget(panel->iconFrm, 15, 50);
1460 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1461 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1463 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1464 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1465 WMResizeWidget(panel->iconLbl, 64, 64);
1466 WMSetLabelRelief(panel->iconLbl, WRGroove);
1467 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1469 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1470 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1471 WMMoveWidget(panel->browseIconBtn, 22, 32);
1472 WMResizeWidget(panel->browseIconBtn, 120, 26);
1473 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1475 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1476 WMMoveWidget(panel->fileLbl, 20, 85);
1477 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1478 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1480 panel->fileText = WMCreateTextField(panel->iconFrm);
1481 WMMoveWidget(panel->fileText, 20, 105);
1482 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1483 WMSetTextFieldText(panel->fileText, NULL);
1484 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1486 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1487 WMMoveWidget(panel->alwChk, 20, 130);
1488 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1489 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1490 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1492 panel->wsFrm = WMCreateFrame(panel->win);
1493 WMMoveWidget(panel->wsFrm, 15, 225);
1494 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1495 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1497 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1498 "first shown."), WMWidgetView(panel->wsFrm));
1500 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1501 WMMoveWidget(panel->wsP, 20, 30);
1502 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1503 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1505 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1506 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1508 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1509 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1510 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1511 else
1512 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1515 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1517 WScreen *scr = wwin->screen_ptr;
1518 int i = 0, flag = 0, tmp;
1519 char *caption = NULL, *descr = NULL;
1522 if (wwin->main_window != None) {
1523 WApplication *wapp = wApplicationOf(wwin->main_window);
1525 panel->appFrm = WMCreateFrame(panel->win);
1526 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1527 WMMoveWidget(panel->appFrm, 15, 50);
1528 WMResizeWidget(panel->appFrm, frame_width, 240);
1530 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1531 switch (i) {
1532 case 0:
1533 caption = _("Start hidden");
1534 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1535 descr = _("Automatically hide application when it's started.");
1536 break;
1537 case 1:
1538 caption = _("No application icon");
1539 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1540 descr = _("Disable the application icon for the application.\n"
1541 "Note that you won't be able to dock it anymore,\n"
1542 "and any icons that are already docked will stop\n"
1543 "working correctly.");
1544 break;
1545 case 2:
1546 caption = _("Shared application icon");
1547 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1548 descr = _("Use a single shared application icon for all of\n"
1549 "the instances of this application.\n");
1550 break;
1552 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1553 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1554 WMResizeWidget(panel->appChk[i], 205, 20);
1555 WMSetButtonSelected(panel->appChk[i], flag);
1556 WMSetButtonText(panel->appChk[i], caption);
1557 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1560 if (WFLAGP(wwin, emulate_appicon)) {
1561 WMSetButtonEnabled(panel->appChk[1], False);
1562 WMSetButtonEnabled(panel->moreChk[7], True);
1563 } else {
1564 WMSetButtonEnabled(panel->appChk[1], True);
1565 WMSetButtonEnabled(panel->moreChk[7], False);
1567 } else {
1568 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1569 || !wwin->wm_class || !wwin->wm_instance)
1570 tmp = False;
1571 else
1572 tmp = True;
1574 WMSetButtonEnabled(panel->moreChk[7], tmp);
1576 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1577 panel->appFrm = NULL;