- Finished moving to the new proplist handling code in WINGs.
[wmaker-crm.git] / src / winspector.c
blobfab9d0452005fb6ed43a26a33940ad01b8d50ef5
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 * Copyright (c) 1998 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 *ACollapseAppIcons;
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 ACollapseAppIcons = WMCreatePLString("CollapseAppIcons");
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, *value, *key;
516 char *icon_file;
517 int flags = 0;
518 int different = 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)+4);
531 strcat(strcat(strcpy(buffer, 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);
561 /* Update icon for window */
562 icon_file = WMGetTextFieldText(panel->fileText);
563 if (icon_file) {
564 if (icon_file[0] != 0) {
565 value = WMCreatePLString(icon_file);
566 different |= insertAttribute(dict, winDic, AIcon, value, flags);
567 WMReleasePropList(value);
569 wfree(icon_file);
573 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
575 i--;
577 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
578 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
579 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
580 flags);
581 WMReleasePropList(value);
585 flags |= IS_BOOLEAN;
587 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
588 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
590 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
591 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
593 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
594 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
596 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
597 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
599 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
600 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
602 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
605 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
606 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
608 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
609 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
611 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
612 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
614 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
615 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
617 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
618 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
620 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
621 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
624 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
625 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
627 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
628 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
630 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
631 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
633 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
634 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
636 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
637 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
639 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
640 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
642 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
643 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
645 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
646 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
648 #ifdef XKB_BUTTON_HINT
649 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
650 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
651 #endif
653 /* application wide settings for when */
654 /* the window is the leader, save the attribute with the others */
655 if (panel->inspected->main_window == panel->inspected->client_win) {
657 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
658 different |= insertAttribute(dict, winDic, AStartHidden, value, flags);
660 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
661 different |= insertAttribute(dict, winDic, ANoAppIcon, value, flags);
663 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
664 different |= insertAttribute(dict, winDic, ACollapseAppIcons, value, flags);
667 WMRemoveFromPLDictionary(dict, key);
668 if (different) {
669 WMPutInPLDictionary(dict, key, winDic);
672 WMReleasePropList(key);
673 WMReleasePropList(winDic);
675 different = 0;
677 /* application wide settings */
678 if (panel->inspected->main_window != panel->inspected->client_win
679 && !(flags & UPDATE_DEFAULTS)) {
680 WApplication *wapp;
681 WMPropList *appDic;
683 wapp = wApplicationOf(panel->inspected->main_window);
684 if (wapp) {
685 char *iconFile;
686 char *buffer;
688 appDic = WMCreatePLDictionary(NULL, NULL, NULL);
690 assert(wapp->main_window_desc->wm_instance!=NULL);
691 assert(wapp->main_window_desc->wm_class!=NULL);
693 buffer = wmalloc(strlen(wapp->main_window_desc->wm_instance)
694 +strlen(wapp->main_window_desc->wm_class)+4);
695 strcat(strcpy(buffer, wapp->main_window_desc->wm_instance), ".");
696 strcat(buffer, wapp->main_window_desc->wm_class);
697 key = WMCreatePLString(buffer);
698 wfree(buffer);
700 iconFile = wDefaultGetIconFile(wwin->screen_ptr,
701 wapp->main_window_desc->wm_instance,
702 wapp->main_window_desc->wm_class,
703 False);
705 if (iconFile && iconFile[0]!=0) {
706 value = WMCreatePLString(iconFile);
707 different |= insertAttribute(dict, appDic, AIcon, value,
708 flags&~IS_BOOLEAN);
709 WMReleasePropList(value);
712 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
713 different |= insertAttribute(dict, appDic, AStartHidden, value,
714 flags);
716 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
717 different |= insertAttribute(dict, appDic, ANoAppIcon, value,
718 flags);
720 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
721 different |= insertAttribute(dict, appDic, ACollapseAppIcons, value,
722 flags);
724 WMRemoveFromPLDictionary(dict, key);
725 if (different) {
726 WMPutInPLDictionary(dict, key, appDic);
728 WMReleasePropList(key);
729 WMReleasePropList(appDic);
733 WMWritePropListToFile(dict, db->path, True);
735 /* clean up */
736 WMPLSetCaseSensitive(False);
740 static void
741 makeAppIconFor(WApplication *wapp)
743 WScreen *scr = wapp->main_window_desc->screen_ptr;
745 if (wapp->app_icon)
746 return;
748 if (!WFLAGP(wapp->main_window_desc, no_appicon))
749 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
750 else
751 wapp->app_icon = NULL;
753 if (wapp->app_icon) {
754 WIcon *icon = wapp->app_icon->icon;
755 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
756 int x=0, y=0;
758 wapp->app_icon->main_window = wapp->main_window;
760 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
761 wapp->app_icon->attracted = 1;
762 if (!wapp->app_icon->icon->shadowed) {
763 wapp->app_icon->icon->shadowed = 1;
764 wapp->app_icon->icon->force_paint = 1;
766 wDockAttachIcon(clip, wapp->app_icon, x, y);
767 } else {
768 PlaceIcon(scr, &x, &y);
769 wAppIconMove(wapp->app_icon, x, y);
771 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
772 XMapWindow(dpy, icon->core->window);
774 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
775 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
780 static void
781 removeAppIconFor(WApplication *wapp)
783 if (!wapp->app_icon)
784 return;
786 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
787 wapp->app_icon->running = 0;
788 /* since we keep it, we don't care if it was attracted or not */
789 wapp->app_icon->attracted = 0;
790 wapp->app_icon->icon->shadowed = 0;
791 wapp->app_icon->main_window = None;
792 wapp->app_icon->pid = 0;
793 wapp->app_icon->icon->owner = NULL;
794 wapp->app_icon->icon->icon_win = None;
795 wapp->app_icon->icon->force_paint = 1;
796 wAppIconPaint(wapp->app_icon);
797 } else if (wapp->app_icon->docked) {
798 wapp->app_icon->running = 0;
799 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
800 } else {
801 wAppIconDestroy(wapp->app_icon);
803 wapp->app_icon = NULL;
804 if (wPreferences.auto_arrange_icons)
805 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
809 static void
810 applySettings(WMButton *button, InspectorPanel *panel)
812 WWindow *wwin = panel->inspected;
813 WApplication *wapp = wApplicationOf(wwin->main_window);
814 int floating, sunken, skip_window_list;
815 int old_omnipresent;
816 int old_no_bind_keys;
817 int old_no_bind_mouse;
819 old_omnipresent = WFLAGP(wwin, omnipresent);
820 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
821 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
823 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
825 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
826 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
827 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
828 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
829 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
830 floating = WMGetButtonSelected(panel->attrChk[5]);
831 sunken = WMGetButtonSelected(panel->attrChk[6]);
832 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
833 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
834 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
835 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
837 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
838 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
839 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
840 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
841 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
842 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
843 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
844 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
845 #ifdef XKB_BUTTON_HINT
846 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
847 #endif
848 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
850 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
851 wUnshadeWindow(wwin);
853 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
855 if (floating) {
856 if (!WFLAGP(wwin, floating))
857 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
858 } else if (sunken) {
859 if (!WFLAGP(wwin, sunken))
860 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
861 } else {
862 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
863 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
866 WSETUFLAG(wwin, sunken, sunken);
867 WSETUFLAG(wwin, floating, floating);
868 wwin->flags.omnipresent = 0;
870 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
871 WSETUFLAG(wwin, skip_window_list, skip_window_list);
872 UpdateSwitchMenu(wwin->screen_ptr, wwin,
873 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
874 } else {
875 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
876 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
880 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
881 if (WFLAGP(wwin, no_bind_keys)) {
882 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
883 } else {
884 wWindowSetKeyGrabs(wwin);
888 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
889 wWindowResetMouseGrabs(wwin);
892 wwin->frame->flags.need_texture_change = 1;
893 wWindowConfigureBorders(wwin);
894 wFrameWindowPaint(wwin->frame);
897 * Can't apply emulate_appicon because it will probably cause problems.
900 if (wapp) {
901 /* do application wide stuff */
902 WSETUFLAG(wapp->main_window_desc, start_hidden,
903 WMGetButtonSelected(panel->appChk[0]));
905 WSETUFLAG(wapp->main_window_desc, no_appicon,
906 WMGetButtonSelected(panel->appChk[1]));
908 WSETUFLAG(wapp->main_window_desc, collapse_appicons,
909 WMGetButtonSelected(panel->appChk[2]));
911 if (WFLAGP(wapp->main_window_desc, no_appicon))
912 removeAppIconFor(wapp);
913 else
914 makeAppIconFor(wapp);
916 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
917 char *file = WMGetTextFieldText(panel->fileText);
919 if (file[0] == 0) {
920 wfree(file);
921 file = NULL;
923 wIconChangeImageFile(wapp->app_icon->icon, file);
924 if (file)
925 wfree(file);
926 wAppIconPaint(wapp->app_icon);
934 static void
935 revertSettings(WMButton *button, InspectorPanel *panel)
937 WWindow *wwin = panel->inspected;
938 WApplication *wapp = wApplicationOf(wwin->main_window);
939 int i, n;
940 char *wm_instance = NULL;
941 char *wm_class = NULL;
942 int workspace, level;
944 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
945 wm_instance = wwin->wm_instance;
946 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
947 wm_class = wwin->wm_class;
948 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
949 wm_instance = wwin->wm_instance;
950 wm_class = wwin->wm_class;
952 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
953 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
954 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
956 wWindowSetupInitialAttributes(wwin, &level, &workspace);
958 for (i=0; i < 11; i++) {
959 int flag = 0;
961 switch (i) {
962 case 0:
963 flag = WFLAGP(wwin, no_titlebar);
964 break;
965 case 1:
966 flag = WFLAGP(wwin, no_resizebar);
967 break;
968 case 2:
969 flag = WFLAGP(wwin, no_close_button);
970 break;
971 case 3:
972 flag = WFLAGP(wwin, no_miniaturize_button);
973 break;
974 case 4:
975 flag = WFLAGP(wwin, no_border);
976 break;
977 case 5:
978 flag = WFLAGP(wwin, floating);
979 break;
980 case 6:
981 flag = WFLAGP(wwin, sunken);
982 break;
983 case 7:
984 flag = WFLAGP(wwin, omnipresent);
985 break;
986 case 8:
987 flag = WFLAGP(wwin, start_miniaturized);
988 break;
989 case 9:
990 flag = WFLAGP(wwin, start_maximized!=0);
991 break;
992 case 10:
993 flag = WFLAGP(wwin, full_maximize);
994 break;
996 WMSetButtonSelected(panel->attrChk[i], flag);
998 for (i=0; i < 8; i++) {
999 int flag = 0;
1001 switch (i) {
1002 case 0:
1003 flag = WFLAGP(wwin, no_bind_keys);
1004 break;
1005 case 1:
1006 flag = WFLAGP(wwin, no_bind_mouse);
1007 break;
1008 case 2:
1009 flag = WFLAGP(wwin, skip_window_list);
1010 break;
1011 case 3:
1012 flag = WFLAGP(wwin, no_focusable);
1013 break;
1014 case 4:
1015 flag = WFLAGP(wwin, dont_move_off);
1016 break;
1017 case 5:
1018 flag = WFLAGP(wwin, no_hide_others);
1019 break;
1020 case 6:
1021 flag = WFLAGP(wwin, dont_save_session);
1022 break;
1023 case 7:
1024 flag = WFLAGP(wwin, emulate_appicon);
1025 break;
1026 #ifdef XKB_BUTTON_HINT
1027 case 8:
1028 flag = WFLAGP(wwin, no_language_button);
1029 break;
1030 #endif
1032 WMSetButtonSelected(panel->moreChk[i], flag);
1034 if (panel->appFrm && wapp) {
1035 for (i=0; i < 2; i++) {
1036 int flag = 0;
1038 switch (i) {
1039 case 0:
1040 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1041 break;
1042 case 1:
1043 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1044 break;
1045 case 2:
1046 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1047 break;
1049 WMSetButtonSelected(panel->appChk[i], flag);
1052 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1054 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1055 REVERT_TO_DEFAULT);
1057 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1059 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1060 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1061 } else {
1062 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1065 /* must auto apply, so that there wno't be internal
1066 * inconsistencies between the state in the flags and
1067 * the actual state of the window */
1068 applySettings(panel->applyBtn, panel);
1072 static void
1073 chooseIconCallback(WMWidget *self, void *clientData)
1075 char *file;
1076 InspectorPanel *panel = (InspectorPanel*)clientData;
1077 int result;
1079 panel->choosingIcon = 1;
1081 WMSetButtonEnabled(panel->browseIconBtn, False);
1083 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1084 panel->inspected->wm_instance,
1085 panel->inspected->wm_class);
1087 panel->choosingIcon = 0;
1089 if (!panel->destroyed) { /* kluge */
1090 if (result) {
1091 WMSetTextFieldText(panel->fileText, file);
1092 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1093 USE_TEXT_FIELD);
1094 wfree(file);
1096 WMSetButtonEnabled(panel->browseIconBtn, True);
1097 } else {
1098 freeInspector(panel);
1103 static void
1104 textEditedObserver(void *observerData, WMNotification *notification)
1106 InspectorPanel *panel = (InspectorPanel*)observerData;
1108 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1109 return;
1111 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1112 USE_TEXT_FIELD);
1114 WMPerformButtonClick(panel->updateIconBtn);
1119 static void
1120 selectSpecification(WMWidget *bPtr, void *data)
1122 InspectorPanel *panel = (InspectorPanel*)data;
1123 char *str;
1124 WWindow *wwin = panel->inspected;
1125 int len;
1127 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1128 WMSetButtonEnabled(panel->applyBtn, False);
1129 } else {
1130 WMSetButtonEnabled(panel->applyBtn, True);
1133 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1134 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1136 str = wmalloc(len);
1138 snprintf(str, len, _("Inspecting %s.%s"),
1139 wwin->wm_instance ? wwin->wm_instance : "?",
1140 wwin->wm_class ? wwin->wm_class : "?");
1142 wFrameWindowChangeTitle(panel->frame->frame, str);
1144 wfree(str);
1148 static void
1149 selectWindow(WMWidget *bPtr, void *data)
1151 InspectorPanel *panel = (InspectorPanel*)data;
1152 WWindow *wwin = panel->inspected;
1153 WScreen *scr = wwin->screen_ptr;
1154 XEvent event;
1155 WWindow *iwin;
1157 if (XGrabPointer(dpy, scr->root_win, True,
1158 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1159 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1160 wwarning("could not grab mouse pointer");
1161 return;
1164 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1166 WMMaskEvent(dpy, ButtonPressMask, &event);
1168 XUngrabPointer(dpy, CurrentTime);
1170 iwin = wWindowFor(event.xbutton.subwindow);
1172 if (iwin && !iwin->flags.internal_window && iwin != wwin
1173 && !iwin->flags.inspector_open) {
1175 iwin->flags.inspector_open = 1;
1176 iwin->inspector = createInspectorForWindow(iwin,
1177 panel->frame->frame_x,
1178 panel->frame->frame_y,
1179 True);
1180 wCloseInspectorForWindow(wwin);
1181 } else {
1182 WMSetLabelText(panel->specLbl, spec_text);
1188 static InspectorPanel*
1189 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1190 Bool showSelectPanel)
1192 WScreen *scr = wwin->screen_ptr;
1193 InspectorPanel *panel;
1194 Window parent;
1195 int i;
1196 int x, y;
1197 int btn_width, frame_width;
1198 WMButton *selectedBtn = NULL;
1199 #ifdef wrong_behaviour
1200 WMPixmap *pixmap;
1201 #endif
1203 spec_text = _("The configuration will apply to all\n"
1204 "windows that have their WM_CLASS\n"
1205 "property set to the above selected\n"
1206 "name, when saved.");
1208 panel = wmalloc(sizeof(InspectorPanel));
1209 memset(panel, 0, sizeof(InspectorPanel));
1211 panel->destroyed = 0;
1214 panel->inspected = wwin;
1216 panel->nextPtr = panelList;
1217 panelList = panel;
1220 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1221 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1224 /**** create common stuff ****/
1226 /* command buttons */
1227 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1228 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1229 panel->saveBtn = WMCreateCommandButton(panel->win);
1230 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1231 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1232 WMSetButtonText(panel->saveBtn, _("Save"));
1233 WMResizeWidget(panel->saveBtn, btn_width, 28);
1234 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1235 WMSetButtonEnabled(panel->saveBtn, False);
1237 panel->applyBtn = WMCreateCommandButton(panel->win);
1238 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1239 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1240 WMSetButtonText(panel->applyBtn, _("Apply"));
1241 WMResizeWidget(panel->applyBtn, btn_width, 28);
1243 panel->revertBtn = WMCreateCommandButton(panel->win);
1244 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1245 WMMoveWidget(panel->revertBtn, 15, 310);
1246 WMSetButtonText(panel->revertBtn, _("Reload"));
1247 WMResizeWidget(panel->revertBtn, btn_width, 28);
1249 /* page selection popup button */
1250 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1251 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1252 WMMoveWidget(panel->pagePopUp, 25, 15);
1253 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1255 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1256 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1257 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1258 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1259 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1261 /**** window spec ****/
1262 frame_width = PWIDTH - (2 * 15);
1264 panel->specFrm = WMCreateFrame(panel->win);
1265 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1266 WMMoveWidget(panel->specFrm, 15, 65);
1267 WMResizeWidget(panel->specFrm, frame_width, 145);
1270 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1271 WMMoveWidget(panel->defaultRb, 10, 78);
1272 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1273 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1274 WMSetButtonSelected(panel->defaultRb, False);
1275 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1277 if (wwin->wm_class && wwin->wm_instance) {
1278 char *str, *tmp;
1280 tmp = wstrconcat(wwin->wm_instance, ".");
1281 str = wstrconcat(tmp, wwin->wm_class);
1283 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1284 WMMoveWidget(panel->bothRb, 10, 18);
1285 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1286 WMSetButtonText(panel->bothRb, str);
1287 wfree(tmp);
1288 wfree(str);
1289 WMGroupButtons(panel->defaultRb, panel->bothRb);
1291 if (!selectedBtn)
1292 selectedBtn = panel->bothRb;
1294 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1297 if (wwin->wm_instance) {
1298 panel->instRb = WMCreateRadioButton(panel->specFrm);
1299 WMMoveWidget(panel->instRb, 10, 38);
1300 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1301 WMSetButtonText(panel->instRb, wwin->wm_instance);
1302 WMGroupButtons(panel->defaultRb, panel->instRb);
1304 if (!selectedBtn)
1305 selectedBtn = panel->instRb;
1307 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1310 if (wwin->wm_class) {
1311 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1312 WMMoveWidget(panel->clsRb, 10, 58);
1313 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1314 WMSetButtonText(panel->clsRb, wwin->wm_class);
1315 WMGroupButtons(panel->defaultRb, panel->clsRb);
1317 if (!selectedBtn)
1318 selectedBtn = panel->clsRb;
1320 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1324 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1325 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1326 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1327 WMSetButtonText(panel->selWinB, _("Select window"));
1328 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1331 panel->specLbl = WMCreateLabel(panel->win);
1332 WMMoveWidget(panel->specLbl, 15, 210);
1333 WMResizeWidget(panel->specLbl, frame_width, 100);
1334 WMSetLabelText(panel->specLbl, spec_text);
1335 WMSetLabelWraps(panel->specLbl, True);
1337 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1339 /**** attributes ****/
1340 panel->attrFrm = WMCreateFrame(panel->win);
1341 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1342 WMMoveWidget(panel->attrFrm, 15, 45);
1343 WMResizeWidget(panel->attrFrm, frame_width, 250);
1345 for (i=0; i < 11; i++) {
1346 char *caption = NULL;
1347 int flag = 0;
1348 char *descr = NULL;
1350 switch (i) {
1351 case 0:
1352 caption = _("Disable titlebar");
1353 flag = WFLAGP(wwin, no_titlebar);
1354 descr = _("Remove the titlebar of this window.\n"
1355 "To access the window commands menu of a window\n"
1356 "without it's titlebar, press Control+Esc (or the\n"
1357 "equivalent shortcut, if you changed the default\n"
1358 "settings).");
1359 break;
1360 case 1:
1361 caption = _("Disable resizebar");
1362 flag = WFLAGP(wwin, no_resizebar);
1363 descr = _("Remove the resizebar of this window.");
1364 break;
1365 case 2:
1366 caption = _("Disable close button");
1367 flag = WFLAGP(wwin, no_close_button);
1368 descr = _("Remove the `close window' button of this window.");
1369 break;
1370 case 3:
1371 caption = _("Disable miniaturize button");
1372 flag = WFLAGP(wwin, no_miniaturize_button);
1373 descr = _("Remove the `miniaturize window' button of the window.");
1374 break;
1375 case 4:
1376 caption = _("Disable border");
1377 flag = WFLAGP(wwin, no_border);
1378 descr = _("Remove the 1 pixel black border around the window.");
1379 break;
1380 case 5:
1381 caption = _("Keep on top (floating)");
1382 flag = WFLAGP(wwin, floating);
1383 descr = _("Keep the window over other windows, not allowing\n"
1384 "them to cover it.");
1385 break;
1386 case 6:
1387 caption = _("Keep at bottom (sunken)");
1388 flag = WFLAGP(wwin, sunken);
1389 descr = _("Keep the window under all other windows.");
1390 break;
1391 case 7:
1392 caption = _("Omnipresent");
1393 flag = WFLAGP(wwin, omnipresent);
1394 descr = _("Make window present in all workspaces.");
1395 break;
1396 case 8:
1397 caption = _("Start miniaturized");
1398 flag = WFLAGP(wwin, start_miniaturized);
1399 descr = _("Make the window be automatically miniaturized when it's\n"
1400 "first shown.");
1401 break;
1402 case 9:
1403 caption = _("Start maximized");
1404 flag = WFLAGP(wwin, start_maximized!=0);
1405 descr = _("Make the window be automatically maximized when it's\n"
1406 "first shown.");
1407 break;
1408 case 10:
1409 caption = _("Full screen maximization");
1410 flag = WFLAGP(wwin, full_maximize);
1411 descr = _("Make the window use the whole screen space when it's\n"
1412 "maximized. The titlebar and resizebar will be moved\n"
1413 "to outside the screen.");
1414 break;
1416 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1417 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1418 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1419 WMSetButtonSelected(panel->attrChk[i], flag);
1420 WMSetButtonText(panel->attrChk[i], caption);
1422 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1426 /**** more attributes ****/
1427 panel->moreFrm = WMCreateFrame(panel->win);
1428 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1429 WMMoveWidget(panel->moreFrm, 15, 45);
1430 WMResizeWidget(panel->moreFrm, frame_width, 250);
1432 for (i=0;
1433 #ifdef XKB_BUTTON_HINT
1434 i < 9;
1435 #else
1436 i < 8;
1437 #endif
1438 i++) {
1439 char *caption = NULL;
1440 int flag = 0;
1441 char *descr = NULL;
1443 switch (i) {
1444 case 0:
1445 caption = _("Do not bind keyboard shortcuts");
1446 flag = WFLAGP(wwin, no_bind_keys);
1447 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1448 "when this window is focused. This will allow the\n"
1449 "window to receive all key combinations regardless\n"
1450 "of your shortcut configuration.");
1451 break;
1452 case 1:
1453 caption = _("Do not bind mouse clicks");
1454 flag = WFLAGP(wwin, no_bind_mouse);
1455 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1456 "in the window (when alt is the modifier you have"
1457 "configured).");
1458 break;
1459 case 2:
1460 caption = _("Do not show in the window list");
1461 flag = WFLAGP(wwin, skip_window_list);
1462 descr = _("Do not list the window in the window list menu.");
1463 break;
1464 case 3:
1465 caption = _("Do not let it take focus");
1466 flag = WFLAGP(wwin, no_focusable);
1467 descr = _("Do not let the window take keyboard focus when you\n"
1468 "click on it.");
1469 break;
1470 case 4:
1471 caption = _("Keep inside screen");
1472 flag = WFLAGP(wwin, dont_move_off);
1473 descr = _("Do not allow the window to move itself completely\n"
1474 "outside the screen. For bug compatibility.\n");
1475 break;
1476 case 5:
1477 caption = _("Ignore 'Hide Others'");
1478 flag = WFLAGP(wwin, no_hide_others);
1479 descr = _("Do not hide the window when issuing the\n"
1480 "`HideOthers' command.");
1481 break;
1482 case 6:
1483 caption = _("Ignore 'Save Session'");
1484 flag = WFLAGP(wwin, dont_save_session);
1485 descr = _("Do not save the associated application in the\n"
1486 "session's state, so that it won't be restarted\n"
1487 "together with other applications when Window Maker\n"
1488 "starts.");
1489 break;
1490 case 7:
1491 caption = _("Emulate application icon");
1492 flag = WFLAGP(wwin, emulate_appicon);
1493 descr = _("Make this window act as an application that provides\n"
1494 "enough information to Window Maker for a dockable\n"
1495 "application icon to be created.");
1496 break;
1497 #ifdef XKB_BUTTON_HINT
1498 case 8:
1499 caption = _("Disable language button");
1500 flag = WFLAGP(wwin, no_language_button);
1501 descr = _("Remove the `toggle language' button of the window.");
1502 break;
1503 #endif
1505 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1506 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1507 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1508 WMSetButtonSelected(panel->moreChk[i], flag);
1509 WMSetButtonText(panel->moreChk[i], caption);
1511 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1514 /* miniwindow/workspace */
1515 panel->iconFrm = WMCreateFrame(panel->win);
1516 WMMoveWidget(panel->iconFrm, 15, 50);
1517 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1518 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1520 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1521 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1522 WMResizeWidget(panel->iconLbl, 64, 64);
1523 WMSetLabelRelief(panel->iconLbl, WRGroove);
1524 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1526 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1527 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1528 WMMoveWidget(panel->browseIconBtn, 22, 32);
1529 WMResizeWidget(panel->browseIconBtn, 120, 26);
1530 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1532 #ifdef wrong_behaviour
1533 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1534 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1535 WMSetButtonImage(panel->updateIconBtn, pixmap);
1536 WMReleasePixmap(pixmap);
1537 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1538 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1539 WMReleasePixmap(pixmap);
1540 #endif
1542 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1543 WMMoveWidget(panel->fileLbl, 20, 85);
1544 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1545 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1547 panel->fileText = WMCreateTextField(panel->iconFrm);
1548 WMMoveWidget(panel->fileText, 20, 105);
1549 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1550 WMSetTextFieldText(panel->fileText, NULL);
1551 WMAddNotificationObserver(textEditedObserver, panel,
1552 WMTextDidEndEditingNotification,
1553 panel->fileText);
1555 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1556 WMMoveWidget(panel->alwChk, 20, 130);
1557 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1558 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1559 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1562 panel->wsFrm = WMCreateFrame(panel->win);
1563 WMMoveWidget(panel->wsFrm, 15, 225);
1564 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1565 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1567 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1568 "first shown."), WMWidgetView(panel->wsFrm));
1570 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1571 WMMoveWidget(panel->wsP, 20, 30);
1572 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1573 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1574 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1575 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1578 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1579 wwin->wm_class);
1580 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1581 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1582 } else {
1583 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1586 /* application wide attributes */
1587 if (wwin->main_window != None) {
1588 WApplication *wapp = wApplicationOf(wwin->main_window);
1590 panel->appFrm = WMCreateFrame(panel->win);
1591 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1592 WMMoveWidget(panel->appFrm, 15, 50);
1593 WMResizeWidget(panel->appFrm, frame_width, 240);
1595 for (i=0; i < 3; i++) {
1596 char *caption = NULL;
1597 int flag = 0;
1598 char *descr = NULL;
1600 switch (i) {
1601 case 0:
1602 caption = _("Start hidden");
1603 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1604 descr = _("Automatically hide application when it's started.");
1605 break;
1606 case 1:
1607 caption = _("No application icon");
1608 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1609 descr = _("Disable the application icon for the application.\n"
1610 "Note that you won't be able to dock it anymore,\n"
1611 "and any icons that are already docked will stop\n"
1612 "working correctly.");
1613 break;
1614 case 2:
1615 caption = _("Collapse application icons");
1616 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1617 descr = _("Collapse application icons from other instances\n"
1618 "of this application into one.\n");
1619 break;
1621 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1622 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1623 WMResizeWidget(panel->appChk[i], 205, 20);
1624 WMSetButtonSelected(panel->appChk[i], flag);
1625 WMSetButtonText(panel->appChk[i], caption);
1627 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1630 if (WFLAGP(wwin, emulate_appicon)) {
1631 WMSetButtonEnabled(panel->appChk[1], False);
1632 WMSetButtonEnabled(panel->moreChk[7], True);
1633 } else {
1634 WMSetButtonEnabled(panel->appChk[1], True);
1635 WMSetButtonEnabled(panel->moreChk[7], False);
1637 } else {
1638 int tmp;
1640 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1641 || !wwin->wm_class || !wwin->wm_instance)
1642 tmp = False;
1643 else
1644 tmp = True;
1645 WMSetButtonEnabled(panel->moreChk[7], tmp);
1647 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1648 panel->appFrm = NULL;
1651 /* if the window is a transient, don't let it have a miniaturize
1652 * button */
1653 if (wWindowFor(wwin->transient_for)!=NULL)
1654 WMSetButtonEnabled(panel->attrChk[3], False);
1655 else
1656 WMSetButtonEnabled(panel->attrChk[3], True);
1659 if (!wwin->wm_class && !wwin->wm_instance) {
1660 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1664 WMRealizeWidget(panel->win);
1666 WMMapSubwidgets(panel->win);
1667 WMMapSubwidgets(panel->specFrm);
1668 WMMapSubwidgets(panel->attrFrm);
1669 WMMapSubwidgets(panel->moreFrm);
1670 WMMapSubwidgets(panel->iconFrm);
1671 WMMapSubwidgets(panel->wsFrm);
1672 if (panel->appFrm)
1673 WMMapSubwidgets(panel->appFrm);
1675 if (showSelectPanel) {
1676 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1677 changePage(panel->pagePopUp, panel);
1678 } else {
1679 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1680 changePage(panel->pagePopUp, panel);
1684 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1685 0, 0, 0);
1686 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1687 panel->parent = parent;
1688 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1690 WMMapWidget(panel->win);
1692 XSetTransientForHint(dpy, parent, wwin->client_win);
1694 if (xpos == UNDEFINED_POS) {
1695 x = wwin->frame_x+wwin->frame->core->width/2;
1696 y = wwin->frame_y+wwin->frame->top_width*2;
1697 if (y + PHEIGHT > scr->scr_height)
1698 y = scr->scr_height - PHEIGHT - 30;
1699 if (x + PWIDTH > scr->scr_width)
1700 x = scr->scr_width - PWIDTH;
1701 } else {
1702 x = xpos;
1703 y = ypos;
1706 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1707 "Inspector", x, y, PWIDTH, PHEIGHT);
1709 if (!selectedBtn)
1710 selectedBtn = panel->defaultRb;
1712 WMSetButtonSelected(selectedBtn, True);
1714 selectSpecification(selectedBtn, panel);
1716 /* kluge to know who should get the key events */
1717 panel->frame->client_leader = WMWidgetXID(panel->win);
1719 WSETUFLAG(panel->frame, no_closable, 0);
1720 WSETUFLAG(panel->frame, no_close_button, 0);
1721 wWindowUpdateButtonImages(panel->frame);
1722 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1723 panel->frame->frame->on_click_right = destroyInspector;
1725 wWindowMap(panel->frame);
1727 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1728 wwin->wm_class, UPDATE_TEXT_FIELD);
1730 return panel;
1734 void
1735 wShowInspectorForWindow(WWindow *wwin)
1737 if (wwin->flags.inspector_open)
1738 return;
1740 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1742 make_keys();
1743 wwin->flags.inspector_open = 1;
1744 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1745 UNDEFINED_POS, False);
1751 void
1752 wHideInspectorForWindow(WWindow *wwin)
1754 WWindow *pwin = wwin->inspector->frame;
1756 wWindowUnmap(pwin);
1757 pwin->flags.hidden = 1;
1759 wClientSetState(pwin, IconicState, None);
1764 void
1765 wUnhideInspectorForWindow(WWindow *wwin)
1767 WWindow *pwin = wwin->inspector->frame;
1769 pwin->flags.hidden = 0;
1770 pwin->flags.mapped = 1;
1771 XMapWindow(dpy, pwin->client_win);
1772 XMapWindow(dpy, pwin->frame->core->window);
1773 wClientSetState(pwin, NormalState, None);
1778 WWindow*
1779 wGetWindowOfInspectorForWindow(WWindow *wwin)
1781 if (wwin->inspector) {
1782 assert(wwin->flags.inspector_open != 0);
1784 return wwin->inspector->frame;
1785 } else
1786 return NULL;
1790 void
1791 wCloseInspectorForWindow(WWindow *wwin)
1793 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1795 (*pwin->frame->on_click_right)(NULL, pwin, NULL);