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 "WindowMaker.h"
33 #endif /* USER_MENU */
35 #include "application.h"
37 #include "properties.h"
40 #include "workspace.h"
43 /******** Global variables ********/
45 extern XContext wAppWinContext
;
46 extern XContext wWinContext
;
47 extern WPreferences wPreferences
;
48 extern WDDomain
*WDWindowAttributes
;
50 /******** Local variables ********/
52 static WWindow
*makeMainWindow(WScreen
* scr
, Window window
)
55 XWindowAttributes attr
;
57 if (!XGetWindowAttributes(dpy
, window
, &attr
))
60 wwin
= wWindowCreate();
61 wwin
->screen_ptr
= scr
;
62 wwin
->client_win
= window
;
63 wwin
->main_window
= window
;
64 wwin
->wm_hints
= XGetWMHints(dpy
, window
);
66 PropGetWMClass(window
, &wwin
->wm_class
, &wwin
->wm_instance
);
68 wDefaultFillAttributes(scr
, wwin
->wm_instance
, wwin
->wm_class
,
69 &wwin
->user_flags
, &wwin
->defined_user_flags
, True
);
71 XSelectInput(dpy
, window
, attr
.your_event_mask
| PropertyChangeMask
| StructureNotifyMask
);
75 WApplication
*wApplicationOf(Window window
)
81 if (XFindContext(dpy
, window
, wAppWinContext
, (XPointer
*) & wapp
) != XCSUCCESS
)
86 static WAppIcon
*findDockIconFor(WDock
* dock
, Window main_window
)
88 WAppIcon
*aicon
= NULL
;
90 aicon
= wDockFindIconForWindow(dock
, main_window
);
92 wDockTrackWindowLaunch(dock
, main_window
);
93 aicon
= wDockFindIconForWindow(dock
, main_window
);
98 static void extractIcon(WWindow
* wwin
)
102 /* Get the application name */
103 progname
= GetProgramNameForWindow(wwin
->client_win
);
105 /* Save the icon path if the application is ".app" */
106 wApplicationExtractDirPackIcon(wwin
->screen_ptr
, progname
, wwin
->wm_instance
, wwin
->wm_class
);
111 void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
)
113 WMPropList
*dict
= WDWindowAttributes
->dictionary
;
114 WMPropList
*adict
, *key
, *iconk
;
121 i
+= strlen(wm_instance
);
123 i
+= strlen(wm_class
);
125 tmp
= wmalloc(i
+ 8);
127 if (wm_class
&& wm_instance
) {
128 sprintf(tmp
, "%s.%s", wm_instance
, wm_class
);
131 strcat(tmp
, wm_instance
);
133 strcat(tmp
, wm_class
);
136 key
= WMCreatePLString(tmp
);
139 adict
= WMGetFromPLDictionary(dict
, key
);
140 iconk
= WMCreatePLString("Icon");
143 val
= WMGetFromPLDictionary(adict
, iconk
);
145 /* no dictionary for app, so create one */
146 adict
= WMCreatePLDictionary(NULL
, NULL
);
147 WMPutInPLDictionary(dict
, key
, adict
);
148 WMReleasePropList(adict
);
153 val
= WMCreatePLString(iconPath
);
154 WMPutInPLDictionary(adict
, iconk
, val
);
155 WMReleasePropList(val
);
160 WMReleasePropList(key
);
161 WMReleasePropList(iconk
);
163 if (val
&& !wPreferences
.flags
.noupdates
)
164 UpdateDomainFile(WDWindowAttributes
);
167 /* This function is used if the application is a .app. It checks if it has an icon in it
168 * like for example /usr/local/GNUstep/Applications/WPrefs.app/WPrefs.tiff
170 void wApplicationExtractDirPackIcon(WScreen
* scr
, char *path
, char *wm_instance
, char *wm_class
)
172 char *iconPath
= NULL
;
175 if (strstr(path
, ".app")) {
176 tmp
= wmalloc(strlen(path
) + 16);
178 if (scr
->flags
.supports_tiff
) {
180 strcat(tmp
, ".tiff");
181 if (access(tmp
, R_OK
) == 0)
188 if (access(tmp
, R_OK
) == 0)
196 wApplicationSaveIconPathFor(iconPath
, wm_instance
, wm_class
);
202 static void app_icon_create_from_docks(WWindow
*wwin
, WApplication
*wapp
, Window main_window
)
204 WScreen
*scr
= wwin
->screen_ptr
;
207 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
209 /* check main dock if we did not find it in last dock */
210 if (!wapp
->app_icon
&& scr
->dock
)
211 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
213 /* finally check clips */
214 if (!wapp
->app_icon
) {
216 for (i
= 0; i
< scr
->workspace_count
; i
++) {
217 WDock
*dock
= scr
->workspaces
[i
]->clip
;
219 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
225 /* If created, then set some flags */
226 if (wapp
->app_icon
) {
227 WWindow
*mainw
= wapp
->main_window_desc
;
229 wapp
->app_icon
->running
= 1;
230 wapp
->app_icon
->icon
->force_paint
= 1;
231 wapp
->app_icon
->icon
->owner
= mainw
;
232 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
& IconWindowHint
))
233 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
235 wAppIconPaint(wapp
->app_icon
);
236 wAppIconSave(wapp
->app_icon
);
238 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
242 WApplication
*wApplicationCreate(WWindow
* wwin
)
244 WScreen
*scr
= wwin
->screen_ptr
;
245 Window main_window
= wwin
->main_window
;
249 if (main_window
== None
|| main_window
== scr
->root_win
)
256 /* check if the window is valid */
257 if (!XGetGeometry(dpy
, main_window
, &root
, &foo
, &foo
, &bar
, &bar
, &bar
, &bar
))
261 wapp
= wApplicationOf(main_window
);
264 if (wapp
->app_icon
&& wapp
->app_icon
->docked
&&
265 wapp
->app_icon
->relaunching
&& wapp
->main_window_desc
->fake_group
)
266 wDockFinishLaunch(wapp
->app_icon
->dock
, wapp
->app_icon
);
271 wapp
= wmalloc(sizeof(WApplication
));
274 wapp
->last_focused
= NULL
;
275 wapp
->urgent_bounce_timer
= NULL
;
277 wapp
->last_workspace
= 0;
279 wapp
->main_window
= main_window
;
280 wapp
->main_window_desc
= makeMainWindow(scr
, main_window
);
281 if (!wapp
->main_window_desc
) {
286 wapp
->main_window_desc
->fake_group
= wwin
->fake_group
;
287 wapp
->main_window_desc
->net_icon_image
= RRetainImage(wwin
->net_icon_image
);
289 extractIcon(wapp
->main_window_desc
);
291 leader
= wWindowFor(main_window
);
293 leader
->main_window
= main_window
;
295 wapp
->menu
= wAppMenuGet(scr
, main_window
);
298 wapp
->menu
= wUserMenuGet(scr
, wapp
->main_window_desc
);
299 #endif /* USER_MENU */
302 * Set application wide attributes from the leader.
304 wapp
->flags
.hidden
= WFLAGP(wapp
->main_window_desc
, start_hidden
);
305 wapp
->flags
.emulated
= WFLAGP(wapp
->main_window_desc
, emulate_appicon
);
307 /* application descriptor */
308 XSaveContext(dpy
, main_window
, wAppWinContext
, (XPointer
) wapp
);
310 /* Create the application icon */
311 wapp
->app_icon
= NULL
;
312 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
)) {
313 /* Create the application icon using the icon from docks
314 * If not found in docks, create a new icon
315 * using the function wAppIconCreate() */
316 app_icon_create_from_docks(wwin
, wapp
, main_window
);
318 /* Now, paint the icon */
319 paint_app_icon(wapp
);
321 /* Save the app_icon in a file */
322 save_app_icon(wwin
, wapp
);
328 void wApplicationDestroy(WApplication
* wapp
)
337 if (wapp
->refcount
> 0)
340 if (wapp
->urgent_bounce_timer
) {
341 WMDeleteTimerHandler(wapp
->urgent_bounce_timer
);
342 wapp
->urgent_bounce_timer
= NULL
;
344 if (wapp
->flags
.bouncing
) {
345 /* event.c:handleDestroyNotify forced this destroy
346 and thereby overlooked the bounce callback */
351 scr
= wapp
->main_window_desc
->screen_ptr
;
353 if (wapp
== scr
->wapp_list
) {
355 wapp
->next
->prev
= NULL
;
356 scr
->wapp_list
= wapp
->next
;
359 wapp
->next
->prev
= wapp
->prev
;
361 wapp
->prev
->next
= wapp
->next
;
364 XDeleteContext(dpy
, wapp
->main_window
, wAppWinContext
);
365 wAppMenuDestroy(wapp
->menu
);
366 wApplicationDeactivate(wapp
);
368 if (wapp
->app_icon
) {
369 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
370 wapp
->app_icon
->running
= 0;
371 /* since we keep it, we don't care if it was attracted or not */
372 wapp
->app_icon
->attracted
= 0;
373 wapp
->app_icon
->icon
->shadowed
= 0;
374 wapp
->app_icon
->main_window
= None
;
375 wapp
->app_icon
->pid
= 0;
376 wapp
->app_icon
->icon
->owner
= NULL
;
377 wapp
->app_icon
->icon
->icon_win
= None
;
378 wapp
->app_icon
->icon
->force_paint
= 1;
379 wAppIconPaint(wapp
->app_icon
);
380 } else if (wapp
->app_icon
->docked
) {
381 wapp
->app_icon
->running
= 0;
382 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
384 wAppIconDestroy(wapp
->app_icon
);
387 wwin
= wWindowFor(wapp
->main_window_desc
->client_win
);
389 wWindowDestroy(wapp
->main_window_desc
);
391 /* undelete client window context that was deleted in
393 XSaveContext(dpy
, wwin
->client_win
, wWinContext
, (XPointer
) & wwin
->client_descriptor
);
397 if (wPreferences
.auto_arrange_icons
)
398 wArrangeIcons(scr
, True
);
401 void wApplicationActivate(WApplication
*wapp
)
404 if (wapp
->app_icon
) {
405 wIconSetHighlited(wapp
->app_icon
->icon
, True
);
406 wAppIconPaint(wapp
->app_icon
);
411 void wApplicationDeactivate(WApplication
*wapp
)
414 if (wapp
->app_icon
) {
415 wIconSetHighlited(wapp
->app_icon
->icon
, False
);
416 wAppIconPaint(wapp
->app_icon
);