Add history to some dialog boxes
[wmaker-crm.git] / src / winspector.c
blobfe473c2f572d5fda8c8566be49148968fdcb1320
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"
50 #ifdef NETWM_HINTS
51 #include "wmspec.h"
52 #endif
54 #include "xinerama.h"
56 #include <WINGs/WUtil.h>
58 typedef struct InspectorPanel {
59 struct InspectorPanel *nextPtr;
61 WWindow *frame;
63 WWindow *inspected; /* the window that's being inspected */
65 WMWindow *win;
67 Window parent;
69 /* common stuff */
70 WMButton *revertBtn;
71 WMButton *applyBtn;
72 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
84 WMButton *selWinB;
86 WMLabel *specLbl;
88 /* second page. attributes */
90 WMFrame *attrFrm;
91 WMButton *attrChk[11];
93 /* 3rd page. more attributes */
94 WMFrame *moreFrm;
95 #ifdef XKB_BUTTON_HINT
96 WMButton *moreChk[10];
97 #else
98 WMButton *moreChk[9];
99 #endif
101 /* 4th page. icon and workspace */
102 WMFrame *iconFrm;
103 WMLabel *iconLbl;
104 WMLabel *fileLbl;
105 WMTextField *fileText;
106 WMButton *alwChk;
108 WMButton *updateIconBtn;
110 WMButton *browseIconBtn;
112 WMFrame *wsFrm;
113 WMPopUpButton *wsP;
115 /* 5th page. application wide attributes */
116 WMFrame *appFrm;
117 WMButton *appChk[3];
119 unsigned int done:1;
120 unsigned int destroyed:1;
121 unsigned int choosingIcon:1;
122 } InspectorPanel;
124 extern Cursor wCursor[WCUR_LAST];
126 extern WDDomain *WDWindowAttributes;
128 static InspectorPanel *panelList = NULL;
130 extern WPreferences wPreferences;
132 static WMPropList *ANoTitlebar = NULL;
133 static WMPropList *ANoResizebar;
134 static WMPropList *ANoMiniaturizeButton;
135 static WMPropList *ANoCloseButton;
136 static WMPropList *ANoBorder;
137 static WMPropList *ANoHideOthers;
138 static WMPropList *ANoMouseBindings;
139 static WMPropList *ANoKeyBindings;
140 static WMPropList *ANoAppIcon;
141 static WMPropList *AKeepOnTop;
142 static WMPropList *AKeepOnBottom;
143 static WMPropList *AOmnipresent;
144 static WMPropList *ASkipWindowList;
145 static WMPropList *AKeepInsideScreen;
146 static WMPropList *AUnfocusable;
147 static WMPropList *ADontFocusAcrossWorkspace;
148 static WMPropList *AAlwaysUserIcon;
149 static WMPropList *AStartMiniaturized;
150 static WMPropList *AStartMaximized;
151 static WMPropList *ADontSaveSession;
152 static WMPropList *AEmulateAppIcon;
153 static WMPropList *AFullMaximize;
154 static WMPropList *ASharedAppIcon;
155 #ifdef XKB_BUTTON_HINT
156 static WMPropList *ANoLanguageButton;
157 #endif
159 static WMPropList *AStartWorkspace;
161 static WMPropList *AIcon;
163 /* application wide options */
164 static WMPropList *AStartHidden;
166 static WMPropList *AnyWindow;
167 static WMPropList *EmptyString;
168 static WMPropList *Yes, *No;
170 #define PWIDTH 270
171 #define PHEIGHT 350
173 static char *spec_text;
175 static void applySettings(WMButton * button, InspectorPanel * panel);
177 #define UNDEFINED_POS 0xffffff
179 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
181 static void make_keys()
183 if (ANoTitlebar != NULL)
184 return;
186 AIcon = WMCreatePLString("Icon");
187 ANoTitlebar = WMCreatePLString("NoTitlebar");
188 ANoResizebar = WMCreatePLString("NoResizebar");
189 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
190 ANoCloseButton = WMCreatePLString("NoCloseButton");
191 ANoBorder = WMCreatePLString("NoBorder");
192 ANoHideOthers = WMCreatePLString("NoHideOthers");
193 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
194 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
195 ANoAppIcon = WMCreatePLString("NoAppIcon");
196 AKeepOnTop = WMCreatePLString("KeepOnTop");
197 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
198 AOmnipresent = WMCreatePLString("Omnipresent");
199 ASkipWindowList = WMCreatePLString("SkipWindowList");
200 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
201 AUnfocusable = WMCreatePLString("Unfocusable");
202 ADontFocusAcrossWorkspace = WMCreatePLString("DontFocusAcrossWorkspace");
203 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
204 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
205 AStartMaximized = WMCreatePLString("StartMaximized");
206 AStartHidden = WMCreatePLString("StartHidden");
207 ADontSaveSession = WMCreatePLString("DontSaveSession");
208 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
209 AFullMaximize = WMCreatePLString("FullMaximize");
210 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
211 #ifdef XKB_BUTTON_HINT
212 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
213 #endif
215 AStartWorkspace = WMCreatePLString("StartWorkspace");
217 AnyWindow = WMCreatePLString("*");
218 EmptyString = WMCreatePLString("");
219 Yes = WMCreatePLString("Yes");
220 No = WMCreatePLString("No");
223 static void freeInspector(InspectorPanel * panel)
225 panel->destroyed = 1;
226 if (panel->choosingIcon)
227 return;
229 WMDestroyWidget(panel->win);
231 XDestroyWindow(dpy, panel->parent);
233 wfree(panel);
236 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
238 InspectorPanel *panel;
239 InspectorPanel *tmp;
241 panel = panelList;
242 while (panel->frame != data)
243 panel = panel->nextPtr;
245 if (panelList == panel)
246 panelList = panel->nextPtr;
247 else {
248 tmp = panelList;
249 while (tmp->nextPtr != panel) {
250 tmp = tmp->nextPtr;
252 tmp->nextPtr = panel->nextPtr;
254 panel->inspected->flags.inspector_open = 0;
255 panel->inspected->inspector = NULL;
257 WMRemoveNotificationObserver(panel);
259 wWindowUnmap(panel->frame);
260 wUnmanageWindow(panel->frame, True, False);
262 freeInspector(panel);
265 void wDestroyInspectorPanels()
267 InspectorPanel *panel;
269 while (panelList != NULL) {
270 panel = panelList;
271 panelList = panelList->nextPtr;
272 wUnmanageWindow(panel->frame, False, False);
273 WMDestroyWidget(panel->win);
275 panel->inspected->flags.inspector_open = 0;
276 panel->inspected->inspector = NULL;
278 wfree(panel);
282 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
284 int page;
286 page = WMGetPopUpButtonSelectedItem(bPtr);
288 if (page == 0) {
289 WMMapWidget(panel->specFrm);
290 WMMapWidget(panel->specLbl);
291 } else if (page == 1) {
292 WMMapWidget(panel->attrFrm);
293 } else if (page == 2) {
294 WMMapWidget(panel->moreFrm);
295 } else if (page == 3) {
296 WMMapWidget(panel->iconFrm);
297 WMMapWidget(panel->wsFrm);
298 } else {
299 WMMapWidget(panel->appFrm);
302 if (page != 0) {
303 WMUnmapWidget(panel->specFrm);
304 WMUnmapWidget(panel->specLbl);
306 if (page != 1)
307 WMUnmapWidget(panel->attrFrm);
308 if (page != 2)
309 WMUnmapWidget(panel->moreFrm);
310 if (page != 3) {
311 WMUnmapWidget(panel->iconFrm);
312 WMUnmapWidget(panel->wsFrm);
314 if (page != 4 && panel->appFrm)
315 WMUnmapWidget(panel->appFrm);
318 #define USE_TEXT_FIELD 1
319 #define UPDATE_TEXT_FIELD 2
320 #define REVERT_TO_DEFAULT 4
322 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
324 WMPixmap *pixmap = (WMPixmap *) NULL;
325 char *file = NULL, *path = NULL;
326 char *db_icon = NULL;
328 if ((flags & USE_TEXT_FIELD) != 0) {
329 file = WMGetTextFieldText(panel->fileText);
330 if (file && file[0] == 0) {
331 wfree(file);
332 file = NULL;
334 } else {
335 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
336 if (db_icon != NULL)
337 file = wstrdup(db_icon);
339 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
340 if (file)
341 file = wstrdup(db_icon);
342 flags |= UPDATE_TEXT_FIELD;
345 if ((flags & UPDATE_TEXT_FIELD) != 0) {
346 WMSetTextFieldText(panel->fileText, file);
349 if (file) {
350 path = FindImage(wPreferences.icon_path, file);
352 if (!path) {
353 char *buf;
354 int len = strlen(file) + 80;
356 buf = wmalloc(len);
357 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
358 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
359 wfree(buf);
360 wfree(file);
361 return -1;
364 pixmap = WMCreatePixmapFromFile(scrPtr, path);
365 wfree(path);
367 if (!pixmap) {
368 char *buf;
369 int len = strlen(file) + 80;
371 buf = wmalloc(len);
372 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
373 file, RMessageForError(RErrorCode));
374 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
375 wfree(buf);
376 wfree(file);
377 return -1;
379 wfree(file);
382 WMSetLabelImage(panel->iconLbl, pixmap);
383 if (pixmap)
384 WMReleasePixmap(pixmap);
386 return 0;
389 #if 0
390 static void updateIcon(WMButton * button, InspectorPanel * panel)
392 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
394 #endif
396 static int getBool(WMPropList * value)
398 char *val;
400 if (!WMIsPLString(value)) {
401 return 0;
403 if (!(val = WMGetFromPLString(value))) {
404 return 0;
407 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
408 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
410 return 1;
411 } else if ((val[1] == '\0'
412 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
413 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
415 return 0;
416 } else {
417 wwarning(_("can't convert \"%s\" to boolean"), val);
418 return 0;
422 #define UPDATE_DEFAULTS 1
423 #define IS_BOOLEAN 2
426 * Will insert the attribute = value; pair in window's list,
427 * if it's different from the defaults.
428 * Defaults means either defaults database, or attributes saved
429 * for the default window "*". This is to let one revert options that are
430 * global because they were saved for all windows ("*").
434 static int
435 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
437 WMPropList *def_win, *def_value = NULL;
438 int update = 0;
439 int modified = 0;
441 if (!(flags & UPDATE_DEFAULTS) && dict) {
442 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
443 def_value = WMGetFromPLDictionary(def_win, attr);
447 /* If we could not find defaults in database, fall to hardcoded values.
448 * Also this is true if we save defaults for all windows
450 if (!def_value)
451 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
453 if ((flags & IS_BOOLEAN))
454 update = (getBool(value) != getBool(def_value));
455 else {
456 update = !WMIsPropListEqualTo(value, def_value);
459 if (update) {
460 WMPutInPLDictionary(window, attr, value);
461 modified = 1;
464 return modified;
467 static void saveSettings(WMButton * button, InspectorPanel * panel)
469 WWindow *wwin = panel->inspected;
470 WDDomain *db = WDWindowAttributes;
471 WMPropList *dict = db->dictionary;
472 WMPropList *winDic, *appDic, *value, *key, *key2;
473 char *icon_file;
474 int flags = 0;
475 int different = 0, different2 = 0;
477 /* Save will apply the changes and save them */
478 applySettings(panel->applyBtn, panel);
480 if (WMGetButtonSelected(panel->instRb) != 0)
481 key = WMCreatePLString(wwin->wm_instance);
482 else if (WMGetButtonSelected(panel->clsRb) != 0)
483 key = WMCreatePLString(wwin->wm_class);
484 else if (WMGetButtonSelected(panel->bothRb) != 0) {
485 char *buffer;
487 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
488 key = WMCreatePLString(buffer);
489 wfree(buffer);
490 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
491 key = WMRetainPropList(AnyWindow);
492 flags = UPDATE_DEFAULTS;
493 } else
494 key = NULL;
496 if (!key)
497 return;
499 if (!dict) {
500 dict = WMCreatePLDictionary(NULL, NULL);
501 if (dict) {
502 db->dictionary = dict;
503 } else {
504 WMReleasePropList(key);
505 return;
509 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
510 return;
512 WMPLSetCaseSensitive(True);
514 winDic = WMCreatePLDictionary(NULL, NULL);
515 appDic = WMCreatePLDictionary(NULL, NULL);
517 /* Update icon for window */
518 icon_file = WMGetTextFieldText(panel->fileText);
519 if (icon_file) {
520 if (icon_file[0] != 0) {
521 value = WMCreatePLString(icon_file);
522 different |= insertAttribute(dict, winDic, AIcon, value, flags);
523 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
524 WMReleasePropList(value);
526 wfree(icon_file);
530 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
532 i--;
534 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
535 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
536 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
537 WMReleasePropList(value);
541 flags |= IS_BOOLEAN;
543 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
544 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
546 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
547 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
549 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
550 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
552 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
553 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
555 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
556 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
558 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
559 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
561 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
562 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
564 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
565 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
567 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
568 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
570 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
571 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
573 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
574 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
576 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
577 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
579 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
580 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
582 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
583 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
585 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
586 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
588 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
589 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
591 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
594 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
595 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
597 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
598 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
600 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
601 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
603 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
604 different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace, value, flags);
606 #ifdef XKB_BUTTON_HINT
607 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
608 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
609 #endif
611 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
612 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
613 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
615 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
616 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
618 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
619 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
622 if (wwin->fake_group) {
623 key2 = WMCreatePLString(wwin->fake_group->identifier);
624 if (WMIsPropListEqualTo(key, key2)) {
625 WMMergePLDictionaries(winDic, appDic, True);
626 different |= different2;
627 } else {
628 WMRemoveFromPLDictionary(dict, key2);
629 if (different2) {
630 WMPutInPLDictionary(dict, key2, appDic);
633 WMReleasePropList(key2);
634 WMReleasePropList(appDic);
635 } else if (wwin->main_window != wwin->client_win) {
636 WApplication *wapp = wApplicationOf(wwin->main_window);
638 if (wapp) {
639 char *instance = wapp->main_window_desc->wm_instance;
640 char *class = wapp->main_window_desc->wm_class;
641 char *buffer;
643 buffer = StrConcatDot(instance, class);
644 key2 = WMCreatePLString(buffer);
645 wfree(buffer);
647 if (WMIsPropListEqualTo(key, key2)) {
648 WMMergePLDictionaries(winDic, appDic, True);
649 different |= different2;
650 } else {
651 WMRemoveFromPLDictionary(dict, key2);
652 if (different2) {
653 WMPutInPLDictionary(dict, key2, appDic);
656 WMReleasePropList(key2);
657 WMReleasePropList(appDic);
659 } else {
660 WMMergePLDictionaries(winDic, appDic, True);
661 different |= different2;
662 WMReleasePropList(appDic);
665 WMRemoveFromPLDictionary(dict, key);
666 if (different) {
667 WMPutInPLDictionary(dict, key, winDic);
670 WMReleasePropList(key);
671 WMReleasePropList(winDic);
673 UpdateDomainFile(db);
675 /* clean up */
676 WMPLSetCaseSensitive(False);
679 static void makeAppIconFor(WApplication * wapp)
681 WScreen *scr = wapp->main_window_desc->screen_ptr;
683 if (wapp->app_icon)
684 return;
686 if (!WFLAGP(wapp->main_window_desc, no_appicon))
687 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
688 else
689 wapp->app_icon = NULL;
691 if (wapp->app_icon) {
692 WIcon *icon = wapp->app_icon->icon;
693 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
694 int x = 0, y = 0;
696 wapp->app_icon->main_window = wapp->main_window;
698 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
699 wapp->app_icon->attracted = 1;
700 if (!wapp->app_icon->icon->shadowed) {
701 wapp->app_icon->icon->shadowed = 1;
702 wapp->app_icon->icon->force_paint = 1;
704 wDockAttachIcon(clip, wapp->app_icon, x, y);
705 } else {
706 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
707 wAppIconMove(wapp->app_icon, x, y);
709 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
710 XMapWindow(dpy, icon->core->window);
712 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
713 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
717 static void removeAppIconFor(WApplication * wapp)
719 if (!wapp->app_icon)
720 return;
722 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
723 wapp->app_icon->running = 0;
724 /* since we keep it, we don't care if it was attracted or not */
725 wapp->app_icon->attracted = 0;
726 wapp->app_icon->icon->shadowed = 0;
727 wapp->app_icon->main_window = None;
728 wapp->app_icon->pid = 0;
729 wapp->app_icon->icon->owner = NULL;
730 wapp->app_icon->icon->icon_win = None;
731 wapp->app_icon->icon->force_paint = 1;
732 wAppIconPaint(wapp->app_icon);
733 } else if (wapp->app_icon->docked) {
734 wapp->app_icon->running = 0;
735 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
736 } else {
737 wAppIconDestroy(wapp->app_icon);
739 wapp->app_icon = NULL;
740 if (wPreferences.auto_arrange_icons)
741 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
744 static void applySettings(WMButton * button, InspectorPanel * panel)
746 WWindow *wwin = panel->inspected;
747 WApplication *wapp = wApplicationOf(wwin->main_window);
748 int floating, sunken, skip_window_list;
749 int old_omnipresent;
750 int old_no_bind_keys;
751 int old_no_bind_mouse;
753 old_omnipresent = WFLAGP(wwin, omnipresent);
754 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
755 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
757 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
759 /* Attributes... --> Window Attributes */
760 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
761 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
762 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
763 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
764 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
765 floating = WMGetButtonSelected(panel->attrChk[5]);
766 sunken = WMGetButtonSelected(panel->attrChk[6]);
767 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
768 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
769 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
770 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
772 /* Attributes... --> Advanced Options */
773 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
774 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
775 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
776 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
777 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
778 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
779 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
780 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
781 WSETUFLAG(wwin, dont_focus_across_wksp, WMGetButtonSelected(panel->moreChk[8]));
782 #ifdef XKB_BUTTON_HINT
783 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[9]));
784 #endif
785 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
787 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
788 wUnshadeWindow(wwin);
790 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
792 if (floating) {
793 if (!WFLAGP(wwin, floating))
794 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
795 } else if (sunken) {
796 if (!WFLAGP(wwin, sunken))
797 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
798 } else {
799 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
800 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
803 WSETUFLAG(wwin, sunken, sunken);
804 WSETUFLAG(wwin, floating, floating);
805 wwin->flags.omnipresent = 0;
807 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
808 WSETUFLAG(wwin, skip_window_list, skip_window_list);
809 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
810 } else {
811 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
812 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
816 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
817 if (WFLAGP(wwin, no_bind_keys)) {
818 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
819 } else {
820 wWindowSetKeyGrabs(wwin);
824 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
825 wWindowResetMouseGrabs(wwin);
828 wwin->frame->flags.need_texture_change = 1;
829 wWindowConfigureBorders(wwin);
830 wFrameWindowPaint(wwin->frame);
831 #ifdef NETWM_HINTS
832 wNETWMUpdateActions(wwin, False);
833 #endif
836 * Can't apply emulate_appicon because it will probably cause problems.
839 if (wapp) {
840 /* do application wide stuff */
841 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
843 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
845 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
847 if (WFLAGP(wapp->main_window_desc, no_appicon))
848 removeAppIconFor(wapp);
849 else
850 makeAppIconFor(wapp);
852 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
853 char *file = WMGetTextFieldText(panel->fileText);
855 if (file[0] == 0) {
856 wfree(file);
857 file = NULL;
859 wIconChangeImageFile(wapp->app_icon->icon, file);
860 if (file)
861 wfree(file);
862 wAppIconPaint(wapp->app_icon);
867 static void revertSettings(WMButton * button, InspectorPanel * panel)
869 WWindow *wwin = panel->inspected;
870 WApplication *wapp = wApplicationOf(wwin->main_window);
871 int i, n;
872 char *wm_instance = NULL;
873 char *wm_class = NULL;
874 int workspace, level;
876 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
877 wm_instance = wwin->wm_instance;
878 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
879 wm_class = wwin->wm_class;
880 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
881 wm_instance = wwin->wm_instance;
882 wm_class = wwin->wm_class;
884 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
885 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
886 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
888 wWindowSetupInitialAttributes(wwin, &level, &workspace);
890 for (i = 0; i < 11; i++) {
891 int flag = 0;
893 switch (i) {
894 case 0:
895 flag = WFLAGP(wwin, no_titlebar);
896 break;
897 case 1:
898 flag = WFLAGP(wwin, no_resizebar);
899 break;
900 case 2:
901 flag = WFLAGP(wwin, no_close_button);
902 break;
903 case 3:
904 flag = WFLAGP(wwin, no_miniaturize_button);
905 break;
906 case 4:
907 flag = WFLAGP(wwin, no_border);
908 break;
909 case 5:
910 flag = WFLAGP(wwin, floating);
911 break;
912 case 6:
913 flag = WFLAGP(wwin, sunken);
914 break;
915 case 7:
916 flag = WFLAGP(wwin, omnipresent);
917 break;
918 case 8:
919 flag = WFLAGP(wwin, start_miniaturized);
920 break;
921 case 9:
922 flag = WFLAGP(wwin, start_maximized != 0);
923 break;
924 case 10:
925 flag = WFLAGP(wwin, full_maximize);
926 break;
928 WMSetButtonSelected(panel->attrChk[i], flag);
930 for (i = 0; i < 9; i++) {
931 int flag = 0;
933 switch (i) {
934 case 0:
935 flag = WFLAGP(wwin, no_bind_keys);
936 break;
937 case 1:
938 flag = WFLAGP(wwin, no_bind_mouse);
939 break;
940 case 2:
941 flag = WFLAGP(wwin, skip_window_list);
942 break;
943 case 3:
944 flag = WFLAGP(wwin, no_focusable);
945 break;
946 case 4:
947 flag = WFLAGP(wwin, dont_move_off);
948 break;
949 case 5:
950 flag = WFLAGP(wwin, no_hide_others);
951 break;
952 case 6:
953 flag = WFLAGP(wwin, dont_save_session);
954 break;
955 case 7:
956 flag = WFLAGP(wwin, emulate_appicon);
957 break;
958 case 8:
959 flag = WFLAGP(wwin, dont_focus_across_wksp);
960 break;
961 #ifdef XKB_BUTTON_HINT
962 case 9:
963 flag = WFLAGP(wwin, no_language_button);
964 break;
965 #endif
967 WMSetButtonSelected(panel->moreChk[i], flag);
969 if (panel->appFrm && wapp) {
970 for (i = 0; i < 2; i++) {
971 int flag = 0;
973 switch (i) {
974 case 0:
975 flag = WFLAGP(wapp->main_window_desc, start_hidden);
976 break;
977 case 1:
978 flag = WFLAGP(wapp->main_window_desc, no_appicon);
979 break;
980 case 2:
981 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
982 break;
984 WMSetButtonSelected(panel->appChk[i], flag);
987 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
989 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
991 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
993 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
994 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
995 } else {
996 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
999 /* must auto apply, so that there wno't be internal
1000 * inconsistencies between the state in the flags and
1001 * the actual state of the window */
1002 applySettings(panel->applyBtn, panel);
1005 static void chooseIconCallback(WMWidget * self, void *clientData)
1007 char *file;
1008 InspectorPanel *panel = (InspectorPanel *) clientData;
1009 int result;
1011 panel->choosingIcon = 1;
1013 WMSetButtonEnabled(panel->browseIconBtn, False);
1015 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1016 panel->inspected->wm_instance, panel->inspected->wm_class);
1018 panel->choosingIcon = 0;
1020 if (!panel->destroyed) { /* kluge */
1021 if (result) {
1022 WMSetTextFieldText(panel->fileText, file);
1023 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1024 wfree(file);
1026 WMSetButtonEnabled(panel->browseIconBtn, True);
1027 } else {
1028 freeInspector(panel);
1032 static void textEditedObserver(void *observerData, WMNotification * notification)
1034 InspectorPanel *panel = (InspectorPanel *) observerData;
1036 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1037 return;
1039 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1041 WMPerformButtonClick(panel->updateIconBtn);
1045 static void selectSpecification(WMWidget * bPtr, void *data)
1047 InspectorPanel *panel = (InspectorPanel *) data;
1048 char *str;
1049 WWindow *wwin = panel->inspected;
1050 int len;
1052 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1053 WMSetButtonEnabled(panel->applyBtn, False);
1054 } else {
1055 WMSetButtonEnabled(panel->applyBtn, True);
1058 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1059 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1061 str = wmalloc(len);
1063 snprintf(str, len, _("Inspecting %s.%s"),
1064 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1066 wFrameWindowChangeTitle(panel->frame->frame, str);
1068 wfree(str);
1071 static void selectWindow(WMWidget * bPtr, void *data)
1073 InspectorPanel *panel = (InspectorPanel *) data;
1074 WWindow *wwin = panel->inspected;
1075 WScreen *scr = wwin->screen_ptr;
1076 XEvent event;
1077 WWindow *iwin;
1079 if (XGrabPointer(dpy, scr->root_win, True,
1080 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1081 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1082 wwarning("could not grab mouse pointer");
1083 return;
1086 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1088 WMMaskEvent(dpy, ButtonPressMask, &event);
1090 XUngrabPointer(dpy, CurrentTime);
1092 iwin = wWindowFor(event.xbutton.subwindow);
1094 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1096 iwin->flags.inspector_open = 1;
1097 iwin->inspector = createInspectorForWindow(iwin,
1098 panel->frame->frame_x, panel->frame->frame_y, True);
1099 wCloseInspectorForWindow(wwin);
1100 } else {
1101 WMSetLabelText(panel->specLbl, spec_text);
1105 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1107 WScreen *scr = wwin->screen_ptr;
1108 InspectorPanel *panel;
1109 Window parent;
1110 int i;
1111 int x, y;
1112 int btn_width, frame_width;
1113 WMButton *selectedBtn = NULL;
1114 #ifdef wrong_behaviour
1115 WMPixmap *pixmap;
1116 #endif
1118 spec_text = _("The configuration will apply to all\n"
1119 "windows that have their WM_CLASS\n"
1120 "property set to the above selected\n" "name, when saved.");
1122 panel = wmalloc(sizeof(InspectorPanel));
1123 memset(panel, 0, sizeof(InspectorPanel));
1125 panel->destroyed = 0;
1127 panel->inspected = wwin;
1129 panel->nextPtr = panelList;
1130 panelList = panel;
1132 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1133 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1135 /**** create common stuff ****/
1137 /* command buttons */
1138 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1139 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1140 panel->saveBtn = WMCreateCommandButton(panel->win);
1141 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1142 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1143 WMSetButtonText(panel->saveBtn, _("Save"));
1144 WMResizeWidget(panel->saveBtn, btn_width, 28);
1145 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1146 WMSetButtonEnabled(panel->saveBtn, False);
1148 panel->applyBtn = WMCreateCommandButton(panel->win);
1149 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1150 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1151 WMSetButtonText(panel->applyBtn, _("Apply"));
1152 WMResizeWidget(panel->applyBtn, btn_width, 28);
1154 panel->revertBtn = WMCreateCommandButton(panel->win);
1155 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1156 WMMoveWidget(panel->revertBtn, 15, 310);
1157 WMSetButtonText(panel->revertBtn, _("Reload"));
1158 WMResizeWidget(panel->revertBtn, btn_width, 28);
1160 /* page selection popup button */
1161 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1162 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1163 WMMoveWidget(panel->pagePopUp, 25, 15);
1164 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1166 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1167 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1168 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1169 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1170 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1172 /**** window spec ****/
1173 frame_width = PWIDTH - (2 * 15);
1175 panel->specFrm = WMCreateFrame(panel->win);
1176 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1177 WMMoveWidget(panel->specFrm, 15, 65);
1178 WMResizeWidget(panel->specFrm, frame_width, 145);
1180 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1181 WMMoveWidget(panel->defaultRb, 10, 78);
1182 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1183 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1184 WMSetButtonSelected(panel->defaultRb, False);
1185 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1187 if (wwin->wm_class && wwin->wm_instance) {
1188 char *str, *tmp;
1190 tmp = wstrconcat(wwin->wm_instance, ".");
1191 str = wstrconcat(tmp, wwin->wm_class);
1193 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1194 WMMoveWidget(panel->bothRb, 10, 18);
1195 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1196 WMSetButtonText(panel->bothRb, str);
1197 wfree(tmp);
1198 wfree(str);
1199 WMGroupButtons(panel->defaultRb, panel->bothRb);
1201 if (!selectedBtn)
1202 selectedBtn = panel->bothRb;
1204 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1207 if (wwin->wm_instance) {
1208 panel->instRb = WMCreateRadioButton(panel->specFrm);
1209 WMMoveWidget(panel->instRb, 10, 38);
1210 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1211 WMSetButtonText(panel->instRb, wwin->wm_instance);
1212 WMGroupButtons(panel->defaultRb, panel->instRb);
1214 if (!selectedBtn)
1215 selectedBtn = panel->instRb;
1217 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1220 if (wwin->wm_class) {
1221 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1222 WMMoveWidget(panel->clsRb, 10, 58);
1223 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1224 WMSetButtonText(panel->clsRb, wwin->wm_class);
1225 WMGroupButtons(panel->defaultRb, panel->clsRb);
1227 if (!selectedBtn)
1228 selectedBtn = panel->clsRb;
1230 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1233 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1234 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1235 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1236 WMSetButtonText(panel->selWinB, _("Select window"));
1237 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1239 panel->specLbl = WMCreateLabel(panel->win);
1240 WMMoveWidget(panel->specLbl, 15, 210);
1241 WMResizeWidget(panel->specLbl, frame_width, 100);
1242 WMSetLabelText(panel->specLbl, spec_text);
1243 WMSetLabelWraps(panel->specLbl, True);
1245 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1247 /**** attributes ****/
1248 panel->attrFrm = WMCreateFrame(panel->win);
1249 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1250 WMMoveWidget(panel->attrFrm, 15, 45);
1251 WMResizeWidget(panel->attrFrm, frame_width, 250);
1253 for (i = 0; i < 11; i++) {
1254 char *caption = NULL;
1255 int flag = 0;
1256 char *descr = NULL;
1258 switch (i) {
1259 case 0:
1260 caption = _("Disable titlebar");
1261 flag = WFLAGP(wwin, no_titlebar);
1262 descr = _("Remove the titlebar of this window.\n"
1263 "To access the window commands menu of a window\n"
1264 "without it's titlebar, press Control+Esc (or the\n"
1265 "equivalent shortcut, if you changed the default\n" "settings).");
1266 break;
1267 case 1:
1268 caption = _("Disable resizebar");
1269 flag = WFLAGP(wwin, no_resizebar);
1270 descr = _("Remove the resizebar of this window.");
1271 break;
1272 case 2:
1273 caption = _("Disable close button");
1274 flag = WFLAGP(wwin, no_close_button);
1275 descr = _("Remove the `close window' button of this window.");
1276 break;
1277 case 3:
1278 caption = _("Disable miniaturize button");
1279 flag = WFLAGP(wwin, no_miniaturize_button);
1280 descr = _("Remove the `miniaturize window' button of the window.");
1281 break;
1282 case 4:
1283 caption = _("Disable border");
1284 flag = WFLAGP(wwin, no_border);
1285 descr = _("Remove the 1 pixel black border around the window.");
1286 break;
1287 case 5:
1288 caption = _("Keep on top (floating)");
1289 flag = WFLAGP(wwin, floating);
1290 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1291 break;
1292 case 6:
1293 caption = _("Keep at bottom (sunken)");
1294 flag = WFLAGP(wwin, sunken);
1295 descr = _("Keep the window under all other windows.");
1296 break;
1297 case 7:
1298 caption = _("Omnipresent");
1299 flag = WFLAGP(wwin, omnipresent);
1300 descr = _("Make window present in all workspaces.");
1301 break;
1302 case 8:
1303 caption = _("Start miniaturized");
1304 flag = WFLAGP(wwin, start_miniaturized);
1305 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1306 break;
1307 case 9:
1308 caption = _("Start maximized");
1309 flag = WFLAGP(wwin, start_maximized != 0);
1310 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1311 break;
1312 case 10:
1313 caption = _("Full screen maximization");
1314 flag = WFLAGP(wwin, full_maximize);
1315 descr = _("Make the window use the whole screen space when it's\n"
1316 "maximized. The titlebar and resizebar will be moved\n"
1317 "to outside the screen.");
1318 break;
1320 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1321 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1322 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1323 WMSetButtonSelected(panel->attrChk[i], flag);
1324 WMSetButtonText(panel->attrChk[i], caption);
1326 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1329 /**** more attributes ****/
1330 panel->moreFrm = WMCreateFrame(panel->win);
1331 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1332 WMMoveWidget(panel->moreFrm, 15, 45);
1333 WMResizeWidget(panel->moreFrm, frame_width, 250);
1335 for (i = 0;
1336 #ifdef XKB_BUTTON_HINT
1337 i < 10;
1338 #else
1339 i < 9;
1340 #endif
1341 i++) {
1342 char *caption = NULL;
1343 int flag = 0;
1344 char *descr = NULL;
1346 switch (i) {
1347 case 0:
1348 caption = _("Do not bind keyboard shortcuts");
1349 flag = WFLAGP(wwin, no_bind_keys);
1350 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1351 "when this window is focused. This will allow the\n"
1352 "window to receive all key combinations regardless\n"
1353 "of your shortcut configuration.");
1354 break;
1355 case 1:
1356 caption = _("Do not bind mouse clicks");
1357 flag = WFLAGP(wwin, no_bind_mouse);
1358 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1359 "in the window (when alt is the modifier you have\n" "configured).");
1360 break;
1361 case 2:
1362 caption = _("Do not show in the window list");
1363 flag = WFLAGP(wwin, skip_window_list);
1364 descr = _("Do not list the window in the window list menu.");
1365 break;
1366 case 3:
1367 caption = _("Do not let it take focus");
1368 flag = WFLAGP(wwin, no_focusable);
1369 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1370 break;
1371 case 4:
1372 caption = _("Keep inside screen");
1373 flag = WFLAGP(wwin, dont_move_off);
1374 descr = _("Do not allow the window to move itself completely\n"
1375 "outside the screen. For bug compatibility.\n");
1376 break;
1377 case 5:
1378 caption = _("Ignore 'Hide Others'");
1379 flag = WFLAGP(wwin, no_hide_others);
1380 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1381 break;
1382 case 6:
1383 caption = _("Ignore 'Save Session'");
1384 flag = WFLAGP(wwin, dont_save_session);
1385 descr = _("Do not save the associated application in the\n"
1386 "session's state, so that it won't be restarted\n"
1387 "together with other applications when Window Maker\n" "starts.");
1388 break;
1389 case 7:
1390 caption = _("Emulate application icon");
1391 flag = WFLAGP(wwin, emulate_appicon);
1392 descr = _("Make this window act as an application that provides\n"
1393 "enough information to Window Maker for a dockable\n"
1394 "application icon to be created.");
1395 break;
1396 case 8:
1397 caption = _("Don't focus across workspaces");
1398 flag = WFLAGP(wwin, dont_focus_across_wksp);
1399 descr = _("Do not allow Window Maker to switch workspace to satisfy\n"
1400 "a focus request (useful e.g. in the case of a multiple-tab\n"
1401 "firefox opening in a different workspace).");
1402 break;
1403 #ifdef XKB_BUTTON_HINT
1404 case 9:
1405 caption = _("Disable language button");
1406 flag = WFLAGP(wwin, no_language_button);
1407 descr = _("Remove the `toggle language' button of the window.");
1408 break;
1409 #endif
1411 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1412 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1413 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1414 WMSetButtonSelected(panel->moreChk[i], flag);
1415 WMSetButtonText(panel->moreChk[i], caption);
1417 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1420 /* miniwindow/workspace */
1421 panel->iconFrm = WMCreateFrame(panel->win);
1422 WMMoveWidget(panel->iconFrm, 15, 50);
1423 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1424 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1426 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1427 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1428 WMResizeWidget(panel->iconLbl, 64, 64);
1429 WMSetLabelRelief(panel->iconLbl, WRGroove);
1430 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1432 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1433 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1434 WMMoveWidget(panel->browseIconBtn, 22, 32);
1435 WMResizeWidget(panel->browseIconBtn, 120, 26);
1436 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1438 #ifdef wrong_behaviour
1439 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1440 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1441 WMSetButtonImage(panel->updateIconBtn, pixmap);
1442 WMReleasePixmap(pixmap);
1443 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1444 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1445 WMReleasePixmap(pixmap);
1446 #endif
1448 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1449 WMMoveWidget(panel->fileLbl, 20, 85);
1450 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1451 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1453 panel->fileText = WMCreateTextField(panel->iconFrm);
1454 WMMoveWidget(panel->fileText, 20, 105);
1455 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1456 WMSetTextFieldText(panel->fileText, NULL);
1457 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1459 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1460 WMMoveWidget(panel->alwChk, 20, 130);
1461 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1462 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1463 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1465 panel->wsFrm = WMCreateFrame(panel->win);
1466 WMMoveWidget(panel->wsFrm, 15, 225);
1467 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1468 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1470 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1471 "first shown."), WMWidgetView(panel->wsFrm));
1473 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1474 WMMoveWidget(panel->wsP, 20, 30);
1475 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1476 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1477 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1478 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1481 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1482 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1483 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1484 } else {
1485 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1488 /* application wide attributes */
1489 if (wwin->main_window != None) {
1490 WApplication *wapp = wApplicationOf(wwin->main_window);
1492 panel->appFrm = WMCreateFrame(panel->win);
1493 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1494 WMMoveWidget(panel->appFrm, 15, 50);
1495 WMResizeWidget(panel->appFrm, frame_width, 240);
1497 for (i = 0; i < 3; i++) {
1498 char *caption = NULL;
1499 int flag = 0;
1500 char *descr = NULL;
1502 switch (i) {
1503 case 0:
1504 caption = _("Start hidden");
1505 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1506 descr = _("Automatically hide application when it's started.");
1507 break;
1508 case 1:
1509 caption = _("No application icon");
1510 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1511 descr = _("Disable the application icon for the application.\n"
1512 "Note that you won't be able to dock it anymore,\n"
1513 "and any icons that are already docked will stop\n"
1514 "working correctly.");
1515 break;
1516 case 2:
1517 caption = _("Shared application icon");
1518 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1519 descr = _("Use a single shared application icon for all of\n"
1520 "the instances of this application.\n");
1521 break;
1523 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1524 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1525 WMResizeWidget(panel->appChk[i], 205, 20);
1526 WMSetButtonSelected(panel->appChk[i], flag);
1527 WMSetButtonText(panel->appChk[i], caption);
1529 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1532 if (WFLAGP(wwin, emulate_appicon)) {
1533 WMSetButtonEnabled(panel->appChk[1], False);
1534 WMSetButtonEnabled(panel->moreChk[7], True);
1535 } else {
1536 WMSetButtonEnabled(panel->appChk[1], True);
1537 WMSetButtonEnabled(panel->moreChk[7], False);
1539 } else {
1540 int tmp;
1542 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1543 || !wwin->wm_class || !wwin->wm_instance)
1544 tmp = False;
1545 else
1546 tmp = True;
1547 WMSetButtonEnabled(panel->moreChk[7], tmp);
1549 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1550 panel->appFrm = NULL;
1553 /* if the window is a transient, don't let it have a miniaturize
1554 * button */
1555 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1556 WMSetButtonEnabled(panel->attrChk[3], False);
1557 else
1558 WMSetButtonEnabled(panel->attrChk[3], True);
1560 if (!wwin->wm_class && !wwin->wm_instance) {
1561 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1564 WMRealizeWidget(panel->win);
1566 WMMapSubwidgets(panel->win);
1567 WMMapSubwidgets(panel->specFrm);
1568 WMMapSubwidgets(panel->attrFrm);
1569 WMMapSubwidgets(panel->moreFrm);
1570 WMMapSubwidgets(panel->iconFrm);
1571 WMMapSubwidgets(panel->wsFrm);
1572 if (panel->appFrm)
1573 WMMapSubwidgets(panel->appFrm);
1575 if (showSelectPanel) {
1576 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1577 changePage(panel->pagePopUp, panel);
1578 } else {
1579 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1580 changePage(panel->pagePopUp, panel);
1583 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1584 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1585 panel->parent = parent;
1586 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1588 WMMapWidget(panel->win);
1590 XSetTransientForHint(dpy, parent, wwin->client_win);
1592 if (xpos == UNDEFINED_POS) {
1593 x = wwin->frame_x + wwin->frame->core->width / 2;
1594 y = wwin->frame_y + wwin->frame->top_width * 2;
1595 if (y + PHEIGHT > scr->scr_height)
1596 y = scr->scr_height - PHEIGHT - 30;
1597 if (x + PWIDTH > scr->scr_width)
1598 x = scr->scr_width - PWIDTH;
1599 } else {
1600 x = xpos;
1601 y = ypos;
1604 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1606 if (!selectedBtn)
1607 selectedBtn = panel->defaultRb;
1609 WMSetButtonSelected(selectedBtn, True);
1611 selectSpecification(selectedBtn, panel);
1613 /* kluge to know who should get the key events */
1614 panel->frame->client_leader = WMWidgetXID(panel->win);
1616 WSETUFLAG(panel->frame, no_closable, 0);
1617 WSETUFLAG(panel->frame, no_close_button, 0);
1618 wWindowUpdateButtonImages(panel->frame);
1619 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1620 panel->frame->frame->on_click_right = destroyInspector;
1622 wWindowMap(panel->frame);
1624 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1626 return panel;
1629 void wShowInspectorForWindow(WWindow * wwin)
1631 if (wwin->flags.inspector_open)
1632 return;
1634 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1636 make_keys();
1637 wwin->flags.inspector_open = 1;
1638 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1641 void wHideInspectorForWindow(WWindow * wwin)
1643 WWindow *pwin = wwin->inspector->frame;
1645 wWindowUnmap(pwin);
1646 pwin->flags.hidden = 1;
1648 wClientSetState(pwin, IconicState, None);
1651 void wUnhideInspectorForWindow(WWindow * wwin)
1653 WWindow *pwin = wwin->inspector->frame;
1655 pwin->flags.hidden = 0;
1656 pwin->flags.mapped = 1;
1657 XMapWindow(dpy, pwin->client_win);
1658 XMapWindow(dpy, pwin->frame->core->window);
1659 wClientSetState(pwin, NormalState, None);
1662 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1664 if (wwin->inspector) {
1665 assert(wwin->flags.inspector_open != 0);
1667 return wwin->inspector->frame;
1668 } else
1669 return NULL;
1672 void wCloseInspectorForWindow(WWindow * wwin)
1674 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1676 (*pwin->frame->on_click_right) (NULL, pwin, NULL);