Change to the linux kernel coding style
[wmaker-crm.git] / src / winspector.c
blob4609a7e3123fb613a7d4fad5c73dbccc2fc0281e
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "funcs.h"
39 #include "defaults.h"
40 #include "dialog.h"
41 #include "icon.h"
42 #include "stacking.h"
43 #include "application.h"
44 #include "appicon.h"
45 #include "actions.h"
46 #include "winspector.h"
47 #include "dock.h"
48 #include "client.h"
50 #ifdef NETWM_HINTS
51 #include "wmspec.h"
52 #endif
54 #include "xinerama.h"
56 #include <WINGs/WUtil.h>
58 typedef struct InspectorPanel {
59 struct InspectorPanel *nextPtr;
61 WWindow *frame;
63 WWindow *inspected; /* the window that's being inspected */
65 WMWindow *win;
67 Window parent;
69 /* common stuff */
70 WMButton *revertBtn;
71 WMButton *applyBtn;
72 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
84 WMButton *selWinB;
86 WMLabel *specLbl;
88 /* second page. attributes */
90 WMFrame *attrFrm;
91 WMButton *attrChk[11];
93 /* 3rd page. more attributes */
94 WMFrame *moreFrm;
95 #ifdef XKB_BUTTON_HINT
96 WMButton *moreChk[9];
97 #else
98 WMButton *moreChk[8];
99 #endif
101 /* 4th page. icon and workspace */
102 WMFrame *iconFrm;
103 WMLabel *iconLbl;
104 WMLabel *fileLbl;
105 WMTextField *fileText;
106 WMButton *alwChk;
108 WMButton *updateIconBtn;
110 WMButton *browseIconBtn;
112 WMFrame *wsFrm;
113 WMPopUpButton *wsP;
115 /* 5th page. application wide attributes */
116 WMFrame *appFrm;
117 WMButton *appChk[3];
119 unsigned int done:1;
120 unsigned int destroyed:1;
121 unsigned int choosingIcon:1;
122 } InspectorPanel;
124 extern Cursor wCursor[WCUR_LAST];
126 extern WDDomain *WDWindowAttributes;
128 static InspectorPanel *panelList = NULL;
130 extern WPreferences wPreferences;
132 static WMPropList *ANoTitlebar = NULL;
133 static WMPropList *ANoResizebar;
134 static WMPropList *ANoMiniaturizeButton;
135 static WMPropList *ANoCloseButton;
136 static WMPropList *ANoBorder;
137 static WMPropList *ANoHideOthers;
138 static WMPropList *ANoMouseBindings;
139 static WMPropList *ANoKeyBindings;
140 static WMPropList *ANoAppIcon;
141 static WMPropList *AKeepOnTop;
142 static WMPropList *AKeepOnBottom;
143 static WMPropList *AOmnipresent;
144 static WMPropList *ASkipWindowList;
145 static WMPropList *AKeepInsideScreen;
146 static WMPropList *AUnfocusable;
147 static WMPropList *AAlwaysUserIcon;
148 static WMPropList *AStartMiniaturized;
149 static WMPropList *AStartMaximized;
150 static WMPropList *ADontSaveSession;
151 static WMPropList *AEmulateAppIcon;
152 static WMPropList *AFullMaximize;
153 static WMPropList *ASharedAppIcon;
154 #ifdef XKB_BUTTON_HINT
155 static WMPropList *ANoLanguageButton;
156 #endif
158 static WMPropList *AStartWorkspace;
160 static WMPropList *AIcon;
162 /* application wide options */
163 static WMPropList *AStartHidden;
165 static WMPropList *AnyWindow;
166 static WMPropList *EmptyString;
167 static WMPropList *Yes, *No;
169 #define PWIDTH 270
170 #define PHEIGHT 350
172 static char *spec_text;
174 static void applySettings(WMButton * button, InspectorPanel * panel);
176 #define UNDEFINED_POS 0xffffff
178 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
180 static void make_keys()
182 if (ANoTitlebar != NULL)
183 return;
185 AIcon = WMCreatePLString("Icon");
186 ANoTitlebar = WMCreatePLString("NoTitlebar");
187 ANoResizebar = WMCreatePLString("NoResizebar");
188 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
189 ANoCloseButton = WMCreatePLString("NoCloseButton");
190 ANoBorder = WMCreatePLString("NoBorder");
191 ANoHideOthers = WMCreatePLString("NoHideOthers");
192 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
193 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
194 ANoAppIcon = WMCreatePLString("NoAppIcon");
195 AKeepOnTop = WMCreatePLString("KeepOnTop");
196 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
197 AOmnipresent = WMCreatePLString("Omnipresent");
198 ASkipWindowList = WMCreatePLString("SkipWindowList");
199 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
200 AUnfocusable = WMCreatePLString("Unfocusable");
201 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
202 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
203 AStartMaximized = WMCreatePLString("StartMaximized");
204 AStartHidden = WMCreatePLString("StartHidden");
205 ADontSaveSession = WMCreatePLString("DontSaveSession");
206 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
207 AFullMaximize = WMCreatePLString("FullMaximize");
208 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
209 #ifdef XKB_BUTTON_HINT
210 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
211 #endif
213 AStartWorkspace = WMCreatePLString("StartWorkspace");
215 AnyWindow = WMCreatePLString("*");
216 EmptyString = WMCreatePLString("");
217 Yes = WMCreatePLString("Yes");
218 No = WMCreatePLString("No");
221 static void freeInspector(InspectorPanel * panel)
223 panel->destroyed = 1;
224 if (panel->choosingIcon)
225 return;
227 WMDestroyWidget(panel->win);
229 XDestroyWindow(dpy, panel->parent);
231 wfree(panel);
234 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
236 InspectorPanel *panel;
237 InspectorPanel *tmp;
239 panel = panelList;
240 while (panel->frame != data)
241 panel = panel->nextPtr;
243 if (panelList == panel)
244 panelList = panel->nextPtr;
245 else {
246 tmp = panelList;
247 while (tmp->nextPtr != panel) {
248 tmp = tmp->nextPtr;
250 tmp->nextPtr = panel->nextPtr;
252 panel->inspected->flags.inspector_open = 0;
253 panel->inspected->inspector = NULL;
255 WMRemoveNotificationObserver(panel);
257 wWindowUnmap(panel->frame);
258 wUnmanageWindow(panel->frame, True, False);
260 freeInspector(panel);
263 void wDestroyInspectorPanels()
265 InspectorPanel *panel;
267 while (panelList != NULL) {
268 panel = panelList;
269 panelList = panelList->nextPtr;
270 wUnmanageWindow(panel->frame, False, False);
271 WMDestroyWidget(panel->win);
273 panel->inspected->flags.inspector_open = 0;
274 panel->inspected->inspector = NULL;
276 wfree(panel);
280 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
282 int page;
284 page = WMGetPopUpButtonSelectedItem(bPtr);
286 if (page == 0) {
287 WMMapWidget(panel->specFrm);
288 WMMapWidget(panel->specLbl);
289 } else if (page == 1) {
290 WMMapWidget(panel->attrFrm);
291 } else if (page == 2) {
292 WMMapWidget(panel->moreFrm);
293 } else if (page == 3) {
294 WMMapWidget(panel->iconFrm);
295 WMMapWidget(panel->wsFrm);
296 } else {
297 WMMapWidget(panel->appFrm);
300 if (page != 0) {
301 WMUnmapWidget(panel->specFrm);
302 WMUnmapWidget(panel->specLbl);
304 if (page != 1)
305 WMUnmapWidget(panel->attrFrm);
306 if (page != 2)
307 WMUnmapWidget(panel->moreFrm);
308 if (page != 3) {
309 WMUnmapWidget(panel->iconFrm);
310 WMUnmapWidget(panel->wsFrm);
312 if (page != 4 && panel->appFrm)
313 WMUnmapWidget(panel->appFrm);
316 #define USE_TEXT_FIELD 1
317 #define UPDATE_TEXT_FIELD 2
318 #define REVERT_TO_DEFAULT 4
320 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
322 WMPixmap *pixmap = (WMPixmap *) NULL;
323 char *file = NULL, *path = NULL;
324 char *db_icon = NULL;
326 if ((flags & USE_TEXT_FIELD) != 0) {
327 file = WMGetTextFieldText(panel->fileText);
328 if (file && file[0] == 0) {
329 wfree(file);
330 file = NULL;
332 } else {
333 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
334 if (db_icon != NULL)
335 file = wstrdup(db_icon);
337 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
338 if (file)
339 file = wstrdup(db_icon);
340 flags |= UPDATE_TEXT_FIELD;
343 if ((flags & UPDATE_TEXT_FIELD) != 0) {
344 WMSetTextFieldText(panel->fileText, file);
347 if (file) {
348 path = FindImage(wPreferences.icon_path, file);
350 if (!path) {
351 char *buf;
352 int len = strlen(file) + 80;
354 buf = wmalloc(len);
355 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
356 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
357 wfree(buf);
358 wfree(file);
359 return -1;
362 pixmap = WMCreatePixmapFromFile(scrPtr, path);
363 wfree(path);
365 if (!pixmap) {
366 char *buf;
367 int len = strlen(file) + 80;
369 buf = wmalloc(len);
370 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
371 file, RMessageForError(RErrorCode));
372 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
373 wfree(buf);
374 wfree(file);
375 return -1;
377 wfree(file);
380 WMSetLabelImage(panel->iconLbl, pixmap);
381 if (pixmap)
382 WMReleasePixmap(pixmap);
384 return 0;
387 #if 0
388 static void updateIcon(WMButton * button, InspectorPanel * panel)
390 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
392 #endif
394 static int getBool(WMPropList * value)
396 char *val;
398 if (!WMIsPLString(value)) {
399 return 0;
401 if (!(val = WMGetFromPLString(value))) {
402 return 0;
405 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
406 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
408 return 1;
409 } else if ((val[1] == '\0'
410 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
411 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
413 return 0;
414 } else {
415 wwarning(_("can't convert \"%s\" to boolean"), val);
416 return 0;
420 #define UPDATE_DEFAULTS 1
421 #define IS_BOOLEAN 2
424 * Will insert the attribute = value; pair in window's list,
425 * if it's different from the defaults.
426 * Defaults means either defaults database, or attributes saved
427 * for the default window "*". This is to let one revert options that are
428 * global because they were saved for all windows ("*").
432 static int
433 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
435 WMPropList *def_win, *def_value = NULL;
436 int update = 0;
437 int modified = 0;
439 if (!(flags & UPDATE_DEFAULTS) && dict) {
440 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
441 def_value = WMGetFromPLDictionary(def_win, attr);
445 /* If we could not find defaults in database, fall to hardcoded values.
446 * Also this is true if we save defaults for all windows
448 if (!def_value)
449 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
451 if ((flags & IS_BOOLEAN))
452 update = (getBool(value) != getBool(def_value));
453 else {
454 update = !WMIsPropListEqualTo(value, def_value);
457 if (update) {
458 WMPutInPLDictionary(window, attr, value);
459 modified = 1;
462 return modified;
465 static void saveSettings(WMButton * button, InspectorPanel * panel)
467 WWindow *wwin = panel->inspected;
468 WDDomain *db = WDWindowAttributes;
469 WMPropList *dict = db->dictionary;
470 WMPropList *winDic, *appDic, *value, *key, *key2;
471 char *icon_file;
472 int flags = 0;
473 int different = 0, different2 = 0;
475 /* Save will apply the changes and save them */
476 applySettings(panel->applyBtn, panel);
478 if (WMGetButtonSelected(panel->instRb) != 0)
479 key = WMCreatePLString(wwin->wm_instance);
480 else if (WMGetButtonSelected(panel->clsRb) != 0)
481 key = WMCreatePLString(wwin->wm_class);
482 else if (WMGetButtonSelected(panel->bothRb) != 0) {
483 char *buffer;
485 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
486 key = WMCreatePLString(buffer);
487 wfree(buffer);
488 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
489 key = WMRetainPropList(AnyWindow);
490 flags = UPDATE_DEFAULTS;
491 } else
492 key = NULL;
494 if (!key)
495 return;
497 if (!dict) {
498 dict = WMCreatePLDictionary(NULL, NULL);
499 if (dict) {
500 db->dictionary = dict;
501 } else {
502 WMReleasePropList(key);
503 return;
507 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
508 return;
510 WMPLSetCaseSensitive(True);
512 winDic = WMCreatePLDictionary(NULL, NULL);
513 appDic = WMCreatePLDictionary(NULL, NULL);
515 /* Update icon for window */
516 icon_file = WMGetTextFieldText(panel->fileText);
517 if (icon_file) {
518 if (icon_file[0] != 0) {
519 value = WMCreatePLString(icon_file);
520 different |= insertAttribute(dict, winDic, AIcon, value, flags);
521 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
522 WMReleasePropList(value);
524 wfree(icon_file);
528 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
530 i--;
532 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
533 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
534 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
535 WMReleasePropList(value);
539 flags |= IS_BOOLEAN;
541 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
544 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
547 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
550 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
553 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
556 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
559 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
562 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
565 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
568 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
569 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
571 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
572 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
574 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
575 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
577 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
578 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
580 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
581 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
583 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
584 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
586 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
587 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
589 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
590 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
592 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
593 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
595 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
596 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
598 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
599 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
601 #ifdef XKB_BUTTON_HINT
602 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
604 #endif
606 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
607 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
608 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
610 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
611 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
613 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
614 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
617 if (wwin->fake_group) {
618 key2 = WMCreatePLString(wwin->fake_group->identifier);
619 if (WMIsPropListEqualTo(key, key2)) {
620 WMMergePLDictionaries(winDic, appDic, True);
621 different |= different2;
622 } else {
623 WMRemoveFromPLDictionary(dict, key2);
624 if (different2) {
625 WMPutInPLDictionary(dict, key2, appDic);
628 WMReleasePropList(key2);
629 WMReleasePropList(appDic);
630 } else if (wwin->main_window != wwin->client_win) {
631 WApplication *wapp = wApplicationOf(wwin->main_window);
633 if (wapp) {
634 char *instance = wapp->main_window_desc->wm_instance;
635 char *class = wapp->main_window_desc->wm_class;
636 char *buffer;
638 buffer = StrConcatDot(instance, class);
639 key2 = WMCreatePLString(buffer);
640 wfree(buffer);
642 if (WMIsPropListEqualTo(key, key2)) {
643 WMMergePLDictionaries(winDic, appDic, True);
644 different |= different2;
645 } else {
646 WMRemoveFromPLDictionary(dict, key2);
647 if (different2) {
648 WMPutInPLDictionary(dict, key2, appDic);
651 WMReleasePropList(key2);
652 WMReleasePropList(appDic);
654 } else {
655 WMMergePLDictionaries(winDic, appDic, True);
656 different |= different2;
657 WMReleasePropList(appDic);
660 WMRemoveFromPLDictionary(dict, key);
661 if (different) {
662 WMPutInPLDictionary(dict, key, winDic);
665 WMReleasePropList(key);
666 WMReleasePropList(winDic);
668 UpdateDomainFile(db);
670 /* clean up */
671 WMPLSetCaseSensitive(False);
674 static void makeAppIconFor(WApplication * wapp)
676 WScreen *scr = wapp->main_window_desc->screen_ptr;
678 if (wapp->app_icon)
679 return;
681 if (!WFLAGP(wapp->main_window_desc, no_appicon))
682 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
683 else
684 wapp->app_icon = NULL;
686 if (wapp->app_icon) {
687 WIcon *icon = wapp->app_icon->icon;
688 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
689 int x = 0, y = 0;
691 wapp->app_icon->main_window = wapp->main_window;
693 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
694 wapp->app_icon->attracted = 1;
695 if (!wapp->app_icon->icon->shadowed) {
696 wapp->app_icon->icon->shadowed = 1;
697 wapp->app_icon->icon->force_paint = 1;
699 wDockAttachIcon(clip, wapp->app_icon, x, y);
700 } else {
701 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
702 wAppIconMove(wapp->app_icon, x, y);
704 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
705 XMapWindow(dpy, icon->core->window);
707 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
708 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
712 static void removeAppIconFor(WApplication * wapp)
714 if (!wapp->app_icon)
715 return;
717 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
718 wapp->app_icon->running = 0;
719 /* since we keep it, we don't care if it was attracted or not */
720 wapp->app_icon->attracted = 0;
721 wapp->app_icon->icon->shadowed = 0;
722 wapp->app_icon->main_window = None;
723 wapp->app_icon->pid = 0;
724 wapp->app_icon->icon->owner = NULL;
725 wapp->app_icon->icon->icon_win = None;
726 wapp->app_icon->icon->force_paint = 1;
727 wAppIconPaint(wapp->app_icon);
728 } else if (wapp->app_icon->docked) {
729 wapp->app_icon->running = 0;
730 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
731 } else {
732 wAppIconDestroy(wapp->app_icon);
734 wapp->app_icon = NULL;
735 if (wPreferences.auto_arrange_icons)
736 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
739 static void applySettings(WMButton * button, InspectorPanel * panel)
741 WWindow *wwin = panel->inspected;
742 WApplication *wapp = wApplicationOf(wwin->main_window);
743 int floating, sunken, skip_window_list;
744 int old_omnipresent;
745 int old_no_bind_keys;
746 int old_no_bind_mouse;
748 old_omnipresent = WFLAGP(wwin, omnipresent);
749 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
750 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
752 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
754 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
755 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
756 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
757 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
758 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
759 floating = WMGetButtonSelected(panel->attrChk[5]);
760 sunken = WMGetButtonSelected(panel->attrChk[6]);
761 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
762 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
763 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
764 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
766 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
767 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
768 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
769 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
770 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
771 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
772 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
773 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
774 #ifdef XKB_BUTTON_HINT
775 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
776 #endif
777 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
779 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
780 wUnshadeWindow(wwin);
782 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
784 if (floating) {
785 if (!WFLAGP(wwin, floating))
786 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
787 } else if (sunken) {
788 if (!WFLAGP(wwin, sunken))
789 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
790 } else {
791 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
792 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
795 WSETUFLAG(wwin, sunken, sunken);
796 WSETUFLAG(wwin, floating, floating);
797 wwin->flags.omnipresent = 0;
799 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
800 WSETUFLAG(wwin, skip_window_list, skip_window_list);
801 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
802 } else {
803 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
804 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
808 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
809 if (WFLAGP(wwin, no_bind_keys)) {
810 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
811 } else {
812 wWindowSetKeyGrabs(wwin);
816 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
817 wWindowResetMouseGrabs(wwin);
820 wwin->frame->flags.need_texture_change = 1;
821 wWindowConfigureBorders(wwin);
822 wFrameWindowPaint(wwin->frame);
823 #ifdef NETWM_HINTS
824 wNETWMUpdateActions(wwin, False);
825 #endif
828 * Can't apply emulate_appicon because it will probably cause problems.
831 if (wapp) {
832 /* do application wide stuff */
833 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
835 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
837 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
839 if (WFLAGP(wapp->main_window_desc, no_appicon))
840 removeAppIconFor(wapp);
841 else
842 makeAppIconFor(wapp);
844 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
845 char *file = WMGetTextFieldText(panel->fileText);
847 if (file[0] == 0) {
848 wfree(file);
849 file = NULL;
851 wIconChangeImageFile(wapp->app_icon->icon, file);
852 if (file)
853 wfree(file);
854 wAppIconPaint(wapp->app_icon);
859 static void revertSettings(WMButton * button, InspectorPanel * panel)
861 WWindow *wwin = panel->inspected;
862 WApplication *wapp = wApplicationOf(wwin->main_window);
863 int i, n;
864 char *wm_instance = NULL;
865 char *wm_class = NULL;
866 int workspace, level;
868 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
869 wm_instance = wwin->wm_instance;
870 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
871 wm_class = wwin->wm_class;
872 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
873 wm_instance = wwin->wm_instance;
874 wm_class = wwin->wm_class;
876 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
877 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
878 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
880 wWindowSetupInitialAttributes(wwin, &level, &workspace);
882 for (i = 0; i < 11; i++) {
883 int flag = 0;
885 switch (i) {
886 case 0:
887 flag = WFLAGP(wwin, no_titlebar);
888 break;
889 case 1:
890 flag = WFLAGP(wwin, no_resizebar);
891 break;
892 case 2:
893 flag = WFLAGP(wwin, no_close_button);
894 break;
895 case 3:
896 flag = WFLAGP(wwin, no_miniaturize_button);
897 break;
898 case 4:
899 flag = WFLAGP(wwin, no_border);
900 break;
901 case 5:
902 flag = WFLAGP(wwin, floating);
903 break;
904 case 6:
905 flag = WFLAGP(wwin, sunken);
906 break;
907 case 7:
908 flag = WFLAGP(wwin, omnipresent);
909 break;
910 case 8:
911 flag = WFLAGP(wwin, start_miniaturized);
912 break;
913 case 9:
914 flag = WFLAGP(wwin, start_maximized != 0);
915 break;
916 case 10:
917 flag = WFLAGP(wwin, full_maximize);
918 break;
920 WMSetButtonSelected(panel->attrChk[i], flag);
922 for (i = 0; i < 8; i++) {
923 int flag = 0;
925 switch (i) {
926 case 0:
927 flag = WFLAGP(wwin, no_bind_keys);
928 break;
929 case 1:
930 flag = WFLAGP(wwin, no_bind_mouse);
931 break;
932 case 2:
933 flag = WFLAGP(wwin, skip_window_list);
934 break;
935 case 3:
936 flag = WFLAGP(wwin, no_focusable);
937 break;
938 case 4:
939 flag = WFLAGP(wwin, dont_move_off);
940 break;
941 case 5:
942 flag = WFLAGP(wwin, no_hide_others);
943 break;
944 case 6:
945 flag = WFLAGP(wwin, dont_save_session);
946 break;
947 case 7:
948 flag = WFLAGP(wwin, emulate_appicon);
949 break;
950 #ifdef XKB_BUTTON_HINT
951 case 8:
952 flag = WFLAGP(wwin, no_language_button);
953 break;
954 #endif
956 WMSetButtonSelected(panel->moreChk[i], flag);
958 if (panel->appFrm && wapp) {
959 for (i = 0; i < 2; i++) {
960 int flag = 0;
962 switch (i) {
963 case 0:
964 flag = WFLAGP(wapp->main_window_desc, start_hidden);
965 break;
966 case 1:
967 flag = WFLAGP(wapp->main_window_desc, no_appicon);
968 break;
969 case 2:
970 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
971 break;
973 WMSetButtonSelected(panel->appChk[i], flag);
976 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
978 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
980 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
982 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
983 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
984 } else {
985 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
988 /* must auto apply, so that there wno't be internal
989 * inconsistencies between the state in the flags and
990 * the actual state of the window */
991 applySettings(panel->applyBtn, panel);
994 static void chooseIconCallback(WMWidget * self, void *clientData)
996 char *file;
997 InspectorPanel *panel = (InspectorPanel *) clientData;
998 int result;
1000 panel->choosingIcon = 1;
1002 WMSetButtonEnabled(panel->browseIconBtn, False);
1004 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1005 panel->inspected->wm_instance, panel->inspected->wm_class);
1007 panel->choosingIcon = 0;
1009 if (!panel->destroyed) { /* kluge */
1010 if (result) {
1011 WMSetTextFieldText(panel->fileText, file);
1012 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1013 wfree(file);
1015 WMSetButtonEnabled(panel->browseIconBtn, True);
1016 } else {
1017 freeInspector(panel);
1021 static void textEditedObserver(void *observerData, WMNotification * notification)
1023 InspectorPanel *panel = (InspectorPanel *) observerData;
1025 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1026 return;
1028 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1030 WMPerformButtonClick(panel->updateIconBtn);
1034 static void selectSpecification(WMWidget * bPtr, void *data)
1036 InspectorPanel *panel = (InspectorPanel *) data;
1037 char *str;
1038 WWindow *wwin = panel->inspected;
1039 int len;
1041 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1042 WMSetButtonEnabled(panel->applyBtn, False);
1043 } else {
1044 WMSetButtonEnabled(panel->applyBtn, True);
1047 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1048 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1050 str = wmalloc(len);
1052 snprintf(str, len, _("Inspecting %s.%s"),
1053 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1055 wFrameWindowChangeTitle(panel->frame->frame, str);
1057 wfree(str);
1060 static void selectWindow(WMWidget * bPtr, void *data)
1062 InspectorPanel *panel = (InspectorPanel *) data;
1063 WWindow *wwin = panel->inspected;
1064 WScreen *scr = wwin->screen_ptr;
1065 XEvent event;
1066 WWindow *iwin;
1068 if (XGrabPointer(dpy, scr->root_win, True,
1069 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1070 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1071 wwarning("could not grab mouse pointer");
1072 return;
1075 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1077 WMMaskEvent(dpy, ButtonPressMask, &event);
1079 XUngrabPointer(dpy, CurrentTime);
1081 iwin = wWindowFor(event.xbutton.subwindow);
1083 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1085 iwin->flags.inspector_open = 1;
1086 iwin->inspector = createInspectorForWindow(iwin,
1087 panel->frame->frame_x, panel->frame->frame_y, True);
1088 wCloseInspectorForWindow(wwin);
1089 } else {
1090 WMSetLabelText(panel->specLbl, spec_text);
1094 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1096 WScreen *scr = wwin->screen_ptr;
1097 InspectorPanel *panel;
1098 Window parent;
1099 int i;
1100 int x, y;
1101 int btn_width, frame_width;
1102 WMButton *selectedBtn = NULL;
1103 #ifdef wrong_behaviour
1104 WMPixmap *pixmap;
1105 #endif
1107 spec_text = _("The configuration will apply to all\n"
1108 "windows that have their WM_CLASS\n"
1109 "property set to the above selected\n" "name, when saved.");
1111 panel = wmalloc(sizeof(InspectorPanel));
1112 memset(panel, 0, sizeof(InspectorPanel));
1114 panel->destroyed = 0;
1116 panel->inspected = wwin;
1118 panel->nextPtr = panelList;
1119 panelList = panel;
1121 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1122 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1124 /**** create common stuff ****/
1126 /* command buttons */
1127 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1128 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1129 panel->saveBtn = WMCreateCommandButton(panel->win);
1130 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1131 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1132 WMSetButtonText(panel->saveBtn, _("Save"));
1133 WMResizeWidget(panel->saveBtn, btn_width, 28);
1134 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1135 WMSetButtonEnabled(panel->saveBtn, False);
1137 panel->applyBtn = WMCreateCommandButton(panel->win);
1138 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1139 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1140 WMSetButtonText(panel->applyBtn, _("Apply"));
1141 WMResizeWidget(panel->applyBtn, btn_width, 28);
1143 panel->revertBtn = WMCreateCommandButton(panel->win);
1144 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1145 WMMoveWidget(panel->revertBtn, 15, 310);
1146 WMSetButtonText(panel->revertBtn, _("Reload"));
1147 WMResizeWidget(panel->revertBtn, btn_width, 28);
1149 /* page selection popup button */
1150 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1151 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1152 WMMoveWidget(panel->pagePopUp, 25, 15);
1153 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1155 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1156 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1157 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1158 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1159 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1161 /**** window spec ****/
1162 frame_width = PWIDTH - (2 * 15);
1164 panel->specFrm = WMCreateFrame(panel->win);
1165 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1166 WMMoveWidget(panel->specFrm, 15, 65);
1167 WMResizeWidget(panel->specFrm, frame_width, 145);
1169 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1170 WMMoveWidget(panel->defaultRb, 10, 78);
1171 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1172 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1173 WMSetButtonSelected(panel->defaultRb, False);
1174 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1176 if (wwin->wm_class && wwin->wm_instance) {
1177 char *str, *tmp;
1179 tmp = wstrconcat(wwin->wm_instance, ".");
1180 str = wstrconcat(tmp, wwin->wm_class);
1182 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1183 WMMoveWidget(panel->bothRb, 10, 18);
1184 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1185 WMSetButtonText(panel->bothRb, str);
1186 wfree(tmp);
1187 wfree(str);
1188 WMGroupButtons(panel->defaultRb, panel->bothRb);
1190 if (!selectedBtn)
1191 selectedBtn = panel->bothRb;
1193 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1196 if (wwin->wm_instance) {
1197 panel->instRb = WMCreateRadioButton(panel->specFrm);
1198 WMMoveWidget(panel->instRb, 10, 38);
1199 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1200 WMSetButtonText(panel->instRb, wwin->wm_instance);
1201 WMGroupButtons(panel->defaultRb, panel->instRb);
1203 if (!selectedBtn)
1204 selectedBtn = panel->instRb;
1206 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1209 if (wwin->wm_class) {
1210 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1211 WMMoveWidget(panel->clsRb, 10, 58);
1212 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1213 WMSetButtonText(panel->clsRb, wwin->wm_class);
1214 WMGroupButtons(panel->defaultRb, panel->clsRb);
1216 if (!selectedBtn)
1217 selectedBtn = panel->clsRb;
1219 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1222 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1223 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1224 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1225 WMSetButtonText(panel->selWinB, _("Select window"));
1226 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1228 panel->specLbl = WMCreateLabel(panel->win);
1229 WMMoveWidget(panel->specLbl, 15, 210);
1230 WMResizeWidget(panel->specLbl, frame_width, 100);
1231 WMSetLabelText(panel->specLbl, spec_text);
1232 WMSetLabelWraps(panel->specLbl, True);
1234 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1236 /**** attributes ****/
1237 panel->attrFrm = WMCreateFrame(panel->win);
1238 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1239 WMMoveWidget(panel->attrFrm, 15, 45);
1240 WMResizeWidget(panel->attrFrm, frame_width, 250);
1242 for (i = 0; i < 11; i++) {
1243 char *caption = NULL;
1244 int flag = 0;
1245 char *descr = NULL;
1247 switch (i) {
1248 case 0:
1249 caption = _("Disable titlebar");
1250 flag = WFLAGP(wwin, no_titlebar);
1251 descr = _("Remove the titlebar of this window.\n"
1252 "To access the window commands menu of a window\n"
1253 "without it's titlebar, press Control+Esc (or the\n"
1254 "equivalent shortcut, if you changed the default\n" "settings).");
1255 break;
1256 case 1:
1257 caption = _("Disable resizebar");
1258 flag = WFLAGP(wwin, no_resizebar);
1259 descr = _("Remove the resizebar of this window.");
1260 break;
1261 case 2:
1262 caption = _("Disable close button");
1263 flag = WFLAGP(wwin, no_close_button);
1264 descr = _("Remove the `close window' button of this window.");
1265 break;
1266 case 3:
1267 caption = _("Disable miniaturize button");
1268 flag = WFLAGP(wwin, no_miniaturize_button);
1269 descr = _("Remove the `miniaturize window' button of the window.");
1270 break;
1271 case 4:
1272 caption = _("Disable border");
1273 flag = WFLAGP(wwin, no_border);
1274 descr = _("Remove the 1 pixel black border around the window.");
1275 break;
1276 case 5:
1277 caption = _("Keep on top (floating)");
1278 flag = WFLAGP(wwin, floating);
1279 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1280 break;
1281 case 6:
1282 caption = _("Keep at bottom (sunken)");
1283 flag = WFLAGP(wwin, sunken);
1284 descr = _("Keep the window under all other windows.");
1285 break;
1286 case 7:
1287 caption = _("Omnipresent");
1288 flag = WFLAGP(wwin, omnipresent);
1289 descr = _("Make window present in all workspaces.");
1290 break;
1291 case 8:
1292 caption = _("Start miniaturized");
1293 flag = WFLAGP(wwin, start_miniaturized);
1294 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1295 break;
1296 case 9:
1297 caption = _("Start maximized");
1298 flag = WFLAGP(wwin, start_maximized != 0);
1299 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1300 break;
1301 case 10:
1302 caption = _("Full screen maximization");
1303 flag = WFLAGP(wwin, full_maximize);
1304 descr = _("Make the window use the whole screen space when it's\n"
1305 "maximized. The titlebar and resizebar will be moved\n"
1306 "to outside the screen.");
1307 break;
1309 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1310 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1311 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1312 WMSetButtonSelected(panel->attrChk[i], flag);
1313 WMSetButtonText(panel->attrChk[i], caption);
1315 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1318 /**** more attributes ****/
1319 panel->moreFrm = WMCreateFrame(panel->win);
1320 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1321 WMMoveWidget(panel->moreFrm, 15, 45);
1322 WMResizeWidget(panel->moreFrm, frame_width, 250);
1324 for (i = 0;
1325 #ifdef XKB_BUTTON_HINT
1326 i < 9;
1327 #else
1328 i < 8;
1329 #endif
1330 i++) {
1331 char *caption = NULL;
1332 int flag = 0;
1333 char *descr = NULL;
1335 switch (i) {
1336 case 0:
1337 caption = _("Do not bind keyboard shortcuts");
1338 flag = WFLAGP(wwin, no_bind_keys);
1339 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1340 "when this window is focused. This will allow the\n"
1341 "window to receive all key combinations regardless\n"
1342 "of your shortcut configuration.");
1343 break;
1344 case 1:
1345 caption = _("Do not bind mouse clicks");
1346 flag = WFLAGP(wwin, no_bind_mouse);
1347 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1348 "in the window (when alt is the modifier you have\n" "configured).");
1349 break;
1350 case 2:
1351 caption = _("Do not show in the window list");
1352 flag = WFLAGP(wwin, skip_window_list);
1353 descr = _("Do not list the window in the window list menu.");
1354 break;
1355 case 3:
1356 caption = _("Do not let it take focus");
1357 flag = WFLAGP(wwin, no_focusable);
1358 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1359 break;
1360 case 4:
1361 caption = _("Keep inside screen");
1362 flag = WFLAGP(wwin, dont_move_off);
1363 descr = _("Do not allow the window to move itself completely\n"
1364 "outside the screen. For bug compatibility.\n");
1365 break;
1366 case 5:
1367 caption = _("Ignore 'Hide Others'");
1368 flag = WFLAGP(wwin, no_hide_others);
1369 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1370 break;
1371 case 6:
1372 caption = _("Ignore 'Save Session'");
1373 flag = WFLAGP(wwin, dont_save_session);
1374 descr = _("Do not save the associated application in the\n"
1375 "session's state, so that it won't be restarted\n"
1376 "together with other applications when Window Maker\n" "starts.");
1377 break;
1378 case 7:
1379 caption = _("Emulate application icon");
1380 flag = WFLAGP(wwin, emulate_appicon);
1381 descr = _("Make this window act as an application that provides\n"
1382 "enough information to Window Maker for a dockable\n"
1383 "application icon to be created.");
1384 break;
1385 #ifdef XKB_BUTTON_HINT
1386 case 8:
1387 caption = _("Disable language button");
1388 flag = WFLAGP(wwin, no_language_button);
1389 descr = _("Remove the `toggle language' button of the window.");
1390 break;
1391 #endif
1393 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1394 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1395 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1396 WMSetButtonSelected(panel->moreChk[i], flag);
1397 WMSetButtonText(panel->moreChk[i], caption);
1399 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1402 /* miniwindow/workspace */
1403 panel->iconFrm = WMCreateFrame(panel->win);
1404 WMMoveWidget(panel->iconFrm, 15, 50);
1405 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1406 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1408 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1409 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1410 WMResizeWidget(panel->iconLbl, 64, 64);
1411 WMSetLabelRelief(panel->iconLbl, WRGroove);
1412 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1414 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1415 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1416 WMMoveWidget(panel->browseIconBtn, 22, 32);
1417 WMResizeWidget(panel->browseIconBtn, 120, 26);
1418 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1420 #ifdef wrong_behaviour
1421 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1422 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1423 WMSetButtonImage(panel->updateIconBtn, pixmap);
1424 WMReleasePixmap(pixmap);
1425 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1426 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1427 WMReleasePixmap(pixmap);
1428 #endif
1430 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1431 WMMoveWidget(panel->fileLbl, 20, 85);
1432 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1433 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1435 panel->fileText = WMCreateTextField(panel->iconFrm);
1436 WMMoveWidget(panel->fileText, 20, 105);
1437 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1438 WMSetTextFieldText(panel->fileText, NULL);
1439 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1441 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1442 WMMoveWidget(panel->alwChk, 20, 130);
1443 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1444 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1445 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1447 panel->wsFrm = WMCreateFrame(panel->win);
1448 WMMoveWidget(panel->wsFrm, 15, 225);
1449 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1450 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1452 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1453 "first shown."), WMWidgetView(panel->wsFrm));
1455 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1456 WMMoveWidget(panel->wsP, 20, 30);
1457 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1458 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1459 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1460 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1463 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1464 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1465 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1466 } else {
1467 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1470 /* application wide attributes */
1471 if (wwin->main_window != None) {
1472 WApplication *wapp = wApplicationOf(wwin->main_window);
1474 panel->appFrm = WMCreateFrame(panel->win);
1475 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1476 WMMoveWidget(panel->appFrm, 15, 50);
1477 WMResizeWidget(panel->appFrm, frame_width, 240);
1479 for (i = 0; i < 3; i++) {
1480 char *caption = NULL;
1481 int flag = 0;
1482 char *descr = NULL;
1484 switch (i) {
1485 case 0:
1486 caption = _("Start hidden");
1487 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1488 descr = _("Automatically hide application when it's started.");
1489 break;
1490 case 1:
1491 caption = _("No application icon");
1492 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1493 descr = _("Disable the application icon for the application.\n"
1494 "Note that you won't be able to dock it anymore,\n"
1495 "and any icons that are already docked will stop\n"
1496 "working correctly.");
1497 break;
1498 case 2:
1499 caption = _("Shared application icon");
1500 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1501 descr = _("Use a single shared application icon for all of\n"
1502 "the instances of this application.\n");
1503 break;
1505 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1506 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1507 WMResizeWidget(panel->appChk[i], 205, 20);
1508 WMSetButtonSelected(panel->appChk[i], flag);
1509 WMSetButtonText(panel->appChk[i], caption);
1511 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1514 if (WFLAGP(wwin, emulate_appicon)) {
1515 WMSetButtonEnabled(panel->appChk[1], False);
1516 WMSetButtonEnabled(panel->moreChk[7], True);
1517 } else {
1518 WMSetButtonEnabled(panel->appChk[1], True);
1519 WMSetButtonEnabled(panel->moreChk[7], False);
1521 } else {
1522 int tmp;
1524 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1525 || !wwin->wm_class || !wwin->wm_instance)
1526 tmp = False;
1527 else
1528 tmp = True;
1529 WMSetButtonEnabled(panel->moreChk[7], tmp);
1531 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1532 panel->appFrm = NULL;
1535 /* if the window is a transient, don't let it have a miniaturize
1536 * button */
1537 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1538 WMSetButtonEnabled(panel->attrChk[3], False);
1539 else
1540 WMSetButtonEnabled(panel->attrChk[3], True);
1542 if (!wwin->wm_class && !wwin->wm_instance) {
1543 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1546 WMRealizeWidget(panel->win);
1548 WMMapSubwidgets(panel->win);
1549 WMMapSubwidgets(panel->specFrm);
1550 WMMapSubwidgets(panel->attrFrm);
1551 WMMapSubwidgets(panel->moreFrm);
1552 WMMapSubwidgets(panel->iconFrm);
1553 WMMapSubwidgets(panel->wsFrm);
1554 if (panel->appFrm)
1555 WMMapSubwidgets(panel->appFrm);
1557 if (showSelectPanel) {
1558 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1559 changePage(panel->pagePopUp, panel);
1560 } else {
1561 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1562 changePage(panel->pagePopUp, panel);
1565 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1566 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1567 panel->parent = parent;
1568 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1570 WMMapWidget(panel->win);
1572 XSetTransientForHint(dpy, parent, wwin->client_win);
1574 if (xpos == UNDEFINED_POS) {
1575 x = wwin->frame_x + wwin->frame->core->width / 2;
1576 y = wwin->frame_y + wwin->frame->top_width * 2;
1577 if (y + PHEIGHT > scr->scr_height)
1578 y = scr->scr_height - PHEIGHT - 30;
1579 if (x + PWIDTH > scr->scr_width)
1580 x = scr->scr_width - PWIDTH;
1581 } else {
1582 x = xpos;
1583 y = ypos;
1586 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1588 if (!selectedBtn)
1589 selectedBtn = panel->defaultRb;
1591 WMSetButtonSelected(selectedBtn, True);
1593 selectSpecification(selectedBtn, panel);
1595 /* kluge to know who should get the key events */
1596 panel->frame->client_leader = WMWidgetXID(panel->win);
1598 WSETUFLAG(panel->frame, no_closable, 0);
1599 WSETUFLAG(panel->frame, no_close_button, 0);
1600 wWindowUpdateButtonImages(panel->frame);
1601 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1602 panel->frame->frame->on_click_right = destroyInspector;
1604 wWindowMap(panel->frame);
1606 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1608 return panel;
1611 void wShowInspectorForWindow(WWindow * wwin)
1613 if (wwin->flags.inspector_open)
1614 return;
1616 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1618 make_keys();
1619 wwin->flags.inspector_open = 1;
1620 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1623 void wHideInspectorForWindow(WWindow * wwin)
1625 WWindow *pwin = wwin->inspector->frame;
1627 wWindowUnmap(pwin);
1628 pwin->flags.hidden = 1;
1630 wClientSetState(pwin, IconicState, None);
1633 void wUnhideInspectorForWindow(WWindow * wwin)
1635 WWindow *pwin = wwin->inspector->frame;
1637 pwin->flags.hidden = 0;
1638 pwin->flags.mapped = 1;
1639 XMapWindow(dpy, pwin->client_win);
1640 XMapWindow(dpy, pwin->frame->core->window);
1641 wClientSetState(pwin, NormalState, None);
1644 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1646 if (wwin->inspector) {
1647 assert(wwin->flags.inspector_open != 0);
1649 return wwin->inspector->frame;
1650 } else
1651 return NULL;
1654 void wCloseInspectorForWindow(WWindow * wwin)
1656 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1658 (*pwin->frame->on_click_right) (NULL, pwin, NULL);