wmaker: Replaced local 'extern' definition of wPreferences by proper header usage
[wmaker-crm.git] / src / winspector.c
blobfedc013aa14599a6b79ba0647dffe60b4a1fd9c3
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 "defaults.h"
39 #include "dialog.h"
40 #include "icon.h"
41 #include "stacking.h"
42 #include "application.h"
43 #include "appicon.h"
44 #include "actions.h"
45 #include "winspector.h"
46 #include "dock.h"
47 #include "client.h"
48 #include "wmspec.h"
49 #include "misc.h"
50 #include "switchmenu.h"
52 #include <WINGs/WUtil.h>
54 #define USE_TEXT_FIELD 1
55 #define UPDATE_TEXT_FIELD 2
56 #define REVERT_TO_DEFAULT 4
57 #define PWIDTH 290
58 #define PHEIGHT 360
59 #define UNDEFINED_POS 0xffffff
60 #define UPDATE_DEFAULTS 1
61 #define IS_BOOLEAN 2
63 typedef struct InspectorPanel {
64 struct InspectorPanel *nextPtr;
66 WWindow *frame;
67 WWindow *inspected; /* the window that's being inspected */
68 WMWindow *win;
69 Window parent;
71 /* common stuff */
72 WMButton *revertBtn;
73 WMButton *applyBtn;
74 WMButton *saveBtn;
75 WMPopUpButton *pagePopUp;
77 /* first page. general stuff */
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
83 WMButton *selWinB;
84 WMLabel *specLbl;
86 /* second page. attributes */
87 WMFrame *attrFrm;
88 WMButton *attrChk[11];
90 /* 3rd page. more attributes */
91 WMFrame *moreFrm;
92 #ifdef XKB_BUTTON_HINT
93 WMButton *moreChk[12];
94 #else
95 WMButton *moreChk[11];
96 #endif
98 /* 4th page. icon and workspace */
99 WMFrame *iconFrm;
100 WMLabel *iconLbl;
101 WMLabel *fileLbl;
102 WMTextField *fileText;
103 WMButton *alwChk;
104 WMButton *browseIconBtn;
105 WMFrame *wsFrm;
106 WMPopUpButton *wsP;
108 /* 5th page. application wide attributes */
109 WMFrame *appFrm;
110 WMButton *appChk[3];
112 unsigned int done:1;
113 unsigned int destroyed:1;
114 unsigned int choosingIcon:1;
115 } InspectorPanel;
117 extern Cursor wCursor[WCUR_LAST];
118 extern WDDomain *WDWindowAttributes;
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, const char *wm_instance, const 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 /* Save the icon info */
479 /* The flag "Ignore client suplied icon is not selected" */
480 buf1 = wmalloc(4);
481 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
482 value1 = WMCreatePLString(buf1);
483 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
484 WMReleasePropList(value1);
485 wfree(buf1);
487 /* The icon filename (if exists) */
488 icon_file = WMGetTextFieldText(panel->fileText);
489 if ((icon_file) && (icon_file[0] != 0)) {
490 value = WMCreatePLString(icon_file);
491 different |= insertAttribute(dict, winDic, AIcon, value, flags);
492 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
493 WMReleasePropList(value);
494 wfree(icon_file);
497 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
498 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
499 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
500 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
501 WMReleasePropList(value);
504 flags |= IS_BOOLEAN;
506 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
507 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
509 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
510 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
512 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
513 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
515 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
516 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
518 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
519 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
521 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
522 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
524 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
525 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
527 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
528 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
530 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
531 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
533 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
534 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
536 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
537 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
539 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
540 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
542 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
543 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
545 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
546 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
548 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
549 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
551 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
552 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
554 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
555 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
557 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
558 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
560 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
561 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
563 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
564 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
566 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
567 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
569 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
570 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
572 #ifdef XKB_BUTTON_HINT
573 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
574 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
575 #endif
577 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
578 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
579 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
581 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
582 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
584 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
585 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
588 if (wwin->fake_group) {
589 key2 = WMCreatePLString(wwin->fake_group->identifier);
590 if (WMIsPropListEqualTo(key, key2)) {
591 WMMergePLDictionaries(winDic, appDic, True);
592 different |= different2;
593 } else {
594 WMRemoveFromPLDictionary(dict, key2);
595 if (different2)
596 WMPutInPLDictionary(dict, key2, appDic);
598 WMReleasePropList(key2);
599 WMReleasePropList(appDic);
600 } else if (wwin->main_window != wwin->client_win) {
601 WApplication *wapp = wApplicationOf(wwin->main_window);
603 if (wapp) {
604 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
605 wapp->main_window_desc->wm_class);
606 key2 = WMCreatePLString(buf2);
607 wfree(buf2);
609 if (WMIsPropListEqualTo(key, key2)) {
610 WMMergePLDictionaries(winDic, appDic, True);
611 different |= different2;
612 } else {
613 WMRemoveFromPLDictionary(dict, key2);
614 if (different2)
615 WMPutInPLDictionary(dict, key2, appDic);
617 WMReleasePropList(key2);
618 WMReleasePropList(appDic);
620 } else {
621 WMMergePLDictionaries(winDic, appDic, True);
622 different |= different2;
623 WMReleasePropList(appDic);
626 WMRemoveFromPLDictionary(dict, key);
627 if (different)
628 WMPutInPLDictionary(dict, key, winDic);
630 WMReleasePropList(key);
631 WMReleasePropList(winDic);
633 UpdateDomainFile(db);
635 /* clean up */
636 WMPLSetCaseSensitive(False);
639 static void applySettings(WMButton *button, InspectorPanel *panel)
641 WWindow *wwin = panel->inspected;
642 WApplication *wapp = wApplicationOf(wwin->main_window);
643 int floating, sunken, skip_window_list;
644 int old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
646 old_omnipresent = WFLAGP(wwin, omnipresent);
647 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
648 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
650 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
652 /* Attributes... --> Window Attributes */
653 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
654 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
655 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
656 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
657 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
658 floating = WMGetButtonSelected(panel->attrChk[5]);
659 sunken = WMGetButtonSelected(panel->attrChk[6]);
660 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
661 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
662 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
663 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
665 /* Attributes... --> Advanced Options */
666 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
667 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
668 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
669 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
670 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
671 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
672 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
673 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
674 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
675 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
676 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
677 #ifdef XKB_BUTTON_HINT
678 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
679 #endif
680 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
682 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
683 wUnshadeWindow(wwin);
685 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
687 if (floating) {
688 if (!WFLAGP(wwin, floating))
689 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
690 } else if (sunken) {
691 if (!WFLAGP(wwin, sunken))
692 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
693 } else {
694 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
695 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
698 WSETUFLAG(wwin, sunken, sunken);
699 WSETUFLAG(wwin, floating, floating);
700 wwin->flags.omnipresent = 0;
702 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
703 WSETUFLAG(wwin, skip_window_list, skip_window_list);
704 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
705 } else {
706 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
707 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
710 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
711 if (WFLAGP(wwin, no_bind_keys))
712 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
713 else
714 wWindowSetKeyGrabs(wwin);
717 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
718 wWindowResetMouseGrabs(wwin);
720 wwin->frame->flags.need_texture_change = 1;
721 wWindowConfigureBorders(wwin);
722 wFrameWindowPaint(wwin->frame);
723 wNETWMUpdateActions(wwin, False);
725 /* Can't apply emulate_appicon because it will probably cause problems. */
726 if (wapp) {
727 /* do application wide stuff */
728 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
729 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
730 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
732 if (WFLAGP(wapp->main_window_desc, no_appicon))
733 unpaint_app_icon(wapp);
734 else
735 paint_app_icon(wapp);
737 char *file = WMGetTextFieldText(panel->fileText);
738 if (file[0] == 0) {
739 wfree(file);
740 file = NULL;
743 /* If always_user_icon flag is set, but the user icon is not set
744 * we use client supplied icon and we unset the flag */
745 if ((WFLAGP(wwin, always_user_icon) && (!file))) {
746 /* Show the warning */
747 char *buf;
748 int len = 100;
750 buf = wmalloc(len);
751 snprintf(buf, len, _("Ignore client supplied icon is set, but icon filename textbox is empty. Using client supplied icon"));
752 wMessageDialog(panel->frame->screen_ptr, _("Warning"), buf, _("OK"), NULL, NULL);
753 wfree(buf);
754 wfree(file);
756 /* Change the flags */
757 WSETUFLAG(wwin, always_user_icon, 0);
758 WMSetButtonSelected(panel->alwChk, 0);
761 /* After test the always_user_icon flag value before,
762 * the "else" block is used only if the flag is set and
763 * the icon text box has an icon path */
764 if (!WFLAGP(wwin, always_user_icon)) {
765 /* Change App Icon image, using the icon provided by the client */
766 if (wapp->app_icon) {
767 RImage *image = get_rimage_icon_from_wm_hints(wapp->app_icon->icon);
768 if (image) {
769 set_icon_image_from_image(wapp->app_icon->icon, image);
770 update_icon_pixmap(wapp->app_icon->icon);
771 } else {
772 wIconUpdate(wapp->app_icon->icon);
776 /* Change icon image if the app is minimized,
777 * using the icon provided by the client */
778 if (wwin->icon) {
779 RImage *image = get_rimage_icon_from_wm_hints(wwin->icon);
780 if (image) {
781 set_icon_image_from_image(wwin->icon, image);
782 update_icon_pixmap(wwin->icon);
783 } else {
784 wIconUpdate(wwin->icon);
787 } else {
788 /* Change App Icon image */
789 if (wapp->app_icon)
790 wIconChangeImageFile(wapp->app_icon->icon, file);
792 /* Change icon image if the app is minimized */
793 if (wwin->icon)
794 wIconChangeImageFile(wwin->icon, file);
797 if (file)
798 wfree(file);
801 wNETFrameExtents(wwin);
804 static void revertSettings(WMButton *button, InspectorPanel *panel)
806 WWindow *wwin = panel->inspected;
807 WApplication *wapp = wApplicationOf(wwin->main_window);
808 int i, n, workspace, level;
809 char *wm_instance = NULL, *wm_class = NULL;
811 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
812 wm_instance = wwin->wm_instance;
813 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
814 wm_class = wwin->wm_class;
815 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
816 wm_instance = wwin->wm_instance;
817 wm_class = wwin->wm_class;
820 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
821 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
822 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
824 wWindowSetupInitialAttributes(wwin, &level, &workspace);
826 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
827 int flag = 0;
829 switch (i) {
830 case 0:
831 flag = WFLAGP(wwin, no_titlebar);
832 break;
833 case 1:
834 flag = WFLAGP(wwin, no_resizebar);
835 break;
836 case 2:
837 flag = WFLAGP(wwin, no_close_button);
838 break;
839 case 3:
840 flag = WFLAGP(wwin, no_miniaturize_button);
841 break;
842 case 4:
843 flag = WFLAGP(wwin, no_border);
844 break;
845 case 5:
846 flag = WFLAGP(wwin, floating);
847 break;
848 case 6:
849 flag = WFLAGP(wwin, sunken);
850 break;
851 case 7:
852 flag = WFLAGP(wwin, omnipresent);
853 break;
854 case 8:
855 flag = WFLAGP(wwin, start_miniaturized);
856 break;
857 case 9:
858 flag = WFLAGP(wwin, start_maximized != 0);
859 break;
860 case 10:
861 flag = WFLAGP(wwin, full_maximize);
862 break;
864 WMSetButtonSelected(panel->attrChk[i], flag);
867 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
868 int flag = 0;
870 switch (i) {
871 case 0:
872 flag = WFLAGP(wwin, no_bind_keys);
873 break;
874 case 1:
875 flag = WFLAGP(wwin, no_bind_mouse);
876 break;
877 case 2:
878 flag = WFLAGP(wwin, skip_window_list);
879 break;
880 case 3:
881 flag = WFLAGP(wwin, skip_switchpanel);
882 break;
883 case 4:
884 flag = WFLAGP(wwin, no_focusable);
885 break;
886 case 5:
887 flag = WFLAGP(wwin, dont_move_off);
888 break;
889 case 6:
890 flag = WFLAGP(wwin, no_hide_others);
891 break;
892 case 7:
893 flag = WFLAGP(wwin, dont_save_session);
894 break;
895 case 8:
896 flag = WFLAGP(wwin, emulate_appicon);
897 break;
898 case 9:
899 flag = WFLAGP(wwin, focus_across_wksp);
900 break;
901 case 10:
902 flag = WFLAGP(wwin, no_miniaturizable);
903 break;
904 #ifdef XKB_BUTTON_HINT
905 case 11:
906 flag = WFLAGP(wwin, no_language_button);
907 break;
908 #endif
910 WMSetButtonSelected(panel->moreChk[i], flag);
912 if (panel->appFrm && wapp) {
913 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
914 int flag = 0;
916 switch (i) {
917 case 0:
918 flag = WFLAGP(wapp->main_window_desc, start_hidden);
919 break;
920 case 1:
921 flag = WFLAGP(wapp->main_window_desc, no_appicon);
922 break;
923 case 2:
924 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
925 break;
927 WMSetButtonSelected(panel->appChk[i], flag);
930 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
932 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
934 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
936 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
937 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
938 else
939 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
941 /* must auto apply, so that there wno't be internal
942 * inconsistencies between the state in the flags and
943 * the actual state of the window */
944 applySettings(panel->applyBtn, panel);
947 static void chooseIconCallback(WMWidget *self, void *clientData)
949 char *file;
950 InspectorPanel *panel = (InspectorPanel *) clientData;
951 int result;
953 panel->choosingIcon = 1;
955 WMSetButtonEnabled(panel->browseIconBtn, False);
957 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
958 panel->inspected->wm_instance,
959 panel->inspected->wm_class);
961 panel->choosingIcon = 0;
963 if (!panel->destroyed) { /* kluge */
964 if (result) {
965 WMSetTextFieldText(panel->fileText, file);
966 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
967 wfree(file);
969 WMSetButtonEnabled(panel->browseIconBtn, True);
970 } else {
971 freeInspector(panel);
975 static void textEditedObserver(void *observerData, WMNotification *notification)
977 InspectorPanel *panel = (InspectorPanel *) observerData;
979 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
980 return;
982 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
985 static void selectSpecification(WMWidget *bPtr, void *data)
987 InspectorPanel *panel = (InspectorPanel *) data;
988 char *str;
989 WWindow *wwin = panel->inspected;
990 int len;
992 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
993 WMSetButtonEnabled(panel->applyBtn, False);
994 else
995 WMSetButtonEnabled(panel->applyBtn, True);
997 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
998 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1000 str = wmalloc(len);
1002 snprintf(str, len, _("Inspecting %s.%s"),
1003 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1005 wFrameWindowChangeTitle(panel->frame->frame, str);
1007 wfree(str);
1010 static void selectWindow(WMWidget *bPtr, void *data)
1012 InspectorPanel *panel = (InspectorPanel *) data;
1013 WWindow *wwin = panel->inspected;
1014 WScreen *scr = wwin->screen_ptr;
1015 XEvent event;
1016 WWindow *iwin;
1018 if (XGrabPointer(dpy, scr->root_win, True,
1019 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1020 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1021 wwarning("could not grab mouse pointer");
1022 return;
1025 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1026 WMMaskEvent(dpy, ButtonPressMask, &event);
1027 XUngrabPointer(dpy, CurrentTime);
1029 iwin = wWindowFor(event.xbutton.subwindow);
1030 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1031 iwin->flags.inspector_open = 1;
1032 iwin->inspector = createInspectorForWindow(iwin,
1033 panel->frame->frame_x, panel->frame->frame_y, True);
1034 wCloseInspectorForWindow(wwin);
1035 } else {
1036 WMSetLabelText(panel->specLbl, spec_text);
1040 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1042 WScreen *scr = wwin->screen_ptr;
1043 InspectorPanel *panel;
1044 Window parent;
1045 char *str = NULL, *tmp = NULL;
1046 int x, y, btn_width, frame_width;
1047 WMButton *selectedBtn = NULL;
1049 spec_text = _("The configuration will apply to all\n"
1050 "windows that have their WM_CLASS\n"
1051 "property set to the above selected\n" "name, when saved.");
1053 panel = wmalloc(sizeof(InspectorPanel));
1054 memset(panel, 0, sizeof(InspectorPanel));
1056 panel->destroyed = 0;
1057 panel->inspected = wwin;
1058 panel->nextPtr = panelList;
1059 panelList = panel;
1060 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1061 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1063 /**** create common stuff ****/
1064 /* command buttons */
1065 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1066 panel->saveBtn = WMCreateCommandButton(panel->win);
1067 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1068 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1069 WMSetButtonText(panel->saveBtn, _("Save"));
1070 WMResizeWidget(panel->saveBtn, btn_width, 28);
1071 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1072 WMSetButtonEnabled(panel->saveBtn, False);
1074 panel->applyBtn = WMCreateCommandButton(panel->win);
1075 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1076 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1077 WMSetButtonText(panel->applyBtn, _("Apply"));
1078 WMResizeWidget(panel->applyBtn, btn_width, 28);
1080 panel->revertBtn = WMCreateCommandButton(panel->win);
1081 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1082 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1083 WMSetButtonText(panel->revertBtn, _("Reload"));
1084 WMResizeWidget(panel->revertBtn, btn_width, 28);
1086 /* page selection popup button */
1087 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1088 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1089 WMMoveWidget(panel->pagePopUp, 25, 15);
1090 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1092 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1093 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1094 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1095 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1096 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1098 /**** window spec ****/
1099 frame_width = PWIDTH - (2 * 15);
1101 panel->specFrm = WMCreateFrame(panel->win);
1102 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1103 WMMoveWidget(panel->specFrm, 15, 65);
1104 WMResizeWidget(panel->specFrm, frame_width, 145);
1106 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1107 WMMoveWidget(panel->defaultRb, 10, 78);
1108 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1109 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1110 WMSetButtonSelected(panel->defaultRb, False);
1111 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1113 if (wwin->wm_class && wwin->wm_instance) {
1114 tmp = wstrconcat(wwin->wm_instance, ".");
1115 str = wstrconcat(tmp, wwin->wm_class);
1117 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1118 WMMoveWidget(panel->bothRb, 10, 18);
1119 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1120 WMSetButtonText(panel->bothRb, str);
1121 wfree(tmp);
1122 wfree(str);
1123 WMGroupButtons(panel->defaultRb, panel->bothRb);
1125 if (!selectedBtn)
1126 selectedBtn = panel->bothRb;
1128 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1131 if (wwin->wm_instance) {
1132 panel->instRb = WMCreateRadioButton(panel->specFrm);
1133 WMMoveWidget(panel->instRb, 10, 38);
1134 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1135 WMSetButtonText(panel->instRb, wwin->wm_instance);
1136 WMGroupButtons(panel->defaultRb, panel->instRb);
1138 if (!selectedBtn)
1139 selectedBtn = panel->instRb;
1141 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1144 if (wwin->wm_class) {
1145 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1146 WMMoveWidget(panel->clsRb, 10, 58);
1147 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1148 WMSetButtonText(panel->clsRb, wwin->wm_class);
1149 WMGroupButtons(panel->defaultRb, panel->clsRb);
1151 if (!selectedBtn)
1152 selectedBtn = panel->clsRb;
1154 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1157 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1158 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1159 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1160 WMSetButtonText(panel->selWinB, _("Select window"));
1161 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1163 panel->specLbl = WMCreateLabel(panel->win);
1164 WMMoveWidget(panel->specLbl, 15, 210);
1165 WMResizeWidget(panel->specLbl, frame_width, 100);
1166 WMSetLabelText(panel->specLbl, spec_text);
1167 WMSetLabelWraps(panel->specLbl, True);
1169 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1171 /**** attributes ****/
1172 create_tab_window_attributes(wwin, panel, frame_width);
1173 create_tab_window_advanced(wwin, panel, frame_width);
1174 create_tab_icon_workspace(wwin, panel, frame_width);
1175 create_tab_app_specific(wwin, panel, frame_width);
1177 /* if the window is a transient, don't let it have a miniaturize button */
1178 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1179 WMSetButtonEnabled(panel->attrChk[3], False);
1180 else
1181 WMSetButtonEnabled(panel->attrChk[3], True);
1183 if (!wwin->wm_class && !wwin->wm_instance)
1184 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1186 WMRealizeWidget(panel->win);
1188 WMMapSubwidgets(panel->win);
1189 WMMapSubwidgets(panel->specFrm);
1190 WMMapSubwidgets(panel->attrFrm);
1191 WMMapSubwidgets(panel->moreFrm);
1192 WMMapSubwidgets(panel->iconFrm);
1193 WMMapSubwidgets(panel->wsFrm);
1194 if (panel->appFrm)
1195 WMMapSubwidgets(panel->appFrm);
1197 if (showSelectPanel) {
1198 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1199 changePage(panel->pagePopUp, panel);
1200 } else {
1201 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1202 changePage(panel->pagePopUp, panel);
1205 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1206 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1207 panel->parent = parent;
1208 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1210 WMMapWidget(panel->win);
1212 XSetTransientForHint(dpy, parent, wwin->client_win);
1214 if (xpos == UNDEFINED_POS) {
1215 x = wwin->frame_x + wwin->frame->core->width / 2;
1216 y = wwin->frame_y + wwin->frame->top_width * 2;
1217 if (y + PHEIGHT > scr->scr_height)
1218 y = scr->scr_height - PHEIGHT - 30;
1219 if (x + PWIDTH > scr->scr_width)
1220 x = scr->scr_width - PWIDTH;
1221 } else {
1222 x = xpos;
1223 y = ypos;
1226 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1228 if (!selectedBtn)
1229 selectedBtn = panel->defaultRb;
1231 WMSetButtonSelected(selectedBtn, True);
1232 selectSpecification(selectedBtn, panel);
1234 /* kluge to know who should get the key events */
1235 panel->frame->client_leader = WMWidgetXID(panel->win);
1237 WSETUFLAG(panel->frame, no_closable, 0);
1238 WSETUFLAG(panel->frame, no_close_button, 0);
1239 wWindowUpdateButtonImages(panel->frame);
1240 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1241 panel->frame->frame->on_click_right = destroyInspector;
1243 wWindowMap(panel->frame);
1245 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1247 return panel;
1250 void wShowInspectorForWindow(WWindow *wwin)
1252 if (wwin->flags.inspector_open)
1253 return;
1255 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1257 make_keys();
1258 wwin->flags.inspector_open = 1;
1259 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1262 void wHideInspectorForWindow(WWindow *wwin)
1264 WWindow *pwin = wwin->inspector->frame;
1266 wWindowUnmap(pwin);
1267 pwin->flags.hidden = 1;
1269 wClientSetState(pwin, IconicState, None);
1272 void wUnhideInspectorForWindow(WWindow *wwin)
1274 WWindow *pwin = wwin->inspector->frame;
1276 pwin->flags.hidden = 0;
1277 pwin->flags.mapped = 1;
1278 XMapWindow(dpy, pwin->client_win);
1279 XMapWindow(dpy, pwin->frame->core->window);
1280 wClientSetState(pwin, NormalState, None);
1283 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1285 if (!wwin->inspector)
1286 return NULL;
1288 assert(wwin->flags.inspector_open != 0);
1289 return wwin->inspector->frame;
1292 void wCloseInspectorForWindow(WWindow *wwin)
1294 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1296 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1299 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1301 int i = 0;
1302 char *caption = NULL, *descr = NULL;
1303 int flag = 0;
1305 panel->attrFrm = WMCreateFrame(panel->win);
1306 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1307 WMMoveWidget(panel->attrFrm, 15, 45);
1308 WMResizeWidget(panel->attrFrm, frame_width, 250);
1310 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1311 switch (i) {
1312 case 0:
1313 caption = _("Disable titlebar");
1314 flag = WFLAGP(wwin, no_titlebar);
1315 descr = _("Remove the titlebar of this window.\n"
1316 "To access the window commands menu of a window\n"
1317 "without it's titlebar, press Control+Esc (or the\n"
1318 "equivalent shortcut, if you changed the default\n" "settings).");
1319 break;
1320 case 1:
1321 caption = _("Disable resizebar");
1322 flag = WFLAGP(wwin, no_resizebar);
1323 descr = _("Remove the resizebar of this window.");
1324 break;
1325 case 2:
1326 caption = _("Disable close button");
1327 flag = WFLAGP(wwin, no_close_button);
1328 descr = _("Remove the `close window' button of this window.");
1329 break;
1330 case 3:
1331 caption = _("Disable miniaturize button");
1332 flag = WFLAGP(wwin, no_miniaturize_button);
1333 descr = _("Remove the `miniaturize window' button of the window.");
1334 break;
1335 case 4:
1336 caption = _("Disable border");
1337 flag = WFLAGP(wwin, no_border);
1338 descr = _("Remove the 1 pixel black border around the window.");
1339 break;
1340 case 5:
1341 caption = _("Keep on top (floating)");
1342 flag = WFLAGP(wwin, floating);
1343 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1344 break;
1345 case 6:
1346 caption = _("Keep at bottom (sunken)");
1347 flag = WFLAGP(wwin, sunken);
1348 descr = _("Keep the window under all other windows.");
1349 break;
1350 case 7:
1351 caption = _("Omnipresent");
1352 flag = WFLAGP(wwin, omnipresent);
1353 descr = _("Make window present in all workspaces.");
1354 break;
1355 case 8:
1356 caption = _("Start miniaturized");
1357 flag = WFLAGP(wwin, start_miniaturized);
1358 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1359 break;
1360 case 9:
1361 caption = _("Start maximized");
1362 flag = WFLAGP(wwin, start_maximized != 0);
1363 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1364 break;
1365 case 10:
1366 caption = _("Full screen maximization");
1367 flag = WFLAGP(wwin, full_maximize);
1368 descr = _("Make the window use the whole screen space when it's\n"
1369 "maximized. The titlebar and resizebar will be moved\n"
1370 "to outside the screen.");
1371 break;
1373 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1374 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1375 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1376 WMSetButtonSelected(panel->attrChk[i], flag);
1377 WMSetButtonText(panel->attrChk[i], caption);
1379 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1383 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1385 int i = 0;
1386 char *caption = NULL, *descr = NULL;
1387 int flag = 0;
1389 panel->moreFrm = WMCreateFrame(panel->win);
1390 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1391 WMMoveWidget(panel->moreFrm, 15, 45);
1392 WMResizeWidget(panel->moreFrm, frame_width, 265);
1394 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1395 switch (i) {
1396 case 0:
1397 caption = _("Do not bind keyboard shortcuts");
1398 flag = WFLAGP(wwin, no_bind_keys);
1399 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1400 "when this window is focused. This will allow the\n"
1401 "window to receive all key combinations regardless\n"
1402 "of your shortcut configuration.");
1403 break;
1404 case 1:
1405 caption = _("Do not bind mouse clicks");
1406 flag = WFLAGP(wwin, no_bind_mouse);
1407 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1408 "in the window (when alt is the modifier you have\n" "configured).");
1409 break;
1410 case 2:
1411 caption = _("Do not show in the window list");
1412 flag = WFLAGP(wwin, skip_window_list);
1413 descr = _("Do not list the window in the window list menu.");
1414 break;
1415 case 3:
1416 caption = _("Do not show in the switch panel");
1417 flag = WFLAGP(wwin, skip_switchpanel);
1418 descr = _("Do not include in switchpanel while alternating windows.");
1419 break;
1420 case 4:
1421 caption = _("Do not let it take focus");
1422 flag = WFLAGP(wwin, no_focusable);
1423 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1424 break;
1425 case 5:
1426 caption = _("Keep inside screen");
1427 flag = WFLAGP(wwin, dont_move_off);
1428 descr = _("Do not allow the window to move itself completely\n"
1429 "outside the screen. For bug compatibility.\n");
1430 break;
1431 case 6:
1432 caption = _("Ignore 'Hide Others'");
1433 flag = WFLAGP(wwin, no_hide_others);
1434 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1435 break;
1436 case 7:
1437 caption = _("Ignore 'Save Session'");
1438 flag = WFLAGP(wwin, dont_save_session);
1439 descr = _("Do not save the associated application in the\n"
1440 "session's state, so that it won't be restarted\n"
1441 "together with other applications when Window Maker\n" "starts.");
1442 break;
1443 case 8:
1444 caption = _("Emulate application icon");
1445 flag = WFLAGP(wwin, emulate_appicon);
1446 descr = _("Make this window act as an application that provides\n"
1447 "enough information to Window Maker for a dockable\n"
1448 "application icon to be created.");
1449 break;
1450 case 9:
1451 caption = _("Focus across workspaces");
1452 flag = WFLAGP(wwin, focus_across_wksp);
1453 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1454 "a focus request (annoying).");
1455 break;
1456 case 10:
1457 caption = _("Do not let it be minimized");
1458 flag = WFLAGP(wwin, no_miniaturizable);
1459 descr = _("Do not let the window of this application be\n"
1460 "minimized.\n");
1461 break;
1462 #ifdef XKB_BUTTON_HINT
1463 case 11:
1464 caption = _("Disable language button");
1465 flag = WFLAGP(wwin, no_language_button);
1466 descr = _("Remove the `toggle language' button of the window.");
1467 break;
1468 #endif
1470 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1471 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1472 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1473 WMSetButtonSelected(panel->moreChk[i], flag);
1474 WMSetButtonText(panel->moreChk[i], caption);
1476 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1480 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1482 WScreen *scr = wwin->screen_ptr;
1483 int i = 0;
1485 /* miniwindow/workspace */
1486 panel->iconFrm = WMCreateFrame(panel->win);
1487 WMMoveWidget(panel->iconFrm, 15, 50);
1488 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1489 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1491 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1492 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1493 WMResizeWidget(panel->iconLbl, 64, 64);
1494 WMSetLabelRelief(panel->iconLbl, WRGroove);
1495 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1497 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1498 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1499 WMMoveWidget(panel->browseIconBtn, 22, 32);
1500 WMResizeWidget(panel->browseIconBtn, 120, 26);
1501 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1503 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1504 WMMoveWidget(panel->fileLbl, 20, 85);
1505 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1506 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1508 panel->fileText = WMCreateTextField(panel->iconFrm);
1509 WMMoveWidget(panel->fileText, 20, 105);
1510 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1511 WMSetTextFieldText(panel->fileText, NULL);
1512 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1514 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1515 WMMoveWidget(panel->alwChk, 20, 130);
1516 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1517 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1518 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1520 panel->wsFrm = WMCreateFrame(panel->win);
1521 WMMoveWidget(panel->wsFrm, 15, 225);
1522 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1523 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1525 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1526 "first shown."), WMWidgetView(panel->wsFrm));
1528 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1529 WMMoveWidget(panel->wsP, 20, 30);
1530 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1531 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1533 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1534 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1536 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1537 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1538 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1539 else
1540 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1543 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1545 WScreen *scr = wwin->screen_ptr;
1546 int i = 0, flag = 0, tmp;
1547 char *caption = NULL, *descr = NULL;
1550 if (wwin->main_window != None) {
1551 WApplication *wapp = wApplicationOf(wwin->main_window);
1553 panel->appFrm = WMCreateFrame(panel->win);
1554 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1555 WMMoveWidget(panel->appFrm, 15, 50);
1556 WMResizeWidget(panel->appFrm, frame_width, 240);
1558 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1559 switch (i) {
1560 case 0:
1561 caption = _("Start hidden");
1562 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1563 descr = _("Automatically hide application when it's started.");
1564 break;
1565 case 1:
1566 caption = _("No application icon");
1567 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1568 descr = _("Disable the application icon for the application.\n"
1569 "Note that you won't be able to dock it anymore,\n"
1570 "and any icons that are already docked will stop\n"
1571 "working correctly.");
1572 break;
1573 case 2:
1574 caption = _("Shared application icon");
1575 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1576 descr = _("Use a single shared application icon for all of\n"
1577 "the instances of this application.\n");
1578 break;
1580 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1581 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1582 WMResizeWidget(panel->appChk[i], 205, 20);
1583 WMSetButtonSelected(panel->appChk[i], flag);
1584 WMSetButtonText(panel->appChk[i], caption);
1585 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1588 if (WFLAGP(wwin, emulate_appicon)) {
1589 WMSetButtonEnabled(panel->appChk[1], False);
1590 WMSetButtonEnabled(panel->moreChk[7], True);
1591 } else {
1592 WMSetButtonEnabled(panel->appChk[1], True);
1593 WMSetButtonEnabled(panel->moreChk[7], False);
1595 } else {
1596 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1597 || !wwin->wm_class || !wwin->wm_instance)
1598 tmp = False;
1599 else
1600 tmp = True;
1602 WMSetButtonEnabled(panel->moreChk[7], tmp);
1604 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1605 panel->appFrm = NULL;