Fix periodic focus bug
[wmaker-crm.git] / src / winspector.c
blobd55b68ef393e07e03cd1032d33af53488c3bd56b
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "funcs.h"
39 #include "defaults.h"
40 #include "dialog.h"
41 #include "icon.h"
42 #include "stacking.h"
43 #include "application.h"
44 #include "appicon.h"
45 #include "actions.h"
46 #include "winspector.h"
47 #include "dock.h"
48 #include "client.h"
50 #ifdef NETWM_HINTS
51 #include "wmspec.h"
52 #endif
54 #include "xinerama.h"
56 #include <WINGs/WUtil.h>
64 typedef struct InspectorPanel {
65 struct InspectorPanel *nextPtr;
67 WWindow *frame;
69 WWindow *inspected; /* the window that's being inspected */
71 WMWindow *win;
73 Window parent;
75 /* common stuff */
76 WMButton *revertBtn;
77 WMButton *applyBtn;
78 WMButton *saveBtn;
80 WMPopUpButton *pagePopUp;
82 /* first page. general stuff */
84 WMFrame *specFrm;
85 WMButton *instRb;
86 WMButton *clsRb;
87 WMButton *bothRb;
88 WMButton *defaultRb;
90 WMButton *selWinB;
92 WMLabel *specLbl;
94 /* second page. attributes */
96 WMFrame *attrFrm;
97 WMButton *attrChk[11];
99 /* 3rd page. more attributes */
100 WMFrame *moreFrm;
101 #ifdef XKB_BUTTON_HINT
102 WMButton *moreChk[9];
103 #else
104 WMButton *moreChk[8];
105 #endif
107 /* 4th page. icon and workspace */
108 WMFrame *iconFrm;
109 WMLabel *iconLbl;
110 WMLabel *fileLbl;
111 WMTextField *fileText;
112 WMButton *alwChk;
114 WMButton *updateIconBtn;
116 WMButton *browseIconBtn;
118 WMFrame *wsFrm;
119 WMPopUpButton *wsP;
121 /* 5th page. application wide attributes */
122 WMFrame *appFrm;
123 WMButton *appChk[3];
125 unsigned int done:1;
126 unsigned int destroyed:1;
127 unsigned int choosingIcon:1;
128 } InspectorPanel;
133 extern Cursor wCursor[WCUR_LAST];
135 extern WDDomain *WDWindowAttributes;
137 static InspectorPanel *panelList=NULL;
139 extern WPreferences wPreferences;
141 static WMPropList *ANoTitlebar = NULL;
142 static WMPropList *ANoResizebar;
143 static WMPropList *ANoMiniaturizeButton;
144 static WMPropList *ANoCloseButton;
145 static WMPropList *ANoBorder;
146 static WMPropList *ANoHideOthers;
147 static WMPropList *ANoMouseBindings;
148 static WMPropList *ANoKeyBindings;
149 static WMPropList *ANoAppIcon;
150 static WMPropList *AKeepOnTop;
151 static WMPropList *AKeepOnBottom;
152 static WMPropList *AOmnipresent;
153 static WMPropList *ASkipWindowList;
154 static WMPropList *AKeepInsideScreen;
155 static WMPropList *AUnfocusable;
156 static WMPropList *AAlwaysUserIcon;
157 static WMPropList *AStartMiniaturized;
158 static WMPropList *AStartMaximized;
159 static WMPropList *ADontSaveSession;
160 static WMPropList *AEmulateAppIcon;
161 static WMPropList *AFullMaximize;
162 static WMPropList *ASharedAppIcon;
163 #ifdef XKB_BUTTON_HINT
164 static WMPropList *ANoLanguageButton;
165 #endif
167 static WMPropList *AStartWorkspace;
169 static WMPropList *AIcon;
171 /* application wide options */
172 static WMPropList *AStartHidden;
175 static WMPropList *AnyWindow;
176 static WMPropList *EmptyString;
177 static WMPropList *Yes, *No;
180 #define PWIDTH 270
181 #define PHEIGHT 350
185 static char *spec_text;
188 static void applySettings(WMButton *button, InspectorPanel *panel);
193 #define UNDEFINED_POS 0xffffff
195 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
196 int xpos, int ypos,
197 Bool showSelectPanel);
201 static void
202 make_keys()
204 if (ANoTitlebar!=NULL)
205 return;
207 AIcon = WMCreatePLString("Icon");
208 ANoTitlebar = WMCreatePLString("NoTitlebar");
209 ANoResizebar = WMCreatePLString("NoResizebar");
210 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
211 ANoCloseButton = WMCreatePLString("NoCloseButton");
212 ANoBorder = WMCreatePLString("NoBorder");
213 ANoHideOthers = WMCreatePLString("NoHideOthers");
214 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
215 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
216 ANoAppIcon = WMCreatePLString("NoAppIcon");
217 AKeepOnTop = WMCreatePLString("KeepOnTop");
218 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
219 AOmnipresent = WMCreatePLString("Omnipresent");
220 ASkipWindowList = WMCreatePLString("SkipWindowList");
221 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
222 AUnfocusable = WMCreatePLString("Unfocusable");
223 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
224 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
225 AStartMaximized = WMCreatePLString("StartMaximized");
226 AStartHidden = WMCreatePLString("StartHidden");
227 ADontSaveSession = WMCreatePLString("DontSaveSession");
228 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
229 AFullMaximize = WMCreatePLString("FullMaximize");
230 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
231 #ifdef XKB_BUTTON_HINT
232 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
233 #endif
235 AStartWorkspace = WMCreatePLString("StartWorkspace");
237 AnyWindow = WMCreatePLString("*");
238 EmptyString = WMCreatePLString("");
239 Yes = WMCreatePLString("Yes");
240 No = WMCreatePLString("No");
245 static void
246 freeInspector(InspectorPanel *panel)
248 panel->destroyed = 1;
249 if (panel->choosingIcon)
250 return;
252 WMDestroyWidget(panel->win);
254 XDestroyWindow(dpy, panel->parent);
256 wfree(panel);
260 static void
261 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
263 InspectorPanel *panel;
264 InspectorPanel *tmp;
266 panel = panelList;
267 while (panel->frame!=data)
268 panel = panel->nextPtr;
270 if (panelList == panel)
271 panelList = panel->nextPtr;
272 else {
273 tmp = panelList;
274 while (tmp->nextPtr!=panel) {
275 tmp = tmp->nextPtr;
277 tmp->nextPtr = panel->nextPtr;
279 panel->inspected->flags.inspector_open = 0;
280 panel->inspected->inspector = NULL;
282 WMRemoveNotificationObserver(panel);
284 wWindowUnmap(panel->frame);
285 wUnmanageWindow(panel->frame, True, False);
287 freeInspector(panel);
292 void
293 wDestroyInspectorPanels()
295 InspectorPanel *panel;
297 while (panelList != NULL) {
298 panel = panelList;
299 panelList = panelList->nextPtr;
300 wUnmanageWindow(panel->frame, False, False);
301 WMDestroyWidget(panel->win);
303 panel->inspected->flags.inspector_open = 0;
304 panel->inspected->inspector = NULL;
306 wfree(panel);
311 static void
312 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
314 int page;
316 page = WMGetPopUpButtonSelectedItem(bPtr);
318 if (page == 0) {
319 WMMapWidget(panel->specFrm);
320 WMMapWidget(panel->specLbl);
321 } else if (page == 1) {
322 WMMapWidget(panel->attrFrm);
323 } else if (page == 2) {
324 WMMapWidget(panel->moreFrm);
325 } else if (page == 3) {
326 WMMapWidget(panel->iconFrm);
327 WMMapWidget(panel->wsFrm);
328 } else {
329 WMMapWidget(panel->appFrm);
332 if (page != 0) {
333 WMUnmapWidget(panel->specFrm);
334 WMUnmapWidget(panel->specLbl);
336 if (page != 1)
337 WMUnmapWidget(panel->attrFrm);
338 if (page != 2)
339 WMUnmapWidget(panel->moreFrm);
340 if (page != 3) {
341 WMUnmapWidget(panel->iconFrm);
342 WMUnmapWidget(panel->wsFrm);
344 if (page != 4 && panel->appFrm)
345 WMUnmapWidget(panel->appFrm);
349 #define USE_TEXT_FIELD 1
350 #define UPDATE_TEXT_FIELD 2
351 #define REVERT_TO_DEFAULT 4
354 static int
355 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
356 char *wm_instance, char *wm_class, int flags)
358 WMPixmap *pixmap = (WMPixmap*) NULL;
359 char *file=NULL, *path=NULL;
360 char *db_icon=NULL;
362 if ((flags & USE_TEXT_FIELD) != 0) {
363 file = WMGetTextFieldText(panel->fileText);
364 if (file && file[0] == 0) {
365 wfree(file);
366 file = NULL;
368 } else {
369 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
370 wm_instance, wm_class, False);
371 if(db_icon != NULL)
372 file = wstrdup(db_icon);
374 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
375 if (file)
376 file = wstrdup(db_icon);
377 flags |= UPDATE_TEXT_FIELD;
380 if ((flags & UPDATE_TEXT_FIELD) != 0) {
381 WMSetTextFieldText(panel->fileText, file);
384 if (file) {
385 path = FindImage(wPreferences.icon_path, file);
387 if (!path) {
388 char *buf;
389 int len = strlen(file)+80;
391 buf = wmalloc(len);
392 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"),
393 file);
394 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
395 _("OK"), NULL, NULL);
396 wfree(buf);
397 wfree(file);
398 return -1;
401 pixmap = WMCreatePixmapFromFile(scrPtr, path);
402 wfree(path);
404 if (!pixmap) {
405 char *buf;
406 int len = strlen(file)+80;
408 buf = wmalloc(len);
409 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
410 file, RMessageForError(RErrorCode));
411 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
412 _("OK"), NULL, NULL);
413 wfree(buf);
414 wfree(file);
415 return -1;
417 wfree(file);
420 WMSetLabelImage(panel->iconLbl, pixmap);
421 if (pixmap)
422 WMReleasePixmap(pixmap);
424 return 0;
427 #if 0
428 static void
429 updateIcon(WMButton *button, InspectorPanel *panel)
431 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
433 #endif
435 static int
436 getBool(WMPropList *value)
438 char *val;
440 if (!WMIsPLString(value)) {
441 return 0;
443 if (!(val = WMGetFromPLString(value))) {
444 return 0;
447 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
448 || val[0]=='t' || val[0]=='1'))
449 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
451 return 1;
452 } else if ((val[1]=='\0'
453 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
454 || val[0]=='f' || val[0]=='0'))
455 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
457 return 0;
458 } else {
459 wwarning(_("can't convert \"%s\" to boolean"), val);
460 return 0;
465 #define UPDATE_DEFAULTS 1
466 #define IS_BOOLEAN 2
470 * Will insert the attribute = value; pair in window's list,
471 * if it's different from the defaults.
472 * Defaults means either defaults database, or attributes saved
473 * for the default window "*". This is to let one revert options that are
474 * global because they were saved for all windows ("*").
479 static int
480 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr,
481 WMPropList *value, int flags)
483 WMPropList *def_win, *def_value=NULL;
484 int update = 0;
485 int modified = 0;
487 if (!(flags & UPDATE_DEFAULTS) && dict) {
488 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
489 def_value = WMGetFromPLDictionary(def_win, attr);
493 /* If we could not find defaults in database, fall to hardcoded values.
494 * Also this is true if we save defaults for all windows
496 if (!def_value)
497 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
499 if ((flags & IS_BOOLEAN))
500 update = (getBool(value) != getBool(def_value));
501 else {
502 update = !WMIsPropListEqualTo(value, def_value);
505 if (update) {
506 WMPutInPLDictionary(window, attr, value);
507 modified = 1;
510 return modified;
514 static void
515 saveSettings(WMButton *button, InspectorPanel *panel)
517 WWindow *wwin = panel->inspected;
518 WDDomain *db = WDWindowAttributes;
519 WMPropList *dict = db->dictionary;
520 WMPropList *winDic, *appDic, *value, *key, *key2;
521 char *icon_file;
522 int flags = 0;
523 int different = 0, different2 = 0;
525 /* Save will apply the changes and save them */
526 applySettings(panel->applyBtn, panel);
528 if (WMGetButtonSelected(panel->instRb) != 0)
529 key = WMCreatePLString(wwin->wm_instance);
530 else if (WMGetButtonSelected(panel->clsRb) != 0)
531 key = WMCreatePLString(wwin->wm_class);
532 else if (WMGetButtonSelected(panel->bothRb) != 0) {
533 char *buffer;
535 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
536 key = WMCreatePLString(buffer);
537 wfree(buffer);
538 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
539 key = WMRetainPropList(AnyWindow);
540 flags = UPDATE_DEFAULTS;
541 } else
542 key = NULL;
544 if (!key)
545 return;
547 if (!dict) {
548 dict = WMCreatePLDictionary(NULL, NULL);
549 if (dict) {
550 db->dictionary = dict;
551 } else {
552 WMReleasePropList(key);
553 return;
557 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
558 USE_TEXT_FIELD) < 0)
559 return;
561 WMPLSetCaseSensitive(True);
563 winDic = WMCreatePLDictionary(NULL, NULL);
564 appDic = WMCreatePLDictionary(NULL, NULL);
566 /* Update icon for window */
567 icon_file = WMGetTextFieldText(panel->fileText);
568 if (icon_file) {
569 if (icon_file[0] != 0) {
570 value = WMCreatePLString(icon_file);
571 different |= insertAttribute(dict, winDic, AIcon, value, flags);
572 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
573 WMReleasePropList(value);
575 wfree(icon_file);
579 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
581 i--;
583 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
584 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
585 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
586 flags);
587 WMReleasePropList(value);
591 flags |= IS_BOOLEAN;
593 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
594 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
596 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
597 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
599 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
600 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
602 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
605 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
606 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
608 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
609 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
611 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
612 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
614 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
615 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
617 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
618 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
620 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
621 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
623 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
624 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
626 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
627 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
630 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
631 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
633 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
634 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
636 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
637 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
639 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
640 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
642 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
643 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
645 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
646 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
648 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
649 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
651 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
652 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
654 #ifdef XKB_BUTTON_HINT
655 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
656 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
657 #endif
659 if (wwin->main_window!=None && wApplicationOf(wwin->main_window)!=NULL) {
660 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
661 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
663 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
664 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
666 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
667 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
670 if (wwin->fake_group) {
671 key2 = WMCreatePLString(wwin->fake_group->identifier);
672 if (WMIsPropListEqualTo(key, key2)) {
673 WMMergePLDictionaries(winDic, appDic, True);
674 different |= different2;
675 } else {
676 WMRemoveFromPLDictionary(dict, key2);
677 if (different2) {
678 WMPutInPLDictionary(dict, key2, appDic);
681 WMReleasePropList(key2);
682 WMReleasePropList(appDic);
683 } else if (wwin->main_window != wwin->client_win) {
684 WApplication *wapp = wApplicationOf(wwin->main_window);
686 if (wapp) {
687 char *instance = wapp->main_window_desc->wm_instance;
688 char *class = wapp->main_window_desc->wm_class;
689 char *buffer;
691 buffer = StrConcatDot(instance, class);
692 key2 = WMCreatePLString(buffer);
693 wfree(buffer);
695 if (WMIsPropListEqualTo(key, key2)) {
696 WMMergePLDictionaries(winDic, appDic, True);
697 different |= different2;
698 } else {
699 WMRemoveFromPLDictionary(dict, key2);
700 if (different2) {
701 WMPutInPLDictionary(dict, key2, appDic);
704 WMReleasePropList(key2);
705 WMReleasePropList(appDic);
707 } else {
708 WMMergePLDictionaries(winDic, appDic, True);
709 different |= different2;
710 WMReleasePropList(appDic);
713 WMRemoveFromPLDictionary(dict, key);
714 if (different) {
715 WMPutInPLDictionary(dict, key, winDic);
718 WMReleasePropList(key);
719 WMReleasePropList(winDic);
721 UpdateDomainFile(db);
723 /* clean up */
724 WMPLSetCaseSensitive(False);
728 static void
729 makeAppIconFor(WApplication *wapp)
731 WScreen *scr = wapp->main_window_desc->screen_ptr;
733 if (wapp->app_icon)
734 return;
736 if (!WFLAGP(wapp->main_window_desc, no_appicon))
737 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
738 else
739 wapp->app_icon = NULL;
741 if (wapp->app_icon) {
742 WIcon *icon = wapp->app_icon->icon;
743 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
744 int x=0, y=0;
746 wapp->app_icon->main_window = wapp->main_window;
748 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
749 wapp->app_icon->attracted = 1;
750 if (!wapp->app_icon->icon->shadowed) {
751 wapp->app_icon->icon->shadowed = 1;
752 wapp->app_icon->icon->force_paint = 1;
754 wDockAttachIcon(clip, wapp->app_icon, x, y);
755 } else {
756 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
757 wAppIconMove(wapp->app_icon, x, y);
759 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
760 XMapWindow(dpy, icon->core->window);
762 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
763 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
768 static void
769 removeAppIconFor(WApplication *wapp)
771 if (!wapp->app_icon)
772 return;
774 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
775 wapp->app_icon->running = 0;
776 /* since we keep it, we don't care if it was attracted or not */
777 wapp->app_icon->attracted = 0;
778 wapp->app_icon->icon->shadowed = 0;
779 wapp->app_icon->main_window = None;
780 wapp->app_icon->pid = 0;
781 wapp->app_icon->icon->owner = NULL;
782 wapp->app_icon->icon->icon_win = None;
783 wapp->app_icon->icon->force_paint = 1;
784 wAppIconPaint(wapp->app_icon);
785 } else if (wapp->app_icon->docked) {
786 wapp->app_icon->running = 0;
787 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
788 } else {
789 wAppIconDestroy(wapp->app_icon);
791 wapp->app_icon = NULL;
792 if (wPreferences.auto_arrange_icons)
793 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
797 static void
798 applySettings(WMButton *button, InspectorPanel *panel)
800 WWindow *wwin = panel->inspected;
801 WApplication *wapp = wApplicationOf(wwin->main_window);
802 int floating, sunken, skip_window_list;
803 int old_omnipresent;
804 int old_no_bind_keys;
805 int old_no_bind_mouse;
807 old_omnipresent = WFLAGP(wwin, omnipresent);
808 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
809 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
811 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
813 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
814 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
815 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
816 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
817 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
818 floating = WMGetButtonSelected(panel->attrChk[5]);
819 sunken = WMGetButtonSelected(panel->attrChk[6]);
820 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
821 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
822 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
823 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
825 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
826 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
827 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
828 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
829 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
830 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
831 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
832 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
833 #ifdef XKB_BUTTON_HINT
834 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
835 #endif
836 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
838 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
839 wUnshadeWindow(wwin);
841 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
843 if (floating) {
844 if (!WFLAGP(wwin, floating))
845 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
846 } else if (sunken) {
847 if (!WFLAGP(wwin, sunken))
848 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
849 } else {
850 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
851 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
854 WSETUFLAG(wwin, sunken, sunken);
855 WSETUFLAG(wwin, floating, floating);
856 wwin->flags.omnipresent = 0;
858 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
859 WSETUFLAG(wwin, skip_window_list, skip_window_list);
860 UpdateSwitchMenu(wwin->screen_ptr, wwin,
861 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
862 } else {
863 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
864 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
868 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
869 if (WFLAGP(wwin, no_bind_keys)) {
870 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
871 } else {
872 wWindowSetKeyGrabs(wwin);
876 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
877 wWindowResetMouseGrabs(wwin);
880 wwin->frame->flags.need_texture_change = 1;
881 wWindowConfigureBorders(wwin);
882 wFrameWindowPaint(wwin->frame);
883 #ifdef NETWM_HINTS
884 wNETWMUpdateActions(wwin, False);
885 #endif
888 * Can't apply emulate_appicon because it will probably cause problems.
891 if (wapp) {
892 /* do application wide stuff */
893 WSETUFLAG(wapp->main_window_desc, start_hidden,
894 WMGetButtonSelected(panel->appChk[0]));
896 WSETUFLAG(wapp->main_window_desc, no_appicon,
897 WMGetButtonSelected(panel->appChk[1]));
899 WSETUFLAG(wapp->main_window_desc, shared_appicon,
900 WMGetButtonSelected(panel->appChk[2]));
902 if (WFLAGP(wapp->main_window_desc, no_appicon))
903 removeAppIconFor(wapp);
904 else
905 makeAppIconFor(wapp);
907 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
908 char *file = WMGetTextFieldText(panel->fileText);
910 if (file[0] == 0) {
911 wfree(file);
912 file = NULL;
914 wIconChangeImageFile(wapp->app_icon->icon, file);
915 if (file)
916 wfree(file);
917 wAppIconPaint(wapp->app_icon);
925 static void
926 revertSettings(WMButton *button, InspectorPanel *panel)
928 WWindow *wwin = panel->inspected;
929 WApplication *wapp = wApplicationOf(wwin->main_window);
930 int i, n;
931 char *wm_instance = NULL;
932 char *wm_class = NULL;
933 int workspace, level;
935 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
936 wm_instance = wwin->wm_instance;
937 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
938 wm_class = wwin->wm_class;
939 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
940 wm_instance = wwin->wm_instance;
941 wm_class = wwin->wm_class;
943 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
944 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
945 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
947 wWindowSetupInitialAttributes(wwin, &level, &workspace);
949 for (i=0; i < 11; i++) {
950 int flag = 0;
952 switch (i) {
953 case 0:
954 flag = WFLAGP(wwin, no_titlebar);
955 break;
956 case 1:
957 flag = WFLAGP(wwin, no_resizebar);
958 break;
959 case 2:
960 flag = WFLAGP(wwin, no_close_button);
961 break;
962 case 3:
963 flag = WFLAGP(wwin, no_miniaturize_button);
964 break;
965 case 4:
966 flag = WFLAGP(wwin, no_border);
967 break;
968 case 5:
969 flag = WFLAGP(wwin, floating);
970 break;
971 case 6:
972 flag = WFLAGP(wwin, sunken);
973 break;
974 case 7:
975 flag = WFLAGP(wwin, omnipresent);
976 break;
977 case 8:
978 flag = WFLAGP(wwin, start_miniaturized);
979 break;
980 case 9:
981 flag = WFLAGP(wwin, start_maximized!=0);
982 break;
983 case 10:
984 flag = WFLAGP(wwin, full_maximize);
985 break;
987 WMSetButtonSelected(panel->attrChk[i], flag);
989 for (i=0; i < 8; i++) {
990 int flag = 0;
992 switch (i) {
993 case 0:
994 flag = WFLAGP(wwin, no_bind_keys);
995 break;
996 case 1:
997 flag = WFLAGP(wwin, no_bind_mouse);
998 break;
999 case 2:
1000 flag = WFLAGP(wwin, skip_window_list);
1001 break;
1002 case 3:
1003 flag = WFLAGP(wwin, no_focusable);
1004 break;
1005 case 4:
1006 flag = WFLAGP(wwin, dont_move_off);
1007 break;
1008 case 5:
1009 flag = WFLAGP(wwin, no_hide_others);
1010 break;
1011 case 6:
1012 flag = WFLAGP(wwin, dont_save_session);
1013 break;
1014 case 7:
1015 flag = WFLAGP(wwin, emulate_appicon);
1016 break;
1017 #ifdef XKB_BUTTON_HINT
1018 case 8:
1019 flag = WFLAGP(wwin, no_language_button);
1020 break;
1021 #endif
1023 WMSetButtonSelected(panel->moreChk[i], flag);
1025 if (panel->appFrm && wapp) {
1026 for (i=0; i < 2; i++) {
1027 int flag = 0;
1029 switch (i) {
1030 case 0:
1031 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1032 break;
1033 case 1:
1034 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1035 break;
1036 case 2:
1037 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1038 break;
1040 WMSetButtonSelected(panel->appChk[i], flag);
1043 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1045 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1046 REVERT_TO_DEFAULT);
1048 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1050 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1051 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1052 } else {
1053 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1056 /* must auto apply, so that there wno't be internal
1057 * inconsistencies between the state in the flags and
1058 * the actual state of the window */
1059 applySettings(panel->applyBtn, panel);
1063 static void
1064 chooseIconCallback(WMWidget *self, void *clientData)
1066 char *file;
1067 InspectorPanel *panel = (InspectorPanel*)clientData;
1068 int result;
1070 panel->choosingIcon = 1;
1072 WMSetButtonEnabled(panel->browseIconBtn, False);
1074 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1075 panel->inspected->wm_instance,
1076 panel->inspected->wm_class);
1078 panel->choosingIcon = 0;
1080 if (!panel->destroyed) { /* kluge */
1081 if (result) {
1082 WMSetTextFieldText(panel->fileText, file);
1083 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1084 USE_TEXT_FIELD);
1085 wfree(file);
1087 WMSetButtonEnabled(panel->browseIconBtn, True);
1088 } else {
1089 freeInspector(panel);
1094 static void
1095 textEditedObserver(void *observerData, WMNotification *notification)
1097 InspectorPanel *panel = (InspectorPanel*)observerData;
1099 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1100 return;
1102 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1103 USE_TEXT_FIELD);
1105 WMPerformButtonClick(panel->updateIconBtn);
1110 static void
1111 selectSpecification(WMWidget *bPtr, void *data)
1113 InspectorPanel *panel = (InspectorPanel*)data;
1114 char *str;
1115 WWindow *wwin = panel->inspected;
1116 int len;
1118 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1119 WMSetButtonEnabled(panel->applyBtn, False);
1120 } else {
1121 WMSetButtonEnabled(panel->applyBtn, True);
1124 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1125 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1127 str = wmalloc(len);
1129 snprintf(str, len, _("Inspecting %s.%s"),
1130 wwin->wm_instance ? wwin->wm_instance : "?",
1131 wwin->wm_class ? wwin->wm_class : "?");
1133 wFrameWindowChangeTitle(panel->frame->frame, str);
1135 wfree(str);
1139 static void
1140 selectWindow(WMWidget *bPtr, void *data)
1142 InspectorPanel *panel = (InspectorPanel*)data;
1143 WWindow *wwin = panel->inspected;
1144 WScreen *scr = wwin->screen_ptr;
1145 XEvent event;
1146 WWindow *iwin;
1148 if (XGrabPointer(dpy, scr->root_win, True,
1149 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1150 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1151 wwarning("could not grab mouse pointer");
1152 return;
1155 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1157 WMMaskEvent(dpy, ButtonPressMask, &event);
1159 XUngrabPointer(dpy, CurrentTime);
1161 iwin = wWindowFor(event.xbutton.subwindow);
1163 if (iwin && !iwin->flags.internal_window && iwin != wwin
1164 && !iwin->flags.inspector_open) {
1166 iwin->flags.inspector_open = 1;
1167 iwin->inspector = createInspectorForWindow(iwin,
1168 panel->frame->frame_x,
1169 panel->frame->frame_y,
1170 True);
1171 wCloseInspectorForWindow(wwin);
1172 } else {
1173 WMSetLabelText(panel->specLbl, spec_text);
1179 static InspectorPanel*
1180 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1181 Bool showSelectPanel)
1183 WScreen *scr = wwin->screen_ptr;
1184 InspectorPanel *panel;
1185 Window parent;
1186 int i;
1187 int x, y;
1188 int btn_width, frame_width;
1189 WMButton *selectedBtn = NULL;
1190 #ifdef wrong_behaviour
1191 WMPixmap *pixmap;
1192 #endif
1194 spec_text = _("The configuration will apply to all\n"
1195 "windows that have their WM_CLASS\n"
1196 "property set to the above selected\n"
1197 "name, when saved.");
1199 panel = wmalloc(sizeof(InspectorPanel));
1200 memset(panel, 0, sizeof(InspectorPanel));
1202 panel->destroyed = 0;
1205 panel->inspected = wwin;
1207 panel->nextPtr = panelList;
1208 panelList = panel;
1211 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1212 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1215 /**** create common stuff ****/
1217 /* command buttons */
1218 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1219 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1220 panel->saveBtn = WMCreateCommandButton(panel->win);
1221 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1222 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1223 WMSetButtonText(panel->saveBtn, _("Save"));
1224 WMResizeWidget(panel->saveBtn, btn_width, 28);
1225 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1226 WMSetButtonEnabled(panel->saveBtn, False);
1228 panel->applyBtn = WMCreateCommandButton(panel->win);
1229 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1230 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1231 WMSetButtonText(panel->applyBtn, _("Apply"));
1232 WMResizeWidget(panel->applyBtn, btn_width, 28);
1234 panel->revertBtn = WMCreateCommandButton(panel->win);
1235 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1236 WMMoveWidget(panel->revertBtn, 15, 310);
1237 WMSetButtonText(panel->revertBtn, _("Reload"));
1238 WMResizeWidget(panel->revertBtn, btn_width, 28);
1240 /* page selection popup button */
1241 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1242 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1243 WMMoveWidget(panel->pagePopUp, 25, 15);
1244 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1246 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1247 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1248 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1249 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1250 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1252 /**** window spec ****/
1253 frame_width = PWIDTH - (2 * 15);
1255 panel->specFrm = WMCreateFrame(panel->win);
1256 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1257 WMMoveWidget(panel->specFrm, 15, 65);
1258 WMResizeWidget(panel->specFrm, frame_width, 145);
1261 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1262 WMMoveWidget(panel->defaultRb, 10, 78);
1263 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1264 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1265 WMSetButtonSelected(panel->defaultRb, False);
1266 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1268 if (wwin->wm_class && wwin->wm_instance) {
1269 char *str, *tmp;
1271 tmp = wstrconcat(wwin->wm_instance, ".");
1272 str = wstrconcat(tmp, wwin->wm_class);
1274 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1275 WMMoveWidget(panel->bothRb, 10, 18);
1276 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1277 WMSetButtonText(panel->bothRb, str);
1278 wfree(tmp);
1279 wfree(str);
1280 WMGroupButtons(panel->defaultRb, panel->bothRb);
1282 if (!selectedBtn)
1283 selectedBtn = panel->bothRb;
1285 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1288 if (wwin->wm_instance) {
1289 panel->instRb = WMCreateRadioButton(panel->specFrm);
1290 WMMoveWidget(panel->instRb, 10, 38);
1291 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1292 WMSetButtonText(panel->instRb, wwin->wm_instance);
1293 WMGroupButtons(panel->defaultRb, panel->instRb);
1295 if (!selectedBtn)
1296 selectedBtn = panel->instRb;
1298 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1301 if (wwin->wm_class) {
1302 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1303 WMMoveWidget(panel->clsRb, 10, 58);
1304 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1305 WMSetButtonText(panel->clsRb, wwin->wm_class);
1306 WMGroupButtons(panel->defaultRb, panel->clsRb);
1308 if (!selectedBtn)
1309 selectedBtn = panel->clsRb;
1311 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1315 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1316 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1317 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1318 WMSetButtonText(panel->selWinB, _("Select window"));
1319 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1322 panel->specLbl = WMCreateLabel(panel->win);
1323 WMMoveWidget(panel->specLbl, 15, 210);
1324 WMResizeWidget(panel->specLbl, frame_width, 100);
1325 WMSetLabelText(panel->specLbl, spec_text);
1326 WMSetLabelWraps(panel->specLbl, True);
1328 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1330 /**** attributes ****/
1331 panel->attrFrm = WMCreateFrame(panel->win);
1332 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1333 WMMoveWidget(panel->attrFrm, 15, 45);
1334 WMResizeWidget(panel->attrFrm, frame_width, 250);
1336 for (i=0; i < 11; i++) {
1337 char *caption = NULL;
1338 int flag = 0;
1339 char *descr = NULL;
1341 switch (i) {
1342 case 0:
1343 caption = _("Disable titlebar");
1344 flag = WFLAGP(wwin, no_titlebar);
1345 descr = _("Remove the titlebar of this window.\n"
1346 "To access the window commands menu of a window\n"
1347 "without it's titlebar, press Control+Esc (or the\n"
1348 "equivalent shortcut, if you changed the default\n"
1349 "settings).");
1350 break;
1351 case 1:
1352 caption = _("Disable resizebar");
1353 flag = WFLAGP(wwin, no_resizebar);
1354 descr = _("Remove the resizebar of this window.");
1355 break;
1356 case 2:
1357 caption = _("Disable close button");
1358 flag = WFLAGP(wwin, no_close_button);
1359 descr = _("Remove the `close window' button of this window.");
1360 break;
1361 case 3:
1362 caption = _("Disable miniaturize button");
1363 flag = WFLAGP(wwin, no_miniaturize_button);
1364 descr = _("Remove the `miniaturize window' button of the window.");
1365 break;
1366 case 4:
1367 caption = _("Disable border");
1368 flag = WFLAGP(wwin, no_border);
1369 descr = _("Remove the 1 pixel black border around the window.");
1370 break;
1371 case 5:
1372 caption = _("Keep on top (floating)");
1373 flag = WFLAGP(wwin, floating);
1374 descr = _("Keep the window over other windows, not allowing\n"
1375 "them to cover it.");
1376 break;
1377 case 6:
1378 caption = _("Keep at bottom (sunken)");
1379 flag = WFLAGP(wwin, sunken);
1380 descr = _("Keep the window under all other windows.");
1381 break;
1382 case 7:
1383 caption = _("Omnipresent");
1384 flag = WFLAGP(wwin, omnipresent);
1385 descr = _("Make window present in all workspaces.");
1386 break;
1387 case 8:
1388 caption = _("Start miniaturized");
1389 flag = WFLAGP(wwin, start_miniaturized);
1390 descr = _("Make the window be automatically miniaturized when it's\n"
1391 "first shown.");
1392 break;
1393 case 9:
1394 caption = _("Start maximized");
1395 flag = WFLAGP(wwin, start_maximized!=0);
1396 descr = _("Make the window be automatically maximized when it's\n"
1397 "first shown.");
1398 break;
1399 case 10:
1400 caption = _("Full screen maximization");
1401 flag = WFLAGP(wwin, full_maximize);
1402 descr = _("Make the window use the whole screen space when it's\n"
1403 "maximized. The titlebar and resizebar will be moved\n"
1404 "to outside the screen.");
1405 break;
1407 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1408 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1409 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1410 WMSetButtonSelected(panel->attrChk[i], flag);
1411 WMSetButtonText(panel->attrChk[i], caption);
1413 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1417 /**** more attributes ****/
1418 panel->moreFrm = WMCreateFrame(panel->win);
1419 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1420 WMMoveWidget(panel->moreFrm, 15, 45);
1421 WMResizeWidget(panel->moreFrm, frame_width, 250);
1423 for (i=0;
1424 #ifdef XKB_BUTTON_HINT
1425 i < 9;
1426 #else
1427 i < 8;
1428 #endif
1429 i++) {
1430 char *caption = NULL;
1431 int flag = 0;
1432 char *descr = NULL;
1434 switch (i) {
1435 case 0:
1436 caption = _("Do not bind keyboard shortcuts");
1437 flag = WFLAGP(wwin, no_bind_keys);
1438 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1439 "when this window is focused. This will allow the\n"
1440 "window to receive all key combinations regardless\n"
1441 "of your shortcut configuration.");
1442 break;
1443 case 1:
1444 caption = _("Do not bind mouse clicks");
1445 flag = WFLAGP(wwin, no_bind_mouse);
1446 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1447 "in the window (when alt is the modifier you have\n"
1448 "configured).");
1449 break;
1450 case 2:
1451 caption = _("Do not show in the window list");
1452 flag = WFLAGP(wwin, skip_window_list);
1453 descr = _("Do not list the window in the window list menu.");
1454 break;
1455 case 3:
1456 caption = _("Do not let it take focus");
1457 flag = WFLAGP(wwin, no_focusable);
1458 descr = _("Do not let the window take keyboard focus when you\n"
1459 "click on it.");
1460 break;
1461 case 4:
1462 caption = _("Keep inside screen");
1463 flag = WFLAGP(wwin, dont_move_off);
1464 descr = _("Do not allow the window to move itself completely\n"
1465 "outside the screen. For bug compatibility.\n");
1466 break;
1467 case 5:
1468 caption = _("Ignore 'Hide Others'");
1469 flag = WFLAGP(wwin, no_hide_others);
1470 descr = _("Do not hide the window when issuing the\n"
1471 "`HideOthers' command.");
1472 break;
1473 case 6:
1474 caption = _("Ignore 'Save Session'");
1475 flag = WFLAGP(wwin, dont_save_session);
1476 descr = _("Do not save the associated application in the\n"
1477 "session's state, so that it won't be restarted\n"
1478 "together with other applications when Window Maker\n"
1479 "starts.");
1480 break;
1481 case 7:
1482 caption = _("Emulate application icon");
1483 flag = WFLAGP(wwin, emulate_appicon);
1484 descr = _("Make this window act as an application that provides\n"
1485 "enough information to Window Maker for a dockable\n"
1486 "application icon to be created.");
1487 break;
1488 #ifdef XKB_BUTTON_HINT
1489 case 8:
1490 caption = _("Disable language button");
1491 flag = WFLAGP(wwin, no_language_button);
1492 descr = _("Remove the `toggle language' button of the window.");
1493 break;
1494 #endif
1496 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1497 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1498 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1499 WMSetButtonSelected(panel->moreChk[i], flag);
1500 WMSetButtonText(panel->moreChk[i], caption);
1502 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1505 /* miniwindow/workspace */
1506 panel->iconFrm = WMCreateFrame(panel->win);
1507 WMMoveWidget(panel->iconFrm, 15, 50);
1508 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1509 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1511 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1512 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1513 WMResizeWidget(panel->iconLbl, 64, 64);
1514 WMSetLabelRelief(panel->iconLbl, WRGroove);
1515 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1517 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1518 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1519 WMMoveWidget(panel->browseIconBtn, 22, 32);
1520 WMResizeWidget(panel->browseIconBtn, 120, 26);
1521 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1523 #ifdef wrong_behaviour
1524 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1525 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1526 WMSetButtonImage(panel->updateIconBtn, pixmap);
1527 WMReleasePixmap(pixmap);
1528 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1529 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1530 WMReleasePixmap(pixmap);
1531 #endif
1533 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1534 WMMoveWidget(panel->fileLbl, 20, 85);
1535 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1536 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1538 panel->fileText = WMCreateTextField(panel->iconFrm);
1539 WMMoveWidget(panel->fileText, 20, 105);
1540 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1541 WMSetTextFieldText(panel->fileText, NULL);
1542 WMAddNotificationObserver(textEditedObserver, panel,
1543 WMTextDidEndEditingNotification,
1544 panel->fileText);
1546 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1547 WMMoveWidget(panel->alwChk, 20, 130);
1548 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1549 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1550 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1553 panel->wsFrm = WMCreateFrame(panel->win);
1554 WMMoveWidget(panel->wsFrm, 15, 225);
1555 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1556 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1558 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1559 "first shown."), WMWidgetView(panel->wsFrm));
1561 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1562 WMMoveWidget(panel->wsP, 20, 30);
1563 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1564 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1565 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1566 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1569 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1570 wwin->wm_class);
1571 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1572 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1573 } else {
1574 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1577 /* application wide attributes */
1578 if (wwin->main_window != None) {
1579 WApplication *wapp = wApplicationOf(wwin->main_window);
1581 panel->appFrm = WMCreateFrame(panel->win);
1582 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1583 WMMoveWidget(panel->appFrm, 15, 50);
1584 WMResizeWidget(panel->appFrm, frame_width, 240);
1586 for (i=0; i < 3; i++) {
1587 char *caption = NULL;
1588 int flag = 0;
1589 char *descr = NULL;
1591 switch (i) {
1592 case 0:
1593 caption = _("Start hidden");
1594 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1595 descr = _("Automatically hide application when it's started.");
1596 break;
1597 case 1:
1598 caption = _("No application icon");
1599 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1600 descr = _("Disable the application icon for the application.\n"
1601 "Note that you won't be able to dock it anymore,\n"
1602 "and any icons that are already docked will stop\n"
1603 "working correctly.");
1604 break;
1605 case 2:
1606 caption = _("Shared application icon");
1607 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1608 descr = _("Use a single shared application icon for all of\n"
1609 "the instances of this application.\n");
1610 break;
1612 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1613 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1614 WMResizeWidget(panel->appChk[i], 205, 20);
1615 WMSetButtonSelected(panel->appChk[i], flag);
1616 WMSetButtonText(panel->appChk[i], caption);
1618 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1621 if (WFLAGP(wwin, emulate_appicon)) {
1622 WMSetButtonEnabled(panel->appChk[1], False);
1623 WMSetButtonEnabled(panel->moreChk[7], True);
1624 } else {
1625 WMSetButtonEnabled(panel->appChk[1], True);
1626 WMSetButtonEnabled(panel->moreChk[7], False);
1628 } else {
1629 int tmp;
1631 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1632 || !wwin->wm_class || !wwin->wm_instance)
1633 tmp = False;
1634 else
1635 tmp = True;
1636 WMSetButtonEnabled(panel->moreChk[7], tmp);
1638 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1639 panel->appFrm = NULL;
1642 /* if the window is a transient, don't let it have a miniaturize
1643 * button */
1644 if (wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1645 WMSetButtonEnabled(panel->attrChk[3], False);
1646 else
1647 WMSetButtonEnabled(panel->attrChk[3], True);
1650 if (!wwin->wm_class && !wwin->wm_instance) {
1651 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1655 WMRealizeWidget(panel->win);
1657 WMMapSubwidgets(panel->win);
1658 WMMapSubwidgets(panel->specFrm);
1659 WMMapSubwidgets(panel->attrFrm);
1660 WMMapSubwidgets(panel->moreFrm);
1661 WMMapSubwidgets(panel->iconFrm);
1662 WMMapSubwidgets(panel->wsFrm);
1663 if (panel->appFrm)
1664 WMMapSubwidgets(panel->appFrm);
1666 if (showSelectPanel) {
1667 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1668 changePage(panel->pagePopUp, panel);
1669 } else {
1670 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1671 changePage(panel->pagePopUp, panel);
1675 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1676 0, 0, 0);
1677 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1678 panel->parent = parent;
1679 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1681 WMMapWidget(panel->win);
1683 XSetTransientForHint(dpy, parent, wwin->client_win);
1685 if (xpos == UNDEFINED_POS) {
1686 x = wwin->frame_x+wwin->frame->core->width/2;
1687 y = wwin->frame_y+wwin->frame->top_width*2;
1688 if (y + PHEIGHT > scr->scr_height)
1689 y = scr->scr_height - PHEIGHT - 30;
1690 if (x + PWIDTH > scr->scr_width)
1691 x = scr->scr_width - PWIDTH;
1692 } else {
1693 x = xpos;
1694 y = ypos;
1697 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1698 "Inspector", x, y, PWIDTH, PHEIGHT);
1700 if (!selectedBtn)
1701 selectedBtn = panel->defaultRb;
1703 WMSetButtonSelected(selectedBtn, True);
1705 selectSpecification(selectedBtn, panel);
1707 /* kluge to know who should get the key events */
1708 panel->frame->client_leader = WMWidgetXID(panel->win);
1710 WSETUFLAG(panel->frame, no_closable, 0);
1711 WSETUFLAG(panel->frame, no_close_button, 0);
1712 wWindowUpdateButtonImages(panel->frame);
1713 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1714 panel->frame->frame->on_click_right = destroyInspector;
1716 wWindowMap(panel->frame);
1718 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1719 wwin->wm_class, UPDATE_TEXT_FIELD);
1721 return panel;
1725 void
1726 wShowInspectorForWindow(WWindow *wwin)
1728 if (wwin->flags.inspector_open)
1729 return;
1731 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1733 make_keys();
1734 wwin->flags.inspector_open = 1;
1735 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1736 UNDEFINED_POS, False);
1742 void
1743 wHideInspectorForWindow(WWindow *wwin)
1745 WWindow *pwin = wwin->inspector->frame;
1747 wWindowUnmap(pwin);
1748 pwin->flags.hidden = 1;
1750 wClientSetState(pwin, IconicState, None);
1755 void
1756 wUnhideInspectorForWindow(WWindow *wwin)
1758 WWindow *pwin = wwin->inspector->frame;
1760 pwin->flags.hidden = 0;
1761 pwin->flags.mapped = 1;
1762 XMapWindow(dpy, pwin->client_win);
1763 XMapWindow(dpy, pwin->frame->core->window);
1764 wClientSetState(pwin, NormalState, None);
1769 WWindow*
1770 wGetWindowOfInspectorForWindow(WWindow *wwin)
1772 if (wwin->inspector) {
1773 assert(wwin->flags.inspector_open != 0);
1775 return wwin->inspector->frame;
1776 } else
1777 return NULL;
1781 void
1782 wCloseInspectorForWindow(WWindow *wwin)
1784 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1786 (*pwin->frame->on_click_right)(NULL, pwin, NULL);