WPrefs: add new mouse actions configuration
[wmaker-crm.git] / src / winspector.c
blob641c7f69fe1dc8f61192e297fc5657e3e6521596
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 static InspectorPanel *panelList = NULL;
118 static WMPropList *ANoTitlebar = NULL;
119 static WMPropList *ANoResizebar;
120 static WMPropList *ANoMiniaturizeButton;
121 static WMPropList *ANoCloseButton;
122 static WMPropList *ANoBorder;
123 static WMPropList *ANoHideOthers;
124 static WMPropList *ANoMouseBindings;
125 static WMPropList *ANoKeyBindings;
126 static WMPropList *ANoAppIcon;
127 static WMPropList *AKeepOnTop;
128 static WMPropList *AKeepOnBottom;
129 static WMPropList *AOmnipresent;
130 static WMPropList *ASkipWindowList;
131 static WMPropList *ASkipSwitchPanel;
132 static WMPropList *AKeepInsideScreen;
133 static WMPropList *AUnfocusable;
134 static WMPropList *AFocusAcrossWorkspace;
135 static WMPropList *AAlwaysUserIcon;
136 static WMPropList *AStartMiniaturized;
137 static WMPropList *AStartMaximized;
138 static WMPropList *ADontSaveSession;
139 static WMPropList *AEmulateAppIcon;
140 static WMPropList *AFullMaximize;
141 static WMPropList *ASharedAppIcon;
142 static WMPropList *ANoMiniaturizable;
143 #ifdef XKB_BUTTON_HINT
144 static WMPropList *ANoLanguageButton;
145 #endif
146 static WMPropList *AStartWorkspace;
147 static WMPropList *AIcon;
149 /* application wide options */
150 static WMPropList *AStartHidden;
151 static WMPropList *AnyWindow;
152 static WMPropList *EmptyString;
153 static WMPropList *Yes, *No;
155 static char *spec_text;
156 static void applySettings(WMWidget *button, void *panel);
158 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
160 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
161 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
162 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel);
163 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
165 static void make_keys(void)
167 if (ANoTitlebar != NULL)
168 return;
170 AIcon = WMCreatePLString("Icon");
171 ANoTitlebar = WMCreatePLString("NoTitlebar");
172 ANoResizebar = WMCreatePLString("NoResizebar");
173 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
174 ANoCloseButton = WMCreatePLString("NoCloseButton");
175 ANoBorder = WMCreatePLString("NoBorder");
176 ANoHideOthers = WMCreatePLString("NoHideOthers");
177 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
178 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
179 ANoAppIcon = WMCreatePLString("NoAppIcon");
180 AKeepOnTop = WMCreatePLString("KeepOnTop");
181 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
182 AOmnipresent = WMCreatePLString("Omnipresent");
183 ASkipWindowList = WMCreatePLString("SkipWindowList");
184 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
185 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
186 AUnfocusable = WMCreatePLString("Unfocusable");
187 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
188 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
189 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
190 AStartMaximized = WMCreatePLString("StartMaximized");
191 AStartHidden = WMCreatePLString("StartHidden");
192 ADontSaveSession = WMCreatePLString("DontSaveSession");
193 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
194 AFullMaximize = WMCreatePLString("FullMaximize");
195 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
196 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
197 #ifdef XKB_BUTTON_HINT
198 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
199 #endif
201 AStartWorkspace = WMCreatePLString("StartWorkspace");
203 AnyWindow = WMCreatePLString("*");
204 EmptyString = WMCreatePLString("");
205 Yes = WMCreatePLString("Yes");
206 No = WMCreatePLString("No");
209 static void freeInspector(InspectorPanel *panel)
211 panel->destroyed = 1;
213 if (panel->choosingIcon)
214 return;
216 WMDestroyWidget(panel->win);
217 XDestroyWindow(dpy, panel->parent);
218 wfree(panel);
221 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
223 InspectorPanel *panel, *tmp;
225 /* Parameter not used, but tell the compiler that it is ok */
226 (void) foo;
227 (void) event;
229 panel = panelList;
230 while (panel->frame != data)
231 panel = panel->nextPtr;
233 if (panelList == panel) {
234 panelList = panel->nextPtr;
235 } else {
236 tmp = panelList;
237 while (tmp->nextPtr != panel)
238 tmp = tmp->nextPtr;
240 tmp->nextPtr = panel->nextPtr;
242 panel->inspected->flags.inspector_open = 0;
243 panel->inspected->inspector = NULL;
245 WMRemoveNotificationObserver(panel);
247 wWindowUnmap(panel->frame);
248 wUnmanageWindow(panel->frame, True, False);
250 freeInspector(panel);
253 void wDestroyInspectorPanels(void)
255 InspectorPanel *panel;
257 while (panelList != NULL) {
258 panel = panelList;
259 panelList = panelList->nextPtr;
260 wUnmanageWindow(panel->frame, False, False);
261 WMDestroyWidget(panel->win);
263 panel->inspected->flags.inspector_open = 0;
264 panel->inspected->inspector = NULL;
266 wfree(panel);
270 static void changePage(WMWidget *bPtr, void *client_data)
272 InspectorPanel *panel = (InspectorPanel *) client_data;
273 int page;
275 page = WMGetPopUpButtonSelectedItem(bPtr);
277 if (page == 0) {
278 WMMapWidget(panel->specFrm);
279 WMMapWidget(panel->specLbl);
280 } else if (page == 1) {
281 WMMapWidget(panel->attrFrm);
282 } else if (page == 2) {
283 WMMapWidget(panel->moreFrm);
284 } else if (page == 3) {
285 WMMapWidget(panel->iconFrm);
286 WMMapWidget(panel->wsFrm);
287 } else {
288 WMMapWidget(panel->appFrm);
291 if (page != 0) {
292 WMUnmapWidget(panel->specFrm);
293 WMUnmapWidget(panel->specLbl);
295 if (page != 1)
296 WMUnmapWidget(panel->attrFrm);
297 if (page != 2)
298 WMUnmapWidget(panel->moreFrm);
299 if (page != 3) {
300 WMUnmapWidget(panel->iconFrm);
301 WMUnmapWidget(panel->wsFrm);
303 if (page != 4 && panel->appFrm)
304 WMUnmapWidget(panel->appFrm);
307 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, const char *wm_instance, const char *wm_class, int flags)
309 WMPixmap *pixmap = (WMPixmap *) NULL;
310 char *file = NULL, *path = NULL;
312 if ((flags & USE_TEXT_FIELD) != 0) {
313 file = WMGetTextFieldText(panel->fileText);
314 if (file && file[0] == 0) {
315 wfree(file);
316 file = NULL;
318 } else if (flags & REVERT_TO_DEFAULT) {
319 const char *db_icon;
321 /* Get the application icon, default NOT included */
322 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
323 if (db_icon != NULL) {
324 file = wstrdup(db_icon);
325 flags |= UPDATE_TEXT_FIELD;
329 if ((flags & UPDATE_TEXT_FIELD) != 0)
330 WMSetTextFieldText(panel->fileText, file);
332 if (file) {
333 path = FindImage(wPreferences.icon_path, file);
335 if (!path) {
336 char *buf;
337 int len = strlen(file) + 80;
339 buf = wmalloc(len);
340 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
341 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
342 wfree(buf);
343 wfree(file);
344 return -1;
347 pixmap = WMCreatePixmapFromFile(scrPtr, path);
348 wfree(path);
350 if (!pixmap) {
351 char *buf;
352 int len = strlen(file) + 80;
354 buf = wmalloc(len);
355 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
356 file, RMessageForError(RErrorCode));
357 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
358 wfree(buf);
359 wfree(file);
360 return -1;
362 wfree(file);
365 WMSetLabelImage(panel->iconLbl, pixmap);
366 if (pixmap)
367 WMReleasePixmap(pixmap);
369 return 0;
372 static int getBool(WMPropList *value)
374 char *val;
376 if (!WMIsPLString(value))
377 return 0;
379 if (!(val = WMGetFromPLString(value)))
380 return 0;
382 if ((val[1] == '\0' &&
383 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
384 val[0] == 't' || val[0] == '1')) ||
385 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
386 return 1;
387 } else if ((val[1] == '\0' &&
388 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
389 val[0] == 'f' || val[0] == '0')) ||
390 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
391 return 0;
392 } else {
393 wwarning(_("can't convert \"%s\" to boolean"), val);
394 return 0;
398 /* Will insert the attribute = value; pair in window's list,
399 * if it's different from the defaults.
400 * Defaults means either defaults database, or attributes saved
401 * for the default window "*". This is to let one revert options that are
402 * global because they were saved for all windows ("*"). */
403 static int
404 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
406 WMPropList *def_win, *def_value = NULL;
407 int update = 0, modified = 0;
409 if (!(flags & UPDATE_DEFAULTS) && dict) {
410 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL)
411 def_value = WMGetFromPLDictionary(def_win, attr);
414 /* If we could not find defaults in database, fall to hardcoded values.
415 * Also this is true if we save defaults for all windows */
416 if (!def_value)
417 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
419 if (flags & IS_BOOLEAN)
420 update = (getBool(value) != getBool(def_value));
421 else
422 update = !WMIsPropListEqualTo(value, def_value);
424 if (update) {
425 WMPutInPLDictionary(window, attr, value);
426 modified = 1;
429 return modified;
432 static void saveSettings(WMWidget *button, void *client_data)
434 InspectorPanel *panel = (InspectorPanel *) client_data;
435 WWindow *wwin = panel->inspected;
436 WDDomain *db = w_global.domain.window_attr;
437 WMPropList *dict = NULL;
438 WMPropList *winDic, *appDic, *value, *value1, *key = NULL, *key2;
439 char *icon_file, *buf1, *buf2;
440 int flags = 0, i = 0, different = 0, different2 = 0;
442 /* Save will apply the changes and save them */
443 applySettings(panel->applyBtn, panel);
445 if (WMGetButtonSelected(panel->instRb) != 0) {
446 key = WMCreatePLString(wwin->wm_instance);
447 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
448 key = WMCreatePLString(wwin->wm_class);
449 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
450 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
451 key = WMCreatePLString(buf1);
452 wfree(buf1);
453 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
454 key = WMRetainPropList(AnyWindow);
455 flags = UPDATE_DEFAULTS;
458 if (!key)
459 return;
461 dict = db->dictionary;
462 if (!dict) {
463 dict = WMCreatePLDictionary(NULL, NULL);
464 if (dict) {
465 db->dictionary = dict;
466 } else {
467 WMReleasePropList(key);
468 return;
472 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
473 return;
475 WMPLSetCaseSensitive(True);
477 winDic = WMCreatePLDictionary(NULL, NULL);
478 appDic = WMCreatePLDictionary(NULL, NULL);
480 /* Save the icon info */
481 /* The flag "Ignore client suplied icon is not selected" */
482 buf1 = wmalloc(4);
483 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
484 value1 = WMCreatePLString(buf1);
485 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
486 WMReleasePropList(value1);
487 wfree(buf1);
489 /* The icon filename (if exists) */
490 icon_file = WMGetTextFieldText(panel->fileText);
491 if (icon_file != NULL) {
492 if (icon_file[0] != '\0') {
493 value = WMCreatePLString(icon_file);
494 different |= insertAttribute(dict, winDic, AIcon, value, flags);
495 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
496 WMReleasePropList(value);
498 wfree(icon_file);
501 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
502 if (i >= 0 && i < w_global.workspace.count) {
503 value = WMCreatePLString(w_global.workspace.array[i]->name);
504 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
505 WMReleasePropList(value);
508 flags |= IS_BOOLEAN;
510 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
511 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
513 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
514 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
516 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
517 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
519 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
520 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
522 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
523 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
525 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
526 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
528 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
529 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
531 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
532 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
534 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
535 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
537 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
538 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
540 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
541 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
543 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
544 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
546 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
547 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
549 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
550 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
552 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
553 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
555 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
556 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
558 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
559 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
561 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
562 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
564 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
565 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
567 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
568 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
570 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
571 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
573 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
574 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
576 #ifdef XKB_BUTTON_HINT
577 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
578 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
579 #endif
581 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
582 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
583 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
585 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
586 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
588 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
589 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
592 if (wwin->fake_group) {
593 key2 = WMCreatePLString(wwin->fake_group->identifier);
594 if (WMIsPropListEqualTo(key, key2)) {
595 WMMergePLDictionaries(winDic, appDic, True);
596 different |= different2;
597 } else {
598 WMRemoveFromPLDictionary(dict, key2);
599 if (different2)
600 WMPutInPLDictionary(dict, key2, appDic);
602 WMReleasePropList(key2);
603 } else if (wwin->main_window != wwin->client_win) {
604 WApplication *wapp = wApplicationOf(wwin->main_window);
606 if (wapp) {
607 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
608 wapp->main_window_desc->wm_class);
609 key2 = WMCreatePLString(buf2);
610 wfree(buf2);
612 if (WMIsPropListEqualTo(key, key2)) {
613 WMMergePLDictionaries(winDic, appDic, True);
614 different |= different2;
615 } else {
616 WMRemoveFromPLDictionary(dict, key2);
617 if (different2)
618 WMPutInPLDictionary(dict, key2, appDic);
620 WMReleasePropList(key2);
622 } else {
623 WMMergePLDictionaries(winDic, appDic, True);
624 different |= different2;
626 WMReleasePropList(appDic);
628 WMRemoveFromPLDictionary(dict, key);
629 if (different)
630 WMPutInPLDictionary(dict, key, winDic);
632 WMReleasePropList(key);
633 WMReleasePropList(winDic);
635 UpdateDomainFile(db);
637 /* clean up */
638 WMPLSetCaseSensitive(False);
641 static void applySettings(WMWidget *button, void *client_data)
643 InspectorPanel *panel = (InspectorPanel *) client_data;
644 WWindow *wwin = panel->inspected;
645 WApplication *wapp = wApplicationOf(wwin->main_window);
646 int floating, sunken, skip_window_list;
647 int old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
649 old_omnipresent = WFLAGP(wwin, omnipresent);
650 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
651 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
653 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
655 /* Attributes... --> Window Attributes */
656 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
657 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
658 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
659 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
660 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
661 floating = WMGetButtonSelected(panel->attrChk[5]);
662 sunken = WMGetButtonSelected(panel->attrChk[6]);
663 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
664 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
665 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
666 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
668 /* Attributes... --> Advanced Options */
669 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
670 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
671 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
672 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
673 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
674 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
675 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
676 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
677 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
678 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
679 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
680 #ifdef XKB_BUTTON_HINT
681 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
682 #endif
683 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
685 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
686 wUnshadeWindow(wwin);
688 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
690 if (floating) {
691 if (!WFLAGP(wwin, floating))
692 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
693 } else if (sunken) {
694 if (!WFLAGP(wwin, sunken))
695 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
696 } else {
697 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
698 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
701 WSETUFLAG(wwin, sunken, sunken);
702 WSETUFLAG(wwin, floating, floating);
703 wwin->flags.omnipresent = 0;
705 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
706 WSETUFLAG(wwin, skip_window_list, skip_window_list);
707 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
708 } else {
709 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
710 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
713 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
714 if (WFLAGP(wwin, no_bind_keys))
715 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
716 else
717 wWindowSetKeyGrabs(wwin);
720 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
721 wWindowResetMouseGrabs(wwin);
723 wwin->frame->flags.need_texture_change = 1;
724 wWindowConfigureBorders(wwin);
725 wFrameWindowPaint(wwin->frame);
726 wNETWMUpdateActions(wwin, False);
728 /* Can't apply emulate_appicon because it will probably cause problems. */
729 if (wapp) {
730 /* do application wide stuff */
731 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
732 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
733 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
735 if (WFLAGP(wapp->main_window_desc, no_appicon))
736 unpaint_app_icon(wapp);
737 else
738 paint_app_icon(wapp);
740 char *file = WMGetTextFieldText(panel->fileText);
741 if (file[0] == 0) {
742 wfree(file);
743 file = NULL;
746 /* If always_user_icon flag is set, but the user icon is not set
747 * we use client supplied icon and we unset the flag */
748 if ((WFLAGP(wwin, always_user_icon) && (!file))) {
749 /* Show the warning */
750 char *buf;
751 int len = 100;
753 buf = wmalloc(len);
754 snprintf(buf, len, _("Ignore client supplied icon is set, but icon filename textbox is empty. Using client supplied icon"));
755 wMessageDialog(panel->frame->screen_ptr, _("Warning"), buf, _("OK"), NULL, NULL);
756 wfree(buf);
757 wfree(file);
759 /* Change the flags */
760 WSETUFLAG(wwin, always_user_icon, 0);
761 WMSetButtonSelected(panel->alwChk, 0);
764 /* After test the always_user_icon flag value before,
765 * the "else" block is used only if the flag is set and
766 * the icon text box has an icon path */
767 if (!WFLAGP(wwin, always_user_icon)) {
768 /* Change App Icon image, using the icon provided by the client */
769 if (wapp->app_icon) {
770 RImage *image = get_rimage_icon_from_wm_hints(wapp->app_icon->icon);
771 if (image) {
772 set_icon_image_from_image(wapp->app_icon->icon, image);
773 update_icon_pixmap(wapp->app_icon->icon);
774 } else {
775 wIconUpdate(wapp->app_icon->icon);
779 /* Change icon image if the app is minimized,
780 * using the icon provided by the client */
781 if (wwin->icon) {
782 RImage *image = get_rimage_icon_from_wm_hints(wwin->icon);
783 if (image) {
784 set_icon_image_from_image(wwin->icon, image);
785 update_icon_pixmap(wwin->icon);
786 } else {
787 wIconUpdate(wwin->icon);
790 } else {
791 /* Change App Icon image */
792 if (wapp->app_icon)
793 wIconChangeImageFile(wapp->app_icon->icon, file);
795 /* Change icon image if the app is minimized */
796 if (wwin->icon)
797 wIconChangeImageFile(wwin->icon, file);
800 if (file)
801 wfree(file);
804 wNETFrameExtents(wwin);
807 static void revertSettings(WMWidget *button, void *client_data)
809 InspectorPanel *panel = (InspectorPanel *) client_data;
810 WWindow *wwin = panel->inspected;
811 WApplication *wapp = wApplicationOf(wwin->main_window);
812 int i, n, workspace, level;
813 char *wm_instance = NULL, *wm_class = NULL;
815 /* Parameter not used, but tell the compiler that it is ok */
816 (void) button;
818 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
819 wm_instance = wwin->wm_instance;
820 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
821 wm_class = wwin->wm_class;
822 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
823 wm_instance = wwin->wm_instance;
824 wm_class = wwin->wm_class;
827 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
828 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
829 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
831 wWindowSetupInitialAttributes(wwin, &level, &workspace);
833 for (i = 0; i < wlengthof(panel->attrChk); i++) {
834 int flag = 0;
836 switch (i) {
837 case 0:
838 flag = WFLAGP(wwin, no_titlebar);
839 break;
840 case 1:
841 flag = WFLAGP(wwin, no_resizebar);
842 break;
843 case 2:
844 flag = WFLAGP(wwin, no_close_button);
845 break;
846 case 3:
847 flag = WFLAGP(wwin, no_miniaturize_button);
848 break;
849 case 4:
850 flag = WFLAGP(wwin, no_border);
851 break;
852 case 5:
853 flag = WFLAGP(wwin, floating);
854 break;
855 case 6:
856 flag = WFLAGP(wwin, sunken);
857 break;
858 case 7:
859 flag = WFLAGP(wwin, omnipresent);
860 break;
861 case 8:
862 flag = WFLAGP(wwin, start_miniaturized);
863 break;
864 case 9:
865 flag = WFLAGP(wwin, start_maximized != 0);
866 break;
867 case 10:
868 flag = WFLAGP(wwin, full_maximize);
869 break;
871 WMSetButtonSelected(panel->attrChk[i], flag);
874 for (i = 0; i < wlengthof(panel->moreChk); i++) {
875 int flag = 0;
877 switch (i) {
878 case 0:
879 flag = WFLAGP(wwin, no_bind_keys);
880 break;
881 case 1:
882 flag = WFLAGP(wwin, no_bind_mouse);
883 break;
884 case 2:
885 flag = WFLAGP(wwin, skip_window_list);
886 break;
887 case 3:
888 flag = WFLAGP(wwin, skip_switchpanel);
889 break;
890 case 4:
891 flag = WFLAGP(wwin, no_focusable);
892 break;
893 case 5:
894 flag = WFLAGP(wwin, dont_move_off);
895 break;
896 case 6:
897 flag = WFLAGP(wwin, no_hide_others);
898 break;
899 case 7:
900 flag = WFLAGP(wwin, dont_save_session);
901 break;
902 case 8:
903 flag = WFLAGP(wwin, emulate_appicon);
904 break;
905 case 9:
906 flag = WFLAGP(wwin, focus_across_wksp);
907 break;
908 case 10:
909 flag = WFLAGP(wwin, no_miniaturizable);
910 break;
911 #ifdef XKB_BUTTON_HINT
912 case 11:
913 flag = WFLAGP(wwin, no_language_button);
914 break;
915 #endif
917 WMSetButtonSelected(panel->moreChk[i], flag);
919 if (panel->appFrm && wapp) {
920 for (i = 0; i < wlengthof(panel->appChk); i++) {
921 int flag = 0;
923 switch (i) {
924 case 0:
925 flag = WFLAGP(wapp->main_window_desc, start_hidden);
926 break;
927 case 1:
928 flag = WFLAGP(wapp->main_window_desc, no_appicon);
929 break;
930 case 2:
931 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
932 break;
934 WMSetButtonSelected(panel->appChk[i], flag);
937 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
939 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
941 n = wDefaultGetStartWorkspace(wm_instance, wm_class);
943 if (n >= 0 && n < w_global.workspace.count)
944 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
945 else
946 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
948 /* must auto apply, so that there wno't be internal
949 * inconsistencies between the state in the flags and
950 * the actual state of the window */
951 applySettings(panel->applyBtn, panel);
954 static void chooseIconCallback(WMWidget *self, void *clientData)
956 char *file;
957 InspectorPanel *panel = (InspectorPanel *) clientData;
958 int result;
960 panel->choosingIcon = 1;
962 WMSetButtonEnabled(panel->browseIconBtn, False);
964 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
965 panel->inspected->wm_instance,
966 panel->inspected->wm_class);
968 panel->choosingIcon = 0;
970 if (!panel->destroyed) { /* kluge */
971 if (result) {
972 WMSetTextFieldText(panel->fileText, file);
973 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
975 WMSetButtonEnabled(panel->browseIconBtn, True);
976 } else {
977 freeInspector(panel);
979 if (result)
980 wfree(file);
983 static void textEditedObserver(void *observerData, WMNotification *notification)
985 InspectorPanel *panel = (InspectorPanel *) observerData;
987 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
988 return;
990 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
993 static void selectSpecification(WMWidget *bPtr, void *data)
995 InspectorPanel *panel = (InspectorPanel *) data;
996 char str[256];
997 WWindow *wwin = panel->inspected;
999 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
1000 WMSetButtonEnabled(panel->applyBtn, False);
1001 else
1002 WMSetButtonEnabled(panel->applyBtn, True);
1004 snprintf(str, sizeof(str),
1005 _("Inspecting %s.%s"),
1006 wwin->wm_instance ? wwin->wm_instance : "?",
1007 wwin->wm_class ? wwin->wm_class : "?");
1009 wFrameWindowChangeTitle(panel->frame->frame, str);
1012 static void selectWindow(WMWidget *bPtr, void *data)
1014 InspectorPanel *panel = (InspectorPanel *) data;
1015 WWindow *wwin = panel->inspected;
1016 WScreen *scr = wwin->screen_ptr;
1017 XEvent event;
1018 WWindow *iwin;
1020 /* Parameter not used, but tell the compiler that it is ok */
1021 (void) bPtr;
1023 if (XGrabPointer(dpy, scr->root_win, True,
1024 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1025 wPreferences.cursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1026 wwarning("could not grab mouse pointer");
1027 return;
1030 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1031 WMMaskEvent(dpy, ButtonPressMask, &event);
1032 XUngrabPointer(dpy, CurrentTime);
1034 iwin = wWindowFor(event.xbutton.subwindow);
1035 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1036 iwin->flags.inspector_open = 1;
1037 iwin->inspector = createInspectorForWindow(iwin,
1038 panel->frame->frame_x, panel->frame->frame_y, True);
1039 wCloseInspectorForWindow(wwin);
1040 } else {
1041 WMSetLabelText(panel->specLbl, spec_text);
1045 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1047 WScreen *scr = wwin->screen_ptr;
1048 InspectorPanel *panel;
1049 Window parent;
1050 char *str = NULL, *tmp = NULL;
1051 int x, y, btn_width, frame_width;
1052 WMButton *selectedBtn = NULL;
1054 spec_text = _("The configuration will apply to all\n"
1055 "windows that have their WM_CLASS\n"
1056 "property set to the above selected\n" "name, when saved.");
1058 panel = wmalloc(sizeof(InspectorPanel));
1059 memset(panel, 0, sizeof(InspectorPanel));
1061 panel->destroyed = 0;
1062 panel->inspected = wwin;
1063 panel->nextPtr = panelList;
1064 panelList = panel;
1065 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1066 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1068 /**** create common stuff ****/
1069 /* command buttons */
1070 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1071 panel->saveBtn = WMCreateCommandButton(panel->win);
1072 WMSetButtonAction(panel->saveBtn, saveSettings, panel);
1073 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1074 WMSetButtonText(panel->saveBtn, _("Save"));
1075 WMResizeWidget(panel->saveBtn, btn_width, 28);
1076 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1077 WMSetButtonEnabled(panel->saveBtn, False);
1079 panel->applyBtn = WMCreateCommandButton(panel->win);
1080 WMSetButtonAction(panel->applyBtn, applySettings, panel);
1081 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1082 WMSetButtonText(panel->applyBtn, _("Apply"));
1083 WMResizeWidget(panel->applyBtn, btn_width, 28);
1085 panel->revertBtn = WMCreateCommandButton(panel->win);
1086 WMSetButtonAction(panel->revertBtn, revertSettings, panel);
1087 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1088 WMSetButtonText(panel->revertBtn, _("Reload"));
1089 WMResizeWidget(panel->revertBtn, btn_width, 28);
1091 /* page selection popup button */
1092 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1093 WMSetPopUpButtonAction(panel->pagePopUp, changePage, panel);
1094 WMMoveWidget(panel->pagePopUp, 25, 15);
1095 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1097 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1098 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1099 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1100 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1101 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1103 /**** window spec ****/
1104 frame_width = PWIDTH - (2 * 15);
1106 panel->specFrm = WMCreateFrame(panel->win);
1107 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1108 WMMoveWidget(panel->specFrm, 15, 65);
1109 WMResizeWidget(panel->specFrm, frame_width, 145);
1111 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1112 WMMoveWidget(panel->defaultRb, 10, 78);
1113 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1114 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1115 WMSetButtonSelected(panel->defaultRb, False);
1116 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1118 if (wwin->wm_class && wwin->wm_instance) {
1119 tmp = wstrconcat(wwin->wm_instance, ".");
1120 str = wstrconcat(tmp, wwin->wm_class);
1122 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1123 WMMoveWidget(panel->bothRb, 10, 18);
1124 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1125 WMSetButtonText(panel->bothRb, str);
1126 wfree(tmp);
1127 wfree(str);
1128 WMGroupButtons(panel->defaultRb, panel->bothRb);
1130 if (!selectedBtn)
1131 selectedBtn = panel->bothRb;
1133 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1136 if (wwin->wm_instance) {
1137 panel->instRb = WMCreateRadioButton(panel->specFrm);
1138 WMMoveWidget(panel->instRb, 10, 38);
1139 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1140 WMSetButtonText(panel->instRb, wwin->wm_instance);
1141 WMGroupButtons(panel->defaultRb, panel->instRb);
1143 if (!selectedBtn)
1144 selectedBtn = panel->instRb;
1146 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1149 if (wwin->wm_class) {
1150 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1151 WMMoveWidget(panel->clsRb, 10, 58);
1152 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1153 WMSetButtonText(panel->clsRb, wwin->wm_class);
1154 WMGroupButtons(panel->defaultRb, panel->clsRb);
1156 if (!selectedBtn)
1157 selectedBtn = panel->clsRb;
1159 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1162 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1163 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1164 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1165 WMSetButtonText(panel->selWinB, _("Select window"));
1166 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1168 panel->specLbl = WMCreateLabel(panel->win);
1169 WMMoveWidget(panel->specLbl, 15, 210);
1170 WMResizeWidget(panel->specLbl, frame_width, 100);
1171 WMSetLabelText(panel->specLbl, spec_text);
1172 WMSetLabelWraps(panel->specLbl, True);
1174 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1176 /**** attributes ****/
1177 create_tab_window_attributes(wwin, panel, frame_width);
1178 create_tab_window_advanced(wwin, panel, frame_width);
1179 create_tab_icon_workspace(wwin, panel);
1180 create_tab_app_specific(wwin, panel, frame_width);
1182 /* if the window is a transient, don't let it have a miniaturize button */
1183 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1184 WMSetButtonEnabled(panel->attrChk[3], False);
1185 else
1186 WMSetButtonEnabled(panel->attrChk[3], True);
1188 if (!wwin->wm_class && !wwin->wm_instance)
1189 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1191 WMRealizeWidget(panel->win);
1193 WMMapSubwidgets(panel->win);
1194 WMMapSubwidgets(panel->specFrm);
1195 WMMapSubwidgets(panel->attrFrm);
1196 WMMapSubwidgets(panel->moreFrm);
1197 WMMapSubwidgets(panel->iconFrm);
1198 WMMapSubwidgets(panel->wsFrm);
1199 if (panel->appFrm)
1200 WMMapSubwidgets(panel->appFrm);
1202 if (showSelectPanel) {
1203 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1204 changePage(panel->pagePopUp, panel);
1205 } else {
1206 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1207 changePage(panel->pagePopUp, panel);
1210 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1211 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1212 panel->parent = parent;
1213 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1215 WMMapWidget(panel->win);
1217 XSetTransientForHint(dpy, parent, wwin->client_win);
1219 if (xpos == UNDEFINED_POS) {
1220 x = wwin->frame_x + wwin->frame->core->width / 2;
1221 y = wwin->frame_y + wwin->frame->top_width * 2;
1222 if (y + PHEIGHT > scr->scr_height)
1223 y = scr->scr_height - PHEIGHT - 30;
1224 if (x + PWIDTH > scr->scr_width)
1225 x = scr->scr_width - PWIDTH;
1226 } else {
1227 x = xpos;
1228 y = ypos;
1231 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1233 if (!selectedBtn)
1234 selectedBtn = panel->defaultRb;
1236 WMSetButtonSelected(selectedBtn, True);
1237 selectSpecification(selectedBtn, panel);
1239 /* kluge to know who should get the key events */
1240 panel->frame->client_leader = WMWidgetXID(panel->win);
1242 WSETUFLAG(panel->frame, no_closable, 0);
1243 WSETUFLAG(panel->frame, no_close_button, 0);
1244 wWindowUpdateButtonImages(panel->frame);
1245 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1246 panel->frame->frame->on_click_right = destroyInspector;
1248 wWindowMap(panel->frame);
1250 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1252 return panel;
1255 void wShowInspectorForWindow(WWindow *wwin)
1257 if (wwin->flags.inspector_open)
1258 return;
1260 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1262 make_keys();
1263 wwin->flags.inspector_open = 1;
1264 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1267 void wHideInspectorForWindow(WWindow *wwin)
1269 WWindow *pwin = wwin->inspector->frame;
1271 wWindowUnmap(pwin);
1272 pwin->flags.hidden = 1;
1274 wClientSetState(pwin, IconicState, None);
1277 void wUnhideInspectorForWindow(WWindow *wwin)
1279 WWindow *pwin = wwin->inspector->frame;
1281 pwin->flags.hidden = 0;
1282 pwin->flags.mapped = 1;
1283 XMapWindow(dpy, pwin->client_win);
1284 XMapWindow(dpy, pwin->frame->core->window);
1285 wClientSetState(pwin, NormalState, None);
1288 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1290 if (!wwin->inspector)
1291 return NULL;
1293 assert(wwin->flags.inspector_open != 0);
1294 return wwin->inspector->frame;
1297 void wCloseInspectorForWindow(WWindow *wwin)
1299 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1301 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1304 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1306 int i = 0;
1307 char *caption = NULL, *descr = NULL;
1308 int flag = 0;
1310 panel->attrFrm = WMCreateFrame(panel->win);
1311 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1312 WMMoveWidget(panel->attrFrm, 15, 45);
1313 WMResizeWidget(panel->attrFrm, frame_width, 250);
1315 for (i = 0; i < wlengthof(panel->attrChk); i++) {
1316 switch (i) {
1317 case 0:
1318 caption = _("Disable titlebar");
1319 flag = WFLAGP(wwin, no_titlebar);
1320 descr = _("Remove the titlebar of this window.\n"
1321 "To access the window commands menu of a window\n"
1322 "without it's titlebar, press Control+Esc (or the\n"
1323 "equivalent shortcut, if you changed the default\n" "settings).");
1324 break;
1325 case 1:
1326 caption = _("Disable resizebar");
1327 flag = WFLAGP(wwin, no_resizebar);
1328 descr = _("Remove the resizebar of this window.");
1329 break;
1330 case 2:
1331 caption = _("Disable close button");
1332 flag = WFLAGP(wwin, no_close_button);
1333 descr = _("Remove the `close window' button of this window.");
1334 break;
1335 case 3:
1336 caption = _("Disable miniaturize button");
1337 flag = WFLAGP(wwin, no_miniaturize_button);
1338 descr = _("Remove the `miniaturize window' button of the window.");
1339 break;
1340 case 4:
1341 caption = _("Disable border");
1342 flag = WFLAGP(wwin, no_border);
1343 descr = _("Remove the 1 pixel black border around the window.");
1344 break;
1345 case 5:
1346 caption = _("Keep on top (floating)");
1347 flag = WFLAGP(wwin, floating);
1348 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1349 break;
1350 case 6:
1351 caption = _("Keep at bottom (sunken)");
1352 flag = WFLAGP(wwin, sunken);
1353 descr = _("Keep the window under all other windows.");
1354 break;
1355 case 7:
1356 caption = _("Omnipresent");
1357 flag = WFLAGP(wwin, omnipresent);
1358 descr = _("Make window present in all workspaces.");
1359 break;
1360 case 8:
1361 caption = _("Start miniaturized");
1362 flag = WFLAGP(wwin, start_miniaturized);
1363 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1364 break;
1365 case 9:
1366 caption = _("Start maximized");
1367 flag = WFLAGP(wwin, start_maximized != 0);
1368 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1369 break;
1370 case 10:
1371 caption = _("Full screen maximization");
1372 flag = WFLAGP(wwin, full_maximize);
1373 descr = _("Make the window use the whole screen space when it's\n"
1374 "maximized. The titlebar and resizebar will be moved\n"
1375 "to outside the screen.");
1376 break;
1378 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1379 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1380 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1381 WMSetButtonSelected(panel->attrChk[i], flag);
1382 WMSetButtonText(panel->attrChk[i], caption);
1384 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1388 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1390 int i = 0;
1391 char *caption = NULL, *descr = NULL;
1392 int flag = 0;
1394 panel->moreFrm = WMCreateFrame(panel->win);
1395 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1396 WMMoveWidget(panel->moreFrm, 15, 45);
1397 WMResizeWidget(panel->moreFrm, frame_width, 265);
1399 for (i = 0; i < wlengthof(panel->moreChk); i++) {
1400 switch (i) {
1401 case 0:
1402 caption = _("Do not bind keyboard shortcuts");
1403 flag = WFLAGP(wwin, no_bind_keys);
1404 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1405 "when this window is focused. This will allow the\n"
1406 "window to receive all key combinations regardless\n"
1407 "of your shortcut configuration.");
1408 break;
1409 case 1:
1410 caption = _("Do not bind mouse clicks");
1411 flag = WFLAGP(wwin, no_bind_mouse);
1412 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1413 "in the window (when alt is the modifier you have\n" "configured).");
1414 break;
1415 case 2:
1416 caption = _("Do not show in the window list");
1417 flag = WFLAGP(wwin, skip_window_list);
1418 descr = _("Do not list the window in the window list menu.");
1419 break;
1420 case 3:
1421 caption = _("Do not show in the switch panel");
1422 flag = WFLAGP(wwin, skip_switchpanel);
1423 descr = _("Do not include in switch panel while cycling windows.");
1424 break;
1425 case 4:
1426 caption = _("Do not let it take focus");
1427 flag = WFLAGP(wwin, no_focusable);
1428 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1429 break;
1430 case 5:
1431 caption = _("Keep inside screen");
1432 flag = WFLAGP(wwin, dont_move_off);
1433 descr = _("Do not allow the window to move itself completely\n"
1434 "outside the screen. For bug compatibility.\n");
1435 break;
1436 case 6:
1437 caption = _("Ignore 'Hide Others'");
1438 flag = WFLAGP(wwin, no_hide_others);
1439 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1440 break;
1441 case 7:
1442 caption = _("Ignore 'Save Session'");
1443 flag = WFLAGP(wwin, dont_save_session);
1444 descr = _("Do not save the associated application in the\n"
1445 "session's state, so that it won't be restarted\n"
1446 "together with other applications when Window Maker\n" "starts.");
1447 break;
1448 case 8:
1449 caption = _("Emulate application icon");
1450 flag = WFLAGP(wwin, emulate_appicon);
1451 descr = _("Make this window act as an application that provides\n"
1452 "enough information to Window Maker for a dockable\n"
1453 "application icon to be created.");
1454 break;
1455 case 9:
1456 caption = _("Focus across workspaces");
1457 flag = WFLAGP(wwin, focus_across_wksp);
1458 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1459 "a focus request (annoying).");
1460 break;
1461 case 10:
1462 caption = _("Do not let it be minimized");
1463 flag = WFLAGP(wwin, no_miniaturizable);
1464 descr = _("Do not let the window of this application be\n"
1465 "minimized.\n");
1466 break;
1467 #ifdef XKB_BUTTON_HINT
1468 case 11:
1469 caption = _("Disable language button");
1470 flag = WFLAGP(wwin, no_language_button);
1471 descr = _("Remove the `toggle language' button of the window.");
1472 break;
1473 #endif
1475 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1476 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1477 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1478 WMSetButtonSelected(panel->moreChk[i], flag);
1479 WMSetButtonText(panel->moreChk[i], caption);
1481 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1485 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel)
1487 int i = 0;
1489 /* miniwindow/workspace */
1490 panel->iconFrm = WMCreateFrame(panel->win);
1491 WMMoveWidget(panel->iconFrm, 15, 50);
1492 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1493 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1495 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1496 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1497 WMResizeWidget(panel->iconLbl, 64, 64);
1498 WMSetLabelRelief(panel->iconLbl, WRGroove);
1499 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1501 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1502 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1503 WMMoveWidget(panel->browseIconBtn, 22, 32);
1504 WMResizeWidget(panel->browseIconBtn, 120, 26);
1505 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1507 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1508 WMMoveWidget(panel->fileLbl, 20, 85);
1509 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1510 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1512 panel->fileText = WMCreateTextField(panel->iconFrm);
1513 WMMoveWidget(panel->fileText, 20, 105);
1514 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1515 WMSetTextFieldText(panel->fileText, NULL);
1516 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1518 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1519 WMMoveWidget(panel->alwChk, 20, 130);
1520 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1521 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1522 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1524 panel->wsFrm = WMCreateFrame(panel->win);
1525 WMMoveWidget(panel->wsFrm, 15, 225);
1526 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1527 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1529 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1530 "first shown."), WMWidgetView(panel->wsFrm));
1532 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1533 WMMoveWidget(panel->wsP, 20, 30);
1534 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1535 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1537 for (i = 0; i < w_global.workspace.count; i++)
1538 WMAddPopUpButtonItem(panel->wsP, w_global.workspace.array[i]->name);
1540 i = wDefaultGetStartWorkspace(wwin->wm_instance, wwin->wm_class);
1541 if (i >= 0 && i <= w_global.workspace.count)
1542 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1543 else
1544 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1547 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1549 WScreen *scr = wwin->screen_ptr;
1550 int i = 0, flag = 0, tmp;
1551 char *caption = NULL, *descr = NULL;
1554 if (wwin->main_window != None) {
1555 WApplication *wapp = wApplicationOf(wwin->main_window);
1557 panel->appFrm = WMCreateFrame(panel->win);
1558 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1559 WMMoveWidget(panel->appFrm, 15, 50);
1560 WMResizeWidget(panel->appFrm, frame_width, 240);
1562 for (i = 0; i < wlengthof(panel->appChk); i++) {
1563 switch (i) {
1564 case 0:
1565 caption = _("Start hidden");
1566 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1567 descr = _("Automatically hide application when it's started.");
1568 break;
1569 case 1:
1570 caption = _("No application icon");
1571 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1572 descr = _("Disable the application icon for the application.\n"
1573 "Note that you won't be able to dock it anymore,\n"
1574 "and any icons that are already docked will stop\n"
1575 "working correctly.");
1576 break;
1577 case 2:
1578 caption = _("Shared application icon");
1579 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1580 descr = _("Use a single shared application icon for all of\n"
1581 "the instances of this application.\n");
1582 break;
1584 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1585 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1586 WMResizeWidget(panel->appChk[i], 205, 20);
1587 WMSetButtonSelected(panel->appChk[i], flag);
1588 WMSetButtonText(panel->appChk[i], caption);
1589 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1592 if (WFLAGP(wwin, emulate_appicon)) {
1593 WMSetButtonEnabled(panel->appChk[1], False);
1594 WMSetButtonEnabled(panel->moreChk[7], True);
1595 } else {
1596 WMSetButtonEnabled(panel->appChk[1], True);
1597 WMSetButtonEnabled(panel->moreChk[7], False);
1599 } else {
1600 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1601 || !wwin->wm_class || !wwin->wm_instance)
1602 tmp = False;
1603 else
1604 tmp = True;
1606 WMSetButtonEnabled(panel->moreChk[7], tmp);
1608 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1609 panel->appFrm = NULL;