- fixed crash when saving window attributes
[wmaker-crm.git] / src / winspector.c
blobeec6673628e0ab71603ada2d9af0939311b620ba
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997-2002 Alfredo K. Kojima
6 * Copyright (c) 1998-2002 Dan Pascu
7 *
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"
51 #include <WINGs/WUtil.h>
59 typedef struct InspectorPanel {
60 struct InspectorPanel *nextPtr;
62 WWindow *frame;
64 WWindow *inspected; /* the window that's being inspected */
66 WMWindow *win;
68 Window parent;
70 /* common stuff */
71 WMButton *revertBtn;
72 WMButton *applyBtn;
73 WMButton *saveBtn;
75 WMPopUpButton *pagePopUp;
77 /* first page. general stuff */
79 WMFrame *specFrm;
80 WMButton *instRb;
81 WMButton *clsRb;
82 WMButton *bothRb;
83 WMButton *defaultRb;
85 WMButton *selWinB;
87 WMLabel *specLbl;
89 /* second page. attributes */
91 WMFrame *attrFrm;
92 WMButton *attrChk[11];
94 /* 3rd page. more attributes */
95 WMFrame *moreFrm;
96 #ifdef XKB_BUTTON_HINT
97 WMButton *moreChk[9];
98 #else
99 WMButton *moreChk[8];
100 #endif
102 /* 4th page. icon and workspace */
103 WMFrame *iconFrm;
104 WMLabel *iconLbl;
105 WMLabel *fileLbl;
106 WMTextField *fileText;
107 WMButton *alwChk;
109 WMButton *updateIconBtn;
111 WMButton *browseIconBtn;
113 WMFrame *wsFrm;
114 WMPopUpButton *wsP;
116 /* 5th page. application wide attributes */
117 WMFrame *appFrm;
118 WMButton *appChk[3];
120 unsigned int done:1;
121 unsigned int destroyed:1;
122 unsigned int choosingIcon:1;
123 } InspectorPanel;
128 extern Cursor wCursor[WCUR_LAST];
130 extern WDDomain *WDWindowAttributes;
132 static InspectorPanel *panelList=NULL;
134 extern WPreferences wPreferences;
136 static WMPropList *ANoTitlebar = NULL;
137 static WMPropList *ANoResizebar;
138 static WMPropList *ANoMiniaturizeButton;
139 static WMPropList *ANoCloseButton;
140 static WMPropList *ANoBorder;
141 static WMPropList *ANoHideOthers;
142 static WMPropList *ANoMouseBindings;
143 static WMPropList *ANoKeyBindings;
144 static WMPropList *ANoAppIcon;
145 static WMPropList *AKeepOnTop;
146 static WMPropList *AKeepOnBottom;
147 static WMPropList *AOmnipresent;
148 static WMPropList *ASkipWindowList;
149 static WMPropList *AKeepInsideScreen;
150 static WMPropList *AUnfocusable;
151 static WMPropList *AAlwaysUserIcon;
152 static WMPropList *AStartMiniaturized;
153 static WMPropList *AStartMaximized;
154 static WMPropList *ADontSaveSession;
155 static WMPropList *AEmulateAppIcon;
156 static WMPropList *AFullMaximize;
157 static WMPropList *ASharedAppIcon;
158 #ifdef XKB_BUTTON_HINT
159 static WMPropList *ANoLanguageButton;
160 #endif
162 static WMPropList *AStartWorkspace;
164 static WMPropList *AIcon;
166 /* application wide options */
167 static WMPropList *AStartHidden;
170 static WMPropList *AnyWindow;
171 static WMPropList *EmptyString;
172 static WMPropList *Yes, *No;
175 #define PWIDTH 270
176 #define PHEIGHT 350
180 static char *spec_text;
183 static void applySettings(WMButton *button, InspectorPanel *panel);
188 #define UNDEFINED_POS 0xffffff
190 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
191 int xpos, int ypos,
192 Bool showSelectPanel);
196 static void
197 make_keys()
199 if (ANoTitlebar!=NULL)
200 return;
202 AIcon = WMCreatePLString("Icon");
203 ANoTitlebar = WMCreatePLString("NoTitlebar");
204 ANoResizebar = WMCreatePLString("NoResizebar");
205 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
206 ANoCloseButton = WMCreatePLString("NoCloseButton");
207 ANoBorder = WMCreatePLString("NoBorder");
208 ANoHideOthers = WMCreatePLString("NoHideOthers");
209 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
210 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
211 ANoAppIcon = WMCreatePLString("NoAppIcon");
212 AKeepOnTop = WMCreatePLString("KeepOnTop");
213 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
214 AOmnipresent = WMCreatePLString("Omnipresent");
215 ASkipWindowList = WMCreatePLString("SkipWindowList");
216 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
217 AUnfocusable = WMCreatePLString("Unfocusable");
218 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
219 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
220 AStartMaximized = WMCreatePLString("StartMaximized");
221 AStartHidden = WMCreatePLString("StartHidden");
222 ADontSaveSession = WMCreatePLString("DontSaveSession");
223 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
224 AFullMaximize = WMCreatePLString("FullMaximize");
225 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
226 #ifdef XKB_BUTTON_HINT
227 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
228 #endif
230 AStartWorkspace = WMCreatePLString("StartWorkspace");
232 AnyWindow = WMCreatePLString("*");
233 EmptyString = WMCreatePLString("");
234 Yes = WMCreatePLString("Yes");
235 No = WMCreatePLString("No");
240 static void
241 freeInspector(InspectorPanel *panel)
243 panel->destroyed = 1;
244 if (panel->choosingIcon)
245 return;
247 WMDestroyWidget(panel->win);
249 XDestroyWindow(dpy, panel->parent);
251 wfree(panel);
255 static void
256 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
258 InspectorPanel *panel;
259 InspectorPanel *tmp;
261 panel = panelList;
262 while (panel->frame!=data)
263 panel = panel->nextPtr;
265 if (panelList == panel)
266 panelList = panel->nextPtr;
267 else {
268 tmp = panelList;
269 while (tmp->nextPtr!=panel) {
270 tmp = tmp->nextPtr;
272 tmp->nextPtr = panel->nextPtr;
274 panel->inspected->flags.inspector_open = 0;
275 panel->inspected->inspector = NULL;
277 WMRemoveNotificationObserver(panel);
279 wWindowUnmap(panel->frame);
280 wUnmanageWindow(panel->frame, True, False);
282 freeInspector(panel);
287 void
288 wDestroyInspectorPanels()
290 InspectorPanel *panel;
292 while (panelList != NULL) {
293 panel = panelList;
294 panelList = panelList->nextPtr;
295 wUnmanageWindow(panel->frame, False, False);
296 WMDestroyWidget(panel->win);
298 panel->inspected->flags.inspector_open = 0;
299 panel->inspected->inspector = NULL;
301 wfree(panel);
306 static void
307 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
309 int page;
311 page = WMGetPopUpButtonSelectedItem(bPtr);
313 if (page == 0) {
314 WMMapWidget(panel->specFrm);
315 WMMapWidget(panel->specLbl);
316 } else if (page == 1) {
317 WMMapWidget(panel->attrFrm);
318 } else if (page == 2) {
319 WMMapWidget(panel->moreFrm);
320 } else if (page == 3) {
321 WMMapWidget(panel->iconFrm);
322 WMMapWidget(panel->wsFrm);
323 } else {
324 WMMapWidget(panel->appFrm);
327 if (page != 0) {
328 WMUnmapWidget(panel->specFrm);
329 WMUnmapWidget(panel->specLbl);
331 if (page != 1)
332 WMUnmapWidget(panel->attrFrm);
333 if (page != 2)
334 WMUnmapWidget(panel->moreFrm);
335 if (page != 3) {
336 WMUnmapWidget(panel->iconFrm);
337 WMUnmapWidget(panel->wsFrm);
339 if (page != 4 && panel->appFrm)
340 WMUnmapWidget(panel->appFrm);
344 #define USE_TEXT_FIELD 1
345 #define UPDATE_TEXT_FIELD 2
346 #define REVERT_TO_DEFAULT 4
349 static int
350 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
351 char *wm_instance, char *wm_class, int flags)
353 WMPixmap *pixmap = (WMPixmap*) NULL;
354 char *file=NULL, *path=NULL;
355 char *db_icon=NULL;
357 if ((flags & USE_TEXT_FIELD) != 0) {
358 file = WMGetTextFieldText(panel->fileText);
359 if (file && file[0] == 0) {
360 wfree(file);
361 file = NULL;
363 } else {
364 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
365 wm_instance, wm_class, False);
366 if(db_icon != NULL)
367 file = wstrdup(db_icon);
369 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
370 if (file)
371 file = wstrdup(db_icon);
372 flags |= UPDATE_TEXT_FIELD;
375 if ((flags & UPDATE_TEXT_FIELD) != 0) {
376 WMSetTextFieldText(panel->fileText, file);
379 if (file) {
380 path = FindImage(wPreferences.icon_path, file);
382 if (!path) {
383 char *buf;
384 int len = strlen(file)+80;
386 buf = wmalloc(len);
387 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"),
388 file);
389 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
390 _("OK"), NULL, NULL);
391 wfree(buf);
392 wfree(file);
393 return -1;
396 pixmap = WMCreatePixmapFromFile(scrPtr, path);
397 wfree(path);
399 if (!pixmap) {
400 char *buf;
401 int len = strlen(file)+80;
403 buf = wmalloc(len);
404 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
405 file, RMessageForError(RErrorCode));
406 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
407 _("OK"), NULL, NULL);
408 wfree(buf);
409 wfree(file);
410 return -1;
412 wfree(file);
415 WMSetLabelImage(panel->iconLbl, pixmap);
416 if (pixmap)
417 WMReleasePixmap(pixmap);
419 return 0;
422 #if 0
423 static void
424 updateIcon(WMButton *button, InspectorPanel *panel)
426 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
428 #endif
430 static int
431 getBool(WMPropList *value)
433 char *val;
435 if (!WMIsPLString(value)) {
436 return 0;
438 if (!(val = WMGetFromPLString(value))) {
439 return 0;
442 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
443 || val[0]=='t' || val[0]=='1'))
444 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
446 return 1;
447 } else if ((val[1]=='\0'
448 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
449 || val[0]=='f' || val[0]=='0'))
450 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
452 return 0;
453 } else {
454 wwarning(_("can't convert \"%s\" to boolean"), val);
455 return 0;
460 #define UPDATE_DEFAULTS 1
461 #define IS_BOOLEAN 2
465 * Will insert the attribute = value; pair in window's list,
466 * if it's different from the defaults.
467 * Defaults means either defaults database, or attributes saved
468 * for the default window "*". This is to let one revert options that are
469 * global because they were saved for all windows ("*").
474 static int
475 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr,
476 WMPropList *value, int flags)
478 WMPropList *def_win, *def_value=NULL;
479 int update = 0;
480 int modified = 0;
482 if (!(flags & UPDATE_DEFAULTS) && dict) {
483 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
484 def_value = WMGetFromPLDictionary(def_win, attr);
488 /* If we could not find defaults in database, fall to hardcoded values.
489 * Also this is true if we save defaults for all windows
491 if (!def_value)
492 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
494 if ((flags & IS_BOOLEAN))
495 update = (getBool(value) != getBool(def_value));
496 else {
497 update = !WMIsPropListEqualTo(value, def_value);
500 if (update) {
501 WMPutInPLDictionary(window, attr, value);
502 modified = 1;
505 return modified;
509 static void
510 saveSettings(WMButton *button, InspectorPanel *panel)
512 WWindow *wwin = panel->inspected;
513 WDDomain *db = WDWindowAttributes;
514 WMPropList *dict = db->dictionary;
515 WMPropList *winDic, *appDic, *value, *key, *key2;
516 char *icon_file;
517 int flags = 0;
518 int different = 0, different2 = 0;
520 /* Save will apply the changes and save them */
521 applySettings(panel->applyBtn, panel);
523 if (WMGetButtonSelected(panel->instRb) != 0)
524 key = WMCreatePLString(wwin->wm_instance);
525 else if (WMGetButtonSelected(panel->clsRb) != 0)
526 key = WMCreatePLString(wwin->wm_class);
527 else if (WMGetButtonSelected(panel->bothRb) != 0) {
528 char *buffer;
530 buffer = wmalloc(strlen(wwin->wm_instance)+strlen(wwin->wm_class)+2);
531 sprintf(buffer, "%s.%s", wwin->wm_instance, wwin->wm_class);
532 key = WMCreatePLString(buffer);
533 wfree(buffer);
534 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
535 key = WMRetainPropList(AnyWindow);
536 flags = UPDATE_DEFAULTS;
537 } else
538 key = NULL;
540 if (!key)
541 return;
543 if (!dict) {
544 dict = WMCreatePLDictionary(NULL, NULL, NULL);
545 if (dict) {
546 db->dictionary = dict;
547 } else {
548 WMReleasePropList(key);
549 return;
553 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
554 USE_TEXT_FIELD) < 0)
555 return;
557 WMPLSetCaseSensitive(True);
559 winDic = WMCreatePLDictionary(NULL, NULL, NULL);
560 appDic = WMCreatePLDictionary(NULL, NULL, NULL);
562 /* Update icon for window */
563 icon_file = WMGetTextFieldText(panel->fileText);
564 if (icon_file) {
565 if (icon_file[0] != 0) {
566 value = WMCreatePLString(icon_file);
567 different |= insertAttribute(dict, winDic, AIcon, value, flags);
568 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
569 WMReleasePropList(value);
571 wfree(icon_file);
575 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
577 i--;
579 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
580 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
581 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
582 flags);
583 WMReleasePropList(value);
587 flags |= IS_BOOLEAN;
589 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
590 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
592 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
593 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
595 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
596 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
598 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
599 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
601 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
602 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
604 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
605 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
607 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
608 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
610 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
611 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
613 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
614 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
616 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
617 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
619 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
620 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
622 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
623 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
626 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
627 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
629 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
630 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
632 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
633 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
635 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
636 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
638 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
639 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
641 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
642 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
644 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
645 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
647 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
648 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
650 #ifdef XKB_BUTTON_HINT
651 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
652 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
653 #endif
655 if (wwin->main_window!=None && wApplicationOf(wwin->main_window)!=NULL) {
656 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
657 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
659 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
660 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
662 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
663 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
666 if (wwin->fake_group) {
667 key2 = WMCreatePLString(wwin->fake_group->identifier);
668 if (WMIsPropListEqualTo(key, key2)) {
669 WMMergePLDictionaries(winDic, appDic, True);
670 different |= different2;
671 } else {
672 WMRemoveFromPLDictionary(dict, key2);
673 if (different2) {
674 WMPutInPLDictionary(dict, key2, appDic);
677 WMReleasePropList(key2);
678 WMReleasePropList(appDic);
679 } else if (wwin->main_window != wwin->client_win) {
680 WApplication *wapp = wApplicationOf(wwin->main_window);
682 if (wapp) {
683 char *instance = wapp->main_window_desc->wm_instance;
684 char *class = wapp->main_window_desc->wm_class;
685 char *buffer;
687 buffer = wmalloc(strlen(instance)+strlen(class)+2);
688 sprintf(buffer, "%s.%s", instance, class);
689 key2 = WMCreatePLString(buffer);
690 wfree(buffer);
692 if (WMIsPropListEqualTo(key, key2)) {
693 WMMergePLDictionaries(winDic, appDic, True);
694 different |= different2;
695 } else {
696 WMRemoveFromPLDictionary(dict, key2);
697 if (different2) {
698 WMPutInPLDictionary(dict, key2, appDic);
701 WMReleasePropList(key2);
702 WMReleasePropList(appDic);
704 } else {
705 WMMergePLDictionaries(winDic, appDic, True);
706 different |= different2;
707 WMReleasePropList(appDic);
710 WMRemoveFromPLDictionary(dict, key);
711 if (different) {
712 WMPutInPLDictionary(dict, key, winDic);
715 WMReleasePropList(key);
716 WMReleasePropList(winDic);
718 UpdateDomainFile(db);
720 /* clean up */
721 WMPLSetCaseSensitive(False);
725 static void
726 makeAppIconFor(WApplication *wapp)
728 WScreen *scr = wapp->main_window_desc->screen_ptr;
730 if (wapp->app_icon)
731 return;
733 if (!WFLAGP(wapp->main_window_desc, no_appicon))
734 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
735 else
736 wapp->app_icon = NULL;
738 if (wapp->app_icon) {
739 WIcon *icon = wapp->app_icon->icon;
740 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
741 int x=0, y=0;
743 wapp->app_icon->main_window = wapp->main_window;
745 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
746 wapp->app_icon->attracted = 1;
747 if (!wapp->app_icon->icon->shadowed) {
748 wapp->app_icon->icon->shadowed = 1;
749 wapp->app_icon->icon->force_paint = 1;
751 wDockAttachIcon(clip, wapp->app_icon, x, y);
752 } else {
753 PlaceIcon(scr, &x, &y);
754 wAppIconMove(wapp->app_icon, x, y);
756 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
757 XMapWindow(dpy, icon->core->window);
759 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
760 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
765 static void
766 removeAppIconFor(WApplication *wapp)
768 if (!wapp->app_icon)
769 return;
771 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
772 wapp->app_icon->running = 0;
773 /* since we keep it, we don't care if it was attracted or not */
774 wapp->app_icon->attracted = 0;
775 wapp->app_icon->icon->shadowed = 0;
776 wapp->app_icon->main_window = None;
777 wapp->app_icon->pid = 0;
778 wapp->app_icon->icon->owner = NULL;
779 wapp->app_icon->icon->icon_win = None;
780 wapp->app_icon->icon->force_paint = 1;
781 wAppIconPaint(wapp->app_icon);
782 } else if (wapp->app_icon->docked) {
783 wapp->app_icon->running = 0;
784 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
785 } else {
786 wAppIconDestroy(wapp->app_icon);
788 wapp->app_icon = NULL;
789 if (wPreferences.auto_arrange_icons)
790 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
794 static void
795 applySettings(WMButton *button, InspectorPanel *panel)
797 WWindow *wwin = panel->inspected;
798 WApplication *wapp = wApplicationOf(wwin->main_window);
799 int floating, sunken, skip_window_list;
800 int old_omnipresent;
801 int old_no_bind_keys;
802 int old_no_bind_mouse;
804 old_omnipresent = WFLAGP(wwin, omnipresent);
805 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
806 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
808 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
810 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
811 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
812 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
813 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
814 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
815 floating = WMGetButtonSelected(panel->attrChk[5]);
816 sunken = WMGetButtonSelected(panel->attrChk[6]);
817 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
818 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
819 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
820 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
822 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
823 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
824 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
825 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
826 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
827 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
828 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
829 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
830 #ifdef XKB_BUTTON_HINT
831 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
832 #endif
833 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
835 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
836 wUnshadeWindow(wwin);
838 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
840 if (floating) {
841 if (!WFLAGP(wwin, floating))
842 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
843 } else if (sunken) {
844 if (!WFLAGP(wwin, sunken))
845 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
846 } else {
847 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
848 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
851 WSETUFLAG(wwin, sunken, sunken);
852 WSETUFLAG(wwin, floating, floating);
853 wwin->flags.omnipresent = 0;
855 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
856 WSETUFLAG(wwin, skip_window_list, skip_window_list);
857 UpdateSwitchMenu(wwin->screen_ptr, wwin,
858 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
859 } else {
860 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
861 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
865 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
866 if (WFLAGP(wwin, no_bind_keys)) {
867 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
868 } else {
869 wWindowSetKeyGrabs(wwin);
873 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
874 wWindowResetMouseGrabs(wwin);
877 wwin->frame->flags.need_texture_change = 1;
878 wWindowConfigureBorders(wwin);
879 wFrameWindowPaint(wwin->frame);
882 * Can't apply emulate_appicon because it will probably cause problems.
885 if (wapp) {
886 /* do application wide stuff */
887 WSETUFLAG(wapp->main_window_desc, start_hidden,
888 WMGetButtonSelected(panel->appChk[0]));
890 WSETUFLAG(wapp->main_window_desc, no_appicon,
891 WMGetButtonSelected(panel->appChk[1]));
893 WSETUFLAG(wapp->main_window_desc, shared_appicon,
894 WMGetButtonSelected(panel->appChk[2]));
896 if (WFLAGP(wapp->main_window_desc, no_appicon))
897 removeAppIconFor(wapp);
898 else
899 makeAppIconFor(wapp);
901 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
902 char *file = WMGetTextFieldText(panel->fileText);
904 if (file[0] == 0) {
905 wfree(file);
906 file = NULL;
908 wIconChangeImageFile(wapp->app_icon->icon, file);
909 if (file)
910 wfree(file);
911 wAppIconPaint(wapp->app_icon);
919 static void
920 revertSettings(WMButton *button, InspectorPanel *panel)
922 WWindow *wwin = panel->inspected;
923 WApplication *wapp = wApplicationOf(wwin->main_window);
924 int i, n;
925 char *wm_instance = NULL;
926 char *wm_class = NULL;
927 int workspace, level;
929 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
930 wm_instance = wwin->wm_instance;
931 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
932 wm_class = wwin->wm_class;
933 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
934 wm_instance = wwin->wm_instance;
935 wm_class = wwin->wm_class;
937 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
938 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
939 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
941 wWindowSetupInitialAttributes(wwin, &level, &workspace);
943 for (i=0; i < 11; i++) {
944 int flag = 0;
946 switch (i) {
947 case 0:
948 flag = WFLAGP(wwin, no_titlebar);
949 break;
950 case 1:
951 flag = WFLAGP(wwin, no_resizebar);
952 break;
953 case 2:
954 flag = WFLAGP(wwin, no_close_button);
955 break;
956 case 3:
957 flag = WFLAGP(wwin, no_miniaturize_button);
958 break;
959 case 4:
960 flag = WFLAGP(wwin, no_border);
961 break;
962 case 5:
963 flag = WFLAGP(wwin, floating);
964 break;
965 case 6:
966 flag = WFLAGP(wwin, sunken);
967 break;
968 case 7:
969 flag = WFLAGP(wwin, omnipresent);
970 break;
971 case 8:
972 flag = WFLAGP(wwin, start_miniaturized);
973 break;
974 case 9:
975 flag = WFLAGP(wwin, start_maximized!=0);
976 break;
977 case 10:
978 flag = WFLAGP(wwin, full_maximize);
979 break;
981 WMSetButtonSelected(panel->attrChk[i], flag);
983 for (i=0; i < 8; i++) {
984 int flag = 0;
986 switch (i) {
987 case 0:
988 flag = WFLAGP(wwin, no_bind_keys);
989 break;
990 case 1:
991 flag = WFLAGP(wwin, no_bind_mouse);
992 break;
993 case 2:
994 flag = WFLAGP(wwin, skip_window_list);
995 break;
996 case 3:
997 flag = WFLAGP(wwin, no_focusable);
998 break;
999 case 4:
1000 flag = WFLAGP(wwin, dont_move_off);
1001 break;
1002 case 5:
1003 flag = WFLAGP(wwin, no_hide_others);
1004 break;
1005 case 6:
1006 flag = WFLAGP(wwin, dont_save_session);
1007 break;
1008 case 7:
1009 flag = WFLAGP(wwin, emulate_appicon);
1010 break;
1011 #ifdef XKB_BUTTON_HINT
1012 case 8:
1013 flag = WFLAGP(wwin, no_language_button);
1014 break;
1015 #endif
1017 WMSetButtonSelected(panel->moreChk[i], flag);
1019 if (panel->appFrm && wapp) {
1020 for (i=0; i < 2; i++) {
1021 int flag = 0;
1023 switch (i) {
1024 case 0:
1025 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1026 break;
1027 case 1:
1028 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1029 break;
1030 case 2:
1031 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1032 break;
1034 WMSetButtonSelected(panel->appChk[i], flag);
1037 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1039 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1040 REVERT_TO_DEFAULT);
1042 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1044 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1045 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1046 } else {
1047 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1050 /* must auto apply, so that there wno't be internal
1051 * inconsistencies between the state in the flags and
1052 * the actual state of the window */
1053 applySettings(panel->applyBtn, panel);
1057 static void
1058 chooseIconCallback(WMWidget *self, void *clientData)
1060 char *file;
1061 InspectorPanel *panel = (InspectorPanel*)clientData;
1062 int result;
1064 panel->choosingIcon = 1;
1066 WMSetButtonEnabled(panel->browseIconBtn, False);
1068 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1069 panel->inspected->wm_instance,
1070 panel->inspected->wm_class);
1072 panel->choosingIcon = 0;
1074 if (!panel->destroyed) { /* kluge */
1075 if (result) {
1076 WMSetTextFieldText(panel->fileText, file);
1077 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1078 USE_TEXT_FIELD);
1079 wfree(file);
1081 WMSetButtonEnabled(panel->browseIconBtn, True);
1082 } else {
1083 freeInspector(panel);
1088 static void
1089 textEditedObserver(void *observerData, WMNotification *notification)
1091 InspectorPanel *panel = (InspectorPanel*)observerData;
1093 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1094 return;
1096 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1097 USE_TEXT_FIELD);
1099 WMPerformButtonClick(panel->updateIconBtn);
1104 static void
1105 selectSpecification(WMWidget *bPtr, void *data)
1107 InspectorPanel *panel = (InspectorPanel*)data;
1108 char *str;
1109 WWindow *wwin = panel->inspected;
1110 int len;
1112 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1113 WMSetButtonEnabled(panel->applyBtn, False);
1114 } else {
1115 WMSetButtonEnabled(panel->applyBtn, True);
1118 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1119 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1121 str = wmalloc(len);
1123 snprintf(str, len, _("Inspecting %s.%s"),
1124 wwin->wm_instance ? wwin->wm_instance : "?",
1125 wwin->wm_class ? wwin->wm_class : "?");
1127 wFrameWindowChangeTitle(panel->frame->frame, str);
1129 wfree(str);
1133 static void
1134 selectWindow(WMWidget *bPtr, void *data)
1136 InspectorPanel *panel = (InspectorPanel*)data;
1137 WWindow *wwin = panel->inspected;
1138 WScreen *scr = wwin->screen_ptr;
1139 XEvent event;
1140 WWindow *iwin;
1142 if (XGrabPointer(dpy, scr->root_win, True,
1143 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1144 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1145 wwarning("could not grab mouse pointer");
1146 return;
1149 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1151 WMMaskEvent(dpy, ButtonPressMask, &event);
1153 XUngrabPointer(dpy, CurrentTime);
1155 iwin = wWindowFor(event.xbutton.subwindow);
1157 if (iwin && !iwin->flags.internal_window && iwin != wwin
1158 && !iwin->flags.inspector_open) {
1160 iwin->flags.inspector_open = 1;
1161 iwin->inspector = createInspectorForWindow(iwin,
1162 panel->frame->frame_x,
1163 panel->frame->frame_y,
1164 True);
1165 wCloseInspectorForWindow(wwin);
1166 } else {
1167 WMSetLabelText(panel->specLbl, spec_text);
1173 static InspectorPanel*
1174 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1175 Bool showSelectPanel)
1177 WScreen *scr = wwin->screen_ptr;
1178 InspectorPanel *panel;
1179 Window parent;
1180 int i;
1181 int x, y;
1182 int btn_width, frame_width;
1183 WMButton *selectedBtn = NULL;
1184 #ifdef wrong_behaviour
1185 WMPixmap *pixmap;
1186 #endif
1188 spec_text = _("The configuration will apply to all\n"
1189 "windows that have their WM_CLASS\n"
1190 "property set to the above selected\n"
1191 "name, when saved.");
1193 panel = wmalloc(sizeof(InspectorPanel));
1194 memset(panel, 0, sizeof(InspectorPanel));
1196 panel->destroyed = 0;
1199 panel->inspected = wwin;
1201 panel->nextPtr = panelList;
1202 panelList = panel;
1205 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1206 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1209 /**** create common stuff ****/
1211 /* command buttons */
1212 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1213 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1214 panel->saveBtn = WMCreateCommandButton(panel->win);
1215 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1216 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1217 WMSetButtonText(panel->saveBtn, _("Save"));
1218 WMResizeWidget(panel->saveBtn, btn_width, 28);
1219 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1220 WMSetButtonEnabled(panel->saveBtn, False);
1222 panel->applyBtn = WMCreateCommandButton(panel->win);
1223 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1224 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1225 WMSetButtonText(panel->applyBtn, _("Apply"));
1226 WMResizeWidget(panel->applyBtn, btn_width, 28);
1228 panel->revertBtn = WMCreateCommandButton(panel->win);
1229 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1230 WMMoveWidget(panel->revertBtn, 15, 310);
1231 WMSetButtonText(panel->revertBtn, _("Reload"));
1232 WMResizeWidget(panel->revertBtn, btn_width, 28);
1234 /* page selection popup button */
1235 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1236 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1237 WMMoveWidget(panel->pagePopUp, 25, 15);
1238 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1240 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1241 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1242 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1243 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1244 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1246 /**** window spec ****/
1247 frame_width = PWIDTH - (2 * 15);
1249 panel->specFrm = WMCreateFrame(panel->win);
1250 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1251 WMMoveWidget(panel->specFrm, 15, 65);
1252 WMResizeWidget(panel->specFrm, frame_width, 145);
1255 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1256 WMMoveWidget(panel->defaultRb, 10, 78);
1257 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1258 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1259 WMSetButtonSelected(panel->defaultRb, False);
1260 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1262 if (wwin->wm_class && wwin->wm_instance) {
1263 char *str, *tmp;
1265 tmp = wstrconcat(wwin->wm_instance, ".");
1266 str = wstrconcat(tmp, wwin->wm_class);
1268 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1269 WMMoveWidget(panel->bothRb, 10, 18);
1270 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1271 WMSetButtonText(panel->bothRb, str);
1272 wfree(tmp);
1273 wfree(str);
1274 WMGroupButtons(panel->defaultRb, panel->bothRb);
1276 if (!selectedBtn)
1277 selectedBtn = panel->bothRb;
1279 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1282 if (wwin->wm_instance) {
1283 panel->instRb = WMCreateRadioButton(panel->specFrm);
1284 WMMoveWidget(panel->instRb, 10, 38);
1285 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1286 WMSetButtonText(panel->instRb, wwin->wm_instance);
1287 WMGroupButtons(panel->defaultRb, panel->instRb);
1289 if (!selectedBtn)
1290 selectedBtn = panel->instRb;
1292 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1295 if (wwin->wm_class) {
1296 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1297 WMMoveWidget(panel->clsRb, 10, 58);
1298 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1299 WMSetButtonText(panel->clsRb, wwin->wm_class);
1300 WMGroupButtons(panel->defaultRb, panel->clsRb);
1302 if (!selectedBtn)
1303 selectedBtn = panel->clsRb;
1305 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1309 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1310 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1311 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1312 WMSetButtonText(panel->selWinB, _("Select window"));
1313 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1316 panel->specLbl = WMCreateLabel(panel->win);
1317 WMMoveWidget(panel->specLbl, 15, 210);
1318 WMResizeWidget(panel->specLbl, frame_width, 100);
1319 WMSetLabelText(panel->specLbl, spec_text);
1320 WMSetLabelWraps(panel->specLbl, True);
1322 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1324 /**** attributes ****/
1325 panel->attrFrm = WMCreateFrame(panel->win);
1326 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1327 WMMoveWidget(panel->attrFrm, 15, 45);
1328 WMResizeWidget(panel->attrFrm, frame_width, 250);
1330 for (i=0; i < 11; i++) {
1331 char *caption = NULL;
1332 int flag = 0;
1333 char *descr = NULL;
1335 switch (i) {
1336 case 0:
1337 caption = _("Disable titlebar");
1338 flag = WFLAGP(wwin, no_titlebar);
1339 descr = _("Remove the titlebar of this window.\n"
1340 "To access the window commands menu of a window\n"
1341 "without it's titlebar, press Control+Esc (or the\n"
1342 "equivalent shortcut, if you changed the default\n"
1343 "settings).");
1344 break;
1345 case 1:
1346 caption = _("Disable resizebar");
1347 flag = WFLAGP(wwin, no_resizebar);
1348 descr = _("Remove the resizebar of this window.");
1349 break;
1350 case 2:
1351 caption = _("Disable close button");
1352 flag = WFLAGP(wwin, no_close_button);
1353 descr = _("Remove the `close window' button of this window.");
1354 break;
1355 case 3:
1356 caption = _("Disable miniaturize button");
1357 flag = WFLAGP(wwin, no_miniaturize_button);
1358 descr = _("Remove the `miniaturize window' button of the window.");
1359 break;
1360 case 4:
1361 caption = _("Disable border");
1362 flag = WFLAGP(wwin, no_border);
1363 descr = _("Remove the 1 pixel black border around the window.");
1364 break;
1365 case 5:
1366 caption = _("Keep on top (floating)");
1367 flag = WFLAGP(wwin, floating);
1368 descr = _("Keep the window over other windows, not allowing\n"
1369 "them to cover it.");
1370 break;
1371 case 6:
1372 caption = _("Keep at bottom (sunken)");
1373 flag = WFLAGP(wwin, sunken);
1374 descr = _("Keep the window under all other windows.");
1375 break;
1376 case 7:
1377 caption = _("Omnipresent");
1378 flag = WFLAGP(wwin, omnipresent);
1379 descr = _("Make window present in all workspaces.");
1380 break;
1381 case 8:
1382 caption = _("Start miniaturized");
1383 flag = WFLAGP(wwin, start_miniaturized);
1384 descr = _("Make the window be automatically miniaturized when it's\n"
1385 "first shown.");
1386 break;
1387 case 9:
1388 caption = _("Start maximized");
1389 flag = WFLAGP(wwin, start_maximized!=0);
1390 descr = _("Make the window be automatically maximized when it's\n"
1391 "first shown.");
1392 break;
1393 case 10:
1394 caption = _("Full screen maximization");
1395 flag = WFLAGP(wwin, full_maximize);
1396 descr = _("Make the window use the whole screen space when it's\n"
1397 "maximized. The titlebar and resizebar will be moved\n"
1398 "to outside the screen.");
1399 break;
1401 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1402 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1403 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1404 WMSetButtonSelected(panel->attrChk[i], flag);
1405 WMSetButtonText(panel->attrChk[i], caption);
1407 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1411 /**** more attributes ****/
1412 panel->moreFrm = WMCreateFrame(panel->win);
1413 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1414 WMMoveWidget(panel->moreFrm, 15, 45);
1415 WMResizeWidget(panel->moreFrm, frame_width, 250);
1417 for (i=0;
1418 #ifdef XKB_BUTTON_HINT
1419 i < 9;
1420 #else
1421 i < 8;
1422 #endif
1423 i++) {
1424 char *caption = NULL;
1425 int flag = 0;
1426 char *descr = NULL;
1428 switch (i) {
1429 case 0:
1430 caption = _("Do not bind keyboard shortcuts");
1431 flag = WFLAGP(wwin, no_bind_keys);
1432 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1433 "when this window is focused. This will allow the\n"
1434 "window to receive all key combinations regardless\n"
1435 "of your shortcut configuration.");
1436 break;
1437 case 1:
1438 caption = _("Do not bind mouse clicks");
1439 flag = WFLAGP(wwin, no_bind_mouse);
1440 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1441 "in the window (when alt is the modifier you have"
1442 "configured).");
1443 break;
1444 case 2:
1445 caption = _("Do not show in the window list");
1446 flag = WFLAGP(wwin, skip_window_list);
1447 descr = _("Do not list the window in the window list menu.");
1448 break;
1449 case 3:
1450 caption = _("Do not let it take focus");
1451 flag = WFLAGP(wwin, no_focusable);
1452 descr = _("Do not let the window take keyboard focus when you\n"
1453 "click on it.");
1454 break;
1455 case 4:
1456 caption = _("Keep inside screen");
1457 flag = WFLAGP(wwin, dont_move_off);
1458 descr = _("Do not allow the window to move itself completely\n"
1459 "outside the screen. For bug compatibility.\n");
1460 break;
1461 case 5:
1462 caption = _("Ignore 'Hide Others'");
1463 flag = WFLAGP(wwin, no_hide_others);
1464 descr = _("Do not hide the window when issuing the\n"
1465 "`HideOthers' command.");
1466 break;
1467 case 6:
1468 caption = _("Ignore 'Save Session'");
1469 flag = WFLAGP(wwin, dont_save_session);
1470 descr = _("Do not save the associated application in the\n"
1471 "session's state, so that it won't be restarted\n"
1472 "together with other applications when Window Maker\n"
1473 "starts.");
1474 break;
1475 case 7:
1476 caption = _("Emulate application icon");
1477 flag = WFLAGP(wwin, emulate_appicon);
1478 descr = _("Make this window act as an application that provides\n"
1479 "enough information to Window Maker for a dockable\n"
1480 "application icon to be created.");
1481 break;
1482 #ifdef XKB_BUTTON_HINT
1483 case 8:
1484 caption = _("Disable language button");
1485 flag = WFLAGP(wwin, no_language_button);
1486 descr = _("Remove the `toggle language' button of the window.");
1487 break;
1488 #endif
1490 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1491 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1492 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1493 WMSetButtonSelected(panel->moreChk[i], flag);
1494 WMSetButtonText(panel->moreChk[i], caption);
1496 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1499 /* miniwindow/workspace */
1500 panel->iconFrm = WMCreateFrame(panel->win);
1501 WMMoveWidget(panel->iconFrm, 15, 50);
1502 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1503 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1505 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1506 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1507 WMResizeWidget(panel->iconLbl, 64, 64);
1508 WMSetLabelRelief(panel->iconLbl, WRGroove);
1509 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1511 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1512 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1513 WMMoveWidget(panel->browseIconBtn, 22, 32);
1514 WMResizeWidget(panel->browseIconBtn, 120, 26);
1515 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1517 #ifdef wrong_behaviour
1518 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1519 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1520 WMSetButtonImage(panel->updateIconBtn, pixmap);
1521 WMReleasePixmap(pixmap);
1522 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1523 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1524 WMReleasePixmap(pixmap);
1525 #endif
1527 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1528 WMMoveWidget(panel->fileLbl, 20, 85);
1529 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1530 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1532 panel->fileText = WMCreateTextField(panel->iconFrm);
1533 WMMoveWidget(panel->fileText, 20, 105);
1534 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1535 WMSetTextFieldText(panel->fileText, NULL);
1536 WMAddNotificationObserver(textEditedObserver, panel,
1537 WMTextDidEndEditingNotification,
1538 panel->fileText);
1540 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1541 WMMoveWidget(panel->alwChk, 20, 130);
1542 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1543 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1544 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1547 panel->wsFrm = WMCreateFrame(panel->win);
1548 WMMoveWidget(panel->wsFrm, 15, 225);
1549 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1550 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1552 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1553 "first shown."), WMWidgetView(panel->wsFrm));
1555 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1556 WMMoveWidget(panel->wsP, 20, 30);
1557 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1558 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1559 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1560 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1563 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1564 wwin->wm_class);
1565 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1566 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1567 } else {
1568 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1571 /* application wide attributes */
1572 if (wwin->main_window != None) {
1573 WApplication *wapp = wApplicationOf(wwin->main_window);
1575 panel->appFrm = WMCreateFrame(panel->win);
1576 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1577 WMMoveWidget(panel->appFrm, 15, 50);
1578 WMResizeWidget(panel->appFrm, frame_width, 240);
1580 for (i=0; i < 3; i++) {
1581 char *caption = NULL;
1582 int flag = 0;
1583 char *descr = NULL;
1585 switch (i) {
1586 case 0:
1587 caption = _("Start hidden");
1588 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1589 descr = _("Automatically hide application when it's started.");
1590 break;
1591 case 1:
1592 caption = _("No application icon");
1593 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1594 descr = _("Disable the application icon for the application.\n"
1595 "Note that you won't be able to dock it anymore,\n"
1596 "and any icons that are already docked will stop\n"
1597 "working correctly.");
1598 break;
1599 case 2:
1600 caption = _("Shared application icon");
1601 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1602 descr = _("Use a single shared application icon for all of\n"
1603 "the instances of this application.\n");
1604 break;
1606 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1607 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1608 WMResizeWidget(panel->appChk[i], 205, 20);
1609 WMSetButtonSelected(panel->appChk[i], flag);
1610 WMSetButtonText(panel->appChk[i], caption);
1612 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1615 if (WFLAGP(wwin, emulate_appicon)) {
1616 WMSetButtonEnabled(panel->appChk[1], False);
1617 WMSetButtonEnabled(panel->moreChk[7], True);
1618 } else {
1619 WMSetButtonEnabled(panel->appChk[1], True);
1620 WMSetButtonEnabled(panel->moreChk[7], False);
1622 } else {
1623 int tmp;
1625 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1626 || !wwin->wm_class || !wwin->wm_instance)
1627 tmp = False;
1628 else
1629 tmp = True;
1630 WMSetButtonEnabled(panel->moreChk[7], tmp);
1632 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1633 panel->appFrm = NULL;
1636 /* if the window is a transient, don't let it have a miniaturize
1637 * button */
1638 if (wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1639 WMSetButtonEnabled(panel->attrChk[3], False);
1640 else
1641 WMSetButtonEnabled(panel->attrChk[3], True);
1644 if (!wwin->wm_class && !wwin->wm_instance) {
1645 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1649 WMRealizeWidget(panel->win);
1651 WMMapSubwidgets(panel->win);
1652 WMMapSubwidgets(panel->specFrm);
1653 WMMapSubwidgets(panel->attrFrm);
1654 WMMapSubwidgets(panel->moreFrm);
1655 WMMapSubwidgets(panel->iconFrm);
1656 WMMapSubwidgets(panel->wsFrm);
1657 if (panel->appFrm)
1658 WMMapSubwidgets(panel->appFrm);
1660 if (showSelectPanel) {
1661 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1662 changePage(panel->pagePopUp, panel);
1663 } else {
1664 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1665 changePage(panel->pagePopUp, panel);
1669 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1670 0, 0, 0);
1671 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1672 panel->parent = parent;
1673 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1675 WMMapWidget(panel->win);
1677 XSetTransientForHint(dpy, parent, wwin->client_win);
1679 if (xpos == UNDEFINED_POS) {
1680 x = wwin->frame_x+wwin->frame->core->width/2;
1681 y = wwin->frame_y+wwin->frame->top_width*2;
1682 if (y + PHEIGHT > scr->scr_height)
1683 y = scr->scr_height - PHEIGHT - 30;
1684 if (x + PWIDTH > scr->scr_width)
1685 x = scr->scr_width - PWIDTH;
1686 } else {
1687 x = xpos;
1688 y = ypos;
1691 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1692 "Inspector", x, y, PWIDTH, PHEIGHT);
1694 if (!selectedBtn)
1695 selectedBtn = panel->defaultRb;
1697 WMSetButtonSelected(selectedBtn, True);
1699 selectSpecification(selectedBtn, panel);
1701 /* kluge to know who should get the key events */
1702 panel->frame->client_leader = WMWidgetXID(panel->win);
1704 WSETUFLAG(panel->frame, no_closable, 0);
1705 WSETUFLAG(panel->frame, no_close_button, 0);
1706 wWindowUpdateButtonImages(panel->frame);
1707 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1708 panel->frame->frame->on_click_right = destroyInspector;
1710 wWindowMap(panel->frame);
1712 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1713 wwin->wm_class, UPDATE_TEXT_FIELD);
1715 return panel;
1719 void
1720 wShowInspectorForWindow(WWindow *wwin)
1722 if (wwin->flags.inspector_open)
1723 return;
1725 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1727 make_keys();
1728 wwin->flags.inspector_open = 1;
1729 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1730 UNDEFINED_POS, False);
1736 void
1737 wHideInspectorForWindow(WWindow *wwin)
1739 WWindow *pwin = wwin->inspector->frame;
1741 wWindowUnmap(pwin);
1742 pwin->flags.hidden = 1;
1744 wClientSetState(pwin, IconicState, None);
1749 void
1750 wUnhideInspectorForWindow(WWindow *wwin)
1752 WWindow *pwin = wwin->inspector->frame;
1754 pwin->flags.hidden = 0;
1755 pwin->flags.mapped = 1;
1756 XMapWindow(dpy, pwin->client_win);
1757 XMapWindow(dpy, pwin->frame->core->window);
1758 wClientSetState(pwin, NormalState, None);
1763 WWindow*
1764 wGetWindowOfInspectorForWindow(WWindow *wwin)
1766 if (wwin->inspector) {
1767 assert(wwin->flags.inspector_open != 0);
1769 return wwin->inspector->frame;
1770 } else
1771 return NULL;
1775 void
1776 wCloseInspectorForWindow(WWindow *wwin)
1778 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1780 (*pwin->frame->on_click_right)(NULL, pwin, NULL);