2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 * Copyright (c) 1998-2003 Dan Pascu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <sys/types.h>
33 #include "WindowMaker.h"
38 #endif /* USER_MENU */
41 #include "application.h"
43 #include "properties.h"
48 #include "workspace.h"
53 /******** Global variables ********/
55 extern XContext wAppWinContext
;
56 extern XContext wWinContext
;
57 extern WPreferences wPreferences
;
59 extern WDDomain
*WDWindowAttributes
;
61 /******** Local variables ********/
63 static WWindow
*makeMainWindow(WScreen
* scr
, Window window
)
66 XWindowAttributes attr
;
68 if (!XGetWindowAttributes(dpy
, window
, &attr
)) {
72 wwin
= wWindowCreate();
73 wwin
->screen_ptr
= scr
;
74 wwin
->client_win
= window
;
75 wwin
->main_window
= window
;
76 wwin
->wm_hints
= XGetWMHints(dpy
, window
);
77 /* if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
78 wwin->frame->title = NULL;
81 PropGetWMClass(window
, &wwin
->wm_class
, &wwin
->wm_instance
);
83 wDefaultFillAttributes(scr
, wwin
->wm_instance
, wwin
->wm_class
,
84 &wwin
->user_flags
, &wwin
->defined_user_flags
, True
);
86 XSelectInput(dpy
, window
, attr
.your_event_mask
| PropertyChangeMask
| StructureNotifyMask
);
90 WApplication
*wApplicationOf(Window window
)
96 if (XFindContext(dpy
, window
, wAppWinContext
, (XPointer
*) & wapp
) != XCSUCCESS
)
101 static WAppIcon
*findDockIconFor(WDock
* dock
, Window main_window
)
103 WAppIcon
*aicon
= NULL
;
105 aicon
= wDockFindIconForWindow(dock
, main_window
);
107 wDockTrackWindowLaunch(dock
, main_window
);
108 aicon
= wDockFindIconForWindow(dock
, main_window
);
113 static void extractIcon(WWindow
* wwin
)
117 /* Get the application name */
118 progname
= GetProgramNameForWindow(wwin
->client_win
);
120 /* Save the icon path if the application is ".app" */
121 wApplicationExtractDirPackIcon(wwin
->screen_ptr
, progname
, wwin
->wm_instance
, wwin
->wm_class
);
126 void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
)
128 WMPropList
*dict
= WDWindowAttributes
->dictionary
;
129 WMPropList
*adict
, *key
, *iconk
;
136 i
+= strlen(wm_instance
);
138 i
+= strlen(wm_class
);
140 tmp
= wmalloc(i
+ 8);
142 if (wm_class
&& wm_instance
) {
143 sprintf(tmp
, "%s.%s", wm_instance
, wm_class
);
146 strcat(tmp
, wm_instance
);
148 strcat(tmp
, wm_class
);
151 key
= WMCreatePLString(tmp
);
154 adict
= WMGetFromPLDictionary(dict
, key
);
155 iconk
= WMCreatePLString("Icon");
158 val
= WMGetFromPLDictionary(adict
, iconk
);
160 /* no dictionary for app, so create one */
161 adict
= WMCreatePLDictionary(NULL
, NULL
);
162 WMPutInPLDictionary(dict
, key
, adict
);
163 WMReleasePropList(adict
);
168 val
= WMCreatePLString(iconPath
);
169 WMPutInPLDictionary(adict
, iconk
, val
);
170 WMReleasePropList(val
);
175 WMReleasePropList(key
);
176 WMReleasePropList(iconk
);
178 if (val
&& !wPreferences
.flags
.noupdates
)
179 UpdateDomainFile(WDWindowAttributes
);
182 /* This function is used if the application is a .app. It checks if it has an icon in it
183 * like for example /usr/local/GNUstep/Applications/WPrefs.app/WPrefs.tiff
185 void wApplicationExtractDirPackIcon(WScreen
* scr
, char *path
, char *wm_instance
, char *wm_class
)
187 char *iconPath
= NULL
;
190 if (strstr(path
, ".app")) {
191 tmp
= wmalloc(strlen(path
) + 16);
193 if (scr
->flags
.supports_tiff
) {
195 strcat(tmp
, ".tiff");
196 if (access(tmp
, R_OK
) == 0)
203 if (access(tmp
, R_OK
) == 0)
211 wApplicationSaveIconPathFor(iconPath
, wm_instance
, wm_class
);
217 WApplication
*wApplicationCreate(WWindow
* wwin
)
219 WScreen
*scr
= wwin
->screen_ptr
;
220 Window main_window
= wwin
->main_window
;
224 if (main_window
== None
|| main_window
== scr
->root_win
)
231 /* check if the window is valid */
232 if (!XGetGeometry(dpy
, main_window
, &root
, &foo
, &foo
, &bar
, &bar
, &bar
, &bar
)) {
237 wapp
= wApplicationOf(main_window
);
240 if (wapp
->app_icon
&& wapp
->app_icon
->docked
&&
241 wapp
->app_icon
->relaunching
&& wapp
->main_window_desc
->fake_group
) {
242 wDockFinishLaunch(wapp
->app_icon
->dock
, wapp
->app_icon
);
248 wapp
= wmalloc(sizeof(WApplication
));
249 memset(wapp
, 0, sizeof(WApplication
));
252 wapp
->last_focused
= NULL
;
253 wapp
->urgent_bounce_timer
= NULL
;
255 wapp
->last_workspace
= 0;
257 wapp
->main_window
= main_window
;
258 wapp
->main_window_desc
= makeMainWindow(scr
, main_window
);
259 if (!wapp
->main_window_desc
) {
264 wapp
->main_window_desc
->fake_group
= wwin
->fake_group
;
265 wapp
->main_window_desc
->net_icon_image
= RRetainImage(wwin
->net_icon_image
);
267 extractIcon(wapp
->main_window_desc
);
269 leader
= wWindowFor(main_window
);
271 leader
->main_window
= main_window
;
273 wapp
->menu
= wAppMenuGet(scr
, main_window
);
276 wapp
->menu
= wUserMenuGet(scr
, wapp
->main_window_desc
);
277 #endif /* USER_MENU */
280 * Set application wide attributes from the leader.
282 wapp
->flags
.hidden
= WFLAGP(wapp
->main_window_desc
, start_hidden
);
283 wapp
->flags
.emulated
= WFLAGP(wapp
->main_window_desc
, emulate_appicon
);
285 /* application descriptor */
286 XSaveContext(dpy
, main_window
, wAppWinContext
, (XPointer
) wapp
);
288 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
)) {
289 wapp
->app_icon
= NULL
;
291 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
293 /* check main dock if we did not find it in last dock */
294 if (!wapp
->app_icon
&& scr
->dock
)
295 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
297 /* finally check clips */
298 if (!wapp
->app_icon
) {
300 for (i
= 0; i
< scr
->workspace_count
; i
++) {
301 WDock
*dock
= scr
->workspaces
[i
]->clip
;
303 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
309 if (wapp
->app_icon
) {
310 WWindow
*mainw
= wapp
->main_window_desc
;
312 wapp
->app_icon
->running
= 1;
313 wapp
->app_icon
->icon
->force_paint
= 1;
314 wapp
->app_icon
->icon
->owner
= mainw
;
315 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
& IconWindowHint
))
316 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
317 wAppIconPaint(wapp
->app_icon
);
318 wAppIconSave(wapp
->app_icon
);
320 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
323 wapp
->app_icon
= NULL
;
327 wapp
->app_icon
->main_window
= main_window
;
329 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
) {
330 WIcon
*icon
= wapp
->app_icon
->icon
;
331 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
334 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
335 wapp
->app_icon
->attracted
= 1;
336 if (!icon
->shadowed
) {
338 icon
->force_paint
= 1;
339 /* wAppIconPaint() is done in wDockAttachIcon() below */
341 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
);
343 PlaceIcon(scr
, &x
, &y
, wGetHeadForWindow(wapp
->main_window_desc
));
344 wAppIconMove(wapp
->app_icon
, x
, y
);
345 wLowerFrame(icon
->core
);
348 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
349 XMapWindow(dpy
, icon
->core
->window
);
352 if (wPreferences
.auto_arrange_icons
&& wapp
->app_icon
&& !wapp
->app_icon
->attracted
)
353 wArrangeIcons(scr
, True
);
355 if (wapp
->app_icon
) {
359 tmp
= wDefaultGetIconFile(scr
, wapp
->app_icon
->wm_instance
, wapp
->app_icon
->wm_class
, True
);
361 /* If the icon was saved by us from the client supplied icon, but is
362 * missing, recreate it. */
363 if (tmp
&& strstr(tmp
, "Library/WindowMaker/CachedPixmaps") != NULL
&&
364 stat(tmp
, &dummy
) != 0 && errno
== ENOENT
) {
365 wmessage(_("recreating missing icon '%s'"), tmp
);
366 path
= wIconStore(wapp
->app_icon
->icon
);
370 wIconUpdate(wapp
->app_icon
->icon
);
371 wAppIconPaint(wapp
->app_icon
);
374 /* if the displayed icon was supplied by the client, save the icon */
375 if (!tmp
|| strstr(tmp
, "Library/WindowMaker/CachedPixmaps") != NULL
)
376 wAppIconSave(wapp
->app_icon
);
381 void wApplicationDestroy(WApplication
* wapp
)
390 if (wapp
->refcount
> 0)
393 if (wapp
->urgent_bounce_timer
) {
394 WMDeleteTimerHandler(wapp
->urgent_bounce_timer
);
395 wapp
->urgent_bounce_timer
= NULL
;
397 if (wapp
->flags
.bouncing
) {
398 /* event.c:handleDestroyNotify forced this destroy
399 and thereby overlooked the bounce callback */
404 scr
= wapp
->main_window_desc
->screen_ptr
;
406 if (wapp
== scr
->wapp_list
) {
408 wapp
->next
->prev
= NULL
;
409 scr
->wapp_list
= wapp
->next
;
412 wapp
->next
->prev
= wapp
->prev
;
414 wapp
->prev
->next
= wapp
->next
;
417 XDeleteContext(dpy
, wapp
->main_window
, wAppWinContext
);
418 wAppMenuDestroy(wapp
->menu
);
419 wApplicationDeactivate(wapp
);
421 if (wapp
->app_icon
) {
422 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
423 wapp
->app_icon
->running
= 0;
424 /* since we keep it, we don't care if it was attracted or not */
425 wapp
->app_icon
->attracted
= 0;
426 wapp
->app_icon
->icon
->shadowed
= 0;
427 wapp
->app_icon
->main_window
= None
;
428 wapp
->app_icon
->pid
= 0;
429 wapp
->app_icon
->icon
->owner
= NULL
;
430 wapp
->app_icon
->icon
->icon_win
= None
;
431 wapp
->app_icon
->icon
->force_paint
= 1;
432 wAppIconPaint(wapp
->app_icon
);
433 } else if (wapp
->app_icon
->docked
) {
434 wapp
->app_icon
->running
= 0;
435 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
437 wAppIconDestroy(wapp
->app_icon
);
440 wwin
= wWindowFor(wapp
->main_window_desc
->client_win
);
442 wWindowDestroy(wapp
->main_window_desc
);
444 /* undelete client window context that was deleted in
446 XSaveContext(dpy
, wwin
->client_win
, wWinContext
, (XPointer
) & wwin
->client_descriptor
);
450 if (wPreferences
.auto_arrange_icons
)
451 wArrangeIcons(scr
, True
);
454 void wApplicationActivate(WApplication
*wapp
)
457 if (wapp
->app_icon
) {
458 wIconSetHighlited(wapp
->app_icon
->icon
, True
);
459 wAppIconPaint(wapp
->app_icon
);
464 void wApplicationDeactivate(WApplication
*wapp
)
467 if (wapp
->app_icon
) {
468 wIconSetHighlited(wapp
->app_icon
->icon
, False
);
469 wAppIconPaint(wapp
->app_icon
);