Address some sparse warnings
[wmaker-crm.git] / src / winspector.c
blob3375736a8b6222b13f918c6784aa79b1359d7f80
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
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.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"
50 #include "xinerama.h"
52 #include <WINGs/WUtil.h>
54 typedef struct InspectorPanel {
55 struct InspectorPanel *nextPtr;
57 WWindow *frame;
59 WWindow *inspected; /* the window that's being inspected */
61 WMWindow *win;
63 Window parent;
65 /* common stuff */
66 WMButton *revertBtn;
67 WMButton *applyBtn;
68 WMButton *saveBtn;
70 WMPopUpButton *pagePopUp;
72 /* first page. general stuff */
74 WMFrame *specFrm;
75 WMButton *instRb;
76 WMButton *clsRb;
77 WMButton *bothRb;
78 WMButton *defaultRb;
80 WMButton *selWinB;
82 WMLabel *specLbl;
84 /* 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[10];
93 #else
94 WMButton *moreChk[9];
95 #endif
97 /* 4th page. icon and workspace */
98 WMFrame *iconFrm;
99 WMLabel *iconLbl;
100 WMLabel *fileLbl;
101 WMTextField *fileText;
102 WMButton *alwChk;
104 WMButton *updateIconBtn;
106 WMButton *browseIconBtn;
108 WMFrame *wsFrm;
109 WMPopUpButton *wsP;
111 /* 5th page. application wide attributes */
112 WMFrame *appFrm;
113 WMButton *appChk[3];
115 unsigned int done:1;
116 unsigned int destroyed:1;
117 unsigned int choosingIcon:1;
118 } InspectorPanel;
120 extern Cursor wCursor[WCUR_LAST];
121 extern WDDomain *WDWindowAttributes;
122 extern WPreferences wPreferences;
124 static InspectorPanel *panelList = NULL;
125 static WMPropList *ANoTitlebar = NULL;
126 static WMPropList *ANoResizebar;
127 static WMPropList *ANoMiniaturizeButton;
128 static WMPropList *ANoCloseButton;
129 static WMPropList *ANoBorder;
130 static WMPropList *ANoHideOthers;
131 static WMPropList *ANoMouseBindings;
132 static WMPropList *ANoKeyBindings;
133 static WMPropList *ANoAppIcon;
134 static WMPropList *AKeepOnTop;
135 static WMPropList *AKeepOnBottom;
136 static WMPropList *AOmnipresent;
137 static WMPropList *ASkipWindowList;
138 static WMPropList *AKeepInsideScreen;
139 static WMPropList *AUnfocusable;
140 static WMPropList *ADontFocusAcrossWorkspace;
141 static WMPropList *AAlwaysUserIcon;
142 static WMPropList *AStartMiniaturized;
143 static WMPropList *AStartMaximized;
144 static WMPropList *ADontSaveSession;
145 static WMPropList *AEmulateAppIcon;
146 static WMPropList *AFullMaximize;
147 static WMPropList *ASharedAppIcon;
148 #ifdef XKB_BUTTON_HINT
149 static WMPropList *ANoLanguageButton;
150 #endif
151 static WMPropList *AStartWorkspace;
152 static WMPropList *AIcon;
154 /* application wide options */
155 static WMPropList *AStartHidden;
156 static WMPropList *AnyWindow;
157 static WMPropList *EmptyString;
158 static WMPropList *Yes, *No;
160 #define PWIDTH 270
161 #define PHEIGHT 350
163 static char *spec_text;
164 static void applySettings(WMButton * button, InspectorPanel * panel);
166 #define UNDEFINED_POS 0xffffff
168 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
170 static void make_keys(void)
172 if (ANoTitlebar != NULL)
173 return;
175 AIcon = WMCreatePLString("Icon");
176 ANoTitlebar = WMCreatePLString("NoTitlebar");
177 ANoResizebar = WMCreatePLString("NoResizebar");
178 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
179 ANoCloseButton = WMCreatePLString("NoCloseButton");
180 ANoBorder = WMCreatePLString("NoBorder");
181 ANoHideOthers = WMCreatePLString("NoHideOthers");
182 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
183 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
184 ANoAppIcon = WMCreatePLString("NoAppIcon");
185 AKeepOnTop = WMCreatePLString("KeepOnTop");
186 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
187 AOmnipresent = WMCreatePLString("Omnipresent");
188 ASkipWindowList = WMCreatePLString("SkipWindowList");
189 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
190 AUnfocusable = WMCreatePLString("Unfocusable");
191 ADontFocusAcrossWorkspace = WMCreatePLString("DontFocusAcrossWorkspace");
192 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
193 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
194 AStartMaximized = WMCreatePLString("StartMaximized");
195 AStartHidden = WMCreatePLString("StartHidden");
196 ADontSaveSession = WMCreatePLString("DontSaveSession");
197 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
198 AFullMaximize = WMCreatePLString("FullMaximize");
199 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
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;
215 if (panel->choosingIcon)
216 return;
218 WMDestroyWidget(panel->win);
220 XDestroyWindow(dpy, panel->parent);
222 wfree(panel);
225 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
227 InspectorPanel *panel;
228 InspectorPanel *tmp;
230 panel = panelList;
231 while (panel->frame != data)
232 panel = panel->nextPtr;
234 if (panelList == panel)
235 panelList = panel->nextPtr;
236 else {
237 tmp = panelList;
238 while (tmp->nextPtr != panel) {
239 tmp = tmp->nextPtr;
241 tmp->nextPtr = panel->nextPtr;
243 panel->inspected->flags.inspector_open = 0;
244 panel->inspected->inspector = NULL;
246 WMRemoveNotificationObserver(panel);
248 wWindowUnmap(panel->frame);
249 wUnmanageWindow(panel->frame, True, False);
251 freeInspector(panel);
254 void wDestroyInspectorPanels(void)
256 InspectorPanel *panel;
258 while (panelList != NULL) {
259 panel = panelList;
260 panelList = panelList->nextPtr;
261 wUnmanageWindow(panel->frame, False, False);
262 WMDestroyWidget(panel->win);
264 panel->inspected->flags.inspector_open = 0;
265 panel->inspected->inspector = NULL;
267 wfree(panel);
271 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
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 #define USE_TEXT_FIELD 1
308 #define UPDATE_TEXT_FIELD 2
309 #define REVERT_TO_DEFAULT 4
311 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
313 WMPixmap *pixmap = (WMPixmap *) NULL;
314 char *file = NULL, *path = NULL;
315 char *db_icon = NULL;
317 if ((flags & USE_TEXT_FIELD) != 0) {
318 file = WMGetTextFieldText(panel->fileText);
319 if (file && file[0] == 0) {
320 wfree(file);
321 file = NULL;
323 } else {
324 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
325 if (db_icon != NULL)
326 file = wstrdup(db_icon);
328 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
329 if (file)
330 file = wstrdup(db_icon);
331 flags |= UPDATE_TEXT_FIELD;
334 if ((flags & UPDATE_TEXT_FIELD) != 0) {
335 WMSetTextFieldText(panel->fileText, file);
338 if (file) {
339 path = FindImage(wPreferences.icon_path, file);
341 if (!path) {
342 char *buf;
343 int len = strlen(file) + 80;
345 buf = wmalloc(len);
346 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
347 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
348 wfree(buf);
349 wfree(file);
350 return -1;
353 pixmap = WMCreatePixmapFromFile(scrPtr, path);
354 wfree(path);
356 if (!pixmap) {
357 char *buf;
358 int len = strlen(file) + 80;
360 buf = wmalloc(len);
361 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
362 file, RMessageForError(RErrorCode));
363 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
364 wfree(buf);
365 wfree(file);
366 return -1;
368 wfree(file);
371 WMSetLabelImage(panel->iconLbl, pixmap);
372 if (pixmap)
373 WMReleasePixmap(pixmap);
375 return 0;
378 #if 0
379 static void updateIcon(WMButton * button, InspectorPanel * panel)
381 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
383 #endif
385 static int getBool(WMPropList * value)
387 char *val;
389 if (!WMIsPLString(value)) {
390 return 0;
392 if (!(val = WMGetFromPLString(value))) {
393 return 0;
396 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
397 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
399 return 1;
400 } else if ((val[1] == '\0'
401 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
402 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
404 return 0;
405 } else {
406 wwarning(_("can't convert \"%s\" to boolean"), val);
407 return 0;
411 #define UPDATE_DEFAULTS 1
412 #define IS_BOOLEAN 2
415 * Will insert the attribute = value; pair in window's list,
416 * if it's different from the defaults.
417 * Defaults means either defaults database, or attributes saved
418 * for the default window "*". This is to let one revert options that are
419 * global because they were saved for all windows ("*").
423 static int
424 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
426 WMPropList *def_win, *def_value = NULL;
427 int update = 0;
428 int modified = 0;
430 if (!(flags & UPDATE_DEFAULTS) && dict) {
431 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
432 def_value = WMGetFromPLDictionary(def_win, attr);
436 /* If we could not find defaults in database, fall to hardcoded values.
437 * Also this is true if we save defaults for all windows
439 if (!def_value)
440 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
442 if ((flags & IS_BOOLEAN))
443 update = (getBool(value) != getBool(def_value));
444 else {
445 update = !WMIsPropListEqualTo(value, def_value);
448 if (update) {
449 WMPutInPLDictionary(window, attr, value);
450 modified = 1;
453 return modified;
456 static void saveSettings(WMButton * button, InspectorPanel * panel)
458 WWindow *wwin = panel->inspected;
459 WDDomain *db = WDWindowAttributes;
460 WMPropList *dict = db->dictionary;
461 WMPropList *winDic, *appDic, *value, *key, *key2;
462 char *icon_file;
463 int flags = 0;
464 int different = 0, different2 = 0;
466 /* Save will apply the changes and save them */
467 applySettings(panel->applyBtn, panel);
469 if (WMGetButtonSelected(panel->instRb) != 0)
470 key = WMCreatePLString(wwin->wm_instance);
471 else if (WMGetButtonSelected(panel->clsRb) != 0)
472 key = WMCreatePLString(wwin->wm_class);
473 else if (WMGetButtonSelected(panel->bothRb) != 0) {
474 char *buffer;
476 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
477 key = WMCreatePLString(buffer);
478 wfree(buffer);
479 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
480 key = WMRetainPropList(AnyWindow);
481 flags = UPDATE_DEFAULTS;
482 } else
483 key = NULL;
485 if (!key)
486 return;
488 if (!dict) {
489 dict = WMCreatePLDictionary(NULL, NULL);
490 if (dict) {
491 db->dictionary = dict;
492 } else {
493 WMReleasePropList(key);
494 return;
498 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
499 return;
501 WMPLSetCaseSensitive(True);
503 winDic = WMCreatePLDictionary(NULL, NULL);
504 appDic = WMCreatePLDictionary(NULL, NULL);
506 /* Update icon for window */
507 icon_file = WMGetTextFieldText(panel->fileText);
508 if (icon_file) {
509 if (icon_file[0] != 0) {
510 value = WMCreatePLString(icon_file);
511 different |= insertAttribute(dict, winDic, AIcon, value, flags);
512 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
513 WMReleasePropList(value);
515 wfree(icon_file);
519 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
521 i--;
523 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
524 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
525 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
526 WMReleasePropList(value);
530 flags |= IS_BOOLEAN;
532 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
533 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
535 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
536 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
538 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
539 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
541 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
544 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
547 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
550 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
553 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
556 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
559 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
562 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
565 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
568 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
569 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
571 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
572 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
574 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
575 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
577 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
578 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
580 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
581 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
583 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
584 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
586 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
587 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
589 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
590 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
592 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
593 different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace, value, flags);
595 #ifdef XKB_BUTTON_HINT
596 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
597 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
598 #endif
600 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
601 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
602 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
604 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
605 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
607 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
608 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
611 if (wwin->fake_group) {
612 key2 = WMCreatePLString(wwin->fake_group->identifier);
613 if (WMIsPropListEqualTo(key, key2)) {
614 WMMergePLDictionaries(winDic, appDic, True);
615 different |= different2;
616 } else {
617 WMRemoveFromPLDictionary(dict, key2);
618 if (different2) {
619 WMPutInPLDictionary(dict, key2, appDic);
622 WMReleasePropList(key2);
623 WMReleasePropList(appDic);
624 } else if (wwin->main_window != wwin->client_win) {
625 WApplication *wapp = wApplicationOf(wwin->main_window);
627 if (wapp) {
628 char *instance = wapp->main_window_desc->wm_instance;
629 char *class = wapp->main_window_desc->wm_class;
630 char *buffer;
632 buffer = StrConcatDot(instance, class);
633 key2 = WMCreatePLString(buffer);
634 wfree(buffer);
636 if (WMIsPropListEqualTo(key, key2)) {
637 WMMergePLDictionaries(winDic, appDic, True);
638 different |= different2;
639 } else {
640 WMRemoveFromPLDictionary(dict, key2);
641 if (different2) {
642 WMPutInPLDictionary(dict, key2, appDic);
645 WMReleasePropList(key2);
646 WMReleasePropList(appDic);
648 } else {
649 WMMergePLDictionaries(winDic, appDic, True);
650 different |= different2;
651 WMReleasePropList(appDic);
654 WMRemoveFromPLDictionary(dict, key);
655 if (different) {
656 WMPutInPLDictionary(dict, key, winDic);
659 WMReleasePropList(key);
660 WMReleasePropList(winDic);
662 UpdateDomainFile(db);
664 /* clean up */
665 WMPLSetCaseSensitive(False);
668 static void makeAppIconFor(WApplication * wapp)
670 WScreen *scr = wapp->main_window_desc->screen_ptr;
672 if (wapp->app_icon)
673 return;
675 if (!WFLAGP(wapp->main_window_desc, no_appicon))
676 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
677 else
678 wapp->app_icon = NULL;
680 if (wapp->app_icon) {
681 WIcon *icon = wapp->app_icon->icon;
682 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
683 int x = 0, y = 0;
685 wapp->app_icon->main_window = wapp->main_window;
687 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
688 wapp->app_icon->attracted = 1;
689 if (!wapp->app_icon->icon->shadowed) {
690 wapp->app_icon->icon->shadowed = 1;
691 wapp->app_icon->icon->force_paint = 1;
693 wDockAttachIcon(clip, wapp->app_icon, x, y);
694 } else {
695 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
696 wAppIconMove(wapp->app_icon, x, y);
698 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
699 XMapWindow(dpy, icon->core->window);
701 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
702 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
706 static void removeAppIconFor(WApplication * wapp)
708 if (!wapp->app_icon)
709 return;
711 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
712 wapp->app_icon->running = 0;
713 /* since we keep it, we don't care if it was attracted or not */
714 wapp->app_icon->attracted = 0;
715 wapp->app_icon->icon->shadowed = 0;
716 wapp->app_icon->main_window = None;
717 wapp->app_icon->pid = 0;
718 wapp->app_icon->icon->owner = NULL;
719 wapp->app_icon->icon->icon_win = None;
720 wapp->app_icon->icon->force_paint = 1;
721 wAppIconPaint(wapp->app_icon);
722 } else if (wapp->app_icon->docked) {
723 wapp->app_icon->running = 0;
724 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
725 } else {
726 wAppIconDestroy(wapp->app_icon);
728 wapp->app_icon = NULL;
729 if (wPreferences.auto_arrange_icons)
730 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
733 static void applySettings(WMButton * button, InspectorPanel * panel)
735 WWindow *wwin = panel->inspected;
736 WApplication *wapp = wApplicationOf(wwin->main_window);
737 int floating, sunken, skip_window_list;
738 int old_omnipresent;
739 int old_no_bind_keys;
740 int old_no_bind_mouse;
742 old_omnipresent = WFLAGP(wwin, omnipresent);
743 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
744 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
746 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
748 /* Attributes... --> Window Attributes */
749 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
750 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
751 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
752 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
753 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
754 floating = WMGetButtonSelected(panel->attrChk[5]);
755 sunken = WMGetButtonSelected(panel->attrChk[6]);
756 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
757 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
758 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
759 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
761 /* Attributes... --> Advanced Options */
762 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
763 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
764 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
765 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
766 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
767 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
768 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
769 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
770 WSETUFLAG(wwin, dont_focus_across_wksp, WMGetButtonSelected(panel->moreChk[8]));
771 #ifdef XKB_BUTTON_HINT
772 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[9]));
773 #endif
774 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
776 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
777 wUnshadeWindow(wwin);
779 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
781 if (floating) {
782 if (!WFLAGP(wwin, floating))
783 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
784 } else if (sunken) {
785 if (!WFLAGP(wwin, sunken))
786 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
787 } else {
788 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
789 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
792 WSETUFLAG(wwin, sunken, sunken);
793 WSETUFLAG(wwin, floating, floating);
794 wwin->flags.omnipresent = 0;
796 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
797 WSETUFLAG(wwin, skip_window_list, skip_window_list);
798 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
799 } else {
800 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
801 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
805 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
806 if (WFLAGP(wwin, no_bind_keys)) {
807 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
808 } else {
809 wWindowSetKeyGrabs(wwin);
813 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
814 wWindowResetMouseGrabs(wwin);
817 wwin->frame->flags.need_texture_change = 1;
818 wWindowConfigureBorders(wwin);
819 wFrameWindowPaint(wwin->frame);
820 wNETWMUpdateActions(wwin, False);
823 * Can't apply emulate_appicon because it will probably cause problems.
825 if (wapp) {
826 /* do application wide stuff */
827 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
829 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
831 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
833 if (WFLAGP(wapp->main_window_desc, no_appicon))
834 removeAppIconFor(wapp);
835 else
836 makeAppIconFor(wapp);
838 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
839 char *file = WMGetTextFieldText(panel->fileText);
841 if (file[0] == 0) {
842 wfree(file);
843 file = NULL;
845 wIconChangeImageFile(wapp->app_icon->icon, file);
846 if (file)
847 wfree(file);
848 wAppIconPaint(wapp->app_icon);
853 static void revertSettings(WMButton * button, InspectorPanel * panel)
855 WWindow *wwin = panel->inspected;
856 WApplication *wapp = wApplicationOf(wwin->main_window);
857 int i, n;
858 char *wm_instance = NULL;
859 char *wm_class = NULL;
860 int workspace, level;
862 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
863 wm_instance = wwin->wm_instance;
864 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
865 wm_class = wwin->wm_class;
866 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
867 wm_instance = wwin->wm_instance;
868 wm_class = wwin->wm_class;
870 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
871 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
872 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
874 wWindowSetupInitialAttributes(wwin, &level, &workspace);
876 for (i = 0; i < 11; i++) {
877 int flag = 0;
879 switch (i) {
880 case 0:
881 flag = WFLAGP(wwin, no_titlebar);
882 break;
883 case 1:
884 flag = WFLAGP(wwin, no_resizebar);
885 break;
886 case 2:
887 flag = WFLAGP(wwin, no_close_button);
888 break;
889 case 3:
890 flag = WFLAGP(wwin, no_miniaturize_button);
891 break;
892 case 4:
893 flag = WFLAGP(wwin, no_border);
894 break;
895 case 5:
896 flag = WFLAGP(wwin, floating);
897 break;
898 case 6:
899 flag = WFLAGP(wwin, sunken);
900 break;
901 case 7:
902 flag = WFLAGP(wwin, omnipresent);
903 break;
904 case 8:
905 flag = WFLAGP(wwin, start_miniaturized);
906 break;
907 case 9:
908 flag = WFLAGP(wwin, start_maximized != 0);
909 break;
910 case 10:
911 flag = WFLAGP(wwin, full_maximize);
912 break;
914 WMSetButtonSelected(panel->attrChk[i], flag);
916 for (i = 0; i < 9; i++) {
917 int flag = 0;
919 switch (i) {
920 case 0:
921 flag = WFLAGP(wwin, no_bind_keys);
922 break;
923 case 1:
924 flag = WFLAGP(wwin, no_bind_mouse);
925 break;
926 case 2:
927 flag = WFLAGP(wwin, skip_window_list);
928 break;
929 case 3:
930 flag = WFLAGP(wwin, no_focusable);
931 break;
932 case 4:
933 flag = WFLAGP(wwin, dont_move_off);
934 break;
935 case 5:
936 flag = WFLAGP(wwin, no_hide_others);
937 break;
938 case 6:
939 flag = WFLAGP(wwin, dont_save_session);
940 break;
941 case 7:
942 flag = WFLAGP(wwin, emulate_appicon);
943 break;
944 case 8:
945 flag = WFLAGP(wwin, dont_focus_across_wksp);
946 break;
947 #ifdef XKB_BUTTON_HINT
948 case 9:
949 flag = WFLAGP(wwin, no_language_button);
950 break;
951 #endif
953 WMSetButtonSelected(panel->moreChk[i], flag);
955 if (panel->appFrm && wapp) {
956 for (i = 0; i < 2; i++) {
957 int flag = 0;
959 switch (i) {
960 case 0:
961 flag = WFLAGP(wapp->main_window_desc, start_hidden);
962 break;
963 case 1:
964 flag = WFLAGP(wapp->main_window_desc, no_appicon);
965 break;
966 case 2:
967 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
968 break;
970 WMSetButtonSelected(panel->appChk[i], flag);
973 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
975 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
977 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
979 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
980 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
981 } else {
982 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
985 /* must auto apply, so that there wno't be internal
986 * inconsistencies between the state in the flags and
987 * the actual state of the window */
988 applySettings(panel->applyBtn, panel);
991 static void chooseIconCallback(WMWidget * self, void *clientData)
993 char *file;
994 InspectorPanel *panel = (InspectorPanel *) clientData;
995 int result;
997 panel->choosingIcon = 1;
999 WMSetButtonEnabled(panel->browseIconBtn, False);
1001 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1002 panel->inspected->wm_instance, panel->inspected->wm_class);
1004 panel->choosingIcon = 0;
1006 if (!panel->destroyed) { /* kluge */
1007 if (result) {
1008 WMSetTextFieldText(panel->fileText, file);
1009 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1010 wfree(file);
1012 WMSetButtonEnabled(panel->browseIconBtn, True);
1013 } else {
1014 freeInspector(panel);
1018 static void textEditedObserver(void *observerData, WMNotification * notification)
1020 InspectorPanel *panel = (InspectorPanel *) observerData;
1022 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1023 return;
1025 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1027 WMPerformButtonClick(panel->updateIconBtn);
1031 static void selectSpecification(WMWidget * bPtr, void *data)
1033 InspectorPanel *panel = (InspectorPanel *) data;
1034 char *str;
1035 WWindow *wwin = panel->inspected;
1036 int len;
1038 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1039 WMSetButtonEnabled(panel->applyBtn, False);
1040 } else {
1041 WMSetButtonEnabled(panel->applyBtn, True);
1044 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1045 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1047 str = wmalloc(len);
1049 snprintf(str, len, _("Inspecting %s.%s"),
1050 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1052 wFrameWindowChangeTitle(panel->frame->frame, str);
1054 wfree(str);
1057 static void selectWindow(WMWidget * bPtr, void *data)
1059 InspectorPanel *panel = (InspectorPanel *) data;
1060 WWindow *wwin = panel->inspected;
1061 WScreen *scr = wwin->screen_ptr;
1062 XEvent event;
1063 WWindow *iwin;
1065 if (XGrabPointer(dpy, scr->root_win, True,
1066 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1067 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1068 wwarning("could not grab mouse pointer");
1069 return;
1072 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1074 WMMaskEvent(dpy, ButtonPressMask, &event);
1076 XUngrabPointer(dpy, CurrentTime);
1078 iwin = wWindowFor(event.xbutton.subwindow);
1080 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1082 iwin->flags.inspector_open = 1;
1083 iwin->inspector = createInspectorForWindow(iwin,
1084 panel->frame->frame_x, panel->frame->frame_y, True);
1085 wCloseInspectorForWindow(wwin);
1086 } else {
1087 WMSetLabelText(panel->specLbl, spec_text);
1091 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1093 WScreen *scr = wwin->screen_ptr;
1094 InspectorPanel *panel;
1095 Window parent;
1096 int i;
1097 int x, y;
1098 int btn_width, frame_width;
1099 WMButton *selectedBtn = NULL;
1100 #ifdef wrong_behaviour
1101 WMPixmap *pixmap;
1102 #endif
1104 spec_text = _("The configuration will apply to all\n"
1105 "windows that have their WM_CLASS\n"
1106 "property set to the above selected\n" "name, when saved.");
1108 panel = wmalloc(sizeof(InspectorPanel));
1109 memset(panel, 0, sizeof(InspectorPanel));
1111 panel->destroyed = 0;
1113 panel->inspected = wwin;
1115 panel->nextPtr = panelList;
1116 panelList = panel;
1118 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1119 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1121 /**** create common stuff ****/
1123 /* command buttons */
1124 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1125 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1126 panel->saveBtn = WMCreateCommandButton(panel->win);
1127 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1128 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1129 WMSetButtonText(panel->saveBtn, _("Save"));
1130 WMResizeWidget(panel->saveBtn, btn_width, 28);
1131 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1132 WMSetButtonEnabled(panel->saveBtn, False);
1134 panel->applyBtn = WMCreateCommandButton(panel->win);
1135 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1136 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1137 WMSetButtonText(panel->applyBtn, _("Apply"));
1138 WMResizeWidget(panel->applyBtn, btn_width, 28);
1140 panel->revertBtn = WMCreateCommandButton(panel->win);
1141 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1142 WMMoveWidget(panel->revertBtn, 15, 310);
1143 WMSetButtonText(panel->revertBtn, _("Reload"));
1144 WMResizeWidget(panel->revertBtn, btn_width, 28);
1146 /* page selection popup button */
1147 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1148 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1149 WMMoveWidget(panel->pagePopUp, 25, 15);
1150 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1152 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1153 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1154 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1155 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1156 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1158 /**** window spec ****/
1159 frame_width = PWIDTH - (2 * 15);
1161 panel->specFrm = WMCreateFrame(panel->win);
1162 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1163 WMMoveWidget(panel->specFrm, 15, 65);
1164 WMResizeWidget(panel->specFrm, frame_width, 145);
1166 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1167 WMMoveWidget(panel->defaultRb, 10, 78);
1168 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1169 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1170 WMSetButtonSelected(panel->defaultRb, False);
1171 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1173 if (wwin->wm_class && wwin->wm_instance) {
1174 char *str, *tmp;
1176 tmp = wstrconcat(wwin->wm_instance, ".");
1177 str = wstrconcat(tmp, wwin->wm_class);
1179 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1180 WMMoveWidget(panel->bothRb, 10, 18);
1181 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1182 WMSetButtonText(panel->bothRb, str);
1183 wfree(tmp);
1184 wfree(str);
1185 WMGroupButtons(panel->defaultRb, panel->bothRb);
1187 if (!selectedBtn)
1188 selectedBtn = panel->bothRb;
1190 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1193 if (wwin->wm_instance) {
1194 panel->instRb = WMCreateRadioButton(panel->specFrm);
1195 WMMoveWidget(panel->instRb, 10, 38);
1196 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1197 WMSetButtonText(panel->instRb, wwin->wm_instance);
1198 WMGroupButtons(panel->defaultRb, panel->instRb);
1200 if (!selectedBtn)
1201 selectedBtn = panel->instRb;
1203 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1206 if (wwin->wm_class) {
1207 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1208 WMMoveWidget(panel->clsRb, 10, 58);
1209 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1210 WMSetButtonText(panel->clsRb, wwin->wm_class);
1211 WMGroupButtons(panel->defaultRb, panel->clsRb);
1213 if (!selectedBtn)
1214 selectedBtn = panel->clsRb;
1216 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1219 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1220 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1221 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1222 WMSetButtonText(panel->selWinB, _("Select window"));
1223 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1225 panel->specLbl = WMCreateLabel(panel->win);
1226 WMMoveWidget(panel->specLbl, 15, 210);
1227 WMResizeWidget(panel->specLbl, frame_width, 100);
1228 WMSetLabelText(panel->specLbl, spec_text);
1229 WMSetLabelWraps(panel->specLbl, True);
1231 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1233 /**** attributes ****/
1234 panel->attrFrm = WMCreateFrame(panel->win);
1235 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1236 WMMoveWidget(panel->attrFrm, 15, 45);
1237 WMResizeWidget(panel->attrFrm, frame_width, 250);
1239 for (i = 0; i < 11; i++) {
1240 char *caption = NULL;
1241 int flag = 0;
1242 char *descr = NULL;
1244 switch (i) {
1245 case 0:
1246 caption = _("Disable titlebar");
1247 flag = WFLAGP(wwin, no_titlebar);
1248 descr = _("Remove the titlebar of this window.\n"
1249 "To access the window commands menu of a window\n"
1250 "without it's titlebar, press Control+Esc (or the\n"
1251 "equivalent shortcut, if you changed the default\n" "settings).");
1252 break;
1253 case 1:
1254 caption = _("Disable resizebar");
1255 flag = WFLAGP(wwin, no_resizebar);
1256 descr = _("Remove the resizebar of this window.");
1257 break;
1258 case 2:
1259 caption = _("Disable close button");
1260 flag = WFLAGP(wwin, no_close_button);
1261 descr = _("Remove the `close window' button of this window.");
1262 break;
1263 case 3:
1264 caption = _("Disable miniaturize button");
1265 flag = WFLAGP(wwin, no_miniaturize_button);
1266 descr = _("Remove the `miniaturize window' button of the window.");
1267 break;
1268 case 4:
1269 caption = _("Disable border");
1270 flag = WFLAGP(wwin, no_border);
1271 descr = _("Remove the 1 pixel black border around the window.");
1272 break;
1273 case 5:
1274 caption = _("Keep on top (floating)");
1275 flag = WFLAGP(wwin, floating);
1276 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1277 break;
1278 case 6:
1279 caption = _("Keep at bottom (sunken)");
1280 flag = WFLAGP(wwin, sunken);
1281 descr = _("Keep the window under all other windows.");
1282 break;
1283 case 7:
1284 caption = _("Omnipresent");
1285 flag = WFLAGP(wwin, omnipresent);
1286 descr = _("Make window present in all workspaces.");
1287 break;
1288 case 8:
1289 caption = _("Start miniaturized");
1290 flag = WFLAGP(wwin, start_miniaturized);
1291 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1292 break;
1293 case 9:
1294 caption = _("Start maximized");
1295 flag = WFLAGP(wwin, start_maximized != 0);
1296 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1297 break;
1298 case 10:
1299 caption = _("Full screen maximization");
1300 flag = WFLAGP(wwin, full_maximize);
1301 descr = _("Make the window use the whole screen space when it's\n"
1302 "maximized. The titlebar and resizebar will be moved\n"
1303 "to outside the screen.");
1304 break;
1306 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1307 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1308 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1309 WMSetButtonSelected(panel->attrChk[i], flag);
1310 WMSetButtonText(panel->attrChk[i], caption);
1312 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1315 /**** more attributes ****/
1316 panel->moreFrm = WMCreateFrame(panel->win);
1317 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1318 WMMoveWidget(panel->moreFrm, 15, 45);
1319 WMResizeWidget(panel->moreFrm, frame_width, 250);
1321 for (i = 0;
1322 #ifdef XKB_BUTTON_HINT
1323 i < 10;
1324 #else
1325 i < 9;
1326 #endif
1327 i++) {
1328 char *caption = NULL;
1329 int flag = 0;
1330 char *descr = NULL;
1332 switch (i) {
1333 case 0:
1334 caption = _("Do not bind keyboard shortcuts");
1335 flag = WFLAGP(wwin, no_bind_keys);
1336 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1337 "when this window is focused. This will allow the\n"
1338 "window to receive all key combinations regardless\n"
1339 "of your shortcut configuration.");
1340 break;
1341 case 1:
1342 caption = _("Do not bind mouse clicks");
1343 flag = WFLAGP(wwin, no_bind_mouse);
1344 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1345 "in the window (when alt is the modifier you have\n" "configured).");
1346 break;
1347 case 2:
1348 caption = _("Do not show in the window list");
1349 flag = WFLAGP(wwin, skip_window_list);
1350 descr = _("Do not list the window in the window list menu.");
1351 break;
1352 case 3:
1353 caption = _("Do not let it take focus");
1354 flag = WFLAGP(wwin, no_focusable);
1355 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1356 break;
1357 case 4:
1358 caption = _("Keep inside screen");
1359 flag = WFLAGP(wwin, dont_move_off);
1360 descr = _("Do not allow the window to move itself completely\n"
1361 "outside the screen. For bug compatibility.\n");
1362 break;
1363 case 5:
1364 caption = _("Ignore 'Hide Others'");
1365 flag = WFLAGP(wwin, no_hide_others);
1366 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1367 break;
1368 case 6:
1369 caption = _("Ignore 'Save Session'");
1370 flag = WFLAGP(wwin, dont_save_session);
1371 descr = _("Do not save the associated application in the\n"
1372 "session's state, so that it won't be restarted\n"
1373 "together with other applications when Window Maker\n" "starts.");
1374 break;
1375 case 7:
1376 caption = _("Emulate application icon");
1377 flag = WFLAGP(wwin, emulate_appicon);
1378 descr = _("Make this window act as an application that provides\n"
1379 "enough information to Window Maker for a dockable\n"
1380 "application icon to be created.");
1381 break;
1382 case 8:
1383 caption = _("Don't focus across workspaces");
1384 flag = WFLAGP(wwin, dont_focus_across_wksp);
1385 descr = _("Do not allow Window Maker to switch workspace to satisfy\n"
1386 "a focus request (useful e.g. in the case of a multiple-tab\n"
1387 "firefox opening in a different workspace).");
1388 break;
1389 #ifdef XKB_BUTTON_HINT
1390 case 9:
1391 caption = _("Disable language button");
1392 flag = WFLAGP(wwin, no_language_button);
1393 descr = _("Remove the `toggle language' button of the window.");
1394 break;
1395 #endif
1397 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1398 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1399 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1400 WMSetButtonSelected(panel->moreChk[i], flag);
1401 WMSetButtonText(panel->moreChk[i], caption);
1403 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1406 /* miniwindow/workspace */
1407 panel->iconFrm = WMCreateFrame(panel->win);
1408 WMMoveWidget(panel->iconFrm, 15, 50);
1409 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1410 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1412 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1413 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1414 WMResizeWidget(panel->iconLbl, 64, 64);
1415 WMSetLabelRelief(panel->iconLbl, WRGroove);
1416 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1418 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1419 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1420 WMMoveWidget(panel->browseIconBtn, 22, 32);
1421 WMResizeWidget(panel->browseIconBtn, 120, 26);
1422 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1424 #ifdef wrong_behaviour
1425 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1426 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1427 WMSetButtonImage(panel->updateIconBtn, pixmap);
1428 WMReleasePixmap(pixmap);
1429 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1430 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1431 WMReleasePixmap(pixmap);
1432 #endif
1434 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1435 WMMoveWidget(panel->fileLbl, 20, 85);
1436 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1437 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1439 panel->fileText = WMCreateTextField(panel->iconFrm);
1440 WMMoveWidget(panel->fileText, 20, 105);
1441 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1442 WMSetTextFieldText(panel->fileText, NULL);
1443 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1445 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1446 WMMoveWidget(panel->alwChk, 20, 130);
1447 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1448 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1449 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1451 panel->wsFrm = WMCreateFrame(panel->win);
1452 WMMoveWidget(panel->wsFrm, 15, 225);
1453 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1454 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1456 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1457 "first shown."), WMWidgetView(panel->wsFrm));
1459 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1460 WMMoveWidget(panel->wsP, 20, 30);
1461 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1462 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1463 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1464 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1467 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1468 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1469 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1470 } else {
1471 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1474 /* application wide attributes */
1475 if (wwin->main_window != None) {
1476 WApplication *wapp = wApplicationOf(wwin->main_window);
1478 panel->appFrm = WMCreateFrame(panel->win);
1479 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1480 WMMoveWidget(panel->appFrm, 15, 50);
1481 WMResizeWidget(panel->appFrm, frame_width, 240);
1483 for (i = 0; i < 3; i++) {
1484 char *caption = NULL;
1485 int flag = 0;
1486 char *descr = NULL;
1488 switch (i) {
1489 case 0:
1490 caption = _("Start hidden");
1491 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1492 descr = _("Automatically hide application when it's started.");
1493 break;
1494 case 1:
1495 caption = _("No application icon");
1496 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1497 descr = _("Disable the application icon for the application.\n"
1498 "Note that you won't be able to dock it anymore,\n"
1499 "and any icons that are already docked will stop\n"
1500 "working correctly.");
1501 break;
1502 case 2:
1503 caption = _("Shared application icon");
1504 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1505 descr = _("Use a single shared application icon for all of\n"
1506 "the instances of this application.\n");
1507 break;
1509 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1510 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1511 WMResizeWidget(panel->appChk[i], 205, 20);
1512 WMSetButtonSelected(panel->appChk[i], flag);
1513 WMSetButtonText(panel->appChk[i], caption);
1515 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1518 if (WFLAGP(wwin, emulate_appicon)) {
1519 WMSetButtonEnabled(panel->appChk[1], False);
1520 WMSetButtonEnabled(panel->moreChk[7], True);
1521 } else {
1522 WMSetButtonEnabled(panel->appChk[1], True);
1523 WMSetButtonEnabled(panel->moreChk[7], False);
1525 } else {
1526 int tmp;
1528 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1529 || !wwin->wm_class || !wwin->wm_instance)
1530 tmp = False;
1531 else
1532 tmp = True;
1533 WMSetButtonEnabled(panel->moreChk[7], tmp);
1535 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1536 panel->appFrm = NULL;
1539 /* if the window is a transient, don't let it have a miniaturize
1540 * button */
1541 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1542 WMSetButtonEnabled(panel->attrChk[3], False);
1543 else
1544 WMSetButtonEnabled(panel->attrChk[3], True);
1546 if (!wwin->wm_class && !wwin->wm_instance) {
1547 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1550 WMRealizeWidget(panel->win);
1552 WMMapSubwidgets(panel->win);
1553 WMMapSubwidgets(panel->specFrm);
1554 WMMapSubwidgets(panel->attrFrm);
1555 WMMapSubwidgets(panel->moreFrm);
1556 WMMapSubwidgets(panel->iconFrm);
1557 WMMapSubwidgets(panel->wsFrm);
1558 if (panel->appFrm)
1559 WMMapSubwidgets(panel->appFrm);
1561 if (showSelectPanel) {
1562 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1563 changePage(panel->pagePopUp, panel);
1564 } else {
1565 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1566 changePage(panel->pagePopUp, panel);
1569 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1570 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1571 panel->parent = parent;
1572 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1574 WMMapWidget(panel->win);
1576 XSetTransientForHint(dpy, parent, wwin->client_win);
1578 if (xpos == UNDEFINED_POS) {
1579 x = wwin->frame_x + wwin->frame->core->width / 2;
1580 y = wwin->frame_y + wwin->frame->top_width * 2;
1581 if (y + PHEIGHT > scr->scr_height)
1582 y = scr->scr_height - PHEIGHT - 30;
1583 if (x + PWIDTH > scr->scr_width)
1584 x = scr->scr_width - PWIDTH;
1585 } else {
1586 x = xpos;
1587 y = ypos;
1590 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1592 if (!selectedBtn)
1593 selectedBtn = panel->defaultRb;
1595 WMSetButtonSelected(selectedBtn, True);
1597 selectSpecification(selectedBtn, panel);
1599 /* kluge to know who should get the key events */
1600 panel->frame->client_leader = WMWidgetXID(panel->win);
1602 WSETUFLAG(panel->frame, no_closable, 0);
1603 WSETUFLAG(panel->frame, no_close_button, 0);
1604 wWindowUpdateButtonImages(panel->frame);
1605 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1606 panel->frame->frame->on_click_right = destroyInspector;
1608 wWindowMap(panel->frame);
1610 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1612 return panel;
1615 void wShowInspectorForWindow(WWindow * wwin)
1617 if (wwin->flags.inspector_open)
1618 return;
1620 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1622 make_keys();
1623 wwin->flags.inspector_open = 1;
1624 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1627 void wHideInspectorForWindow(WWindow * wwin)
1629 WWindow *pwin = wwin->inspector->frame;
1631 wWindowUnmap(pwin);
1632 pwin->flags.hidden = 1;
1634 wClientSetState(pwin, IconicState, None);
1637 void wUnhideInspectorForWindow(WWindow * wwin)
1639 WWindow *pwin = wwin->inspector->frame;
1641 pwin->flags.hidden = 0;
1642 pwin->flags.mapped = 1;
1643 XMapWindow(dpy, pwin->client_win);
1644 XMapWindow(dpy, pwin->frame->core->window);
1645 wClientSetState(pwin, NormalState, None);
1648 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1650 if (wwin->inspector) {
1651 assert(wwin->flags.inspector_open != 0);
1653 return wwin->inspector->frame;
1654 } else
1655 return NULL;
1658 void wCloseInspectorForWindow(WWindow * wwin)
1660 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1662 (*pwin->frame->on_click_right) (NULL, pwin, NULL);