Variable workspace_count moved to the workspace object in the global namespace
[wmaker-crm.git] / src / winspector.c
blob8b7367598ae59f5c43ec1c4d75a0e9761fd5ab46
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 WDDomain *WDWindowAttributes;
119 static InspectorPanel *panelList = NULL;
120 static WMPropList *ANoTitlebar = NULL;
121 static WMPropList *ANoResizebar;
122 static WMPropList *ANoMiniaturizeButton;
123 static WMPropList *ANoCloseButton;
124 static WMPropList *ANoBorder;
125 static WMPropList *ANoHideOthers;
126 static WMPropList *ANoMouseBindings;
127 static WMPropList *ANoKeyBindings;
128 static WMPropList *ANoAppIcon;
129 static WMPropList *AKeepOnTop;
130 static WMPropList *AKeepOnBottom;
131 static WMPropList *AOmnipresent;
132 static WMPropList *ASkipWindowList;
133 static WMPropList *ASkipSwitchPanel;
134 static WMPropList *AKeepInsideScreen;
135 static WMPropList *AUnfocusable;
136 static WMPropList *AFocusAcrossWorkspace;
137 static WMPropList *AAlwaysUserIcon;
138 static WMPropList *AStartMiniaturized;
139 static WMPropList *AStartMaximized;
140 static WMPropList *ADontSaveSession;
141 static WMPropList *AEmulateAppIcon;
142 static WMPropList *AFullMaximize;
143 static WMPropList *ASharedAppIcon;
144 static WMPropList *ANoMiniaturizable;
145 #ifdef XKB_BUTTON_HINT
146 static WMPropList *ANoLanguageButton;
147 #endif
148 static WMPropList *AStartWorkspace;
149 static WMPropList *AIcon;
151 /* application wide options */
152 static WMPropList *AStartHidden;
153 static WMPropList *AnyWindow;
154 static WMPropList *EmptyString;
155 static WMPropList *Yes, *No;
157 static char *spec_text;
158 static void applySettings(WMButton *button, InspectorPanel *panel);
160 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
162 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
163 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
164 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width);
165 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
167 static void make_keys(void)
169 if (ANoTitlebar != NULL)
170 return;
172 AIcon = WMCreatePLString("Icon");
173 ANoTitlebar = WMCreatePLString("NoTitlebar");
174 ANoResizebar = WMCreatePLString("NoResizebar");
175 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
176 ANoCloseButton = WMCreatePLString("NoCloseButton");
177 ANoBorder = WMCreatePLString("NoBorder");
178 ANoHideOthers = WMCreatePLString("NoHideOthers");
179 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
180 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
181 ANoAppIcon = WMCreatePLString("NoAppIcon");
182 AKeepOnTop = WMCreatePLString("KeepOnTop");
183 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
184 AOmnipresent = WMCreatePLString("Omnipresent");
185 ASkipWindowList = WMCreatePLString("SkipWindowList");
186 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
187 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
188 AUnfocusable = WMCreatePLString("Unfocusable");
189 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
190 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
191 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
192 AStartMaximized = WMCreatePLString("StartMaximized");
193 AStartHidden = WMCreatePLString("StartHidden");
194 ADontSaveSession = WMCreatePLString("DontSaveSession");
195 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
196 AFullMaximize = WMCreatePLString("FullMaximize");
197 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
198 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
199 #ifdef XKB_BUTTON_HINT
200 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
201 #endif
203 AStartWorkspace = WMCreatePLString("StartWorkspace");
205 AnyWindow = WMCreatePLString("*");
206 EmptyString = WMCreatePLString("");
207 Yes = WMCreatePLString("Yes");
208 No = WMCreatePLString("No");
211 static void freeInspector(InspectorPanel *panel)
213 panel->destroyed = 1;
215 if (panel->choosingIcon)
216 return;
218 WMDestroyWidget(panel->win);
219 XDestroyWindow(dpy, panel->parent);
220 wfree(panel);
223 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
225 InspectorPanel *panel, *tmp;
227 panel = panelList;
228 while (panel->frame != data)
229 panel = panel->nextPtr;
231 if (panelList == panel) {
232 panelList = panel->nextPtr;
233 } else {
234 tmp = panelList;
235 while (tmp->nextPtr != panel)
236 tmp = tmp->nextPtr;
238 tmp->nextPtr = panel->nextPtr;
240 panel->inspected->flags.inspector_open = 0;
241 panel->inspected->inspector = NULL;
243 WMRemoveNotificationObserver(panel);
245 wWindowUnmap(panel->frame);
246 wUnmanageWindow(panel->frame, True, False);
248 freeInspector(panel);
251 void wDestroyInspectorPanels(void)
253 InspectorPanel *panel;
255 while (panelList != NULL) {
256 panel = panelList;
257 panelList = panelList->nextPtr;
258 wUnmanageWindow(panel->frame, False, False);
259 WMDestroyWidget(panel->win);
261 panel->inspected->flags.inspector_open = 0;
262 panel->inspected->inspector = NULL;
264 wfree(panel);
268 static void changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
270 int page;
272 page = WMGetPopUpButtonSelectedItem(bPtr);
274 if (page == 0) {
275 WMMapWidget(panel->specFrm);
276 WMMapWidget(panel->specLbl);
277 } else if (page == 1) {
278 WMMapWidget(panel->attrFrm);
279 } else if (page == 2) {
280 WMMapWidget(panel->moreFrm);
281 } else if (page == 3) {
282 WMMapWidget(panel->iconFrm);
283 WMMapWidget(panel->wsFrm);
284 } else {
285 WMMapWidget(panel->appFrm);
288 if (page != 0) {
289 WMUnmapWidget(panel->specFrm);
290 WMUnmapWidget(panel->specLbl);
292 if (page != 1)
293 WMUnmapWidget(panel->attrFrm);
294 if (page != 2)
295 WMUnmapWidget(panel->moreFrm);
296 if (page != 3) {
297 WMUnmapWidget(panel->iconFrm);
298 WMUnmapWidget(panel->wsFrm);
300 if (page != 4 && panel->appFrm)
301 WMUnmapWidget(panel->appFrm);
304 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, const char *wm_instance, const char *wm_class, int flags)
306 WMPixmap *pixmap = (WMPixmap *) NULL;
307 char *file = NULL, *path = NULL, *db_icon = NULL;
309 if ((flags & USE_TEXT_FIELD) != 0) {
310 file = WMGetTextFieldText(panel->fileText);
311 if (file && file[0] == 0) {
312 wfree(file);
313 file = NULL;
315 } else {
316 /* Get the application icon, default NOT included */
317 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
318 if (db_icon != NULL)
319 file = wstrdup(db_icon);
321 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
322 if (file)
323 file = wstrdup(db_icon);
324 flags |= UPDATE_TEXT_FIELD;
327 if ((flags & UPDATE_TEXT_FIELD) != 0)
328 WMSetTextFieldText(panel->fileText, file);
330 if (file) {
331 path = FindImage(wPreferences.icon_path, file);
333 if (!path) {
334 char *buf;
335 int len = strlen(file) + 80;
337 buf = wmalloc(len);
338 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
339 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
340 wfree(buf);
341 wfree(file);
342 return -1;
345 pixmap = WMCreatePixmapFromFile(scrPtr, path);
346 wfree(path);
348 if (!pixmap) {
349 char *buf;
350 int len = strlen(file) + 80;
352 buf = wmalloc(len);
353 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
354 file, RMessageForError(RErrorCode));
355 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
356 wfree(buf);
357 wfree(file);
358 return -1;
360 wfree(file);
363 WMSetLabelImage(panel->iconLbl, pixmap);
364 if (pixmap)
365 WMReleasePixmap(pixmap);
367 return 0;
370 static int getBool(WMPropList *value)
372 char *val;
374 if (!WMIsPLString(value))
375 return 0;
377 if (!(val = WMGetFromPLString(value)))
378 return 0;
380 if ((val[1] == '\0' &&
381 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
382 val[0] == 't' || val[0] == '1')) ||
383 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
384 return 1;
385 } else if ((val[1] == '\0' &&
386 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
387 val[0] == 'f' || val[0] == '0')) ||
388 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
389 return 0;
390 } else {
391 wwarning(_("can't convert \"%s\" to boolean"), val);
392 return 0;
396 /* Will insert the attribute = value; pair in window's list,
397 * if it's different from the defaults.
398 * Defaults means either defaults database, or attributes saved
399 * for the default window "*". This is to let one revert options that are
400 * global because they were saved for all windows ("*"). */
401 static int
402 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
404 WMPropList *def_win, *def_value = NULL;
405 int update = 0, modified = 0;
407 if (!(flags & UPDATE_DEFAULTS) && dict) {
408 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL)
409 def_value = WMGetFromPLDictionary(def_win, attr);
412 /* If we could not find defaults in database, fall to hardcoded values.
413 * Also this is true if we save defaults for all windows */
414 if (!def_value)
415 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
417 if (flags & IS_BOOLEAN)
418 update = (getBool(value) != getBool(def_value));
419 else
420 update = !WMIsPropListEqualTo(value, def_value);
422 if (update) {
423 WMPutInPLDictionary(window, attr, value);
424 modified = 1;
427 return modified;
430 static void saveSettings(WMButton *button, InspectorPanel *panel)
432 WWindow *wwin = panel->inspected;
433 WDDomain *db = WDWindowAttributes;
434 WMPropList *dict = NULL;
435 WMPropList *winDic, *appDic, *value, *value1, *key = NULL, *key2;
436 char *icon_file, *buf1, *buf2;
437 int flags = 0, i = 0, different = 0, different2 = 0;
439 /* Save will apply the changes and save them */
440 applySettings(panel->applyBtn, panel);
442 if (WMGetButtonSelected(panel->instRb) != 0) {
443 key = WMCreatePLString(wwin->wm_instance);
444 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
445 key = WMCreatePLString(wwin->wm_class);
446 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
447 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
448 key = WMCreatePLString(buf1);
449 wfree(buf1);
450 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
451 key = WMRetainPropList(AnyWindow);
452 flags = UPDATE_DEFAULTS;
455 if (!key)
456 return;
458 dict = db->dictionary;
459 if (!dict) {
460 dict = WMCreatePLDictionary(NULL, NULL);
461 if (dict) {
462 db->dictionary = dict;
463 } else {
464 WMReleasePropList(key);
465 return;
469 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
470 return;
472 WMPLSetCaseSensitive(True);
474 winDic = WMCreatePLDictionary(NULL, NULL);
475 appDic = WMCreatePLDictionary(NULL, NULL);
477 /* Save the icon info */
478 /* The flag "Ignore client suplied icon is not selected" */
479 buf1 = wmalloc(4);
480 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
481 value1 = WMCreatePLString(buf1);
482 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
483 WMReleasePropList(value1);
484 wfree(buf1);
486 /* The icon filename (if exists) */
487 icon_file = WMGetTextFieldText(panel->fileText);
488 if ((icon_file) && (icon_file[0] != 0)) {
489 value = WMCreatePLString(icon_file);
490 different |= insertAttribute(dict, winDic, AIcon, value, flags);
491 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
492 WMReleasePropList(value);
493 wfree(icon_file);
496 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
497 if (i >= 0 && i < w_global.workspace.count) {
498 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
499 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
500 WMReleasePropList(value);
503 flags |= IS_BOOLEAN;
505 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
506 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
508 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
509 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
511 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
512 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
514 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
515 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
517 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
518 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
520 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
521 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
523 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
524 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
526 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
527 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
529 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
530 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
532 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
533 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
535 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
536 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
538 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
539 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
541 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
544 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
547 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
550 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
553 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
556 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
559 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
562 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
565 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
568 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
569 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
571 #ifdef XKB_BUTTON_HINT
572 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
573 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
574 #endif
576 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
577 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
578 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
580 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
581 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
583 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
584 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
587 if (wwin->fake_group) {
588 key2 = WMCreatePLString(wwin->fake_group->identifier);
589 if (WMIsPropListEqualTo(key, key2)) {
590 WMMergePLDictionaries(winDic, appDic, True);
591 different |= different2;
592 } else {
593 WMRemoveFromPLDictionary(dict, key2);
594 if (different2)
595 WMPutInPLDictionary(dict, key2, appDic);
597 WMReleasePropList(key2);
598 WMReleasePropList(appDic);
599 } else if (wwin->main_window != wwin->client_win) {
600 WApplication *wapp = wApplicationOf(wwin->main_window);
602 if (wapp) {
603 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
604 wapp->main_window_desc->wm_class);
605 key2 = WMCreatePLString(buf2);
606 wfree(buf2);
608 if (WMIsPropListEqualTo(key, key2)) {
609 WMMergePLDictionaries(winDic, appDic, True);
610 different |= different2;
611 } else {
612 WMRemoveFromPLDictionary(dict, key2);
613 if (different2)
614 WMPutInPLDictionary(dict, key2, appDic);
616 WMReleasePropList(key2);
617 WMReleasePropList(appDic);
619 } else {
620 WMMergePLDictionaries(winDic, appDic, True);
621 different |= different2;
622 WMReleasePropList(appDic);
625 WMRemoveFromPLDictionary(dict, key);
626 if (different)
627 WMPutInPLDictionary(dict, key, winDic);
629 WMReleasePropList(key);
630 WMReleasePropList(winDic);
632 UpdateDomainFile(db);
634 /* clean up */
635 WMPLSetCaseSensitive(False);
638 static void applySettings(WMButton *button, InspectorPanel *panel)
640 WWindow *wwin = panel->inspected;
641 WApplication *wapp = wApplicationOf(wwin->main_window);
642 int floating, sunken, skip_window_list;
643 int old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
645 old_omnipresent = WFLAGP(wwin, omnipresent);
646 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
647 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
649 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
651 /* Attributes... --> Window Attributes */
652 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
653 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
654 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
655 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
656 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
657 floating = WMGetButtonSelected(panel->attrChk[5]);
658 sunken = WMGetButtonSelected(panel->attrChk[6]);
659 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
660 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
661 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
662 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
664 /* Attributes... --> Advanced Options */
665 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
666 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
667 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
668 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
669 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
670 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
671 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
672 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
673 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
674 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
675 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
676 #ifdef XKB_BUTTON_HINT
677 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
678 #endif
679 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
681 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
682 wUnshadeWindow(wwin);
684 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
686 if (floating) {
687 if (!WFLAGP(wwin, floating))
688 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
689 } else if (sunken) {
690 if (!WFLAGP(wwin, sunken))
691 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
692 } else {
693 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
694 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
697 WSETUFLAG(wwin, sunken, sunken);
698 WSETUFLAG(wwin, floating, floating);
699 wwin->flags.omnipresent = 0;
701 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
702 WSETUFLAG(wwin, skip_window_list, skip_window_list);
703 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
704 } else {
705 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
706 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
709 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
710 if (WFLAGP(wwin, no_bind_keys))
711 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
712 else
713 wWindowSetKeyGrabs(wwin);
716 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
717 wWindowResetMouseGrabs(wwin);
719 wwin->frame->flags.need_texture_change = 1;
720 wWindowConfigureBorders(wwin);
721 wFrameWindowPaint(wwin->frame);
722 wNETWMUpdateActions(wwin, False);
724 /* Can't apply emulate_appicon because it will probably cause problems. */
725 if (wapp) {
726 /* do application wide stuff */
727 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
728 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
729 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
731 if (WFLAGP(wapp->main_window_desc, no_appicon))
732 unpaint_app_icon(wapp);
733 else
734 paint_app_icon(wapp);
736 char *file = WMGetTextFieldText(panel->fileText);
737 if (file[0] == 0) {
738 wfree(file);
739 file = NULL;
742 /* If always_user_icon flag is set, but the user icon is not set
743 * we use client supplied icon and we unset the flag */
744 if ((WFLAGP(wwin, always_user_icon) && (!file))) {
745 /* Show the warning */
746 char *buf;
747 int len = 100;
749 buf = wmalloc(len);
750 snprintf(buf, len, _("Ignore client supplied icon is set, but icon filename textbox is empty. Using client supplied icon"));
751 wMessageDialog(panel->frame->screen_ptr, _("Warning"), buf, _("OK"), NULL, NULL);
752 wfree(buf);
753 wfree(file);
755 /* Change the flags */
756 WSETUFLAG(wwin, always_user_icon, 0);
757 WMSetButtonSelected(panel->alwChk, 0);
760 /* After test the always_user_icon flag value before,
761 * the "else" block is used only if the flag is set and
762 * the icon text box has an icon path */
763 if (!WFLAGP(wwin, always_user_icon)) {
764 /* Change App Icon image, using the icon provided by the client */
765 if (wapp->app_icon) {
766 RImage *image = get_rimage_icon_from_wm_hints(wapp->app_icon->icon);
767 if (image) {
768 set_icon_image_from_image(wapp->app_icon->icon, image);
769 update_icon_pixmap(wapp->app_icon->icon);
770 } else {
771 wIconUpdate(wapp->app_icon->icon);
775 /* Change icon image if the app is minimized,
776 * using the icon provided by the client */
777 if (wwin->icon) {
778 RImage *image = get_rimage_icon_from_wm_hints(wwin->icon);
779 if (image) {
780 set_icon_image_from_image(wwin->icon, image);
781 update_icon_pixmap(wwin->icon);
782 } else {
783 wIconUpdate(wwin->icon);
786 } else {
787 /* Change App Icon image */
788 if (wapp->app_icon)
789 wIconChangeImageFile(wapp->app_icon->icon, file);
791 /* Change icon image if the app is minimized */
792 if (wwin->icon)
793 wIconChangeImageFile(wwin->icon, file);
796 if (file)
797 wfree(file);
800 wNETFrameExtents(wwin);
803 static void revertSettings(WMButton *button, InspectorPanel *panel)
805 WWindow *wwin = panel->inspected;
806 WApplication *wapp = wApplicationOf(wwin->main_window);
807 int i, n, workspace, level;
808 char *wm_instance = NULL, *wm_class = NULL;
810 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
811 wm_instance = wwin->wm_instance;
812 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
813 wm_class = wwin->wm_class;
814 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
815 wm_instance = wwin->wm_instance;
816 wm_class = wwin->wm_class;
819 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
820 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
821 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
823 wWindowSetupInitialAttributes(wwin, &level, &workspace);
825 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
826 int flag = 0;
828 switch (i) {
829 case 0:
830 flag = WFLAGP(wwin, no_titlebar);
831 break;
832 case 1:
833 flag = WFLAGP(wwin, no_resizebar);
834 break;
835 case 2:
836 flag = WFLAGP(wwin, no_close_button);
837 break;
838 case 3:
839 flag = WFLAGP(wwin, no_miniaturize_button);
840 break;
841 case 4:
842 flag = WFLAGP(wwin, no_border);
843 break;
844 case 5:
845 flag = WFLAGP(wwin, floating);
846 break;
847 case 6:
848 flag = WFLAGP(wwin, sunken);
849 break;
850 case 7:
851 flag = WFLAGP(wwin, omnipresent);
852 break;
853 case 8:
854 flag = WFLAGP(wwin, start_miniaturized);
855 break;
856 case 9:
857 flag = WFLAGP(wwin, start_maximized != 0);
858 break;
859 case 10:
860 flag = WFLAGP(wwin, full_maximize);
861 break;
863 WMSetButtonSelected(panel->attrChk[i], flag);
866 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
867 int flag = 0;
869 switch (i) {
870 case 0:
871 flag = WFLAGP(wwin, no_bind_keys);
872 break;
873 case 1:
874 flag = WFLAGP(wwin, no_bind_mouse);
875 break;
876 case 2:
877 flag = WFLAGP(wwin, skip_window_list);
878 break;
879 case 3:
880 flag = WFLAGP(wwin, skip_switchpanel);
881 break;
882 case 4:
883 flag = WFLAGP(wwin, no_focusable);
884 break;
885 case 5:
886 flag = WFLAGP(wwin, dont_move_off);
887 break;
888 case 6:
889 flag = WFLAGP(wwin, no_hide_others);
890 break;
891 case 7:
892 flag = WFLAGP(wwin, dont_save_session);
893 break;
894 case 8:
895 flag = WFLAGP(wwin, emulate_appicon);
896 break;
897 case 9:
898 flag = WFLAGP(wwin, focus_across_wksp);
899 break;
900 case 10:
901 flag = WFLAGP(wwin, no_miniaturizable);
902 break;
903 #ifdef XKB_BUTTON_HINT
904 case 11:
905 flag = WFLAGP(wwin, no_language_button);
906 break;
907 #endif
909 WMSetButtonSelected(panel->moreChk[i], flag);
911 if (panel->appFrm && wapp) {
912 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
913 int flag = 0;
915 switch (i) {
916 case 0:
917 flag = WFLAGP(wapp->main_window_desc, start_hidden);
918 break;
919 case 1:
920 flag = WFLAGP(wapp->main_window_desc, no_appicon);
921 break;
922 case 2:
923 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
924 break;
926 WMSetButtonSelected(panel->appChk[i], flag);
929 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
931 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
933 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
935 if (n >= 0 && n < w_global.workspace.count)
936 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
937 else
938 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
940 /* must auto apply, so that there wno't be internal
941 * inconsistencies between the state in the flags and
942 * the actual state of the window */
943 applySettings(panel->applyBtn, panel);
946 static void chooseIconCallback(WMWidget *self, void *clientData)
948 char *file;
949 InspectorPanel *panel = (InspectorPanel *) clientData;
950 int result;
952 panel->choosingIcon = 1;
954 WMSetButtonEnabled(panel->browseIconBtn, False);
956 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
957 panel->inspected->wm_instance,
958 panel->inspected->wm_class);
960 panel->choosingIcon = 0;
962 if (!panel->destroyed) { /* kluge */
963 if (result) {
964 WMSetTextFieldText(panel->fileText, file);
965 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
966 wfree(file);
968 WMSetButtonEnabled(panel->browseIconBtn, True);
969 } else {
970 freeInspector(panel);
974 static void textEditedObserver(void *observerData, WMNotification *notification)
976 InspectorPanel *panel = (InspectorPanel *) observerData;
978 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
979 return;
981 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
984 static void selectSpecification(WMWidget *bPtr, void *data)
986 InspectorPanel *panel = (InspectorPanel *) data;
987 char *str;
988 WWindow *wwin = panel->inspected;
989 int len;
991 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
992 WMSetButtonEnabled(panel->applyBtn, False);
993 else
994 WMSetButtonEnabled(panel->applyBtn, True);
996 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
997 + strlen(wwin->wm_class ? wwin->wm_class : "?");
999 str = wmalloc(len);
1001 snprintf(str, len, _("Inspecting %s.%s"),
1002 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1004 wFrameWindowChangeTitle(panel->frame->frame, str);
1006 wfree(str);
1009 static void selectWindow(WMWidget *bPtr, void *data)
1011 InspectorPanel *panel = (InspectorPanel *) data;
1012 WWindow *wwin = panel->inspected;
1013 WScreen *scr = wwin->screen_ptr;
1014 XEvent event;
1015 WWindow *iwin;
1017 if (XGrabPointer(dpy, scr->root_win, True,
1018 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1019 wPreferences.cursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1020 wwarning("could not grab mouse pointer");
1021 return;
1024 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1025 WMMaskEvent(dpy, ButtonPressMask, &event);
1026 XUngrabPointer(dpy, CurrentTime);
1028 iwin = wWindowFor(event.xbutton.subwindow);
1029 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1030 iwin->flags.inspector_open = 1;
1031 iwin->inspector = createInspectorForWindow(iwin,
1032 panel->frame->frame_x, panel->frame->frame_y, True);
1033 wCloseInspectorForWindow(wwin);
1034 } else {
1035 WMSetLabelText(panel->specLbl, spec_text);
1039 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1041 WScreen *scr = wwin->screen_ptr;
1042 InspectorPanel *panel;
1043 Window parent;
1044 char *str = NULL, *tmp = NULL;
1045 int x, y, btn_width, frame_width;
1046 WMButton *selectedBtn = NULL;
1048 spec_text = _("The configuration will apply to all\n"
1049 "windows that have their WM_CLASS\n"
1050 "property set to the above selected\n" "name, when saved.");
1052 panel = wmalloc(sizeof(InspectorPanel));
1053 memset(panel, 0, sizeof(InspectorPanel));
1055 panel->destroyed = 0;
1056 panel->inspected = wwin;
1057 panel->nextPtr = panelList;
1058 panelList = panel;
1059 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1060 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1062 /**** create common stuff ****/
1063 /* command buttons */
1064 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1065 panel->saveBtn = WMCreateCommandButton(panel->win);
1066 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1067 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1068 WMSetButtonText(panel->saveBtn, _("Save"));
1069 WMResizeWidget(panel->saveBtn, btn_width, 28);
1070 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1071 WMSetButtonEnabled(panel->saveBtn, False);
1073 panel->applyBtn = WMCreateCommandButton(panel->win);
1074 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1075 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1076 WMSetButtonText(panel->applyBtn, _("Apply"));
1077 WMResizeWidget(panel->applyBtn, btn_width, 28);
1079 panel->revertBtn = WMCreateCommandButton(panel->win);
1080 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1081 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1082 WMSetButtonText(panel->revertBtn, _("Reload"));
1083 WMResizeWidget(panel->revertBtn, btn_width, 28);
1085 /* page selection popup button */
1086 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1087 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1088 WMMoveWidget(panel->pagePopUp, 25, 15);
1089 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1091 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1092 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1093 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1094 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1095 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1097 /**** window spec ****/
1098 frame_width = PWIDTH - (2 * 15);
1100 panel->specFrm = WMCreateFrame(panel->win);
1101 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1102 WMMoveWidget(panel->specFrm, 15, 65);
1103 WMResizeWidget(panel->specFrm, frame_width, 145);
1105 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1106 WMMoveWidget(panel->defaultRb, 10, 78);
1107 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1108 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1109 WMSetButtonSelected(panel->defaultRb, False);
1110 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1112 if (wwin->wm_class && wwin->wm_instance) {
1113 tmp = wstrconcat(wwin->wm_instance, ".");
1114 str = wstrconcat(tmp, wwin->wm_class);
1116 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1117 WMMoveWidget(panel->bothRb, 10, 18);
1118 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1119 WMSetButtonText(panel->bothRb, str);
1120 wfree(tmp);
1121 wfree(str);
1122 WMGroupButtons(panel->defaultRb, panel->bothRb);
1124 if (!selectedBtn)
1125 selectedBtn = panel->bothRb;
1127 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1130 if (wwin->wm_instance) {
1131 panel->instRb = WMCreateRadioButton(panel->specFrm);
1132 WMMoveWidget(panel->instRb, 10, 38);
1133 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1134 WMSetButtonText(panel->instRb, wwin->wm_instance);
1135 WMGroupButtons(panel->defaultRb, panel->instRb);
1137 if (!selectedBtn)
1138 selectedBtn = panel->instRb;
1140 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1143 if (wwin->wm_class) {
1144 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1145 WMMoveWidget(panel->clsRb, 10, 58);
1146 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1147 WMSetButtonText(panel->clsRb, wwin->wm_class);
1148 WMGroupButtons(panel->defaultRb, panel->clsRb);
1150 if (!selectedBtn)
1151 selectedBtn = panel->clsRb;
1153 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1156 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1157 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1158 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1159 WMSetButtonText(panel->selWinB, _("Select window"));
1160 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1162 panel->specLbl = WMCreateLabel(panel->win);
1163 WMMoveWidget(panel->specLbl, 15, 210);
1164 WMResizeWidget(panel->specLbl, frame_width, 100);
1165 WMSetLabelText(panel->specLbl, spec_text);
1166 WMSetLabelWraps(panel->specLbl, True);
1168 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1170 /**** attributes ****/
1171 create_tab_window_attributes(wwin, panel, frame_width);
1172 create_tab_window_advanced(wwin, panel, frame_width);
1173 create_tab_icon_workspace(wwin, panel, frame_width);
1174 create_tab_app_specific(wwin, panel, frame_width);
1176 /* if the window is a transient, don't let it have a miniaturize button */
1177 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1178 WMSetButtonEnabled(panel->attrChk[3], False);
1179 else
1180 WMSetButtonEnabled(panel->attrChk[3], True);
1182 if (!wwin->wm_class && !wwin->wm_instance)
1183 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1185 WMRealizeWidget(panel->win);
1187 WMMapSubwidgets(panel->win);
1188 WMMapSubwidgets(panel->specFrm);
1189 WMMapSubwidgets(panel->attrFrm);
1190 WMMapSubwidgets(panel->moreFrm);
1191 WMMapSubwidgets(panel->iconFrm);
1192 WMMapSubwidgets(panel->wsFrm);
1193 if (panel->appFrm)
1194 WMMapSubwidgets(panel->appFrm);
1196 if (showSelectPanel) {
1197 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1198 changePage(panel->pagePopUp, panel);
1199 } else {
1200 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1201 changePage(panel->pagePopUp, panel);
1204 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1205 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1206 panel->parent = parent;
1207 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1209 WMMapWidget(panel->win);
1211 XSetTransientForHint(dpy, parent, wwin->client_win);
1213 if (xpos == UNDEFINED_POS) {
1214 x = wwin->frame_x + wwin->frame->core->width / 2;
1215 y = wwin->frame_y + wwin->frame->top_width * 2;
1216 if (y + PHEIGHT > scr->scr_height)
1217 y = scr->scr_height - PHEIGHT - 30;
1218 if (x + PWIDTH > scr->scr_width)
1219 x = scr->scr_width - PWIDTH;
1220 } else {
1221 x = xpos;
1222 y = ypos;
1225 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1227 if (!selectedBtn)
1228 selectedBtn = panel->defaultRb;
1230 WMSetButtonSelected(selectedBtn, True);
1231 selectSpecification(selectedBtn, panel);
1233 /* kluge to know who should get the key events */
1234 panel->frame->client_leader = WMWidgetXID(panel->win);
1236 WSETUFLAG(panel->frame, no_closable, 0);
1237 WSETUFLAG(panel->frame, no_close_button, 0);
1238 wWindowUpdateButtonImages(panel->frame);
1239 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1240 panel->frame->frame->on_click_right = destroyInspector;
1242 wWindowMap(panel->frame);
1244 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1246 return panel;
1249 void wShowInspectorForWindow(WWindow *wwin)
1251 if (wwin->flags.inspector_open)
1252 return;
1254 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1256 make_keys();
1257 wwin->flags.inspector_open = 1;
1258 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1261 void wHideInspectorForWindow(WWindow *wwin)
1263 WWindow *pwin = wwin->inspector->frame;
1265 wWindowUnmap(pwin);
1266 pwin->flags.hidden = 1;
1268 wClientSetState(pwin, IconicState, None);
1271 void wUnhideInspectorForWindow(WWindow *wwin)
1273 WWindow *pwin = wwin->inspector->frame;
1275 pwin->flags.hidden = 0;
1276 pwin->flags.mapped = 1;
1277 XMapWindow(dpy, pwin->client_win);
1278 XMapWindow(dpy, pwin->frame->core->window);
1279 wClientSetState(pwin, NormalState, None);
1282 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1284 if (!wwin->inspector)
1285 return NULL;
1287 assert(wwin->flags.inspector_open != 0);
1288 return wwin->inspector->frame;
1291 void wCloseInspectorForWindow(WWindow *wwin)
1293 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1295 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1298 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1300 int i = 0;
1301 char *caption = NULL, *descr = NULL;
1302 int flag = 0;
1304 panel->attrFrm = WMCreateFrame(panel->win);
1305 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1306 WMMoveWidget(panel->attrFrm, 15, 45);
1307 WMResizeWidget(panel->attrFrm, frame_width, 250);
1309 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1310 switch (i) {
1311 case 0:
1312 caption = _("Disable titlebar");
1313 flag = WFLAGP(wwin, no_titlebar);
1314 descr = _("Remove the titlebar of this window.\n"
1315 "To access the window commands menu of a window\n"
1316 "without it's titlebar, press Control+Esc (or the\n"
1317 "equivalent shortcut, if you changed the default\n" "settings).");
1318 break;
1319 case 1:
1320 caption = _("Disable resizebar");
1321 flag = WFLAGP(wwin, no_resizebar);
1322 descr = _("Remove the resizebar of this window.");
1323 break;
1324 case 2:
1325 caption = _("Disable close button");
1326 flag = WFLAGP(wwin, no_close_button);
1327 descr = _("Remove the `close window' button of this window.");
1328 break;
1329 case 3:
1330 caption = _("Disable miniaturize button");
1331 flag = WFLAGP(wwin, no_miniaturize_button);
1332 descr = _("Remove the `miniaturize window' button of the window.");
1333 break;
1334 case 4:
1335 caption = _("Disable border");
1336 flag = WFLAGP(wwin, no_border);
1337 descr = _("Remove the 1 pixel black border around the window.");
1338 break;
1339 case 5:
1340 caption = _("Keep on top (floating)");
1341 flag = WFLAGP(wwin, floating);
1342 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1343 break;
1344 case 6:
1345 caption = _("Keep at bottom (sunken)");
1346 flag = WFLAGP(wwin, sunken);
1347 descr = _("Keep the window under all other windows.");
1348 break;
1349 case 7:
1350 caption = _("Omnipresent");
1351 flag = WFLAGP(wwin, omnipresent);
1352 descr = _("Make window present in all workspaces.");
1353 break;
1354 case 8:
1355 caption = _("Start miniaturized");
1356 flag = WFLAGP(wwin, start_miniaturized);
1357 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1358 break;
1359 case 9:
1360 caption = _("Start maximized");
1361 flag = WFLAGP(wwin, start_maximized != 0);
1362 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1363 break;
1364 case 10:
1365 caption = _("Full screen maximization");
1366 flag = WFLAGP(wwin, full_maximize);
1367 descr = _("Make the window use the whole screen space when it's\n"
1368 "maximized. The titlebar and resizebar will be moved\n"
1369 "to outside the screen.");
1370 break;
1372 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1373 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1374 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1375 WMSetButtonSelected(panel->attrChk[i], flag);
1376 WMSetButtonText(panel->attrChk[i], caption);
1378 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1382 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1384 int i = 0;
1385 char *caption = NULL, *descr = NULL;
1386 int flag = 0;
1388 panel->moreFrm = WMCreateFrame(panel->win);
1389 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1390 WMMoveWidget(panel->moreFrm, 15, 45);
1391 WMResizeWidget(panel->moreFrm, frame_width, 265);
1393 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1394 switch (i) {
1395 case 0:
1396 caption = _("Do not bind keyboard shortcuts");
1397 flag = WFLAGP(wwin, no_bind_keys);
1398 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1399 "when this window is focused. This will allow the\n"
1400 "window to receive all key combinations regardless\n"
1401 "of your shortcut configuration.");
1402 break;
1403 case 1:
1404 caption = _("Do not bind mouse clicks");
1405 flag = WFLAGP(wwin, no_bind_mouse);
1406 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1407 "in the window (when alt is the modifier you have\n" "configured).");
1408 break;
1409 case 2:
1410 caption = _("Do not show in the window list");
1411 flag = WFLAGP(wwin, skip_window_list);
1412 descr = _("Do not list the window in the window list menu.");
1413 break;
1414 case 3:
1415 caption = _("Do not show in the switch panel");
1416 flag = WFLAGP(wwin, skip_switchpanel);
1417 descr = _("Do not include in switchpanel while alternating windows.");
1418 break;
1419 case 4:
1420 caption = _("Do not let it take focus");
1421 flag = WFLAGP(wwin, no_focusable);
1422 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1423 break;
1424 case 5:
1425 caption = _("Keep inside screen");
1426 flag = WFLAGP(wwin, dont_move_off);
1427 descr = _("Do not allow the window to move itself completely\n"
1428 "outside the screen. For bug compatibility.\n");
1429 break;
1430 case 6:
1431 caption = _("Ignore 'Hide Others'");
1432 flag = WFLAGP(wwin, no_hide_others);
1433 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1434 break;
1435 case 7:
1436 caption = _("Ignore 'Save Session'");
1437 flag = WFLAGP(wwin, dont_save_session);
1438 descr = _("Do not save the associated application in the\n"
1439 "session's state, so that it won't be restarted\n"
1440 "together with other applications when Window Maker\n" "starts.");
1441 break;
1442 case 8:
1443 caption = _("Emulate application icon");
1444 flag = WFLAGP(wwin, emulate_appicon);
1445 descr = _("Make this window act as an application that provides\n"
1446 "enough information to Window Maker for a dockable\n"
1447 "application icon to be created.");
1448 break;
1449 case 9:
1450 caption = _("Focus across workspaces");
1451 flag = WFLAGP(wwin, focus_across_wksp);
1452 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1453 "a focus request (annoying).");
1454 break;
1455 case 10:
1456 caption = _("Do not let it be minimized");
1457 flag = WFLAGP(wwin, no_miniaturizable);
1458 descr = _("Do not let the window of this application be\n"
1459 "minimized.\n");
1460 break;
1461 #ifdef XKB_BUTTON_HINT
1462 case 11:
1463 caption = _("Disable language button");
1464 flag = WFLAGP(wwin, no_language_button);
1465 descr = _("Remove the `toggle language' button of the window.");
1466 break;
1467 #endif
1469 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1470 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1471 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1472 WMSetButtonSelected(panel->moreChk[i], flag);
1473 WMSetButtonText(panel->moreChk[i], caption);
1475 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1479 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1481 WScreen *scr = wwin->screen_ptr;
1482 int i = 0;
1484 /* miniwindow/workspace */
1485 panel->iconFrm = WMCreateFrame(panel->win);
1486 WMMoveWidget(panel->iconFrm, 15, 50);
1487 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1488 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1490 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1491 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1492 WMResizeWidget(panel->iconLbl, 64, 64);
1493 WMSetLabelRelief(panel->iconLbl, WRGroove);
1494 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1496 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1497 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1498 WMMoveWidget(panel->browseIconBtn, 22, 32);
1499 WMResizeWidget(panel->browseIconBtn, 120, 26);
1500 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1502 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1503 WMMoveWidget(panel->fileLbl, 20, 85);
1504 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1505 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1507 panel->fileText = WMCreateTextField(panel->iconFrm);
1508 WMMoveWidget(panel->fileText, 20, 105);
1509 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1510 WMSetTextFieldText(panel->fileText, NULL);
1511 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1513 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1514 WMMoveWidget(panel->alwChk, 20, 130);
1515 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1516 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1517 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1519 panel->wsFrm = WMCreateFrame(panel->win);
1520 WMMoveWidget(panel->wsFrm, 15, 225);
1521 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1522 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1524 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1525 "first shown."), WMWidgetView(panel->wsFrm));
1527 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1528 WMMoveWidget(panel->wsP, 20, 30);
1529 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1530 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1532 for (i = 0; i < w_global.workspace.count; i++)
1533 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1535 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1536 if (i >= 0 && i <= w_global.workspace.count)
1537 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1538 else
1539 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1542 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1544 WScreen *scr = wwin->screen_ptr;
1545 int i = 0, flag = 0, tmp;
1546 char *caption = NULL, *descr = NULL;
1549 if (wwin->main_window != None) {
1550 WApplication *wapp = wApplicationOf(wwin->main_window);
1552 panel->appFrm = WMCreateFrame(panel->win);
1553 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1554 WMMoveWidget(panel->appFrm, 15, 50);
1555 WMResizeWidget(panel->appFrm, frame_width, 240);
1557 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1558 switch (i) {
1559 case 0:
1560 caption = _("Start hidden");
1561 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1562 descr = _("Automatically hide application when it's started.");
1563 break;
1564 case 1:
1565 caption = _("No application icon");
1566 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1567 descr = _("Disable the application icon for the application.\n"
1568 "Note that you won't be able to dock it anymore,\n"
1569 "and any icons that are already docked will stop\n"
1570 "working correctly.");
1571 break;
1572 case 2:
1573 caption = _("Shared application icon");
1574 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1575 descr = _("Use a single shared application icon for all of\n"
1576 "the instances of this application.\n");
1577 break;
1579 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1580 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1581 WMResizeWidget(panel->appChk[i], 205, 20);
1582 WMSetButtonSelected(panel->appChk[i], flag);
1583 WMSetButtonText(panel->appChk[i], caption);
1584 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1587 if (WFLAGP(wwin, emulate_appicon)) {
1588 WMSetButtonEnabled(panel->appChk[1], False);
1589 WMSetButtonEnabled(panel->moreChk[7], True);
1590 } else {
1591 WMSetButtonEnabled(panel->appChk[1], True);
1592 WMSetButtonEnabled(panel->moreChk[7], False);
1594 } else {
1595 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1596 || !wwin->wm_class || !wwin->wm_instance)
1597 tmp = False;
1598 else
1599 tmp = True;
1601 WMSetButtonEnabled(panel->moreChk[7], tmp);
1603 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1604 panel->appFrm = NULL;