Wrap appicons when dock is moved up and down
[wmaker-crm.git] / src / winspector.c
blob8d5923af073d88d7060b510a9cb3eb5b119a6795
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <strings.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "funcs.h"
39 #include "defaults.h"
40 #include "dialog.h"
41 #include "icon.h"
42 #include "stacking.h"
43 #include "application.h"
44 #include "appicon.h"
45 #include "actions.h"
46 #include "winspector.h"
47 #include "dock.h"
48 #include "client.h"
49 #include "wmspec.h"
51 #include <WINGs/WUtil.h>
53 #define USE_TEXT_FIELD 1
54 #define UPDATE_TEXT_FIELD 2
55 #define REVERT_TO_DEFAULT 4
56 #define PWIDTH 290
57 #define PHEIGHT 360
58 #define UNDEFINED_POS 0xffffff
59 #define UPDATE_DEFAULTS 1
60 #define IS_BOOLEAN 2
62 typedef struct InspectorPanel {
63 struct InspectorPanel *nextPtr;
65 WWindow *frame;
66 WWindow *inspected; /* the window that's being inspected */
67 WMWindow *win;
68 Window parent;
70 /* common stuff */
71 WMButton *revertBtn;
72 WMButton *applyBtn;
73 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
77 WMFrame *specFrm;
78 WMButton *instRb;
79 WMButton *clsRb;
80 WMButton *bothRb;
81 WMButton *defaultRb;
82 WMButton *selWinB;
83 WMLabel *specLbl;
85 /* second page. attributes */
86 WMFrame *attrFrm;
87 WMButton *attrChk[11];
89 /* 3rd page. more attributes */
90 WMFrame *moreFrm;
91 #ifdef XKB_BUTTON_HINT
92 WMButton *moreChk[12];
93 #else
94 WMButton *moreChk[11];
95 #endif
97 /* 4th page. icon and workspace */
98 WMFrame *iconFrm;
99 WMLabel *iconLbl;
100 WMLabel *fileLbl;
101 WMTextField *fileText;
102 WMButton *alwChk;
103 WMButton *browseIconBtn;
104 WMFrame *wsFrm;
105 WMPopUpButton *wsP;
107 /* 5th page. application wide attributes */
108 WMFrame *appFrm;
109 WMButton *appChk[3];
111 unsigned int done:1;
112 unsigned int destroyed:1;
113 unsigned int choosingIcon:1;
114 } InspectorPanel;
116 extern Cursor wCursor[WCUR_LAST];
117 extern WDDomain *WDWindowAttributes;
118 extern WPreferences wPreferences;
120 static InspectorPanel *panelList = NULL;
121 static WMPropList *ANoTitlebar = NULL;
122 static WMPropList *ANoResizebar;
123 static WMPropList *ANoMiniaturizeButton;
124 static WMPropList *ANoCloseButton;
125 static WMPropList *ANoBorder;
126 static WMPropList *ANoHideOthers;
127 static WMPropList *ANoMouseBindings;
128 static WMPropList *ANoKeyBindings;
129 static WMPropList *ANoAppIcon;
130 static WMPropList *AKeepOnTop;
131 static WMPropList *AKeepOnBottom;
132 static WMPropList *AOmnipresent;
133 static WMPropList *ASkipWindowList;
134 static WMPropList *ASkipSwitchPanel;
135 static WMPropList *AKeepInsideScreen;
136 static WMPropList *AUnfocusable;
137 static WMPropList *AFocusAcrossWorkspace;
138 static WMPropList *AAlwaysUserIcon;
139 static WMPropList *AStartMiniaturized;
140 static WMPropList *AStartMaximized;
141 static WMPropList *ADontSaveSession;
142 static WMPropList *AEmulateAppIcon;
143 static WMPropList *AFullMaximize;
144 static WMPropList *ASharedAppIcon;
145 static WMPropList *ANoMiniaturizable;
146 #ifdef XKB_BUTTON_HINT
147 static WMPropList *ANoLanguageButton;
148 #endif
149 static WMPropList *AStartWorkspace;
150 static WMPropList *AIcon;
152 /* application wide options */
153 static WMPropList *AStartHidden;
154 static WMPropList *AnyWindow;
155 static WMPropList *EmptyString;
156 static WMPropList *Yes, *No;
158 static char *spec_text;
159 static void applySettings(WMButton *button, InspectorPanel *panel);
161 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
163 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
164 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
165 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width);
166 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
168 static void make_keys(void)
170 if (ANoTitlebar != NULL)
171 return;
173 AIcon = WMCreatePLString("Icon");
174 ANoTitlebar = WMCreatePLString("NoTitlebar");
175 ANoResizebar = WMCreatePLString("NoResizebar");
176 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
177 ANoCloseButton = WMCreatePLString("NoCloseButton");
178 ANoBorder = WMCreatePLString("NoBorder");
179 ANoHideOthers = WMCreatePLString("NoHideOthers");
180 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
181 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
182 ANoAppIcon = WMCreatePLString("NoAppIcon");
183 AKeepOnTop = WMCreatePLString("KeepOnTop");
184 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
185 AOmnipresent = WMCreatePLString("Omnipresent");
186 ASkipWindowList = WMCreatePLString("SkipWindowList");
187 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
188 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
189 AUnfocusable = WMCreatePLString("Unfocusable");
190 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
191 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
192 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
193 AStartMaximized = WMCreatePLString("StartMaximized");
194 AStartHidden = WMCreatePLString("StartHidden");
195 ADontSaveSession = WMCreatePLString("DontSaveSession");
196 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
197 AFullMaximize = WMCreatePLString("FullMaximize");
198 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
199 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
200 #ifdef XKB_BUTTON_HINT
201 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
202 #endif
204 AStartWorkspace = WMCreatePLString("StartWorkspace");
206 AnyWindow = WMCreatePLString("*");
207 EmptyString = WMCreatePLString("");
208 Yes = WMCreatePLString("Yes");
209 No = WMCreatePLString("No");
212 static void freeInspector(InspectorPanel *panel)
214 panel->destroyed = 1;
216 if (panel->choosingIcon)
217 return;
219 WMDestroyWidget(panel->win);
220 XDestroyWindow(dpy, panel->parent);
221 wfree(panel);
224 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
226 InspectorPanel *panel, *tmp;
228 panel = panelList;
229 while (panel->frame != data)
230 panel = panel->nextPtr;
232 if (panelList == panel) {
233 panelList = panel->nextPtr;
234 } else {
235 tmp = panelList;
236 while (tmp->nextPtr != panel)
237 tmp = tmp->nextPtr;
239 tmp->nextPtr = panel->nextPtr;
241 panel->inspected->flags.inspector_open = 0;
242 panel->inspected->inspector = NULL;
244 WMRemoveNotificationObserver(panel);
246 wWindowUnmap(panel->frame);
247 wUnmanageWindow(panel->frame, True, False);
249 freeInspector(panel);
252 void wDestroyInspectorPanels(void)
254 InspectorPanel *panel;
256 while (panelList != NULL) {
257 panel = panelList;
258 panelList = panelList->nextPtr;
259 wUnmanageWindow(panel->frame, False, False);
260 WMDestroyWidget(panel->win);
262 panel->inspected->flags.inspector_open = 0;
263 panel->inspected->inspector = NULL;
265 wfree(panel);
269 static void changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
271 int page;
273 page = WMGetPopUpButtonSelectedItem(bPtr);
275 if (page == 0) {
276 WMMapWidget(panel->specFrm);
277 WMMapWidget(panel->specLbl);
278 } else if (page == 1) {
279 WMMapWidget(panel->attrFrm);
280 } else if (page == 2) {
281 WMMapWidget(panel->moreFrm);
282 } else if (page == 3) {
283 WMMapWidget(panel->iconFrm);
284 WMMapWidget(panel->wsFrm);
285 } else {
286 WMMapWidget(panel->appFrm);
289 if (page != 0) {
290 WMUnmapWidget(panel->specFrm);
291 WMUnmapWidget(panel->specLbl);
293 if (page != 1)
294 WMUnmapWidget(panel->attrFrm);
295 if (page != 2)
296 WMUnmapWidget(panel->moreFrm);
297 if (page != 3) {
298 WMUnmapWidget(panel->iconFrm);
299 WMUnmapWidget(panel->wsFrm);
301 if (page != 4 && panel->appFrm)
302 WMUnmapWidget(panel->appFrm);
305 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, char *wm_instance, char *wm_class, int flags)
307 WMPixmap *pixmap = (WMPixmap *) NULL;
308 char *file = NULL, *path = NULL, *db_icon = NULL;
310 if ((flags & USE_TEXT_FIELD) != 0) {
311 file = WMGetTextFieldText(panel->fileText);
312 if (file && file[0] == 0) {
313 wfree(file);
314 file = NULL;
316 } else {
317 /* Get the application icon, default NOT included */
318 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
319 if (db_icon != NULL)
320 file = wstrdup(db_icon);
322 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
323 if (file)
324 file = wstrdup(db_icon);
325 flags |= UPDATE_TEXT_FIELD;
328 if ((flags & UPDATE_TEXT_FIELD) != 0)
329 WMSetTextFieldText(panel->fileText, file);
331 if (file) {
332 path = FindImage(wPreferences.icon_path, file);
334 if (!path) {
335 char *buf;
336 int len = strlen(file) + 80;
338 buf = wmalloc(len);
339 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
340 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
341 wfree(buf);
342 wfree(file);
343 return -1;
346 pixmap = WMCreatePixmapFromFile(scrPtr, path);
347 wfree(path);
349 if (!pixmap) {
350 char *buf;
351 int len = strlen(file) + 80;
353 buf = wmalloc(len);
354 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
355 file, RMessageForError(RErrorCode));
356 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
357 wfree(buf);
358 wfree(file);
359 return -1;
361 wfree(file);
364 WMSetLabelImage(panel->iconLbl, pixmap);
365 if (pixmap)
366 WMReleasePixmap(pixmap);
368 return 0;
371 static int getBool(WMPropList *value)
373 char *val;
375 if (!WMIsPLString(value))
376 return 0;
378 if (!(val = WMGetFromPLString(value)))
379 return 0;
381 if ((val[1] == '\0' &&
382 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
383 val[0] == 't' || val[0] == '1')) ||
384 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
385 return 1;
386 } else if ((val[1] == '\0' &&
387 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
388 val[0] == 'f' || val[0] == '0')) ||
389 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
390 return 0;
391 } else {
392 wwarning(_("can't convert \"%s\" to boolean"), val);
393 return 0;
397 /* Will insert the attribute = value; pair in window's list,
398 * if it's different from the defaults.
399 * Defaults means either defaults database, or attributes saved
400 * for the default window "*". This is to let one revert options that are
401 * global because they were saved for all windows ("*"). */
402 static int
403 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
405 WMPropList *def_win, *def_value = NULL;
406 int update = 0, modified = 0;
408 if (!(flags & UPDATE_DEFAULTS) && dict) {
409 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL)
410 def_value = WMGetFromPLDictionary(def_win, attr);
413 /* If we could not find defaults in database, fall to hardcoded values.
414 * Also this is true if we save defaults for all windows */
415 if (!def_value)
416 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
418 if (flags & IS_BOOLEAN)
419 update = (getBool(value) != getBool(def_value));
420 else
421 update = !WMIsPropListEqualTo(value, def_value);
423 if (update) {
424 WMPutInPLDictionary(window, attr, value);
425 modified = 1;
428 return modified;
431 static void saveSettings(WMButton *button, InspectorPanel *panel)
433 WWindow *wwin = panel->inspected;
434 WDDomain *db = WDWindowAttributes;
435 WMPropList *dict = NULL;
436 WMPropList *winDic, *appDic, *value, *value1, *key = NULL, *key2;
437 char *icon_file, *buf1, *buf2;
438 int flags = 0, i = 0, different = 0, different2 = 0;
440 /* Save will apply the changes and save them */
441 applySettings(panel->applyBtn, panel);
443 if (WMGetButtonSelected(panel->instRb) != 0) {
444 key = WMCreatePLString(wwin->wm_instance);
445 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
446 key = WMCreatePLString(wwin->wm_class);
447 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
448 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
449 key = WMCreatePLString(buf1);
450 wfree(buf1);
451 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
452 key = WMRetainPropList(AnyWindow);
453 flags = UPDATE_DEFAULTS;
456 if (!key)
457 return;
459 dict = db->dictionary;
460 if (!dict) {
461 dict = WMCreatePLDictionary(NULL, NULL);
462 if (dict) {
463 db->dictionary = dict;
464 } else {
465 WMReleasePropList(key);
466 return;
470 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
471 return;
473 WMPLSetCaseSensitive(True);
475 winDic = WMCreatePLDictionary(NULL, NULL);
476 appDic = WMCreatePLDictionary(NULL, NULL);
478 /* 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 wIconUpdate(wapp->app_icon->icon,
768 get_rimage_icon_from_wm_hints(wapp->app_icon->icon));
770 /* Change icon image if the app is minimized,
771 * using the icon provided by the client */
772 if (wwin->icon)
773 wIconUpdate(wwin->icon, get_rimage_icon_from_wm_hints(wwin->icon));
774 } else {
775 /* Change App Icon image */
776 if (wapp->app_icon)
777 wIconChangeImageFile(wapp->app_icon->icon, file);
779 /* Change icon image if the app is minimized */
780 if (wwin->icon)
781 wIconChangeImageFile(wwin->icon, file);
784 if (file)
785 wfree(file);
788 wNETFrameExtents(wwin);
791 static void revertSettings(WMButton *button, InspectorPanel *panel)
793 WWindow *wwin = panel->inspected;
794 WApplication *wapp = wApplicationOf(wwin->main_window);
795 int i, n, workspace, level;
796 char *wm_instance = NULL, *wm_class = NULL;
798 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
799 wm_instance = wwin->wm_instance;
800 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
801 wm_class = wwin->wm_class;
802 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
803 wm_instance = wwin->wm_instance;
804 wm_class = wwin->wm_class;
807 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
808 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
809 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
811 wWindowSetupInitialAttributes(wwin, &level, &workspace);
813 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
814 int flag = 0;
816 switch (i) {
817 case 0:
818 flag = WFLAGP(wwin, no_titlebar);
819 break;
820 case 1:
821 flag = WFLAGP(wwin, no_resizebar);
822 break;
823 case 2:
824 flag = WFLAGP(wwin, no_close_button);
825 break;
826 case 3:
827 flag = WFLAGP(wwin, no_miniaturize_button);
828 break;
829 case 4:
830 flag = WFLAGP(wwin, no_border);
831 break;
832 case 5:
833 flag = WFLAGP(wwin, floating);
834 break;
835 case 6:
836 flag = WFLAGP(wwin, sunken);
837 break;
838 case 7:
839 flag = WFLAGP(wwin, omnipresent);
840 break;
841 case 8:
842 flag = WFLAGP(wwin, start_miniaturized);
843 break;
844 case 9:
845 flag = WFLAGP(wwin, start_maximized != 0);
846 break;
847 case 10:
848 flag = WFLAGP(wwin, full_maximize);
849 break;
851 WMSetButtonSelected(panel->attrChk[i], flag);
854 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
855 int flag = 0;
857 switch (i) {
858 case 0:
859 flag = WFLAGP(wwin, no_bind_keys);
860 break;
861 case 1:
862 flag = WFLAGP(wwin, no_bind_mouse);
863 break;
864 case 2:
865 flag = WFLAGP(wwin, skip_window_list);
866 break;
867 case 3:
868 flag = WFLAGP(wwin, skip_switchpanel);
869 break;
870 case 4:
871 flag = WFLAGP(wwin, no_focusable);
872 break;
873 case 5:
874 flag = WFLAGP(wwin, dont_move_off);
875 break;
876 case 6:
877 flag = WFLAGP(wwin, no_hide_others);
878 break;
879 case 7:
880 flag = WFLAGP(wwin, dont_save_session);
881 break;
882 case 8:
883 flag = WFLAGP(wwin, emulate_appicon);
884 break;
885 case 9:
886 flag = WFLAGP(wwin, focus_across_wksp);
887 break;
888 case 10:
889 flag = WFLAGP(wwin, no_miniaturizable);
890 break;
891 #ifdef XKB_BUTTON_HINT
892 case 11:
893 flag = WFLAGP(wwin, no_language_button);
894 break;
895 #endif
897 WMSetButtonSelected(panel->moreChk[i], flag);
899 if (panel->appFrm && wapp) {
900 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
901 int flag = 0;
903 switch (i) {
904 case 0:
905 flag = WFLAGP(wapp->main_window_desc, start_hidden);
906 break;
907 case 1:
908 flag = WFLAGP(wapp->main_window_desc, no_appicon);
909 break;
910 case 2:
911 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
912 break;
914 WMSetButtonSelected(panel->appChk[i], flag);
917 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
919 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
921 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
923 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
924 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
925 else
926 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
928 /* must auto apply, so that there wno't be internal
929 * inconsistencies between the state in the flags and
930 * the actual state of the window */
931 applySettings(panel->applyBtn, panel);
934 static void chooseIconCallback(WMWidget *self, void *clientData)
936 char *file;
937 InspectorPanel *panel = (InspectorPanel *) clientData;
938 int result;
940 panel->choosingIcon = 1;
942 WMSetButtonEnabled(panel->browseIconBtn, False);
944 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
945 panel->inspected->wm_instance,
946 panel->inspected->wm_class);
948 panel->choosingIcon = 0;
950 if (!panel->destroyed) { /* kluge */
951 if (result) {
952 WMSetTextFieldText(panel->fileText, file);
953 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
954 wfree(file);
956 WMSetButtonEnabled(panel->browseIconBtn, True);
957 } else {
958 freeInspector(panel);
962 static void textEditedObserver(void *observerData, WMNotification *notification)
964 InspectorPanel *panel = (InspectorPanel *) observerData;
966 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
967 return;
969 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
972 static void selectSpecification(WMWidget *bPtr, void *data)
974 InspectorPanel *panel = (InspectorPanel *) data;
975 char *str;
976 WWindow *wwin = panel->inspected;
977 int len;
979 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
980 WMSetButtonEnabled(panel->applyBtn, False);
981 else
982 WMSetButtonEnabled(panel->applyBtn, True);
984 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
985 + strlen(wwin->wm_class ? wwin->wm_class : "?");
987 str = wmalloc(len);
989 snprintf(str, len, _("Inspecting %s.%s"),
990 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
992 wFrameWindowChangeTitle(panel->frame->frame, str);
994 wfree(str);
997 static void selectWindow(WMWidget *bPtr, void *data)
999 InspectorPanel *panel = (InspectorPanel *) data;
1000 WWindow *wwin = panel->inspected;
1001 WScreen *scr = wwin->screen_ptr;
1002 XEvent event;
1003 WWindow *iwin;
1005 if (XGrabPointer(dpy, scr->root_win, True,
1006 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1007 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1008 wwarning("could not grab mouse pointer");
1009 return;
1012 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1013 WMMaskEvent(dpy, ButtonPressMask, &event);
1014 XUngrabPointer(dpy, CurrentTime);
1016 iwin = wWindowFor(event.xbutton.subwindow);
1017 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1018 iwin->flags.inspector_open = 1;
1019 iwin->inspector = createInspectorForWindow(iwin,
1020 panel->frame->frame_x, panel->frame->frame_y, True);
1021 wCloseInspectorForWindow(wwin);
1022 } else {
1023 WMSetLabelText(panel->specLbl, spec_text);
1027 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1029 WScreen *scr = wwin->screen_ptr;
1030 InspectorPanel *panel;
1031 Window parent;
1032 char *str = NULL, *tmp = NULL;
1033 int x, y, btn_width, frame_width;
1034 WMButton *selectedBtn = NULL;
1036 spec_text = _("The configuration will apply to all\n"
1037 "windows that have their WM_CLASS\n"
1038 "property set to the above selected\n" "name, when saved.");
1040 panel = wmalloc(sizeof(InspectorPanel));
1041 memset(panel, 0, sizeof(InspectorPanel));
1043 panel->destroyed = 0;
1044 panel->inspected = wwin;
1045 panel->nextPtr = panelList;
1046 panelList = panel;
1047 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1048 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1050 /**** create common stuff ****/
1051 /* command buttons */
1052 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1053 panel->saveBtn = WMCreateCommandButton(panel->win);
1054 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1055 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1056 WMSetButtonText(panel->saveBtn, _("Save"));
1057 WMResizeWidget(panel->saveBtn, btn_width, 28);
1058 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1059 WMSetButtonEnabled(panel->saveBtn, False);
1061 panel->applyBtn = WMCreateCommandButton(panel->win);
1062 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1063 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1064 WMSetButtonText(panel->applyBtn, _("Apply"));
1065 WMResizeWidget(panel->applyBtn, btn_width, 28);
1067 panel->revertBtn = WMCreateCommandButton(panel->win);
1068 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1069 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1070 WMSetButtonText(panel->revertBtn, _("Reload"));
1071 WMResizeWidget(panel->revertBtn, btn_width, 28);
1073 /* page selection popup button */
1074 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1075 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1076 WMMoveWidget(panel->pagePopUp, 25, 15);
1077 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1079 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1080 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1081 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1082 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1083 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1085 /**** window spec ****/
1086 frame_width = PWIDTH - (2 * 15);
1088 panel->specFrm = WMCreateFrame(panel->win);
1089 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1090 WMMoveWidget(panel->specFrm, 15, 65);
1091 WMResizeWidget(panel->specFrm, frame_width, 145);
1093 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1094 WMMoveWidget(panel->defaultRb, 10, 78);
1095 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1096 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1097 WMSetButtonSelected(panel->defaultRb, False);
1098 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1100 if (wwin->wm_class && wwin->wm_instance) {
1101 tmp = wstrconcat(wwin->wm_instance, ".");
1102 str = wstrconcat(tmp, wwin->wm_class);
1104 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1105 WMMoveWidget(panel->bothRb, 10, 18);
1106 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1107 WMSetButtonText(panel->bothRb, str);
1108 wfree(tmp);
1109 wfree(str);
1110 WMGroupButtons(panel->defaultRb, panel->bothRb);
1112 if (!selectedBtn)
1113 selectedBtn = panel->bothRb;
1115 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1118 if (wwin->wm_instance) {
1119 panel->instRb = WMCreateRadioButton(panel->specFrm);
1120 WMMoveWidget(panel->instRb, 10, 38);
1121 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1122 WMSetButtonText(panel->instRb, wwin->wm_instance);
1123 WMGroupButtons(panel->defaultRb, panel->instRb);
1125 if (!selectedBtn)
1126 selectedBtn = panel->instRb;
1128 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1131 if (wwin->wm_class) {
1132 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1133 WMMoveWidget(panel->clsRb, 10, 58);
1134 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1135 WMSetButtonText(panel->clsRb, wwin->wm_class);
1136 WMGroupButtons(panel->defaultRb, panel->clsRb);
1138 if (!selectedBtn)
1139 selectedBtn = panel->clsRb;
1141 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1144 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1145 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1146 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1147 WMSetButtonText(panel->selWinB, _("Select window"));
1148 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1150 panel->specLbl = WMCreateLabel(panel->win);
1151 WMMoveWidget(panel->specLbl, 15, 210);
1152 WMResizeWidget(panel->specLbl, frame_width, 100);
1153 WMSetLabelText(panel->specLbl, spec_text);
1154 WMSetLabelWraps(panel->specLbl, True);
1156 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1158 /**** attributes ****/
1159 create_tab_window_attributes(wwin, panel, frame_width);
1160 create_tab_window_advanced(wwin, panel, frame_width);
1161 create_tab_icon_workspace(wwin, panel, frame_width);
1162 create_tab_app_specific(wwin, panel, frame_width);
1164 /* if the window is a transient, don't let it have a miniaturize button */
1165 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1166 WMSetButtonEnabled(panel->attrChk[3], False);
1167 else
1168 WMSetButtonEnabled(panel->attrChk[3], True);
1170 if (!wwin->wm_class && !wwin->wm_instance)
1171 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1173 WMRealizeWidget(panel->win);
1175 WMMapSubwidgets(panel->win);
1176 WMMapSubwidgets(panel->specFrm);
1177 WMMapSubwidgets(panel->attrFrm);
1178 WMMapSubwidgets(panel->moreFrm);
1179 WMMapSubwidgets(panel->iconFrm);
1180 WMMapSubwidgets(panel->wsFrm);
1181 if (panel->appFrm)
1182 WMMapSubwidgets(panel->appFrm);
1184 if (showSelectPanel) {
1185 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1186 changePage(panel->pagePopUp, panel);
1187 } else {
1188 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1189 changePage(panel->pagePopUp, panel);
1192 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1193 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1194 panel->parent = parent;
1195 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1197 WMMapWidget(panel->win);
1199 XSetTransientForHint(dpy, parent, wwin->client_win);
1201 if (xpos == UNDEFINED_POS) {
1202 x = wwin->frame_x + wwin->frame->core->width / 2;
1203 y = wwin->frame_y + wwin->frame->top_width * 2;
1204 if (y + PHEIGHT > scr->scr_height)
1205 y = scr->scr_height - PHEIGHT - 30;
1206 if (x + PWIDTH > scr->scr_width)
1207 x = scr->scr_width - PWIDTH;
1208 } else {
1209 x = xpos;
1210 y = ypos;
1213 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1215 if (!selectedBtn)
1216 selectedBtn = panel->defaultRb;
1218 WMSetButtonSelected(selectedBtn, True);
1219 selectSpecification(selectedBtn, panel);
1221 /* kluge to know who should get the key events */
1222 panel->frame->client_leader = WMWidgetXID(panel->win);
1224 WSETUFLAG(panel->frame, no_closable, 0);
1225 WSETUFLAG(panel->frame, no_close_button, 0);
1226 wWindowUpdateButtonImages(panel->frame);
1227 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1228 panel->frame->frame->on_click_right = destroyInspector;
1230 wWindowMap(panel->frame);
1232 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1234 return panel;
1237 void wShowInspectorForWindow(WWindow *wwin)
1239 if (wwin->flags.inspector_open)
1240 return;
1242 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1244 make_keys();
1245 wwin->flags.inspector_open = 1;
1246 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1249 void wHideInspectorForWindow(WWindow *wwin)
1251 WWindow *pwin = wwin->inspector->frame;
1253 wWindowUnmap(pwin);
1254 pwin->flags.hidden = 1;
1256 wClientSetState(pwin, IconicState, None);
1259 void wUnhideInspectorForWindow(WWindow *wwin)
1261 WWindow *pwin = wwin->inspector->frame;
1263 pwin->flags.hidden = 0;
1264 pwin->flags.mapped = 1;
1265 XMapWindow(dpy, pwin->client_win);
1266 XMapWindow(dpy, pwin->frame->core->window);
1267 wClientSetState(pwin, NormalState, None);
1270 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1272 if (!wwin->inspector)
1273 return NULL;
1275 assert(wwin->flags.inspector_open != 0);
1276 return wwin->inspector->frame;
1279 void wCloseInspectorForWindow(WWindow *wwin)
1281 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1283 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1286 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1288 int i = 0;
1289 char *caption = NULL, *descr = NULL;
1290 int flag = 0;
1292 panel->attrFrm = WMCreateFrame(panel->win);
1293 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1294 WMMoveWidget(panel->attrFrm, 15, 45);
1295 WMResizeWidget(panel->attrFrm, frame_width, 250);
1297 for (i = 0; i < (sizeof(panel->attrChk) / sizeof(panel->attrChk[0])); i++) {
1298 switch (i) {
1299 case 0:
1300 caption = _("Disable titlebar");
1301 flag = WFLAGP(wwin, no_titlebar);
1302 descr = _("Remove the titlebar of this window.\n"
1303 "To access the window commands menu of a window\n"
1304 "without it's titlebar, press Control+Esc (or the\n"
1305 "equivalent shortcut, if you changed the default\n" "settings).");
1306 break;
1307 case 1:
1308 caption = _("Disable resizebar");
1309 flag = WFLAGP(wwin, no_resizebar);
1310 descr = _("Remove the resizebar of this window.");
1311 break;
1312 case 2:
1313 caption = _("Disable close button");
1314 flag = WFLAGP(wwin, no_close_button);
1315 descr = _("Remove the `close window' button of this window.");
1316 break;
1317 case 3:
1318 caption = _("Disable miniaturize button");
1319 flag = WFLAGP(wwin, no_miniaturize_button);
1320 descr = _("Remove the `miniaturize window' button of the window.");
1321 break;
1322 case 4:
1323 caption = _("Disable border");
1324 flag = WFLAGP(wwin, no_border);
1325 descr = _("Remove the 1 pixel black border around the window.");
1326 break;
1327 case 5:
1328 caption = _("Keep on top (floating)");
1329 flag = WFLAGP(wwin, floating);
1330 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1331 break;
1332 case 6:
1333 caption = _("Keep at bottom (sunken)");
1334 flag = WFLAGP(wwin, sunken);
1335 descr = _("Keep the window under all other windows.");
1336 break;
1337 case 7:
1338 caption = _("Omnipresent");
1339 flag = WFLAGP(wwin, omnipresent);
1340 descr = _("Make window present in all workspaces.");
1341 break;
1342 case 8:
1343 caption = _("Start miniaturized");
1344 flag = WFLAGP(wwin, start_miniaturized);
1345 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1346 break;
1347 case 9:
1348 caption = _("Start maximized");
1349 flag = WFLAGP(wwin, start_maximized != 0);
1350 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1351 break;
1352 case 10:
1353 caption = _("Full screen maximization");
1354 flag = WFLAGP(wwin, full_maximize);
1355 descr = _("Make the window use the whole screen space when it's\n"
1356 "maximized. The titlebar and resizebar will be moved\n"
1357 "to outside the screen.");
1358 break;
1360 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1361 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1362 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1363 WMSetButtonSelected(panel->attrChk[i], flag);
1364 WMSetButtonText(panel->attrChk[i], caption);
1366 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1370 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1372 int i = 0;
1373 char *caption = NULL, *descr = NULL;
1374 int flag = 0;
1376 panel->moreFrm = WMCreateFrame(panel->win);
1377 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1378 WMMoveWidget(panel->moreFrm, 15, 45);
1379 WMResizeWidget(panel->moreFrm, frame_width, 265);
1381 for (i = 0; i < (sizeof(panel->moreChk) / sizeof(panel->moreChk[0])); i++) {
1382 switch (i) {
1383 case 0:
1384 caption = _("Do not bind keyboard shortcuts");
1385 flag = WFLAGP(wwin, no_bind_keys);
1386 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1387 "when this window is focused. This will allow the\n"
1388 "window to receive all key combinations regardless\n"
1389 "of your shortcut configuration.");
1390 break;
1391 case 1:
1392 caption = _("Do not bind mouse clicks");
1393 flag = WFLAGP(wwin, no_bind_mouse);
1394 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1395 "in the window (when alt is the modifier you have\n" "configured).");
1396 break;
1397 case 2:
1398 caption = _("Do not show in the window list");
1399 flag = WFLAGP(wwin, skip_window_list);
1400 descr = _("Do not list the window in the window list menu.");
1401 break;
1402 case 3:
1403 caption = _("Do not show in the switch panel");
1404 flag = WFLAGP(wwin, skip_switchpanel);
1405 descr = _("Do not include in switchpanel while alternating windows.");
1406 break;
1407 case 4:
1408 caption = _("Do not let it take focus");
1409 flag = WFLAGP(wwin, no_focusable);
1410 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1411 break;
1412 case 5:
1413 caption = _("Keep inside screen");
1414 flag = WFLAGP(wwin, dont_move_off);
1415 descr = _("Do not allow the window to move itself completely\n"
1416 "outside the screen. For bug compatibility.\n");
1417 break;
1418 case 6:
1419 caption = _("Ignore 'Hide Others'");
1420 flag = WFLAGP(wwin, no_hide_others);
1421 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1422 break;
1423 case 7:
1424 caption = _("Ignore 'Save Session'");
1425 flag = WFLAGP(wwin, dont_save_session);
1426 descr = _("Do not save the associated application in the\n"
1427 "session's state, so that it won't be restarted\n"
1428 "together with other applications when Window Maker\n" "starts.");
1429 break;
1430 case 8:
1431 caption = _("Emulate application icon");
1432 flag = WFLAGP(wwin, emulate_appicon);
1433 descr = _("Make this window act as an application that provides\n"
1434 "enough information to Window Maker for a dockable\n"
1435 "application icon to be created.");
1436 break;
1437 case 9:
1438 caption = _("Focus across workspaces");
1439 flag = WFLAGP(wwin, focus_across_wksp);
1440 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1441 "a focus request (annoying).");
1442 break;
1443 case 10:
1444 caption = _("Do not let it be minimized");
1445 flag = WFLAGP(wwin, no_miniaturizable);
1446 descr = _("Do not let the window of this application be\n"
1447 "minimized.\n");
1448 break;
1449 #ifdef XKB_BUTTON_HINT
1450 case 11:
1451 caption = _("Disable language button");
1452 flag = WFLAGP(wwin, no_language_button);
1453 descr = _("Remove the `toggle language' button of the window.");
1454 break;
1455 #endif
1457 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1458 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1459 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1460 WMSetButtonSelected(panel->moreChk[i], flag);
1461 WMSetButtonText(panel->moreChk[i], caption);
1463 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1467 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel, int frame_width)
1469 WScreen *scr = wwin->screen_ptr;
1470 int i = 0;
1472 /* miniwindow/workspace */
1473 panel->iconFrm = WMCreateFrame(panel->win);
1474 WMMoveWidget(panel->iconFrm, 15, 50);
1475 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1476 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1478 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1479 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1480 WMResizeWidget(panel->iconLbl, 64, 64);
1481 WMSetLabelRelief(panel->iconLbl, WRGroove);
1482 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1484 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1485 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1486 WMMoveWidget(panel->browseIconBtn, 22, 32);
1487 WMResizeWidget(panel->browseIconBtn, 120, 26);
1488 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1490 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1491 WMMoveWidget(panel->fileLbl, 20, 85);
1492 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1493 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1495 panel->fileText = WMCreateTextField(panel->iconFrm);
1496 WMMoveWidget(panel->fileText, 20, 105);
1497 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1498 WMSetTextFieldText(panel->fileText, NULL);
1499 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1501 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1502 WMMoveWidget(panel->alwChk, 20, 130);
1503 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1504 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1505 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1507 panel->wsFrm = WMCreateFrame(panel->win);
1508 WMMoveWidget(panel->wsFrm, 15, 225);
1509 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1510 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1512 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1513 "first shown."), WMWidgetView(panel->wsFrm));
1515 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1516 WMMoveWidget(panel->wsP, 20, 30);
1517 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1518 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1520 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1521 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1523 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1524 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1525 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1526 else
1527 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1530 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1532 WScreen *scr = wwin->screen_ptr;
1533 int i = 0, flag = 0, tmp;
1534 char *caption = NULL, *descr = NULL;
1537 if (wwin->main_window != None) {
1538 WApplication *wapp = wApplicationOf(wwin->main_window);
1540 panel->appFrm = WMCreateFrame(panel->win);
1541 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1542 WMMoveWidget(panel->appFrm, 15, 50);
1543 WMResizeWidget(panel->appFrm, frame_width, 240);
1545 for (i = 0; i < (sizeof(panel->appChk) / sizeof(panel->appChk[0])); i++) {
1546 switch (i) {
1547 case 0:
1548 caption = _("Start hidden");
1549 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1550 descr = _("Automatically hide application when it's started.");
1551 break;
1552 case 1:
1553 caption = _("No application icon");
1554 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1555 descr = _("Disable the application icon for the application.\n"
1556 "Note that you won't be able to dock it anymore,\n"
1557 "and any icons that are already docked will stop\n"
1558 "working correctly.");
1559 break;
1560 case 2:
1561 caption = _("Shared application icon");
1562 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1563 descr = _("Use a single shared application icon for all of\n"
1564 "the instances of this application.\n");
1565 break;
1567 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1568 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1569 WMResizeWidget(panel->appChk[i], 205, 20);
1570 WMSetButtonSelected(panel->appChk[i], flag);
1571 WMSetButtonText(panel->appChk[i], caption);
1572 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1575 if (WFLAGP(wwin, emulate_appicon)) {
1576 WMSetButtonEnabled(panel->appChk[1], False);
1577 WMSetButtonEnabled(panel->moreChk[7], True);
1578 } else {
1579 WMSetButtonEnabled(panel->appChk[1], True);
1580 WMSetButtonEnabled(panel->moreChk[7], False);
1582 } else {
1583 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1584 || !wwin->wm_class || !wwin->wm_instance)
1585 tmp = False;
1586 else
1587 tmp = True;
1589 WMSetButtonEnabled(panel->moreChk[7], tmp);
1591 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1592 panel->appFrm = NULL;