7e916e78c677d0db524ba243da8e1d9e25607493
[wmaker-crm.git] / src / winspector.c
blob7e916e78c677d0db524ba243da8e1d9e25607493
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 (WFLAGP(wwin, always_user_icon)) {
740 /* Change icon image if the app is minimized */
741 if (wwin->icon)
742 wIconChangeImageFile(wwin->icon, file);
744 /* Change App Icon image */
745 if (wapp->app_icon)
746 wIconChangeImageFile(wapp->app_icon->icon, file);
747 } else {
748 /* Change App Icon image */
749 if (wapp->app_icon)
750 wIconUpdate(wapp->app_icon->icon, get_rimage_icon_from_wm_hints(wapp->app_icon->icon));
752 /* Change icon image if the app is minimized */
753 if (wwin->icon)
754 wIconUpdate(wwin->icon, get_rimage_icon_from_wm_hints(wwin->icon));
757 if (file)
758 wfree(file);
761 wNETFrameExtents(wwin);
764 static void revertSettings(WMButton *button, InspectorPanel *panel)
766 WWindow *wwin = panel->inspected;
767 WApplication *wapp = wApplicationOf(wwin->main_window);
768 int i, n, workspace, level;
769 char *wm_instance = NULL, *wm_class = NULL;
771 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
772 wm_instance = wwin->wm_instance;
773 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
774 wm_class = wwin->wm_class;
775 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
776 wm_instance = wwin->wm_instance;
777 wm_class = wwin->wm_class;
780 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
781 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
782 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
784 wWindowSetupInitialAttributes(wwin, &level, &workspace);
786 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
787 int flag = 0;
789 switch (i) {
790 case 0:
791 flag = WFLAGP(wwin, no_titlebar);
792 break;
793 case 1:
794 flag = WFLAGP(wwin, no_resizebar);
795 break;
796 case 2:
797 flag = WFLAGP(wwin, no_close_button);
798 break;
799 case 3:
800 flag = WFLAGP(wwin, no_miniaturize_button);
801 break;
802 case 4:
803 flag = WFLAGP(wwin, no_border);
804 break;
805 case 5:
806 flag = WFLAGP(wwin, floating);
807 break;
808 case 6:
809 flag = WFLAGP(wwin, sunken);
810 break;
811 case 7:
812 flag = WFLAGP(wwin, omnipresent);
813 break;
814 case 8:
815 flag = WFLAGP(wwin, start_miniaturized);
816 break;
817 case 9:
818 flag = WFLAGP(wwin, start_maximized != 0);
819 break;
820 case 10:
821 flag = WFLAGP(wwin, full_maximize);
822 break;
824 WMSetButtonSelected(panel->attrChk[i], flag);
827 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
828 int flag = 0;
830 switch (i) {
831 case 0:
832 flag = WFLAGP(wwin, no_bind_keys);
833 break;
834 case 1:
835 flag = WFLAGP(wwin, no_bind_mouse);
836 break;
837 case 2:
838 flag = WFLAGP(wwin, skip_window_list);
839 break;
840 case 3:
841 flag = WFLAGP(wwin, skip_switchpanel);
842 break;
843 case 4:
844 flag = WFLAGP(wwin, no_focusable);
845 break;
846 case 5:
847 flag = WFLAGP(wwin, dont_move_off);
848 break;
849 case 6:
850 flag = WFLAGP(wwin, no_hide_others);
851 break;
852 case 7:
853 flag = WFLAGP(wwin, dont_save_session);
854 break;
855 case 8:
856 flag = WFLAGP(wwin, emulate_appicon);
857 break;
858 case 9:
859 flag = WFLAGP(wwin, focus_across_wksp);
860 break;
861 case 10:
862 flag = WFLAGP(wwin, no_miniaturizable);
863 break;
864 #ifdef XKB_BUTTON_HINT
865 case 11:
866 flag = WFLAGP(wwin, no_language_button);
867 break;
868 #endif
870 WMSetButtonSelected(panel->moreChk[i], flag);
872 if (panel->appFrm && wapp) {
873 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
874 int flag = 0;
876 switch (i) {
877 case 0:
878 flag = WFLAGP(wapp->main_window_desc, start_hidden);
879 break;
880 case 1:
881 flag = WFLAGP(wapp->main_window_desc, no_appicon);
882 break;
883 case 2:
884 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
885 break;
887 WMSetButtonSelected(panel->appChk[i], flag);
890 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
892 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
894 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
896 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
897 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
898 else
899 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
901 /* must auto apply, so that there wno't be internal
902 * inconsistencies between the state in the flags and
903 * the actual state of the window */
904 applySettings(panel->applyBtn, panel);
907 static void chooseIconCallback(WMWidget *self, void *clientData)
909 char *file;
910 InspectorPanel *panel = (InspectorPanel *) clientData;
911 int result;
913 panel->choosingIcon = 1;
915 WMSetButtonEnabled(panel->browseIconBtn, False);
917 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
918 panel->inspected->wm_instance,
919 panel->inspected->wm_class);
921 panel->choosingIcon = 0;
923 if (!panel->destroyed) { /* kluge */
924 if (result) {
925 WMSetTextFieldText(panel->fileText, file);
926 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
927 wfree(file);
929 WMSetButtonEnabled(panel->browseIconBtn, True);
930 } else {
931 freeInspector(panel);
935 static void textEditedObserver(void *observerData, WMNotification *notification)
937 InspectorPanel *panel = (InspectorPanel *) observerData;
939 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
940 return;
942 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
945 static void selectSpecification(WMWidget *bPtr, void *data)
947 InspectorPanel *panel = (InspectorPanel *) data;
948 char *str;
949 WWindow *wwin = panel->inspected;
950 int len;
952 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
953 WMSetButtonEnabled(panel->applyBtn, False);
954 else
955 WMSetButtonEnabled(panel->applyBtn, True);
957 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
958 + strlen(wwin->wm_class ? wwin->wm_class : "?");
960 str = wmalloc(len);
962 snprintf(str, len, _("Inspecting %s.%s"),
963 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
965 wFrameWindowChangeTitle(panel->frame->frame, str);
967 wfree(str);
970 static void selectWindow(WMWidget *bPtr, void *data)
972 InspectorPanel *panel = (InspectorPanel *) data;
973 WWindow *wwin = panel->inspected;
974 WScreen *scr = wwin->screen_ptr;
975 XEvent event;
976 WWindow *iwin;
978 if (XGrabPointer(dpy, scr->root_win, True,
979 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
980 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
981 wwarning("could not grab mouse pointer");
982 return;
985 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
986 WMMaskEvent(dpy, ButtonPressMask, &event);
987 XUngrabPointer(dpy, CurrentTime);
989 iwin = wWindowFor(event.xbutton.subwindow);
990 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
991 iwin->flags.inspector_open = 1;
992 iwin->inspector = createInspectorForWindow(iwin,
993 panel->frame->frame_x, panel->frame->frame_y, True);
994 wCloseInspectorForWindow(wwin);
995 } else {
996 WMSetLabelText(panel->specLbl, spec_text);
1000 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1002 WScreen *scr = wwin->screen_ptr;
1003 InspectorPanel *panel;
1004 Window parent;
1005 char *str = NULL, *tmp = NULL;
1006 int x, y, btn_width, frame_width;
1007 WMButton *selectedBtn = NULL;
1009 spec_text = _("The configuration will apply to all\n"
1010 "windows that have their WM_CLASS\n"
1011 "property set to the above selected\n" "name, when saved.");
1013 panel = wmalloc(sizeof(InspectorPanel));
1014 memset(panel, 0, sizeof(InspectorPanel));
1016 panel->destroyed = 0;
1017 panel->inspected = wwin;
1018 panel->nextPtr = panelList;
1019 panelList = panel;
1020 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1021 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1023 /**** create common stuff ****/
1024 /* command buttons */
1025 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1026 panel->saveBtn = WMCreateCommandButton(panel->win);
1027 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1028 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1029 WMSetButtonText(panel->saveBtn, _("Save"));
1030 WMResizeWidget(panel->saveBtn, btn_width, 28);
1031 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1032 WMSetButtonEnabled(panel->saveBtn, False);
1034 panel->applyBtn = WMCreateCommandButton(panel->win);
1035 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1036 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1037 WMSetButtonText(panel->applyBtn, _("Apply"));
1038 WMResizeWidget(panel->applyBtn, btn_width, 28);
1040 panel->revertBtn = WMCreateCommandButton(panel->win);
1041 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1042 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1043 WMSetButtonText(panel->revertBtn, _("Reload"));
1044 WMResizeWidget(panel->revertBtn, btn_width, 28);
1046 /* page selection popup button */
1047 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1048 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1049 WMMoveWidget(panel->pagePopUp, 25, 15);
1050 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1052 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1053 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1054 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1055 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1056 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1058 /**** window spec ****/
1059 frame_width = PWIDTH - (2 * 15);
1061 panel->specFrm = WMCreateFrame(panel->win);
1062 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1063 WMMoveWidget(panel->specFrm, 15, 65);
1064 WMResizeWidget(panel->specFrm, frame_width, 145);
1066 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1067 WMMoveWidget(panel->defaultRb, 10, 78);
1068 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1069 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1070 WMSetButtonSelected(panel->defaultRb, False);
1071 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1073 if (wwin->wm_class && wwin->wm_instance) {
1074 tmp = wstrconcat(wwin->wm_instance, ".");
1075 str = wstrconcat(tmp, wwin->wm_class);
1077 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1078 WMMoveWidget(panel->bothRb, 10, 18);
1079 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1080 WMSetButtonText(panel->bothRb, str);
1081 wfree(tmp);
1082 wfree(str);
1083 WMGroupButtons(panel->defaultRb, panel->bothRb);
1085 if (!selectedBtn)
1086 selectedBtn = panel->bothRb;
1088 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1091 if (wwin->wm_instance) {
1092 panel->instRb = WMCreateRadioButton(panel->specFrm);
1093 WMMoveWidget(panel->instRb, 10, 38);
1094 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1095 WMSetButtonText(panel->instRb, wwin->wm_instance);
1096 WMGroupButtons(panel->defaultRb, panel->instRb);
1098 if (!selectedBtn)
1099 selectedBtn = panel->instRb;
1101 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1104 if (wwin->wm_class) {
1105 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1106 WMMoveWidget(panel->clsRb, 10, 58);
1107 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1108 WMSetButtonText(panel->clsRb, wwin->wm_class);
1109 WMGroupButtons(panel->defaultRb, panel->clsRb);
1111 if (!selectedBtn)
1112 selectedBtn = panel->clsRb;
1114 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1117 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1118 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1119 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1120 WMSetButtonText(panel->selWinB, _("Select window"));
1121 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1123 panel->specLbl = WMCreateLabel(panel->win);
1124 WMMoveWidget(panel->specLbl, 15, 210);
1125 WMResizeWidget(panel->specLbl, frame_width, 100);
1126 WMSetLabelText(panel->specLbl, spec_text);
1127 WMSetLabelWraps(panel->specLbl, True);
1129 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1131 /**** attributes ****/
1132 create_tab_window_attributes(wwin, panel, frame_width);
1133 create_tab_window_advanced(wwin, panel, frame_width);
1134 create_tab_icon_workspace(wwin, panel, frame_width);
1135 create_tab_app_specific(wwin, panel, frame_width);
1137 /* if the window is a transient, don't let it have a miniaturize button */
1138 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1139 WMSetButtonEnabled(panel->attrChk[3], False);
1140 else
1141 WMSetButtonEnabled(panel->attrChk[3], True);
1143 if (!wwin->wm_class && !wwin->wm_instance)
1144 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1146 WMRealizeWidget(panel->win);
1148 WMMapSubwidgets(panel->win);
1149 WMMapSubwidgets(panel->specFrm);
1150 WMMapSubwidgets(panel->attrFrm);
1151 WMMapSubwidgets(panel->moreFrm);
1152 WMMapSubwidgets(panel->iconFrm);
1153 WMMapSubwidgets(panel->wsFrm);
1154 if (panel->appFrm)
1155 WMMapSubwidgets(panel->appFrm);
1157 if (showSelectPanel) {
1158 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1159 changePage(panel->pagePopUp, panel);
1160 } else {
1161 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1162 changePage(panel->pagePopUp, panel);
1165 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1166 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1167 panel->parent = parent;
1168 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1170 WMMapWidget(panel->win);
1172 XSetTransientForHint(dpy, parent, wwin->client_win);
1174 if (xpos == UNDEFINED_POS) {
1175 x = wwin->frame_x + wwin->frame->core->width / 2;
1176 y = wwin->frame_y + wwin->frame->top_width * 2;
1177 if (y + PHEIGHT > scr->scr_height)
1178 y = scr->scr_height - PHEIGHT - 30;
1179 if (x + PWIDTH > scr->scr_width)
1180 x = scr->scr_width - PWIDTH;
1181 } else {
1182 x = xpos;
1183 y = ypos;
1186 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1188 if (!selectedBtn)
1189 selectedBtn = panel->defaultRb;
1191 WMSetButtonSelected(selectedBtn, True);
1192 selectSpecification(selectedBtn, panel);
1194 /* kluge to know who should get the key events */
1195 panel->frame->client_leader = WMWidgetXID(panel->win);
1197 WSETUFLAG(panel->frame, no_closable, 0);
1198 WSETUFLAG(panel->frame, no_close_button, 0);
1199 wWindowUpdateButtonImages(panel->frame);
1200 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1201 panel->frame->frame->on_click_right = destroyInspector;
1203 wWindowMap(panel->frame);
1205 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1207 return panel;
1210 void wShowInspectorForWindow(WWindow *wwin)
1212 if (wwin->flags.inspector_open)
1213 return;
1215 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1217 make_keys();
1218 wwin->flags.inspector_open = 1;
1219 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1222 void wHideInspectorForWindow(WWindow *wwin)
1224 WWindow *pwin = wwin->inspector->frame;
1226 wWindowUnmap(pwin);
1227 pwin->flags.hidden = 1;
1229 wClientSetState(pwin, IconicState, None);
1232 void wUnhideInspectorForWindow(WWindow *wwin)
1234 WWindow *pwin = wwin->inspector->frame;
1236 pwin->flags.hidden = 0;
1237 pwin->flags.mapped = 1;
1238 XMapWindow(dpy, pwin->client_win);
1239 XMapWindow(dpy, pwin->frame->core->window);
1240 wClientSetState(pwin, NormalState, None);
1243 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1245 if (!wwin->inspector)
1246 return NULL;
1248 assert(wwin->flags.inspector_open != 0);
1249 return wwin->inspector->frame;
1252 void wCloseInspectorForWindow(WWindow *wwin)
1254 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1256 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1259 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1261 int i = 0;
1262 char *caption = NULL, *descr = NULL;
1263 int flag = 0;
1265 panel->attrFrm = WMCreateFrame(panel->win);
1266 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1267 WMMoveWidget(panel->attrFrm, 15, 45);
1268 WMResizeWidget(panel->attrFrm, frame_width, 250);
1270 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1271 switch (i) {
1272 case 0:
1273 caption = _("Disable titlebar");
1274 flag = WFLAGP(wwin, no_titlebar);
1275 descr = _("Remove the titlebar of this window.\n"
1276 "To access the window commands menu of a window\n"
1277 "without it's titlebar, press Control+Esc (or the\n"
1278 "equivalent shortcut, if you changed the default\n" "settings).");
1279 break;
1280 case 1:
1281 caption = _("Disable resizebar");
1282 flag = WFLAGP(wwin, no_resizebar);
1283 descr = _("Remove the resizebar of this window.");
1284 break;
1285 case 2:
1286 caption = _("Disable close button");
1287 flag = WFLAGP(wwin, no_close_button);
1288 descr = _("Remove the `close window' button of this window.");
1289 break;
1290 case 3:
1291 caption = _("Disable miniaturize button");
1292 flag = WFLAGP(wwin, no_miniaturize_button);
1293 descr = _("Remove the `miniaturize window' button of the window.");
1294 break;
1295 case 4:
1296 caption = _("Disable border");
1297 flag = WFLAGP(wwin, no_border);
1298 descr = _("Remove the 1 pixel black border around the window.");
1299 break;
1300 case 5:
1301 caption = _("Keep on top (floating)");
1302 flag = WFLAGP(wwin, floating);
1303 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1304 break;
1305 case 6:
1306 caption = _("Keep at bottom (sunken)");
1307 flag = WFLAGP(wwin, sunken);
1308 descr = _("Keep the window under all other windows.");
1309 break;
1310 case 7:
1311 caption = _("Omnipresent");
1312 flag = WFLAGP(wwin, omnipresent);
1313 descr = _("Make window present in all workspaces.");
1314 break;
1315 case 8:
1316 caption = _("Start miniaturized");
1317 flag = WFLAGP(wwin, start_miniaturized);
1318 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1319 break;
1320 case 9:
1321 caption = _("Start maximized");
1322 flag = WFLAGP(wwin, start_maximized != 0);
1323 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1324 break;
1325 case 10:
1326 caption = _("Full screen maximization");
1327 flag = WFLAGP(wwin, full_maximize);
1328 descr = _("Make the window use the whole screen space when it's\n"
1329 "maximized. The titlebar and resizebar will be moved\n"
1330 "to outside the screen.");
1331 break;
1333 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1334 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1335 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1336 WMSetButtonSelected(panel->attrChk[i], flag);
1337 WMSetButtonText(panel->attrChk[i], caption);
1339 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1343 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1345 int i = 0;
1346 char *caption = NULL, *descr = NULL;
1347 int flag = 0;
1349 panel->moreFrm = WMCreateFrame(panel->win);
1350 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1351 WMMoveWidget(panel->moreFrm, 15, 45);
1352 WMResizeWidget(panel->moreFrm, frame_width, 265);
1354 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1355 switch (i) {
1356 case 0:
1357 caption = _("Do not bind keyboard shortcuts");
1358 flag = WFLAGP(wwin, no_bind_keys);
1359 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1360 "when this window is focused. This will allow the\n"
1361 "window to receive all key combinations regardless\n"
1362 "of your shortcut configuration.");
1363 break;
1364 case 1:
1365 caption = _("Do not bind mouse clicks");
1366 flag = WFLAGP(wwin, no_bind_mouse);
1367 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1368 "in the window (when alt is the modifier you have\n" "configured).");
1369 break;
1370 case 2:
1371 caption = _("Do not show in the window list");
1372 flag = WFLAGP(wwin, skip_window_list);
1373 descr = _("Do not list the window in the window list menu.");
1374 break;
1375 case 3:
1376 caption = _("Do not show in the switch panel");
1377 flag = WFLAGP(wwin, skip_switchpanel);
1378 descr = _("Do not include in switchpanel while alternating windows.");
1379 break;
1380 case 4:
1381 caption = _("Do not let it take focus");
1382 flag = WFLAGP(wwin, no_focusable);
1383 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1384 break;
1385 case 5:
1386 caption = _("Keep inside screen");
1387 flag = WFLAGP(wwin, dont_move_off);
1388 descr = _("Do not allow the window to move itself completely\n"
1389 "outside the screen. For bug compatibility.\n");
1390 break;
1391 case 6:
1392 caption = _("Ignore 'Hide Others'");
1393 flag = WFLAGP(wwin, no_hide_others);
1394 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1395 break;
1396 case 7:
1397 caption = _("Ignore 'Save Session'");
1398 flag = WFLAGP(wwin, dont_save_session);
1399 descr = _("Do not save the associated application in the\n"
1400 "session's state, so that it won't be restarted\n"
1401 "together with other applications when Window Maker\n" "starts.");
1402 break;
1403 case 8:
1404 caption = _("Emulate application icon");
1405 flag = WFLAGP(wwin, emulate_appicon);
1406 descr = _("Make this window act as an application that provides\n"
1407 "enough information to Window Maker for a dockable\n"
1408 "application icon to be created.");
1409 break;
1410 case 9:
1411 caption = _("Focus across workspaces");
1412 flag = WFLAGP(wwin, focus_across_wksp);
1413 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1414 "a focus request (annoying).");
1415 break;
1416 case 10:
1417 caption = _("Do not let it be minimized");
1418 flag = WFLAGP(wwin, no_miniaturizable);
1419 descr = _("Do not let the window of this application be\n"
1420 "minimized.\n");
1421 break;
1422 #ifdef XKB_BUTTON_HINT
1423 case 11:
1424 caption = _("Disable language button");
1425 flag = WFLAGP(wwin, no_language_button);
1426 descr = _("Remove the `toggle language' button of the window.");
1427 break;
1428 #endif
1430 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1431 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1432 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1433 WMSetButtonSelected(panel->moreChk[i], flag);
1434 WMSetButtonText(panel->moreChk[i], caption);
1436 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1440 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1442 WScreen *scr = wwin->screen_ptr;
1443 int i = 0;
1445 /* miniwindow/workspace */
1446 panel->iconFrm = WMCreateFrame(panel->win);
1447 WMMoveWidget(panel->iconFrm, 15, 50);
1448 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1449 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1451 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1452 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1453 WMResizeWidget(panel->iconLbl, 64, 64);
1454 WMSetLabelRelief(panel->iconLbl, WRGroove);
1455 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1457 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1458 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1459 WMMoveWidget(panel->browseIconBtn, 22, 32);
1460 WMResizeWidget(panel->browseIconBtn, 120, 26);
1461 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1463 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1464 WMMoveWidget(panel->fileLbl, 20, 85);
1465 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1466 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1468 panel->fileText = WMCreateTextField(panel->iconFrm);
1469 WMMoveWidget(panel->fileText, 20, 105);
1470 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1471 WMSetTextFieldText(panel->fileText, NULL);
1472 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1474 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1475 WMMoveWidget(panel->alwChk, 20, 130);
1476 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1477 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1478 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1480 panel->wsFrm = WMCreateFrame(panel->win);
1481 WMMoveWidget(panel->wsFrm, 15, 225);
1482 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1483 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1485 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1486 "first shown."), WMWidgetView(panel->wsFrm));
1488 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1489 WMMoveWidget(panel->wsP, 20, 30);
1490 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1491 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1493 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1494 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1496 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1497 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1498 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1499 else
1500 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1503 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1505 WScreen *scr = wwin->screen_ptr;
1506 int i = 0, flag = 0, tmp;
1507 char *caption = NULL, *descr = NULL;
1510 if (wwin->main_window != None) {
1511 WApplication *wapp = wApplicationOf(wwin->main_window);
1513 panel->appFrm = WMCreateFrame(panel->win);
1514 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1515 WMMoveWidget(panel->appFrm, 15, 50);
1516 WMResizeWidget(panel->appFrm, frame_width, 240);
1518 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1519 switch (i) {
1520 case 0:
1521 caption = _("Start hidden");
1522 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1523 descr = _("Automatically hide application when it's started.");
1524 break;
1525 case 1:
1526 caption = _("No application icon");
1527 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1528 descr = _("Disable the application icon for the application.\n"
1529 "Note that you won't be able to dock it anymore,\n"
1530 "and any icons that are already docked will stop\n"
1531 "working correctly.");
1532 break;
1533 case 2:
1534 caption = _("Shared application icon");
1535 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1536 descr = _("Use a single shared application icon for all of\n"
1537 "the instances of this application.\n");
1538 break;
1540 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1541 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1542 WMResizeWidget(panel->appChk[i], 205, 20);
1543 WMSetButtonSelected(panel->appChk[i], flag);
1544 WMSetButtonText(panel->appChk[i], caption);
1545 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1548 if (WFLAGP(wwin, emulate_appicon)) {
1549 WMSetButtonEnabled(panel->appChk[1], False);
1550 WMSetButtonEnabled(panel->moreChk[7], True);
1551 } else {
1552 WMSetButtonEnabled(panel->appChk[1], True);
1553 WMSetButtonEnabled(panel->moreChk[7], False);
1555 } else {
1556 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1557 || !wwin->wm_class || !wwin->wm_instance)
1558 tmp = False;
1559 else
1560 tmp = True;
1562 WMSetButtonEnabled(panel->moreChk[7], tmp);
1564 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1565 panel->appFrm = NULL;