2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 /* This module is based on Twm, but has been siginificantly modified
20 * Copyright 1988 by Evans & Sutherland Computer Corporation,
21 * Salt Lake City, Utah
22 * Portions Copyright 1989 by the Massachusetts Institute of Technology
23 * Cambridge, Massachusetts
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby
29 * granted, provided that the above copyright notice appear in all
30 * copies and that both that copyright notice and this permis-
31 * sion notice appear in supporting documentation, and that the
32 * names of Evans & Sutherland and M.I.T. not be used in advertising
33 * in publicity pertaining to distribution of the software without
34 * specific, written prior permission.
36 * EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD
37 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
38 * ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR
39 * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM-
40 * AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
41 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
42 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
43 * OR PERFORMANCE OF THIS SOFTWARE.
46 /* ---------------------------- included header files ---------------------- */
52 #include "libs/fvwmlib.h"
53 #include "libs/FShape.h"
54 #include "libs/FScreen.h"
55 #include "libs/Picture.h"
56 #include "libs/PictureUtils.h"
57 #include "libs/charmap.h"
58 #include "libs/wcontext.h"
59 #include "libs/Grab.h"
60 #include "libs/Strings.h"
61 #include "libs/XResource.h"
65 #include "execcontext.h"
70 #include "add_window.h"
72 #include "eventhandler.h"
73 #include "eventmask.h"
74 #include "module_interface.h"
82 #include "placement.h"
85 #include "move_resize.h"
88 #include "colormaps.h"
89 #include "decorations.h"
90 #include "functions.h"
92 /* ---------------------------- local definitions -------------------------- */
94 /* ---------------------------- local macros ------------------------------- */
96 /* ---------------------------- imports ------------------------------------ */
98 /* ---------------------------- included code files ------------------------ */
100 /* ---------------------------- local types -------------------------------- */
102 /* ---------------------------- forward declarations ----------------------- */
104 /* ---------------------------- local variables ---------------------------- */
106 /* ---------------------------- exported variables (globals) --------------- */
108 char NoName
[] = "Untitled"; /* name if no name in XA_WM_NAME */
109 char NoClass
[] = "NoClass"; /* Class if no res_class in class hints */
110 char NoResource
[] = "NoResource"; /* Class if no res_name in class hints */
112 /* ---------------------------- local functions ---------------------------- */
114 static void delete_client_context(FvwmWindow
*fw
)
118 /* We can not simply delete the context. X might have reused the
119 * window structure so we would delete the context that was established
120 * by another FvwmWindow structure in the mean time. */
122 dpy
, FW_W(fw
), FvwmContext
, (caddr_t
*)&cw
) !=
125 XDeleteContext(dpy
, FW_W(fw
), FvwmContext
);
137 * Decorates windows at start-up and during recaptures
141 static void CaptureOneWindow(
142 const exec_context_t
*exc
, FvwmWindow
*fw
, Window window
,
143 Window keep_on_top_win
, Window parent_win
, Bool is_recapture
)
146 unsigned long data
[1];
147 initial_window_options_t win_opts
;
149 exec_context_changes_t ecc
;
156 if (IS_SCHEDULED_FOR_DESTROY(fw
))
158 /* Fvwm might crash in complex functions if we really try to
159 * the dying window here because AddWindow() may fail and leave
160 * a destroyed window in some structures. By the way, it is
161 * pretty useless to recapture a window that will vanish in a
165 /* Grab the server to make sure the window does not die during the
170 dpy
, FW_W(fw
), &JunkRoot
, &JunkX
, &JunkY
,
171 (unsigned int*)&JunkWidth
, (unsigned int*)&JunkHeight
,
172 (unsigned int*)&JunkBW
, (unsigned int*)&JunkDepth
))
174 /* The window has already died, do not recapture it! */
175 MyXUngrabServer(dpy
);
178 if (XFindContext(dpy
, window
, FvwmContext
, (caddr_t
*)&fw
) != XCNOENT
)
180 Bool is_mapped
= IS_MAPPED(fw
);
182 memset(&win_opts
, 0, sizeof(win_opts
));
183 win_opts
.initial_state
= DontCareState
;
184 win_opts
.flags
.do_override_ppos
= 1;
185 win_opts
.flags
.is_recapture
= 1;
186 if (IS_ICONIFIED(fw
))
188 win_opts
.initial_state
= IconicState
;
189 win_opts
.flags
.is_iconified_by_parent
=
190 IS_ICONIFIED_BY_PARENT(fw
);
194 win_opts
.initial_state
= NormalState
;
195 win_opts
.flags
.is_iconified_by_parent
= 0;
196 if (Scr
.CurrentDesk
!= fw
->Desk
)
198 SetMapStateProp(fw
, NormalState
);
201 data
[0] = (unsigned long) fw
->Desk
;
203 dpy
, FW_W(fw
), _XA_WM_DESKTOP
, _XA_WM_DESKTOP
, 32,
204 PropModeReplace
, (unsigned char *) data
, 1);
206 /* are all these really needed ? */
207 /* EWMH_SetWMDesktop(fw); */
211 GNOME_SetWinArea(fw
);
213 XSelectInput(dpy
, FW_W(fw
), NoEventMask
);
215 XUnmapWindow(dpy
, FW_W_FRAME(fw
));
216 border_undraw_decorations(fw
);
217 RestoreWithdrawnLocation(fw
, is_recapture
, parent_win
);
218 SET_DO_REUSE_DESTROYED(fw
, 1); /* RBW - 1999/03/20 */
220 win_opts
.flags
.is_menu
=
221 (is_recapture
&& fw
!= NULL
&& IS_TEAR_OFF_MENU(fw
));
224 fev_make_null_event(&e
, dpy
);
225 e
.xmaprequest
.window
= w
;
226 e
.xmaprequest
.parent
= Scr
.Root
;
230 ecc
.w
.wcontext
= C_ROOT
;
231 ea
.exc
= exc_clone_context(
232 exc
, &ecc
, ECC_ETRIGGER
| ECC_FW
| ECC_W
|
234 HandleMapRequestKeepRaised(&ea
, keep_on_top_win
, fw
, &win_opts
);
235 exc_destroy_context(ea
.exc
);
237 /* HandleMapRequestKeepRaised may have destroyed the fw if the
238 * window vanished while in AddWindow(), so don't access fw
239 * anymore before checking if it is a valid window. */
240 if (check_if_fvwm_window_exists(fw
))
244 SET_MAP_PENDING(fw
, 0);
245 SET_MAPPED(fw
, is_mapped
);
249 MyXUngrabServer(dpy
);
254 /* Put a transparent window all over the screen to hide what happens below. */
255 static void hide_screen(
256 Bool do_hide
, Window
*ret_hide_win
, Window
*ret_parent_win
)
258 static Bool is_hidden
= False
;
259 static Window hide_win
= None
;
260 static Window parent_win
= None
;
261 XSetWindowAttributes xswa
;
262 unsigned long valuemask
;
264 if (do_hide
== is_hidden
)
269 *ret_hide_win
= hide_win
;
273 *ret_parent_win
= parent_win
;
281 xswa
.override_redirect
= True
;
282 xswa
.cursor
= Scr
.FvwmCursors
[CRS_WAIT
];
283 xswa
.backing_store
= NotUseful
;
284 xswa
.save_under
= False
;
285 xswa
.background_pixmap
= None
;
286 valuemask
= CWOverrideRedirect
| CWCursor
| CWSaveUnder
|
287 CWBackingStore
| CWBackPixmap
;
288 hide_win
= XCreateWindow(
289 dpy
, Scr
.Root
, 0, 0, Scr
.MyDisplayWidth
,
290 Scr
.MyDisplayHeight
, 0, Pdepth
, InputOutput
,
291 Pvisual
, valuemask
, &xswa
);
294 /* When recapturing, all windows are reparented to this
295 * window. If they are reparented to the root window,
296 * they will flash over the hide_win with XFree. So
297 * reparent them to an unmapped window that looks like
298 * the root window. */
299 parent_win
= XCreateWindow(
300 dpy
, Scr
.Root
, 0, 0, Scr
.MyDisplayWidth
,
301 Scr
.MyDisplayHeight
, 0, CopyFromParent
,
302 InputOutput
, CopyFromParent
, valuemask
, &xswa
);
305 XDestroyWindow(dpy
, hide_win
);
310 XMapWindow(dpy
, hide_win
);
317 if (hide_win
!= None
)
319 XDestroyWindow(dpy
, hide_win
);
321 if (parent_win
!= None
)
323 XDestroyWindow(dpy
, parent_win
);
331 *ret_hide_win
= hide_win
;
335 *ret_parent_win
= parent_win
;
344 * MappedNotOverride - checks to see if we should really
345 * put a fvwm frame on the window
348 * 1 - go ahead and frame the window
349 * 0 - don't frame the window
352 * w - the window to check
356 static int MappedNotOverride(
357 Window w
, initial_window_options_t
*win_opts
)
359 XWindowAttributes wa
;
362 unsigned long nitems
, bytes_remain
;
365 win_opts
->initial_state
= DontCareState
;
366 if ((w
==Scr
.NoFocusWin
)||(!XGetWindowAttributes(dpy
, w
, &wa
)))
370 if (XGetWindowProperty(
371 dpy
,w
,_XA_WM_STATE
,0L,3L,False
,_XA_WM_STATE
,
372 &atype
,&aformat
,&nitems
,&bytes_remain
,&prop
)==Success
)
376 win_opts
->initial_state
= *(long *)prop
;
380 if (wa
.override_redirect
== True
)
382 XSelectInput(dpy
, w
, XEVMASK_ORW
);
386 return (((win_opts
->initial_state
== IconicState
) ||
387 (wa
.map_state
!= IsUnmapped
)) &&
388 (wa
.override_redirect
!= True
));
391 static void do_recapture(F_CMD_ARGS
, Bool fSingle
)
393 FvwmWindow
*fw
= exc
->w
.fw
;
399 exc
, fw
, FW_W(fw
), None
, None
, True
);
403 CaptureAllWindows(exc
, True
);
405 /* Throw away queued up events. We don't want user input during a
406 * recapture. The window the user clicks in might disapper at the very
407 * same moment and the click goes through to the root window. Not good
409 XAllowEvents(dpy
, AsyncPointer
, CurrentTime
);
411 ButtonPressMask
|ButtonReleaseMask
|ButtonMotionMask
| \
412 PointerMotionMask
|KeyPressMask
|KeyReleaseMask
);
413 #ifdef DEBUG_STACK_RING
414 verify_stack_ring_consistency();
416 MyXUngrabServer(dpy
);
421 static void setup_window_structure(
422 FvwmWindow
**pfw
, Window w
, FvwmWindow
*ReuseWin
)
424 FvwmWindow save_state
;
425 FvwmWindow
*savewin
= NULL
;
428 Allocate space for the FvwmWindow struct, or reuse an
429 old one (on Recapture).
431 if (ReuseWin
== NULL
)
433 *pfw
= (FvwmWindow
*)safemalloc(sizeof(FvwmWindow
));
438 savewin
= &save_state
;
439 memcpy(savewin
, ReuseWin
, sizeof(FvwmWindow
));
443 RBW - 1999/05/28 - modify this when we implement the preserving of
444 various states across a Recapture. The Destroy function in misc.c may
445 also need tweaking, depending on what you want to preserve.
446 For now, just zap any old information, except the desk.
448 memset(*pfw
, '\0', sizeof(FvwmWindow
));
452 (*pfw
)->Desk
= savewin
->Desk
;
453 SET_SHADED(*pfw
, IS_SHADED(savewin
));
454 SET_USED_TITLE_DIR_FOR_SHADING(
455 *pfw
, USED_TITLE_DIR_FOR_SHADING(savewin
));
456 SET_SHADED_DIR(*pfw
, SHADED_DIR(savewin
));
457 SET_NAME_CHANGED(*pfw
,IS_NAME_CHANGED(savewin
));
458 (*pfw
)->placed_by_button
= savewin
->placed_by_button
;
459 SET_PLACED_BY_FVWM(*pfw
, IS_PLACED_BY_FVWM(savewin
));
460 SET_HAS_EWMH_WM_ICON_HINT(*pfw
, HAS_EWMH_WM_ICON_HINT(savewin
));
461 (*pfw
)->ewmh_mini_icon_width
= savewin
->ewmh_mini_icon_width
;
462 (*pfw
)->ewmh_mini_icon_height
= savewin
->ewmh_mini_icon_height
;
463 (*pfw
)->ewmh_icon_width
= savewin
->ewmh_icon_width
;
464 (*pfw
)->ewmh_icon_height
= savewin
->ewmh_icon_height
;
465 (*pfw
)->ewmh_hint_desktop
= savewin
->ewmh_hint_desktop
;
466 /* restore ewmh state */
467 EWMH_SetWMState(savewin
, True
);
468 SET_HAS_EWMH_INIT_WM_DESKTOP(
469 *pfw
, HAS_EWMH_INIT_WM_DESKTOP(savewin
));
470 SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
471 *pfw
, HAS_EWMH_INIT_FULLSCREEN_STATE(savewin
));
472 SET_HAS_EWMH_INIT_HIDDEN_STATE(
473 *pfw
, HAS_EWMH_INIT_HIDDEN_STATE(savewin
));
474 SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
475 *pfw
, HAS_EWMH_INIT_MAXHORIZ_STATE(savewin
));
476 SET_HAS_EWMH_INIT_MAXVERT_STATE(
477 *pfw
, HAS_EWMH_INIT_MAXVERT_STATE(savewin
));
478 SET_HAS_EWMH_INIT_SHADED_STATE(
479 *pfw
, HAS_EWMH_INIT_SHADED_STATE(savewin
));
480 SET_HAS_EWMH_INIT_STICKY_STATE(
481 *pfw
, HAS_EWMH_INIT_STICKY_STATE(savewin
));
482 CLEAR_USER_STATES(*pfw
, ~0);
483 SET_USER_STATES(*pfw
, GET_USER_STATES(savewin
));
487 /* make sure that new windows *remember* being shaded with
489 SET_USED_TITLE_DIR_FOR_SHADING(*pfw
,1);
492 (*pfw
)->cmap_windows
= (Window
*)NULL
;
493 if (FMiniIconsSupported
)
495 (*pfw
)->mini_pixmap_file
= NULL
;
496 (*pfw
)->mini_icon
= NULL
;
502 static void setup_name_count(FvwmWindow
*fw
, Bool is_icon
)
507 int win_count_counterpart
;
509 FlocaleNameString
*titlename
, *title_counterpart
;
510 FlocaleNameString
*t_titlename
, *t_title_counterpart
;
512 titlename
= (is_icon
) ?
513 &(fw
->icon_name
) : &(fw
->name
);
515 title_counterpart
= (is_icon
) ?
516 &(fw
->name
) : &(fw
->icon_name
);
518 if (!titlename
->name
)
523 if (titlename
->name
&& title_counterpart
->name
&&
524 strcmp(titlename
->name
, title_counterpart
->name
) == 0)
526 count
= is_icon
? fw
->icon_name_count
:
533 for (t
= Scr
.FvwmRoot
.next
; t
!= NULL
; t
= t
->next
)
539 win_count
= is_icon
? t
->icon_name_count
:
541 win_count_counterpart
= is_icon
?
542 t
->name_count
: t
->icon_name_count
;
544 t_titlename
= is_icon
? &(t
->icon_name
) :
546 t_title_counterpart
= is_icon
? &(t
->name
) :
549 if ((t_titlename
->name
&&
550 strcmp(titlename
->name
,
551 t_titlename
->name
) == 0 &&
552 win_count
== count
) ||
553 (t_title_counterpart
->name
&&
554 strcmp(t_title_counterpart
->name
,
555 titlename
->name
) == 0 &&
556 win_count_counterpart
== count
))
567 fw
->icon_name_count
= count
;
569 fw
->name_count
= count
;
575 static void setup_class_and_resource(FvwmWindow
*fw
)
577 /* removing NoClass change for now... */
578 fw
->class.res_name
= NoResource
;
579 fw
->class.res_class
= NoClass
;
580 XGetClassHint(dpy
, FW_W(fw
), &fw
->class);
581 if (fw
->class.res_name
== NULL
)
583 fw
->class.res_name
= NoResource
;
585 if (fw
->class.res_class
== NULL
)
587 fw
->class.res_class
= NoClass
;
589 FetchWmProtocols (fw
);
590 FetchWmColormapWindows (fw
);
595 static void setup_window_attr(
596 FvwmWindow
*fw
, XWindowAttributes
*ret_attr
)
598 if (XGetWindowAttributes(dpy
, FW_W(fw
), ret_attr
) == 0)
600 /* can't happen because fvwm has grabbed the server and does
601 * not destroy the window itself */
603 fw
->attr_backup
.backing_store
= ret_attr
->backing_store
;
604 fw
->attr_backup
.border_width
= ret_attr
->border_width
;
605 fw
->attr_backup
.depth
= ret_attr
->depth
;
606 fw
->attr_backup
.bit_gravity
= ret_attr
->bit_gravity
;
607 fw
->attr_backup
.is_bit_gravity_stored
= 0;
608 fw
->attr_backup
.visual
= ret_attr
->visual
;
609 fw
->attr_backup
.colormap
= ret_attr
->colormap
;
614 static void destroy_window_font(FvwmWindow
*fw
)
616 if (IS_WINDOW_FONT_LOADED(fw
) && !USING_DEFAULT_WINDOW_FONT(fw
) &&
617 fw
->title_font
!= Scr
.DefaultFont
)
619 FlocaleUnloadFont(dpy
, fw
->title_font
);
621 SET_WINDOW_FONT_LOADED(fw
, 0);
622 /* Fall back to default font. There are some race conditions when a
623 * window is destroyed and recaptured where an invalid font might be
624 * accessed otherwise. */
625 fw
->title_font
= Scr
.DefaultFont
;
626 SET_USING_DEFAULT_WINDOW_FONT(fw
, 1);
631 static void destroy_icon_font(FvwmWindow
*fw
)
633 if (IS_ICON_FONT_LOADED(fw
) && !USING_DEFAULT_ICON_FONT(fw
) &&
634 fw
->icon_font
!= Scr
.DefaultFont
)
636 FlocaleUnloadFont(dpy
, fw
->icon_font
);
638 SET_ICON_FONT_LOADED(fw
, 0);
639 /* Fall back to default font (see comment above). */
640 fw
->icon_font
= Scr
.DefaultFont
;
641 SET_USING_DEFAULT_ICON_FONT(fw
, 1);
646 static void adjust_fvwm_internal_windows(FvwmWindow
*fw
)
648 if (fw
== Scr
.Hilite
)
652 update_last_screen_focus_window(fw
);
653 restore_focus_after_unmap(fw
, False
);
654 frame_destroyed_frame(FW_W(fw
));
655 if (FW_W(fw
) == Scr
.StolenFocusWin
)
657 Scr
.StolenFocusWin
= None
;
659 if (Scr
.focus_in_pending_window
== fw
)
661 Scr
.focus_in_pending_window
= NULL
;
663 if (Scr
.cascade_window
== fw
)
665 Scr
.cascade_window
= NULL
;
671 static void broadcast_mini_icon(FvwmWindow
*fw
)
673 if (!FMiniIconsSupported
)
677 if (fw
->mini_pixmap_file
&& fw
->mini_icon
)
679 BroadcastFvwmPicture(
681 FW_W(fw
), FW_W_FRAME(fw
), (unsigned long)fw
,
682 fw
->mini_icon
, fw
->mini_pixmap_file
);
688 static void setup_mini_icon(FvwmWindow
*fw
, window_style
*pstyle
)
690 FvwmPictureAttributes fpa
;
692 if (!FMiniIconsSupported
)
696 if (SHAS_MINI_ICON(&pstyle
->flags
))
698 fw
->mini_pixmap_file
= SGET_MINI_ICON_NAME(*pstyle
);
702 fw
->mini_pixmap_file
= NULL
;
704 if (fw
->mini_pixmap_file
)
707 fw
->mini_icon
= PCacheFvwmPicture(
708 dpy
, Scr
.NoFocusWin
, NULL
, fw
->mini_pixmap_file
, fpa
);
712 fw
->mini_icon
= NULL
;
719 * Copy icon size limits from window_style structure to FvwmWindow
722 void setup_icon_size_limits(FvwmWindow
*fw
, window_style
*pstyle
)
724 if (SHAS_ICON_SIZE_LIMITS(&pstyle
->flags
))
726 fw
->min_icon_width
= SGET_MIN_ICON_WIDTH(*pstyle
);
727 fw
->min_icon_height
= SGET_MIN_ICON_HEIGHT(*pstyle
);
728 fw
->max_icon_width
= SGET_MAX_ICON_WIDTH(*pstyle
);
729 fw
->max_icon_height
= SGET_MAX_ICON_HEIGHT(*pstyle
);
730 fw
->icon_resize_type
= SGET_ICON_RESIZE_TYPE(*pstyle
);
734 fw
->min_icon_width
= MIN_ALLOWABLE_ICON_DIMENSION
;
735 fw
->min_icon_height
= MIN_ALLOWABLE_ICON_DIMENSION
;
736 fw
->max_icon_width
= MAX_ALLOWABLE_ICON_DIMENSION
;
737 fw
->max_icon_height
= MAX_ALLOWABLE_ICON_DIMENSION
;
738 fw
->icon_resize_type
= ICON_RESIZE_TYPE_NONE
;
744 void setup_icon_background_parameters(FvwmWindow
*fw
, window_style
*pstyle
)
746 if (SHAS_ICON_BACKGROUND_PADDING(&pstyle
->flags
))
748 fw
->icon_background_padding
=
749 SGET_ICON_BACKGROUND_PADDING(*pstyle
);
753 fw
->icon_background_padding
= ICON_BACKGROUND_PADDING
;
755 if (SHAS_ICON_BACKGROUND_RELIEF(&pstyle
->flags
))
757 fw
->icon_background_relief
=
758 SGET_ICON_BACKGROUND_RELIEF(*pstyle
);
762 fw
->icon_background_relief
= ICON_RELIEF_WIDTH
;
767 void setup_icon_title_parameters(FvwmWindow
*fw
, window_style
*pstyle
)
769 if (SHAS_ICON_TITLE_RELIEF(&pstyle
->flags
))
771 fw
->icon_title_relief
=
772 SGET_ICON_TITLE_RELIEF(*pstyle
);
776 fw
->icon_title_relief
= ICON_RELIEF_WIDTH
;
781 void setup_numeric_vals(FvwmWindow
*fw
, window_style
*pstyle
)
783 /****** window shading ******/
784 fw
->shade_anim_steps
= pstyle
->shade_anim_steps
;
786 /****** snapattraction, snapgrid, paging ******/
787 fw
->snap_proximity
= pstyle
->snap_proximity
;
788 fw
->snap_mode
= pstyle
->snap_mode
;
789 fw
->snap_grid_x
= pstyle
->snap_grid_x
;
790 fw
->snap_grid_y
= pstyle
->snap_grid_y
;
791 if (pstyle
->flags
.has_edge_delay_ms_move
)
793 fw
->edge_delay_ms_move
= pstyle
->edge_delay_ms_move
;
797 fw
->edge_delay_ms_move
= DEFAULT_MOVE_DELAY
;
799 if (pstyle
->flags
.has_edge_delay_ms_resize
)
801 fw
->edge_delay_ms_resize
= pstyle
->edge_delay_ms_resize
;
805 fw
->edge_delay_ms_resize
= DEFAULT_RESIZE_DELAY
;
807 fw
->edge_resistance_move
= pstyle
->edge_resistance_move
;
808 fw
->edge_resistance_xinerama_move
=
809 pstyle
->edge_resistance_xinerama_move
;
814 static void setup_frame_window(
817 XSetWindowAttributes attributes
;
821 FRenderPictFormat
*format
;
823 valuemask
= CWBackingStore
| CWBackPixmap
| CWEventMask
| CWSaveUnder
826 /* This adds preliminary support for ARGB windows in fvwm. It should
827 evolve to proper ARGB support in frames, menus and modules */
828 format
=FRenderFindVisualFormat(dpy
, fw
->attr_backup
.visual
);
829 if (format
!= NULL
&& format
->type
== FRenderPictTypeDirect
&&
830 format
->direct
.alphaMask
> 0)
832 depth
= fw
->attr_backup
.depth
;
833 visual
= fw
->attr_backup
.visual
;
834 attributes
.colormap
= fw
->attr_backup
.colormap
;
835 attributes
.background_pixel
= -1;
836 attributes
.border_pixel
= -1;
837 valuemask
|= CWColormap
| CWBackPixel
| CWBorderPixel
;
841 depth
= CopyFromParent
;
842 visual
= CopyFromParent
;
844 attributes
.backing_store
= NotUseful
;
845 attributes
.background_pixmap
= None
;
846 attributes
.cursor
= Scr
.FvwmCursors
[CRS_DEFAULT
];
847 attributes
.event_mask
= XEVMASK_FRAMEW_CAPTURE
;
848 attributes
.save_under
= False
;
849 /* create the frame window, child of root, grandparent of client */
850 FW_W_FRAME(fw
) = XCreateWindow(
851 dpy
, Scr
.Root
, fw
->g
.frame
.x
, fw
->g
.frame
.y
,
852 fw
->g
.frame
.width
, fw
->g
.frame
.height
, 0, depth
,
853 InputOutput
, visual
, valuemask
, &attributes
);
854 XSaveContext(dpy
, FW_W(fw
), FvwmContext
, (caddr_t
) fw
);
855 XSaveContext(dpy
, FW_W_FRAME(fw
), FvwmContext
, (caddr_t
) fw
);
860 static void setup_title_window(
861 FvwmWindow
*fw
, int valuemask
, XSetWindowAttributes
*pattributes
)
863 valuemask
|= CWCursor
| CWEventMask
;
864 pattributes
->cursor
= Scr
.FvwmCursors
[CRS_TITLE
];
865 pattributes
->event_mask
= XEVMASK_TITLEW
;
867 FW_W_TITLE(fw
) = XCreateWindow(
868 dpy
, FW_W_FRAME(fw
), 0, 0, 1, 1, 0, Pdepth
, InputOutput
,
869 Pvisual
, valuemask
, pattributes
);
870 XSaveContext(dpy
, FW_W_TITLE(fw
), FvwmContext
, (caddr_t
) fw
);
875 static void destroy_title_window(FvwmWindow
*fw
, Bool do_only_delete_context
)
877 if (!do_only_delete_context
)
879 XDestroyWindow(dpy
, FW_W_TITLE(fw
));
880 FW_W_TITLE(fw
) = None
;
882 XDeleteContext(dpy
, FW_W_TITLE(fw
), FvwmContext
);
884 FW_W_TITLE(fw
) = None
;
889 static void change_title_window(
890 FvwmWindow
*fw
, int valuemask
, XSetWindowAttributes
*pattributes
)
892 if (HAS_TITLE(fw
) && FW_W_TITLE(fw
) == None
)
894 setup_title_window(fw
, valuemask
, pattributes
);
896 else if (!HAS_TITLE(fw
) && FW_W_TITLE(fw
) != None
)
898 destroy_title_window(fw
, False
);
904 static void setup_button_windows(
905 FvwmWindow
*fw
, int valuemask
, XSetWindowAttributes
*pattributes
,
910 Bool is_deleted
= False
;
912 valuemask
|= CWCursor
| CWEventMask
;
913 pattributes
->cursor
= Scr
.FvwmCursors
[CRS_SYS
];
914 pattributes
->event_mask
= XEVMASK_BUTTONW
;
916 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
918 has_button
= (((!(i
& 1) && i
/ 2 < Scr
.nr_left_buttons
) ||
919 ( (i
& 1) && i
/ 2 < Scr
.nr_right_buttons
)) &&
920 (buttons
& (1 << i
)));
921 if (FW_W_BUTTON(fw
, i
) == None
&& has_button
)
925 dpy
, FW_W_FRAME(fw
), 0, 0, 1, 1, 0,
926 Pdepth
, InputOutput
, Pvisual
,
927 valuemask
, pattributes
);
929 dpy
, FW_W_BUTTON(fw
, i
), FvwmContext
,
932 else if (FW_W_BUTTON(fw
, i
) != None
&& !has_button
)
934 /* destroy the current button window */
935 XDestroyWindow(dpy
, FW_W_BUTTON(fw
, i
));
936 XDeleteContext(dpy
, FW_W_BUTTON(fw
, i
), FvwmContext
);
938 FW_W_BUTTON(fw
, i
) = None
;
941 if (is_deleted
== True
)
949 static void destroy_button_windows(FvwmWindow
*fw
, Bool do_only_delete_context
)
952 Bool is_deleted
= False
;
954 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
++)
956 if (FW_W_BUTTON(fw
, i
) != None
)
958 if (!do_only_delete_context
)
960 XDestroyWindow(dpy
, FW_W_BUTTON(fw
, i
));
961 FW_W_BUTTON(fw
, i
) = None
;
963 XDeleteContext(dpy
, FW_W_BUTTON(fw
, i
), FvwmContext
);
965 FW_W_BUTTON(fw
, i
) = None
;
968 if (is_deleted
== True
)
976 static void change_button_windows(
977 FvwmWindow
*fw
, int valuemask
, XSetWindowAttributes
*pattributes
,
982 setup_button_windows(
983 fw
, valuemask
, pattributes
, buttons
);
987 destroy_button_windows(fw
, False
);
993 static void setup_parent_window(FvwmWindow
*fw
)
997 XSetWindowAttributes attributes
;
1000 valuemask
= CWBackingStore
| CWBackPixmap
| CWCursor
| CWEventMask
|
1002 attributes
.backing_store
= NotUseful
;
1003 attributes
.background_pixmap
= None
;
1004 attributes
.cursor
= Scr
.FvwmCursors
[CRS_DEFAULT
];
1005 attributes
.event_mask
= XEVMASK_PARENTW
;
1006 attributes
.save_under
= False
;
1008 /* This window is exactly the same size as the client for the benefit
1009 * of some clients */
1010 get_window_borders(fw
, &b
);
1011 FW_W_PARENT(fw
) = XCreateWindow(
1012 dpy
, FW_W_FRAME(fw
), b
.top_left
.width
, b
.top_left
.height
,
1013 fw
->g
.frame
.width
- b
.total_size
.width
,
1014 fw
->g
.frame
.height
- b
.total_size
.height
,
1015 0, CopyFromParent
, InputOutput
, CopyFromParent
, valuemask
,
1018 XSaveContext(dpy
, FW_W_PARENT(fw
), FvwmContext
, (caddr_t
) fw
);
1023 static void setup_resize_handle_cursors(FvwmWindow
*fw
)
1025 unsigned long valuemask
;
1026 XSetWindowAttributes attributes
;
1029 if (HAS_NO_BORDER(fw
))
1033 valuemask
= CWCursor
;
1034 attributes
.cursor
= Scr
.FvwmCursors
[CRS_DEFAULT
];
1036 for (i
= 0; i
< 4; i
++)
1038 if (HAS_HANDLES(fw
))
1040 attributes
.cursor
= Scr
.FvwmCursors
[CRS_TOP_LEFT
+ i
];
1042 XChangeWindowAttributes(
1043 dpy
, FW_W_CORNER(fw
, i
), valuemask
, &attributes
);
1044 if (HAS_HANDLES(fw
))
1046 attributes
.cursor
= Scr
.FvwmCursors
[CRS_TOP
+ i
];
1048 XChangeWindowAttributes(
1049 dpy
, FW_W_SIDE(fw
, i
), valuemask
, &attributes
);
1055 static void setup_resize_handle_windows(FvwmWindow
*fw
)
1057 unsigned long valuemask
;
1058 XSetWindowAttributes attributes
;
1073 if (HAS_NO_BORDER(fw
))
1077 valuemask
= CWEventMask
| CWBackingStore
| CWSaveUnder
| CWWinGravity
|
1078 CWBorderPixel
| CWColormap
;
1079 attributes
.event_mask
= XEVMASK_BORDERW
;
1080 attributes
.backing_store
= NotUseful
;
1081 attributes
.save_under
= False
;
1082 attributes
.border_pixel
= 0;
1083 attributes
.colormap
= Pcmap
;
1084 /* Just dump the windows any old place and let frame_setup_window take
1085 * care of the mess */
1086 for (i
= 0; i
< 4; i
++)
1088 attributes
.win_gravity
= c_grav
[i
];
1089 FW_W_CORNER(fw
, i
) = XCreateWindow(
1090 dpy
, FW_W_FRAME(fw
), -1, -1, 1, 1, 0, Pdepth
,
1091 InputOutput
, Pvisual
, valuemask
, &attributes
);
1093 dpy
, FW_W_CORNER(fw
, i
), FvwmContext
, (caddr_t
)fw
);
1094 attributes
.win_gravity
= s_grav
[i
];
1095 FW_W_SIDE(fw
, i
) = XCreateWindow(
1096 dpy
, FW_W_FRAME(fw
), -1, -1, 1, 1, 0, Pdepth
,
1097 InputOutput
, Pvisual
, valuemask
, &attributes
);
1098 XSaveContext(dpy
, FW_W_SIDE(fw
, i
), FvwmContext
, (caddr_t
)fw
);
1100 setup_resize_handle_cursors(fw
);
1105 static void destroy_resize_handle_windows(
1106 FvwmWindow
*fw
, Bool do_only_delete_context
)
1110 for (i
= 0; i
< 4 ; i
++)
1112 XDeleteContext(dpy
, FW_W_SIDE(fw
, i
), FvwmContext
);
1113 XDeleteContext(dpy
, FW_W_CORNER(fw
, i
), FvwmContext
);
1114 if (!do_only_delete_context
)
1116 XDestroyWindow(dpy
, FW_W_SIDE(fw
, i
));
1117 XDestroyWindow(dpy
, FW_W_CORNER(fw
, i
));
1118 FW_W_SIDE(fw
, i
) = None
;
1119 FW_W_CORNER(fw
, i
) = None
;
1127 static void change_resize_handle_windows(FvwmWindow
*fw
)
1129 if (!HAS_NO_BORDER(fw
) && FW_W_SIDE(fw
, 0) == None
)
1131 setup_resize_handle_windows(fw
);
1133 else if (HAS_NO_BORDER(fw
) && FW_W_SIDE(fw
, 0) != None
)
1135 destroy_resize_handle_windows(fw
, False
);
1139 setup_resize_handle_cursors(fw
);
1145 static void setup_frame_stacking(FvwmWindow
*fw
)
1149 Window w
[10 + NUMBER_OF_TITLE_BUTTONS
];
1151 /* Stacking order (top to bottom):
1153 * - Title and buttons
1160 w
[n
] = FW_W_PARENT(fw
);
1165 for (i
= 0; i
< NUMBER_OF_TITLE_BUTTONS
; i
+= 2)
1167 if (FW_W_BUTTON(fw
, i
) != None
)
1169 w
[n
] = FW_W_BUTTON(fw
, i
);
1173 for (i
= 2 * NR_RIGHT_BUTTONS
- 1; i
> 0; i
-= 2)
1175 if (FW_W_BUTTON(fw
, i
) != None
)
1177 w
[n
] = FW_W_BUTTON(fw
, i
);
1181 if (FW_W_TITLE(fw
) != None
)
1183 w
[n
] = FW_W_TITLE(fw
);
1187 for (i
= 0; i
< 4; i
++)
1189 if (FW_W_CORNER(fw
, i
) != None
)
1191 w
[n
] = FW_W_CORNER(fw
, i
);
1195 for (i
= 0; i
< 4; i
++)
1197 if (FW_W_SIDE(fw
, i
) != None
)
1199 w
[n
] = FW_W_SIDE(fw
, i
);
1205 w
[n
] = FW_W_PARENT(fw
);
1208 XRestackWindows(dpy
, w
, n
);
1213 static void get_default_window_attributes(
1214 FvwmWindow
*fw
, unsigned long *pvaluemask
,
1215 XSetWindowAttributes
*pattributes
)
1217 *pvaluemask
|= CWBackingStore
| CWCursor
| CWSaveUnder
| CWBorderPixel
|
1218 CWColormap
| CWBackPixmap
;
1219 pattributes
->background_pixel
= 0;
1220 pattributes
->background_pixmap
= None
;
1221 pattributes
->backing_store
= NotUseful
;
1222 pattributes
->cursor
= Scr
.FvwmCursors
[CRS_DEFAULT
];
1223 pattributes
->save_under
= False
;
1224 pattributes
->border_pixel
= 0;
1225 pattributes
->colormap
= Pcmap
;
1230 static void setup_auxiliary_windows(
1231 FvwmWindow
*fw
, Bool setup_frame_and_parent
, short buttons
)
1233 unsigned long valuemask_save
= 0;
1234 XSetWindowAttributes attributes
;
1236 get_default_window_attributes(fw
, &valuemask_save
, &attributes
);
1238 if (setup_frame_and_parent
)
1240 setup_frame_window(fw
);
1241 setup_parent_window(fw
);
1243 setup_resize_handle_windows(fw
);
1246 setup_title_window(fw
, valuemask_save
, &attributes
);
1247 setup_button_windows(fw
, valuemask_save
, &attributes
, buttons
);
1249 setup_frame_stacking(fw
);
1250 XMapSubwindows (dpy
, FW_W_FRAME(fw
));
1255 static void destroy_auxiliary_windows(
1256 FvwmWindow
*fw
, Bool destroy_frame_and_parent
)
1258 if (destroy_frame_and_parent
)
1260 XDeleteContext(dpy
, FW_W_FRAME(fw
), FvwmContext
);
1261 XDeleteContext(dpy
, FW_W_PARENT(fw
), FvwmContext
);
1262 delete_client_context(fw
);
1263 XDestroyWindow(dpy
, FW_W_FRAME(fw
));
1267 destroy_title_window(fw
, True
);
1271 destroy_button_windows(fw
, True
);
1273 if (!HAS_NO_BORDER(fw
))
1275 destroy_resize_handle_windows(fw
, True
);
1282 static void setup_icon(FvwmWindow
*fw
, window_style
*pstyle
)
1284 increase_icon_hint_count(fw
);
1285 /* find a suitable icon pixmap */
1286 if ((fw
->wmhints
) && (fw
->wmhints
->flags
& IconWindowHint
))
1288 if (SHAS_ICON(&pstyle
->flags
) &&
1289 S_ICON_OVERRIDE(SCF(*pstyle
)) == ICON_OVERRIDE
)
1291 ICON_DBG((stderr
,"si: iwh ignored '%s'\n",
1293 fw
->icon_bitmap_file
= SGET_ICON_NAME(*pstyle
);
1297 ICON_DBG((stderr
,"si: using iwh '%s'\n",
1299 fw
->icon_bitmap_file
= NULL
;
1302 else if ((fw
->wmhints
) && (fw
->wmhints
->flags
& IconPixmapHint
))
1304 if (SHAS_ICON(&pstyle
->flags
) &&
1305 S_ICON_OVERRIDE(SCF(*pstyle
)) != NO_ICON_OVERRIDE
)
1307 ICON_DBG((stderr
,"si: iph ignored '%s'\n",
1309 fw
->icon_bitmap_file
= SGET_ICON_NAME(*pstyle
);
1313 ICON_DBG((stderr
,"si: using iph '%s'\n",
1315 fw
->icon_bitmap_file
= NULL
;
1318 else if (SHAS_ICON(&pstyle
->flags
))
1320 /* an icon was specified */
1321 ICON_DBG((stderr
,"si: using style '%s'\n", fw
->name
.name
));
1322 fw
->icon_bitmap_file
= SGET_ICON_NAME(*pstyle
);
1326 /* use default icon */
1327 ICON_DBG((stderr
,"si: using default '%s'\n", fw
->name
.name
));
1328 fw
->icon_bitmap_file
= Scr
.DefaultIcon
;
1332 if (!EWMH_WMIconName(fw
, NULL
, NULL
, 0))
1334 fw
->icon_name
.name
= NoName
;
1335 fw
->icon_name
.name_list
= NULL
;
1336 FlocaleGetNameProperty(
1337 XGetWMIconName
, dpy
, FW_W(fw
), &(fw
->icon_name
));
1339 if (fw
->icon_name
.name
== NoName
)
1341 fw
->icon_name
.name
= fw
->name
.name
;
1342 SET_WAS_ICON_NAME_PROVIDED(fw
, 0);
1344 setup_visible_name(fw
, True
);
1347 /* wait until the window is iconified and the icon window is mapped
1348 * before creating the icon window
1350 FW_W_ICON_TITLE(fw
) = None
;
1352 EWMH_SetVisibleName(fw
, True
);
1353 BroadcastWindowIconNames(fw
, False
, True
);
1354 if (fw
->icon_bitmap_file
!= NULL
&&
1355 fw
->icon_bitmap_file
!= Scr
.DefaultIcon
)
1357 BroadcastName(M_ICON_FILE
,FW_W(fw
),FW_W_FRAME(fw
),
1358 (unsigned long)fw
,fw
->icon_bitmap_file
);
1364 static void destroy_icon(FvwmWindow
*fw
)
1366 free_window_names(fw
, False
, True
);
1367 if (IS_PIXMAP_OURS(fw
))
1369 XFreePixmap(dpy
, fw
->iconPixmap
);
1370 fw
->iconPixmap
= None
;
1371 if (fw
->icon_maskPixmap
!= None
)
1373 XFreePixmap(dpy
, fw
->icon_maskPixmap
);
1374 fw
->icon_maskPixmap
= None
;
1376 if (fw
->icon_alphaPixmap
!= None
)
1378 XFreePixmap(dpy
, fw
->icon_alphaPixmap
);
1379 fw
->icon_alphaPixmap
= None
;
1381 if (fw
->icon_alloc_pixels
!= NULL
)
1383 if (fw
->icon_nalloc_pixels
!= 0)
1386 dpy
, Pcmap
, fw
->icon_alloc_pixels
,
1387 fw
->icon_nalloc_pixels
, 0,
1390 free(fw
->icon_alloc_pixels
);
1391 fw
->icon_alloc_pixels
= NULL
;
1392 fw
->icon_nalloc_pixels
= 0;
1393 fw
->icon_no_limit
= 0;
1396 if (FW_W_ICON_TITLE(fw
))
1398 XDestroyWindow(dpy
, FW_W_ICON_TITLE(fw
));
1399 XDeleteContext(dpy
, FW_W_ICON_TITLE(fw
), FvwmContext
);
1402 if (FW_W_ICON_PIXMAP(fw
) != None
)
1404 if (IS_ICON_OURS(fw
))
1406 XDestroyWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
1410 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
1412 XDeleteContext(dpy
, FW_W_ICON_PIXMAP(fw
), FvwmContext
);
1420 static void setup_icon_boxes(FvwmWindow
*fw
, window_style
*pstyle
)
1424 /* copy iconboxes ptr (if any) */
1425 if (SHAS_ICON_BOXES(&pstyle
->flags
))
1427 fw
->IconBoxes
= SGET_ICON_BOXES(*pstyle
);
1428 for (ib
= fw
->IconBoxes
; ib
; ib
= ib
->next
)
1435 fw
->IconBoxes
= NULL
;
1441 static void destroy_icon_boxes(FvwmWindow
*fw
)
1445 fw
->IconBoxes
->use_count
--;
1446 if (fw
->IconBoxes
->use_count
== 0 && fw
->IconBoxes
->is_orphan
)
1448 /* finally destroy the icon box */
1449 free_icon_boxes(fw
->IconBoxes
);
1450 fw
->IconBoxes
= NULL
;
1457 static void setup_layer(FvwmWindow
*fw
, window_style
*pstyle
)
1462 if (SUSE_LAYER(&pstyle
->flags
))
1464 /* use layer from style */
1465 layer
= SGET_LAYER(*pstyle
);
1467 else if ((tf
= get_transientfor_fvwmwindow(fw
)) != NULL
)
1469 /* inherit layer from transientfor window */
1470 layer
= get_layer(tf
);
1474 /* use default layer */
1475 layer
= Scr
.DefaultLayer
;
1477 set_default_layer(fw
, layer
);
1478 set_layer(fw
, layer
);
1483 static void destroy_mini_icon(FvwmWindow
*fw
)
1487 PDestroyFvwmPicture(dpy
, fw
->mini_icon
);
1494 static void setup_key_and_button_grabs(FvwmWindow
*fw
)
1496 #ifdef BUGS_ARE_COOL
1497 /* dv (29-May-2001): If keys are grabbed separately for C_WINDOW and
1498 * the other contexts, new windows have problems when bindings are
1499 * removed. Therefore, grab all keys in a single pass through the
1502 dpy
, FW_W_FRAME(fw
), Scr
.AllBindings
,
1503 C_WINDOW
|C_TITLE
|C_RALL
|C_LALL
|C_SIDEBAR
, GetUnusedModifiers(),
1507 dpy
, FW_W_FRAME(fw
), Scr
.AllBindings
,
1508 C_TITLE
|C_RALL
|C_LALL
|C_SIDEBAR
|C_WINDOW
, GetUnusedModifiers(),
1510 setup_focus_policy(fw
);
1515 static void __add_window_handle_x_resources(FvwmWindow
*fw
)
1517 int client_argc
= 0;
1518 char **client_argv
= NULL
;
1520 XrmDatabase db
= NULL
;
1521 static XrmOptionDescRec table
[] = {
1522 {"-xrn", NULL
, XrmoptionResArg
, (caddr_t
) NULL
},
1523 {"-xrm", NULL
, XrmoptionResArg
, (caddr_t
) NULL
},
1525 /* Get global X resources */
1526 MergeXResources(dpy
, &db
, False
);
1527 /* Find out if the client requested a specific style on the command
1530 if (XGetCommand(dpy
, FW_W(fw
), &client_argv
, &client_argc
))
1532 if (client_argc
> 0 && client_argv
!= NULL
)
1534 /* command line takes precedence over all */
1535 MergeCmdLineResources(
1536 &db
, table
, 2, fw
->class.res_name
,
1537 &client_argc
, client_argv
, True
);
1542 /* parse the database values */
1543 if (GetResourceString(db
, "fvwmstyle", fw
->class.res_name
, &rm_value
)
1544 && rm_value
.size
!= 0)
1548 style_name
= rm_value
.addr
;
1549 name_len
= rm_value
.size
-1;
1550 /* Trim spaces at the start of the name */
1551 while (name_len
>0 && isspace(*style_name
))
1556 /* Trim spaces at the end of the name */
1557 while (name_len
>0 && isspace(*(style_name
+name_len
-1)))
1562 fw
->style_name
= (char*)safemalloc(sizeof(char)*
1564 memcpy(fw
->style_name
,style_name
,name_len
);
1565 fw
->style_name
[name_len
] = 0;
1568 XFreeStringList(client_argv
);
1569 XrmDestroyDatabase(db
);
1573 /* ---------------------------- interface functions ------------------------ */
1575 void setup_visible_name(FvwmWindow
*fw
, Bool is_icon
)
1584 /* should never happen */
1588 setup_name_count(fw
, is_icon
);
1592 if (fw
->visible_icon_name
!= NULL
&&
1593 fw
->visible_icon_name
!= fw
->icon_name
.name
&&
1594 fw
->visible_icon_name
!= fw
->name
.name
&&
1595 fw
->visible_icon_name
!= NoName
)
1597 free(fw
->visible_icon_name
);
1598 fw
->visible_icon_name
= NULL
;
1600 name
= fw
->icon_name
.name
;
1601 count
= fw
->icon_name_count
;
1605 if (fw
->visible_name
!= NULL
&&
1606 fw
->visible_name
!= fw
->name
.name
&&
1607 fw
->visible_name
!= NoName
)
1609 free(fw
->visible_name
);
1610 fw
->visible_name
= NULL
;
1612 name
= fw
->name
.name
;
1613 count
= fw
->name_count
;
1618 return; /* should never happen */
1621 if (count
> MAX_WINDOW_NAME_NUMBER
- 1)
1623 count
= MAX_WINDOW_NAME_NUMBER
- 1;
1627 ((is_icon
&& USE_INDEXED_ICON_NAME(fw
)) ||
1628 (!is_icon
&& USE_INDEXED_WINDOW_NAME(fw
))))
1632 ext_name
= (char *)safemalloc(
1633 len
+ MAX_WINDOW_NAME_NUMBER_DIGITS
+ 4);
1634 sprintf(ext_name
,"%s (%d)", name
, count
);
1643 fw
->visible_icon_name
= ext_name
;
1647 fw
->visible_name
= ext_name
;
1653 void setup_window_name(FvwmWindow
*fw
)
1655 if (!EWMH_WMName(fw
, NULL
, NULL
, 0))
1657 fw
->name
.name
= NoName
;
1658 fw
->name
.name_list
= NULL
;
1659 FlocaleGetNameProperty(XGetWMName
, dpy
, FW_W(fw
), &(fw
->name
));
1665 void setup_wm_hints(FvwmWindow
*fw
)
1667 fw
->wmhints
= XGetWMHints(dpy
, FW_W(fw
));
1668 set_focus_model(fw
);
1673 void setup_title_geometry(
1674 FvwmWindow
*fw
, window_style
*pstyle
)
1679 get_title_font_size_and_offset(
1680 fw
, S_TITLE_DIR(SCF(*pstyle
)),
1681 S_IS_LEFT_TITLE_ROTATED_CW(SCF(*pstyle
)),
1682 S_IS_RIGHT_TITLE_ROTATED_CW(SCF(*pstyle
)),
1683 S_IS_TOP_TITLE_ROTATED(SCF(*pstyle
)),
1684 S_IS_BOTTOM_TITLE_ROTATED(SCF(*pstyle
)),
1686 fw
->title_thickness
= width
;
1687 fw
->title_text_offset
= offset
;
1688 fw
->corner_width
= fw
->title_thickness
+ fw
->boundary_width
;
1691 fw
->title_thickness
= 0;
1697 void setup_window_font(
1698 FvwmWindow
*fw
, window_style
*pstyle
, Bool do_destroy
)
1700 /* get rid of old font */
1703 destroy_window_font(fw
);
1704 /* destroy_window_font resets the IS_WINDOW_FONT_LOADED flag */
1707 if (!IS_WINDOW_FONT_LOADED(fw
))
1709 if (S_HAS_WINDOW_FONT(SCF(*pstyle
)) &&
1710 SGET_WINDOW_FONT(*pstyle
) &&
1712 FlocaleLoadFont(dpy
, SGET_WINDOW_FONT(*pstyle
), "fvwm")))
1714 SET_USING_DEFAULT_WINDOW_FONT(fw
, 0);
1718 /* no explicit font or failed to load, use default font
1720 fw
->title_font
= Scr
.DefaultFont
;
1721 SET_USING_DEFAULT_WINDOW_FONT(fw
, 1);
1723 SET_WINDOW_FONT_LOADED(fw
, 1);
1725 setup_title_geometry(fw
, pstyle
);
1730 void setup_icon_font(
1731 FvwmWindow
*fw
, window_style
*pstyle
, Bool do_destroy
)
1735 if (IS_ICON_SUPPRESSED(fw
) || HAS_NO_ICON_TITLE(fw
))
1737 if (IS_ICON_FONT_LOADED(fw
))
1739 destroy_icon_font(fw
);
1740 /* destroy_icon_font resets the IS_ICON_FONT_LOADED
1745 /* get rid of old font */
1746 if (do_destroy
&& IS_ICON_FONT_LOADED(fw
))
1748 destroy_icon_font(fw
);
1749 /* destroy_icon_font resets the IS_ICON_FONT_LOADED flag */
1752 if (!IS_ICON_FONT_LOADED(fw
))
1754 if (S_HAS_ICON_FONT(SCF(*pstyle
)) && SGET_ICON_FONT(*pstyle
) &&
1756 FlocaleLoadFont(dpy
, SGET_ICON_FONT(*pstyle
), "fvwm")))
1758 SET_USING_DEFAULT_ICON_FONT(fw
, 0);
1762 /* no explicit font or failed to load, use default font
1764 fw
->icon_font
= Scr
.DefaultFont
;
1765 SET_USING_DEFAULT_ICON_FONT(fw
, 1);
1767 SET_ICON_FONT_LOADED(fw
, 1);
1769 /* adjust y position of existing icons */
1770 height
= (IS_ICON_FONT_LOADED(fw
)) ? fw
->icon_font
->height
: 0;
1773 resize_icon_title_height(fw
, height
- fw
->icon_font
->height
);
1774 /* this repositions the icon even if the window is not
1776 DrawIconWindow(fw
, True
, True
, False
, False
, NULL
);
1782 void setup_style_and_decor(
1783 FvwmWindow
*fw
, window_style
*pstyle
, short *buttons
)
1785 /* first copy the static styles into the window struct */
1786 memcpy(&(FW_COMMON_FLAGS(fw
)), &(SCF(*pstyle
)),
1787 sizeof(common_flags_t
));
1789 if (FShapesSupported
)
1796 /* suppress compiler warnings w/o shape extension */
1801 FShapeSelectInput(dpy
, FW_W(fw
), FShapeNotifyMask
);
1802 if (FShapeQueryExtents(
1803 dpy
, FW_W(fw
), &boundingShaped
, &i
, &i
, &u
, &u
, &b
,
1806 fw
->wShaped
= boundingShaped
;
1811 /* search for a UseDecor tag in the style */
1812 if (!IS_DECOR_CHANGED(fw
))
1814 FvwmDecor
*decor
= &Scr
.DefaultDecor
;
1816 for (; decor
; decor
= decor
->next
)
1818 if (StrEquals(SGET_DECOR_NAME(*pstyle
), decor
->tag
))
1825 if (fw
->decor
== NULL
)
1827 fw
->decor
= &Scr
.DefaultDecor
;
1834 fw
->buttons
= SIS_BUTTON_DISABLED(&pstyle
->flags
);
1835 SelectDecor(fw
, pstyle
, buttons
);
1837 if (IS_TRANSIENT(fw
) && !pstyle
->flags
.do_decorate_transient
)
1839 SET_HAS_HANDLES(fw
, 0);
1840 SET_HAS_TITLE(fw
, 0);
1842 /* set boundary width to zero for shaped windows */
1843 if (FHaveShapeExtension
)
1847 set_window_border_size(fw
, fw
->unshaped_boundary_width
);
1848 SET_HAS_NO_BORDER(fw
, 1);
1849 SET_HAS_HANDLES(fw
, 0);
1853 /****** window colors ******/
1854 update_window_color_style(fw
, pstyle
);
1855 update_window_color_hi_style(fw
, pstyle
);
1857 /***** icons colorsets *****/
1858 update_icon_title_cs_style(fw
, pstyle
);
1859 update_icon_title_cs_hi_style(fw
, pstyle
);
1860 update_icon_background_cs_style(fw
, pstyle
);
1862 /***** icons title/background parameters ****/
1863 setup_icon_background_parameters(fw
, pstyle
);
1864 setup_icon_title_parameters(fw
, pstyle
);
1866 /****** some numeric values ******/
1867 setup_numeric_vals(fw
, pstyle
);
1869 /****** GNOME style hints ******/
1870 if (!S_DO_IGNORE_GNOME_HINTS(SCF(*pstyle
)))
1872 GNOME_GetStyle(fw
, pstyle
);
1875 /* ConfigureNotify motion method */
1876 if (SCR_MOTION_METHOD(&pstyle
->flag_mask
))
1878 CR_MOTION_METHOD(fw
) = SCR_MOTION_METHOD(&pstyle
->flags
);
1884 void change_icon_boxes(FvwmWindow
*fw
, window_style
*pstyle
)
1886 destroy_icon_boxes(fw
);
1887 setup_icon_boxes(fw
, pstyle
);
1892 void setup_frame_size_limits(FvwmWindow
*fw
, window_style
*pstyle
)
1894 if (SHAS_MIN_WINDOW_SIZE(&pstyle
->flags
))
1896 fw
->min_window_width
= SGET_MIN_WINDOW_WIDTH(*pstyle
);
1897 fw
->min_window_height
= SGET_MIN_WINDOW_HEIGHT(*pstyle
);
1901 fw
->min_window_width
= 0;
1902 fw
->min_window_height
= 0;
1904 if (SHAS_MAX_WINDOW_SIZE(&pstyle
->flags
))
1906 fw
->max_window_width
= SGET_MAX_WINDOW_WIDTH(*pstyle
);
1907 fw
->max_window_height
= SGET_MAX_WINDOW_HEIGHT(*pstyle
);
1911 fw
->max_window_width
= DEFAULT_MAX_MAX_WINDOW_WIDTH
;
1912 fw
->max_window_height
= DEFAULT_MAX_MAX_WINDOW_HEIGHT
;
1918 void setup_placement_penalty(FvwmWindow
*fw
, window_style
*pstyle
)
1920 if (!SHAS_PLACEMENT_PENALTY(&pstyle
->flags
))
1922 pl_penalty_struct
*p
;
1924 p
= SGET_PLACEMENT_PENALTY_PTR(*pstyle
);
1925 *p
= default_pl_penalty
;
1927 if (!SHAS_PLACEMENT_PERCENTAGE_PENALTY(&pstyle
->flags
))
1929 pl_percent_penalty_struct
*p
;
1931 p
= SGET_PLACEMENT_PERCENTAGE_PENALTY_PTR(*pstyle
);
1932 *p
= default_pl_percent_penalty
;
1934 fw
->pl_penalty
= (*pstyle
).pl_penalty
;
1935 fw
->pl_percent_penalty
= (*pstyle
).pl_percent_penalty
;
1940 void setup_frame_attributes(
1941 FvwmWindow
*fw
, window_style
*pstyle
)
1943 XSetWindowAttributes xswa
;
1945 /* Backing_store is controlled on the client, borders, title & buttons
1947 switch (pstyle
->flags
.use_backing_store
)
1949 case BACKINGSTORE_DEFAULT
:
1950 xswa
.backing_store
= fw
->attr_backup
.backing_store
;
1952 case BACKINGSTORE_ON
:
1953 xswa
.backing_store
= Scr
.use_backing_store
;
1955 case BACKINGSTORE_OFF
:
1957 xswa
.backing_store
= NotUseful
;
1960 /* parent_relative is applied to the frame and the parent */
1961 xswa
.background_pixmap
= pstyle
->flags
.use_parent_relative
1962 ? ParentRelative
: None
;
1963 /* Save_under is only useful on the frame */
1964 xswa
.save_under
= pstyle
->flags
.do_save_under
1965 ? Scr
.flags
.do_save_under
: NotUseful
;
1966 XChangeWindowAttributes(dpy
, FW_W(fw
), CWBackingStore
, &xswa
);
1967 XChangeWindowAttributes(
1968 dpy
, FW_W_PARENT(fw
), CWBackPixmap
| CWBackingStore
, &xswa
);
1969 XChangeWindowAttributes(
1970 dpy
, FW_W_FRAME(fw
),
1971 CWBackPixmap
| CWBackingStore
| CWSaveUnder
, &xswa
);
1976 void change_auxiliary_windows(FvwmWindow
*fw
, short buttons
)
1978 unsigned long valuemask_save
= 0;
1979 XSetWindowAttributes attributes
;
1981 get_default_window_attributes(fw
, &valuemask_save
, &attributes
);
1982 change_title_window(fw
, valuemask_save
, &attributes
);
1983 change_button_windows(fw
, valuemask_save
, &attributes
, buttons
);
1984 change_resize_handle_windows(fw
);
1985 setup_frame_stacking(fw
);
1986 XMapSubwindows (dpy
, FW_W_FRAME(fw
));
1991 void increase_icon_hint_count(FvwmWindow
*fw
)
1994 (fw
->wmhints
->flags
& (IconWindowHint
| IconPixmapHint
)))
1996 switch (WAS_ICON_HINT_PROVIDED(fw
))
1998 case ICON_HINT_NEVER
:
1999 SET_WAS_ICON_HINT_PROVIDED(fw
, ICON_HINT_ONCE
);
2001 case ICON_HINT_ONCE
:
2002 SET_WAS_ICON_HINT_PROVIDED(fw
, ICON_HINT_MULTIPLE
);
2004 case ICON_HINT_MULTIPLE
:
2008 ICON_DBG((stderr
,"icon hint count++ (%d) '%s'\n",
2009 (int)WAS_ICON_HINT_PROVIDED(fw
), fw
->name
.name
));
2015 void change_icon(FvwmWindow
*fw
, window_style
*pstyle
)
2018 setup_icon(fw
, pstyle
);
2023 void change_mini_icon(FvwmWindow
*fw
, window_style
*pstyle
)
2025 FvwmPicture
*old_mi
= fw
->mini_icon
;
2026 destroy_mini_icon(fw
);
2027 setup_mini_icon(fw
, pstyle
);
2028 broadcast_mini_icon(fw
);
2029 if (old_mi
!= NULL
&& fw
->mini_icon
== 0)
2031 /* this case is not handled in setup_mini_icon, so we must
2032 * broadcast here explicitly */
2033 BroadcastFvwmPicture(
2034 M_MINI_ICON
, FW_W(fw
), FW_W_FRAME(fw
),
2035 (unsigned long)fw
, NULL
, "");
2041 void setup_focus_policy(FvwmWindow
*fw
)
2043 focus_grab_buttons(fw
);
2048 Bool
validate_transientfor(FvwmWindow
*fw
)
2050 XWindowAttributes wa
;
2054 w
= FW_W_TRANSIENTFOR(fw
);
2055 if (w
== None
|| w
== FW_W(fw
) || w
== IS_EWMH_DESKTOP(w
))
2057 FW_W_TRANSIENTFOR(fw
) = Scr
.Root
;
2060 else if (XFindContext(dpy
, w
, FvwmContext
, (caddr_t
*)&cw
) != XCNOENT
)
2064 /* It's a transient of itself, ignore the hint */
2065 FW_W_TRANSIENTFOR(fw
) = Scr
.Root
;
2068 /* Check for transient loops */
2069 while (XFindContext(
2070 dpy
, FW_W_TRANSIENTFOR(cw
), FvwmContext
,
2071 (caddr_t
*)&cw
) != XCNOENT
&&
2074 if (FW_W_TRANSIENTFOR(cw
) == FW_W(fw
) || cw
== fw
)
2076 /* loop detected, ignore the hint */
2077 FW_W_TRANSIENTFOR(fw
) = Scr
.Root
;
2082 else if (!XGetWindowAttributes(dpy
, w
, &wa
) ||
2083 wa
.map_state
!= IsViewable
)
2085 /* transientfor does not exist or is not viewable or unmapped */
2086 FW_W_TRANSIENTFOR(fw
) = Scr
.Root
;
2093 Bool
setup_transientfor(FvwmWindow
*fw
)
2097 rc
= XGetTransientForHint(dpy
, FW_W(fw
), &FW_W_TRANSIENTFOR(fw
));
2098 SET_TRANSIENT(fw
, rc
);
2101 FW_W_TRANSIENTFOR(fw
) = Scr
.Root
;
2103 validate_transientfor(fw
);
2111 * AddWindow - add a new window to the fvwm list
2114 FvwmWindow
*AddWindow(
2115 const char **ret_initial_map_command
, const exec_context_t
*exc
,
2116 FvwmWindow
*ReuseWin
, initial_window_options_t
* win_opts
)
2118 /* new fvwm window structure */
2119 register FvwmWindow
*fw
;
2121 /* mask for create windows */
2122 unsigned long valuemask
;
2123 /* attributes for create windows */
2124 XSetWindowAttributes attributes
;
2125 XWindowAttributes wattr
;
2126 /* area for merged styles */
2128 /* used for faster access */
2129 style_flags
*sflags
;
2131 Bool used_sm
= False
;
2132 Bool do_resize_too
= False
;
2134 frame_move_resize_args mr_args
;
2135 mwtsm_state_args state_args
;
2136 Window w
= exc
->w
.w
;
2137 const exec_context_t
*exc2
;
2138 exec_context_changes_t ecc
;
2140 /****** init window structure ******/
2141 setup_window_structure(&tmp
, w
, ReuseWin
);
2144 /****** Make sure the client window still exists. We don't want to
2145 * leave an orphan frame window if it doesn't. Since we now have the
2146 * server grabbed, the window can't disappear later without having been
2147 * reparented, so we'll get a DestroyNotify for it. We won't have
2148 * gotten one for anything up to here, however. ******/
2151 dpy
, w
, &JunkRoot
, &JunkX
, &JunkY
,
2152 (unsigned int*)&JunkWidth
, (unsigned int*)&JunkHeight
,
2153 (unsigned int*)&JunkBW
, (unsigned int*)&JunkDepth
) == 0)
2155 if (Scr
.bo
.do_display_new_window_names
)
2157 fvwm_msg(INFO
, "AddWindow", "new window disappeared");
2160 MyXUngrabServer(dpy
);
2164 /****** window name ******/
2165 setup_window_name(fw
);
2166 setup_class_and_resource(fw
);
2168 /****** style setup ******/
2169 __add_window_handle_x_resources(fw
);
2170 /* get merged styles */
2171 lookup_style(fw
, &style
);
2172 sflags
= SGET_FLAGS_POINTER(style
);
2173 if (SIS_UNMANAGED(sflags
))
2175 if (Scr
.bo
.do_display_new_window_names
)
2178 INFO
, "AddWindow", "new window is unmanaged:\n"
2180 " icon name: (unknown)\n"
2183 fw
->name
.name
, fw
->class.res_name
,
2184 fw
->class.res_class
);
2186 free_window_names(fw
, True
, True
);
2189 free(fw
->style_name
);
2192 MyXUngrabServer(dpy
);
2193 return AW_UNMANAGED
;
2196 /****** window attributes and hints ******/
2197 setup_window_attr(fw
, &wattr
);
2200 /****** basic style and decor ******/
2201 /* If the window is in the NoTitle list, or is a transient, dont
2202 * decorate it. If its a transient, and DecorateTransients was
2203 * specified, decorate anyway. */
2204 setup_transientfor(fw
);
2205 if (win_opts
->flags
.is_menu
)
2207 SET_TEAR_OFF_MENU(fw
, 1);
2210 setup_style_and_decor(fw
, &style
, &buttons
);
2212 /****** fonts ******/
2213 setup_window_font(fw
, &style
, False
);
2214 setup_icon_font(fw
, &style
, False
);
2216 /***** visible window name ****/
2217 setup_visible_name(fw
, False
);
2218 EWMH_SetVisibleName(fw
, False
);
2219 if (Scr
.bo
.do_display_new_window_names
)
2222 INFO
, "AddWindow", "new window:\n"
2227 fw
->name
.name
, (fw
->icon_name
.name
== NULL
) ?
2228 "(unknown)" : fw
->icon_name
.name
, fw
->class.res_name
,
2229 fw
->class.res_class
);
2232 /****** InitialMapCommand ******/
2233 *ret_initial_map_command
=
2234 (style
.flags
.has_initial_map_command_string
) ?
2235 SGET_INITIAL_MAP_COMMAND_STRING(style
) : NULL
;
2237 /****** state setup ******/
2238 setup_icon_boxes(fw
, &style
);
2239 SET_ICONIFIED(fw
, 0);
2240 SET_ICON_UNMAPPED(fw
, 0);
2241 SET_MAXIMIZED(fw
, 0);
2243 * Reparenting generates an UnmapNotify event, followed by a MapNotify.
2244 * Set the map state to 0 to prevent a transition back to
2245 * WithdrawnState in HandleUnmapNotify. Map state gets set corrected
2246 * again in HandleMapNotify.
2250 /****** window list and stack ring ******/
2251 /* add the window to the end of the fvwm list */
2252 fw
->next
= Scr
.FvwmRoot
.next
;
2253 fw
->prev
= &Scr
.FvwmRoot
;
2254 while (fw
->next
!= NULL
)
2256 fw
->prev
= fw
->next
;
2257 fw
->next
= fw
->next
->next
;
2259 /* fw->prev points to the last window in the list, fw->next is
2260 * NULL. Now fix the last window to point to fw */
2261 fw
->prev
->next
= fw
;
2263 * RBW - 11/13/1998 - add it into the stacking order chain also.
2264 * This chain is anchored at both ends on Scr.FvwmRoot, there are
2267 add_window_to_stack_ring_after(fw
, &Scr
.FvwmRoot
);
2269 /****** calculate frame size ******/
2270 fw
->hints
.win_gravity
= NorthWestGravity
;
2271 GetWindowSizeHints(fw
);
2273 /****** border width ******/
2274 XSetWindowBorderWidth(dpy
, FW_W(fw
), 0);
2276 /****** icon size limits ******/
2277 setup_icon_size_limits(fw
, &style
);
2279 /***** placement penalities *****/
2280 setup_placement_penalty(fw
, &style
);
2282 * MatchWinToSM changes fw->attr and the stacking order.
2283 * Thus it is important have this call *after* PlaceWindow and the
2284 * stacking order initialization.
2286 get_window_borders(fw
, &b
);
2287 memset(&state_args
, 0, sizeof(state_args
));
2288 used_sm
= MatchWinToSM(fw
, &state_args
, win_opts
);
2291 /* read the requested absolute geometry */
2292 gravity_translate_to_northwest_geometry_no_bw(
2293 fw
->hints
.win_gravity
, fw
, &fw
->g
.normal
,
2296 fw
->hints
.win_gravity
, &fw
->g
.normal
,
2297 b
.total_size
.width
, b
.total_size
.height
);
2298 fw
->g
.frame
= fw
->g
.normal
;
2299 fw
->g
.frame
.x
-= Scr
.Vx
;
2300 fw
->g
.frame
.y
-= Scr
.Vy
;
2302 /****** calculate frame size ******/
2303 setup_frame_size_limits(fw
, &style
);
2305 fw
, NULL
, &fw
->g
.frame
.width
,
2306 &fw
->g
.frame
.height
, 0, 0, 0);
2308 /****** maximize ******/
2309 if (state_args
.do_max
)
2311 SET_MAXIMIZED(fw
, 1);
2313 fw
, NULL
, &fw
->g
.max
.width
, &fw
->g
.max
.height
,
2314 0, 0, CS_UPDATE_MAX_DEFECT
);
2315 get_relative_geometry(&fw
->g
.frame
, &fw
->g
.max
);
2319 get_relative_geometry(&fw
->g
.frame
, &fw
->g
.normal
);
2328 state_args
.do_shade
= 1;
2329 state_args
.used_title_dir_for_shading
=
2330 USED_TITLE_DIR_FOR_SHADING(fw
);
2331 state_args
.shade_dir
= SHADED_DIR(fw
);
2334 /* Tentative size estimate */
2335 fw
->g
.frame
.width
= wattr
.width
+ b
.total_size
.width
;
2336 fw
->g
.frame
.height
= wattr
.height
+ b
.total_size
.height
;
2338 /****** calculate frame size ******/
2339 setup_frame_size_limits(fw
, &style
);
2341 /****** layer ******/
2342 setup_layer(fw
, &style
);
2344 /****** window placement ******/
2347 attr_g
.width
= wattr
.width
;
2348 attr_g
.height
= wattr
.height
;
2349 do_resize_too
= setup_window_placement(
2350 fw
, &style
, &attr_g
, win_opts
, PLACE_INITIAL
);
2354 /* set up geometry */
2355 fw
->g
.frame
.x
= wattr
.x
;
2356 fw
->g
.frame
.y
= wattr
.y
;
2357 fw
->g
.frame
.width
= wattr
.width
+ b
.total_size
.width
;
2358 fw
->g
.frame
.height
= wattr
.height
+ b
.total_size
.height
;
2359 gravity_constrain_size(
2360 fw
->hints
.win_gravity
, fw
, &fw
->g
.frame
, 0);
2361 update_absolute_geometry(fw
);
2364 /****** auxiliary window setup ******/
2365 setup_auxiliary_windows(fw
, True
, buttons
);
2367 /****** 'backing store' and 'save under' window setup ******/
2368 setup_frame_attributes(fw
, &style
);
2370 /****** reparent the window ******/
2371 XReparentWindow(dpy
, FW_W(fw
), FW_W_PARENT(fw
), 0, 0);
2373 /****** select events ******/
2374 valuemask
= CWEventMask
| CWDontPropagate
;
2375 if (IS_TEAR_OFF_MENU(fw
))
2377 attributes
.event_mask
= XEVMASK_TEAR_OFF_MENUW
;
2381 attributes
.event_mask
= XEVMASK_CLIENTW
;
2383 attributes
.do_not_propagate_mask
= ButtonPressMask
| ButtonReleaseMask
;
2384 XChangeWindowAttributes(dpy
, FW_W(fw
), valuemask
, &attributes
);
2385 /****** make sure the window is not destroyed when fvwm dies ******/
2386 if (!IS_TEAR_OFF_MENU(fw
))
2388 /* menus were created by fvwm itself, don't add them to the
2390 XAddToSaveSet(dpy
, FW_W(fw
));
2393 /****** now we can sefely ungrab the server ******/
2394 MyXUngrabServer(dpy
);
2396 /* need to set up the mini icon before drawing */
2397 if (FMiniIconsSupported
)
2399 setup_mini_icon(fw
, &style
);
2402 /****** arrange the frame ******/
2404 if (is_resizing_event_pending(fw
) == True
)
2406 SET_FORCE_NEXT_CR(fw
, 1);
2407 SET_FORCE_NEXT_PN(fw
, 1);
2408 mr_args
= frame_create_move_resize_args(
2409 fw
, FRAME_MR_FORCE_SETUP_NO_W
| FRAME_MR_DONT_DRAW
,
2410 NULL
, &fw
->g
.frame
, 0, DIR_NONE
);
2414 mr_args
= frame_create_move_resize_args(
2415 fw
, FRAME_MR_FORCE_SETUP
| FRAME_MR_DONT_DRAW
, NULL
,
2416 &fw
->g
.frame
, 0, DIR_NONE
);
2418 frame_move_resize(fw
, mr_args
);
2419 frame_free_move_resize_args(fw
, mr_args
);
2421 SET_WAS_NEVER_DRAWN(fw
, 1);
2423 /****** grab keys and buttons ******/
2424 setup_key_and_button_grabs(fw
);
2426 /****** inform modules of new window ******/
2427 BroadcastConfig(M_ADD_WINDOW
,fw
);
2428 BroadcastWindowIconNames(fw
, True
, False
);
2430 /****** place the window in the stack ring ******/
2431 if (!position_new_window_in_stack_ring(fw
, SDO_START_LOWERED(sflags
)))
2434 xwc
.sibling
= FW_W_FRAME(get_next_window_in_stack_ring(fw
));
2435 xwc
.stack_mode
= Above
;
2437 dpy
, FW_W_FRAME(fw
), CWSibling
|CWStackMode
, &xwc
);
2440 /* these are sent and broadcast before res_{class,name} for the benefit
2441 * of FvwmIconBox which can't handle M_ICON_FILE after M_RES_NAME */
2442 /****** icon and mini icon ******/
2443 /* migo (20-Jan-2000): the logic is to unset this flag on NULL values */
2444 SET_WAS_ICON_NAME_PROVIDED(fw
, 1);
2445 setup_icon(fw
, &style
);
2446 if (FMiniIconsSupported
)
2448 broadcast_mini_icon(fw
);
2450 BroadcastName(M_RES_CLASS
,FW_W(fw
),FW_W_FRAME(fw
),
2451 (unsigned long)fw
,fw
->class.res_class
);
2452 BroadcastName(M_RES_NAME
,FW_W(fw
),FW_W_FRAME(fw
),
2453 (unsigned long)fw
,fw
->class.res_name
);
2455 /****** stick window ******/
2456 if (!(fw
->hints
.flags
& USPosition
) || used_sm
)
2461 stick_page
= is_window_sticky_across_pages(fw
);
2462 stick_desk
= is_window_sticky_across_desks(fw
);
2464 !IsRectangleOnThisPage(&fw
->g
.frame
, Scr
.CurrentDesk
)) ||
2465 (stick_desk
&& fw
->Desk
!= Scr
.CurrentDesk
))
2467 /* If it's sticky and the user didn't ask for an
2468 * explicit position, force it on screen now. Don't do
2469 * that with USPosition because we have to assume the
2470 * user knows what (s)he is doing. This is necessary
2471 * e.g. if we want a sticky 'panel' in FvwmButtons but
2472 * don't want to see when it's mapped in the void. */
2474 ecc
.w
.w
= FW_W_FRAME(fw
);
2475 ecc
.w
.wcontext
= C_FRAME
;
2476 exc2
= exc_clone_context(
2477 exc
, &ecc
, ECC_FW
| ECC_W
| ECC_WCONTEXT
);
2478 SET_STICKY_ACROSS_PAGES(fw
, 0);
2479 SET_STICKY_ACROSS_DESKS(fw
, 0);
2481 NULL
, exc2
, "", stick_page
, stick_desk
, 1, 0);
2482 exc_destroy_context(exc2
);
2486 /****** resize window ******/
2491 memset(&e
, 0, sizeof(e
));
2493 dpy
, Scr
.Root
, Scr
.Root
, 0, 0, Scr
.MyDisplayWidth
,
2494 Scr
.MyDisplayHeight
,
2495 fw
->g
.frame
.x
+ (fw
->g
.frame
.width
>>1),
2496 fw
->g
.frame
.y
+ (fw
->g
.frame
.height
>>1));
2497 e
.xany
.type
= ButtonPress
;
2498 e
.xbutton
.button
= 1;
2499 e
.xbutton
.state
= Button1Mask
;
2500 e
.xbutton
.x_root
= fw
->g
.frame
.x
+ (fw
->g
.frame
.width
>>1);
2501 e
.xbutton
.y_root
= fw
->g
.frame
.y
+ (fw
->g
.frame
.height
>>1);
2502 e
.xbutton
.x
= (fw
->g
.frame
.width
>>1);
2503 e
.xbutton
.y
= (fw
->g
.frame
.height
>>1);
2504 e
.xbutton
.subwindow
= None
;
2505 e
.xany
.window
= FW_W(fw
);
2507 ecc
.x
.etrigger
= &e
;
2509 ecc
.w
.wcontext
= C_WINDOW
;
2510 exc2
= exc_clone_context(
2511 exc
, &ecc
, ECC_ETRIGGER
| ECC_FW
| ECC_WCONTEXT
);
2512 CMD_Resize(NULL
, exc2
, "");
2513 exc_destroy_context(exc2
);
2516 /****** window colormap ******/
2517 ReInstallActiveColormap();
2519 /****** ewmh setup *******/
2520 EWMH_WindowInit(fw
);
2522 /****** gnome setup ******/
2523 /* set GNOME hints on the window from flags set on fw */
2527 GNOME_SetWinArea(fw
);
2529 /****** windowshade ******/
2530 if (state_args
.do_shade
|| SDO_START_SHADED(sflags
))
2534 frame_move_resize_args mr_args
;
2536 if (state_args
.used_title_dir_for_shading
)
2538 state_args
.shade_dir
= GET_TITLE_DIR(fw
);
2540 /* If we've set a style for StartShaded, ensure we override
2541 * the state for it here. -- TA.
2543 if (SDO_START_SHADED(sflags
) && !state_args
.do_shade
)
2545 state_args
.shade_dir
= SGET_STARTS_SHADED_DIR(style
);
2547 big_g
= (IS_MAXIMIZED(fw
)) ? fw
->g
.max
: fw
->g
.frame
;
2549 get_shaded_geometry_with_dir(
2550 fw
, &new_g
, &new_g
, state_args
.shade_dir
);
2551 mr_args
= frame_create_move_resize_args(
2552 fw
, FRAME_MR_SHRINK
| FRAME_MR_DONT_DRAW
, &big_g
,
2553 &new_g
, 0, state_args
.shade_dir
);
2554 frame_move_resize(fw
, mr_args
);
2556 SET_SHADED_DIR(fw
, state_args
.shade_dir
);
2557 frame_free_move_resize_args(fw
, mr_args
);
2559 if (!IS_SHADED(fw
) && !IS_ICONIFIED(fw
))
2561 /* TK always wants some special treatment: If the window is
2562 * simply mapped, the tk menus come up at funny Y coordinates.
2563 * Tell it it's geometry *again* to work around this problem.
2565 SendConfigureNotify(
2566 fw
, fw
->g
.frame
.x
, fw
->g
.frame
.y
, fw
->g
.frame
.width
,
2567 fw
->g
.frame
.height
, 0, False
);
2570 HAS_EWMH_INIT_MAXVERT_STATE(fw
) == EWMH_STATE_HAS_HINT
||
2571 HAS_EWMH_INIT_MAXHORIZ_STATE(fw
) == EWMH_STATE_HAS_HINT
)
2578 is_function_allowed(
2579 F_MAXIMIZE
, NULL
, fw
, RQORIG_PROGRAM_US
,
2582 h
= (HAS_EWMH_INIT_MAXHORIZ_STATE(fw
) ==
2583 EWMH_STATE_HAS_HINT
) ? 100 : 0;
2584 v
= (HAS_EWMH_INIT_MAXVERT_STATE(fw
) ==
2585 EWMH_STATE_HAS_HINT
) ? 100 : 0;
2586 sprintf(cmd
,"Maximize on %i %i", h
, v
);
2587 execute_function_override_window(
2588 NULL
, NULL
, cmd
, 0, fw
);
2591 if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw
) == EWMH_STATE_HAS_HINT
)
2593 EWMH_fullscreen(fw
);
2596 dpy
, FW_W(fw
), &JunkRoot
, &JunkX
, &JunkY
,
2597 (unsigned int*)&JunkWidth
, (unsigned int*)&JunkHeight
,
2598 (unsigned int*)&JunkBW
, (unsigned int*)&JunkDepth
))
2600 /* The window has disappeared somehow. For some reason we do
2601 * not always get a DestroyNotify on the window, so make sure
2602 * it is destroyed. */
2614 * FetchWMProtocols - finds out which protocols the window supports
2617 * tmp - the fvwm window structure to use
2620 void FetchWmProtocols(FvwmWindow
*tmp
)
2622 Atom
*protocols
= NULL
, *ap
;
2623 unsigned long *l_protocols
;
2627 unsigned long bytes_remain
,nitems
;
2633 /* First, try the Xlib function to read the protocols.
2634 * This is what Twm uses. */
2635 if (XGetWMProtocols (dpy
, FW_W(tmp
), &protocols
, &n
))
2637 for (i
= 0, ap
= protocols
; i
< n
; i
++, ap
++)
2639 if (*ap
== (Atom
)_XA_WM_TAKE_FOCUS
)
2641 SET_WM_TAKES_FOCUS(tmp
, 1);
2642 set_focus_model(tmp
);
2644 if (*ap
== (Atom
)_XA_WM_DELETE_WINDOW
)
2646 SET_WM_DELETES_WINDOW(tmp
, 1);
2651 XFree((char *)protocols
);
2656 /* Next, read it the hard way. mosaic from Coreldraw needs to
2657 * be read in this way. */
2658 if ((XGetWindowProperty(
2659 dpy
, FW_W(tmp
), _XA_WM_PROTOCOLS
, 0L, 10L, False
,
2660 _XA_WM_PROTOCOLS
, &atype
, &aformat
, &nitems
,
2662 (unsigned char **)&l_protocols
)) == Success
)
2664 for (i
= 0; i
< nitems
; i
++)
2666 ap
= &(l_protocols
[i
]);
2667 if (*ap
== (Atom
)_XA_WM_TAKE_FOCUS
)
2669 SET_WM_TAKES_FOCUS(tmp
, 1);
2670 set_focus_model(tmp
);
2672 if (*ap
== (Atom
)_XA_WM_DELETE_WINDOW
)
2674 SET_WM_DELETES_WINDOW(tmp
, 1);
2679 XFree((char *)protocols
);
2692 * GetWindowSizeHints - gets application supplied size info
2695 * tmp - the fvwm window structure to use
2699 void GetWindowSizeHints(FvwmWindow
*fw
)
2702 char *broken_cause
="";
2703 XSizeHints orig_hints
;
2706 fw
->orig_hints
.width_inc
= 1;
2707 fw
->orig_hints
.height_inc
= 1;
2708 rc
= XGetWMNormalHints(dpy
, FW_W(fw
), &orig_hints
, &supplied
);
2711 fw
->hints
.flags
= 0;
2712 memset(&orig_hints
, 0, sizeof(orig_hints
));
2716 fw
->hints
= orig_hints
;
2717 if (fw
->hints
.flags
& PResizeInc
)
2719 fw
->orig_hints
.width_inc
= fw
->hints
.width_inc
;
2720 fw
->orig_hints
.height_inc
= fw
->hints
.height_inc
;
2722 if (HAS_OVERRIDE_SIZE_HINTS(fw
))
2724 /* ignore the WMNormal hints */
2725 fw
->hints
.flags
&= ~(PMinSize
| PMaxSize
| PResizeInc
);
2726 fw
->hints
.min_width
= 0;
2727 fw
->hints
.min_height
= 0;
2728 fw
->hints
.max_width
= 0;
2729 fw
->hints
.max_height
= 0;
2730 fw
->hints
.width_inc
= 1;
2731 fw
->hints
.height_inc
= 1;
2735 /* Beat up our copy of the hints, so that all important field are
2737 if (fw
->hints
.flags
& PResizeInc
)
2739 SET_SIZE_INC_SET(fw
, 1);
2740 if (fw
->hints
.width_inc
<= 0)
2742 if (fw
->hints
.width_inc
< 0 ||
2743 (fw
->hints
.width_inc
== 0 &&
2744 (fw
->hints
.flags
& PMinSize
) &&
2745 (fw
->hints
.flags
& PMaxSize
) &&
2746 fw
->hints
.min_width
!= fw
->hints
.max_width
))
2748 broken_cause
= "width_inc";
2750 fw
->hints
.width_inc
= 1;
2751 SET_SIZE_INC_SET(fw
, 0);
2753 if (fw
->hints
.height_inc
<= 0)
2755 if (fw
->hints
.height_inc
< 0 ||
2756 (fw
->hints
.height_inc
== 0 &&
2757 (fw
->hints
.flags
& PMinSize
) &&
2758 (fw
->hints
.flags
& PMaxSize
) &&
2759 fw
->hints
.min_height
!= fw
->hints
.max_height
))
2763 broken_cause
= "height_inc";
2766 fw
->hints
.height_inc
= 1;
2767 SET_SIZE_INC_SET(fw
, 0);
2772 SET_SIZE_INC_SET(fw
, 0);
2773 fw
->hints
.width_inc
= 1;
2774 fw
->hints
.height_inc
= 1;
2777 if (fw
->hints
.flags
& PMinSize
)
2779 if (fw
->hints
.min_width
< 0 && !*broken_cause
)
2781 broken_cause
= "min_width";
2783 if (fw
->hints
.min_height
< 0 && !*broken_cause
)
2785 broken_cause
= "min_height";
2790 if (fw
->hints
.flags
& PBaseSize
)
2792 fw
->hints
.min_width
= fw
->hints
.base_width
;
2793 fw
->hints
.min_height
= fw
->hints
.base_height
;
2797 fw
->hints
.min_width
= 1;
2798 fw
->hints
.min_height
= 1;
2801 if (fw
->hints
.min_width
<= 0)
2803 fw
->hints
.min_width
= 1;
2805 if (fw
->hints
.min_height
<= 0)
2807 fw
->hints
.min_height
= 1;
2810 if (fw
->hints
.flags
& PMaxSize
)
2812 if (fw
->hints
.max_width
< fw
->hints
.min_width
)
2814 fw
->hints
.max_width
= DEFAULT_MAX_MAX_WINDOW_WIDTH
;
2817 broken_cause
= "max_width";
2820 if (fw
->hints
.max_height
< fw
->hints
.min_height
)
2822 fw
->hints
.max_height
= DEFAULT_MAX_MAX_WINDOW_HEIGHT
;
2825 broken_cause
= "max_height";
2831 fw
->hints
.max_width
= DEFAULT_MAX_MAX_WINDOW_WIDTH
;
2832 fw
->hints
.max_height
= DEFAULT_MAX_MAX_WINDOW_HEIGHT
;
2836 * ICCCM says that PMinSize is the default if no PBaseSize is given,
2840 if (fw
->hints
.flags
& PBaseSize
)
2842 if (fw
->hints
.base_width
< 0)
2844 fw
->hints
.base_width
= 0;
2847 broken_cause
= "base_width";
2850 if (fw
->hints
.base_height
< 0)
2852 fw
->hints
.base_height
= 0;
2855 broken_cause
= "base_height";
2858 if ((fw
->hints
.base_width
> fw
->hints
.min_width
) ||
2859 (fw
->hints
.base_height
> fw
->hints
.min_height
))
2861 /* In this case, doing the aspect ratio calculation
2862 for window_size - base_size as prescribed by the
2863 ICCCM is going to fail.
2864 Resetting the flag disables the use of base_size
2865 in aspect ratio calculation while it is still used
2868 fw
->hints
.flags
&= ~PBaseSize
;
2870 /* Keep silent about this, since the Xlib manual
2871 * actually recommends making min <= base <= max ! */
2878 if (fw
->hints
.flags
& PMinSize
)
2880 fw
->hints
.base_width
= fw
->hints
.min_width
;
2881 fw
->hints
.base_height
= fw
->hints
.min_height
;
2885 fw
->hints
.base_width
= 0;
2886 fw
->hints
.base_height
= 0;
2890 if (!(fw
->hints
.flags
& PWinGravity
))
2892 fw
->hints
.win_gravity
= NorthWestGravity
;
2895 if ((fw
->hints
.flags
& PMaxSize
) &&
2896 ((fw
->hints
.flags
& PMinSize
) || (fw
->hints
.flags
& PBaseSize
)))
2898 if (fw
->hints
.max_width
< fw
->hints
.base_width
)
2900 fw
->hints
.max_width
= DEFAULT_MAX_MAX_WINDOW_WIDTH
;
2903 broken_cause
= "max_width";
2906 if (fw
->hints
.max_height
< fw
->hints
.base_height
)
2908 fw
->hints
.max_height
= DEFAULT_MAX_MAX_WINDOW_HEIGHT
;
2911 broken_cause
= "max_height";
2916 if (fw
->hints
.flags
& PAspect
)
2919 ** check to make sure min/max aspect ratios look valid
2921 #define maxAspectX fw->hints.max_aspect.x
2922 #define maxAspectY fw->hints.max_aspect.y
2923 #define minAspectX fw->hints.min_aspect.x
2924 #define minAspectY fw->hints.min_aspect.y
2928 ** The math looks like this:
2930 ** minAspectX maxAspectX
2931 ** ---------- <= ----------
2932 ** minAspectY maxAspectY
2934 ** If that is multiplied out, this must be satisfied:
2936 ** minAspectX * maxAspectY <= maxAspectX * minAspectY
2938 ** So, what to do if this isn't met? Ignoring it entirely
2943 /* We also ignore people who put negative entries into
2944 * their aspect ratios. They deserve it.
2946 * We cast to double here, since the values may be large.
2948 if ((maxAspectX
< 0) || (maxAspectY
< 0) ||
2949 (minAspectX
< 0) || (minAspectY
< 0) ||
2950 (((double)minAspectX
* (double)maxAspectY
) >
2951 ((double)maxAspectX
* (double)minAspectY
)))
2955 broken_cause
= "aspect ratio";
2957 fw
->hints
.flags
&= ~PAspect
;
2959 WARN
, "GetWindowSizeHints",
2960 "The applicaton window (window id %#lx)\n"
2961 " \"%s\" has broken aspect ratio: "
2963 " fvwm is ignoring this aspect ratio. ",
2964 FW_W(fw
), fw
->name
.name
, minAspectX
,
2965 minAspectY
, maxAspectX
, maxAspectY
);
2966 fvwm_msg_report_app();
2970 /* protect against overflow */
2971 if ((maxAspectX
> 65536) || (maxAspectY
> 65536))
2974 (double) maxAspectX
/
2975 (double) maxAspectY
;
2979 maxAspectY
= 65536 / ratio
;
2983 maxAspectX
= 65536 * ratio
;
2987 if ((minAspectX
> 65536) || (minAspectY
> 65536))
2990 (double) minAspectX
/
2991 (double) minAspectY
;
2995 minAspectY
= 65536 / ratio
;
2999 minAspectX
= 65536 * ratio
;
3010 if (*broken_cause
!= 0)
3013 WARN
, "GetWindowSizeHints",
3014 "The application window (id %#lx)\n"
3015 " \"%s\" has broken size hints (%s).\n"
3016 " fvwm is ignoring those hints. "
3017 " hint override = %d, flags = %lx\n"
3018 " min_width = %d, min_height = %d, "
3019 "max_width = %d, max_height = %d\n"
3020 " width_inc = %d, height_inc = %d\n"
3021 " min_aspect = %d/%d, max_aspect = %d/%d\n"
3022 " base_width = %d, base_height = %d\n"
3023 " win_gravity = %d\n",
3024 FW_W(fw
), fw
->name
.name
, broken_cause
,
3025 HAS_OVERRIDE_SIZE_HINTS(fw
),
3027 orig_hints
.min_width
, orig_hints
.min_height
,
3028 orig_hints
.max_width
, orig_hints
.max_height
,
3029 orig_hints
.width_inc
, orig_hints
.height_inc
,
3030 orig_hints
.min_aspect
.x
, orig_hints
.min_aspect
.y
,
3031 orig_hints
.max_aspect
.x
, orig_hints
.max_aspect
.y
,
3032 orig_hints
.base_width
, orig_hints
.base_height
,
3033 orig_hints
.win_gravity
);
3034 fvwm_msg_report_app();
3042 * Releases dynamically allocated space used to store window/icon names
3045 void free_window_names(FvwmWindow
*fw
, Bool nukename
, Bool nukeicon
)
3054 if (fw
->visible_name
&& fw
->visible_name
!= fw
->name
.name
&&
3055 fw
->visible_name
!= NoName
)
3057 free(fw
->visible_name
);
3059 fw
->visible_name
= NoName
;
3062 if (fw
->icon_name
.name
== fw
->name
.name
)
3064 fw
->icon_name
.name
= NoName
;
3066 if (fw
->visible_icon_name
== fw
->name
.name
)
3068 fw
->visible_icon_name
= fw
->icon_name
.name
;
3070 if (fw
->name
.name
!= NoName
)
3072 FlocaleFreeNameProperty(&(fw
->name
));
3073 fw
->visible_name
= NULL
;
3079 if (fw
->visible_icon_name
&&
3080 fw
->visible_icon_name
!= fw
->name
.name
&&
3081 fw
->visible_icon_name
!= fw
->icon_name
.name
&&
3082 fw
->visible_icon_name
!= NoName
)
3084 free(fw
->visible_icon_name
);
3086 fw
->visible_icon_name
= NoName
;
3087 if (fw
->icon_name
.name
)
3089 if ((fw
->icon_name
.name
!= fw
->name
.name
) &&
3090 fw
->icon_name
.name
!= NoName
)
3092 FlocaleFreeNameProperty(&(fw
->icon_name
));
3093 fw
->visible_icon_name
= NULL
;
3105 * Handles destruction of a window
3108 void destroy_window(FvwmWindow
*fw
)
3110 /* Warning, this is also called by HandleUnmapNotify; if it ever needs
3111 * to look at the event, HandleUnmapNotify will have to mash the
3112 * UnmapNotify into a DestroyNotify. */
3118 /* remove window style */
3119 if (!IS_SCHEDULED_FOR_DESTROY(fw
) && !DO_REUSE_DESTROYED(fw
))
3123 memset(&s_id
, 0, sizeof(style_id_t
));
3124 SID_SET_WINDOW_ID(s_id
, (XID
)FW_W(fw
));
3125 SID_SET_HAS_WINDOW_ID(s_id
, True
);
3127 style_destroy_style(s_id
);
3130 /****** remove from window list ******/
3131 /* if the window is sheduled fro destroy the window has been already
3132 * removed from list */
3133 if (!IS_SCHEDULED_FOR_DESTROY(fw
))
3135 /* first, remove the window from the list of all windows! */
3136 if (fw
->prev
!= NULL
)
3138 fw
->prev
->next
= fw
->next
;
3140 if (fw
->next
!= NULL
)
3142 fw
->next
->prev
= fw
->prev
;
3147 /****** also remove it from the stack ring ******/
3150 * RBW - 11/13/1998 - new: have to unhook the stacking order
3151 chain also. There's always a prev and next, since this is a
3152 ring anchored on Scr.FvwmRoot
3154 remove_window_from_stack_ring(fw
);
3157 /****** check if we have to delay window destruction ******/
3159 if ((Scr
.flags
.is_executing_complex_function
||
3160 Scr
.flags
.is_executing_menu_function
) &&
3161 !DO_REUSE_DESTROYED(fw
))
3163 if (IS_SCHEDULED_FOR_DESTROY(fw
))
3167 /* mark window for destruction */
3168 SET_SCHEDULED_FOR_DESTROY(fw
, 1);
3169 Scr
.flags
.is_window_scheduled_for_destroy
= 1;
3170 /* this is necessary in case the application destroys the
3171 * client window and a new window is created with the same
3173 delete_client_context(fw
);
3175 /* unmap the the window to fake that it was already removed */
3176 if (IS_ICONIFIED(fw
))
3178 if (FW_W_ICON_TITLE(fw
))
3180 XUnmapWindow(dpy
, FW_W_ICON_TITLE(fw
));
3182 if (FW_W_ICON_PIXMAP(fw
) != None
)
3184 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
3189 XUnmapWindow(dpy
, FW_W_FRAME(fw
));
3191 adjust_fvwm_internal_windows(fw
);
3193 M_DESTROY_WINDOW
, 3, (long)FW_W(fw
),
3194 (long)FW_W_FRAME(fw
), (unsigned long)fw
);
3195 EWMH_DestroyWindow(fw
);
3196 focus_grab_buttons_on_layer(fw
->layer
);
3197 Scr
.FWScheduledForDestroy
= flist_append_obj(
3198 Scr
.FWScheduledForDestroy
, fw
);
3202 /****** unmap the frame ******/
3204 XUnmapWindow(dpy
, FW_W_FRAME(fw
));
3206 /* already done above? */
3207 if (!IS_SCHEDULED_FOR_DESTROY(fw
))
3209 SET_SCHEDULED_FOR_DESTROY(fw
, 1);
3210 adjust_fvwm_internal_windows(fw
);
3212 M_DESTROY_WINDOW
, 3, (long)FW_W(fw
),
3213 (long)FW_W_FRAME(fw
), (unsigned long)fw
);
3214 EWMH_DestroyWindow(fw
);
3216 focus_grab_buttons_on_layer(fw
->layer
);
3218 /****** destroy auxiliary windows ******/
3220 destroy_auxiliary_windows(fw
, True
);
3222 /****** destroy icon ******/
3224 destroy_icon_boxes(fw
);
3227 /****** destroy mini icon ******/
3230 destroy_mini_icon(fw
);
3233 /****** free strings ******/
3235 free_window_names(fw
, True
, True
);
3239 free(fw
->style_name
);
3240 fw
->style_name
= NULL
;
3242 if (fw
->class.res_name
&& fw
->class.res_name
!= NoResource
)
3244 XFree ((char *)fw
->class.res_name
);
3245 fw
->class.res_name
= NoResource
;
3247 if (fw
->class.res_class
&& fw
->class.res_class
!= NoClass
)
3249 XFree ((char *)fw
->class.res_class
);
3250 fw
->class.res_class
= NoClass
;
3254 XFree((char *)fw
->mwm_hints
);
3255 fw
->mwm_hints
= NULL
;
3258 /****** free fonts ******/
3260 destroy_window_font(fw
);
3261 destroy_icon_font(fw
);
3263 /****** free wmhints ******/
3267 XFree ((char *)fw
->wmhints
);
3271 /****** free colormap windows ******/
3273 if (fw
->cmap_windows
!= (Window
*)NULL
)
3275 XFree((void *)fw
->cmap_windows
);
3276 fw
->cmap_windows
= NULL
;
3279 /****** throw away the structure ******/
3281 /* Recapture reuses this struct, so don't free it. */
3282 if (!DO_REUSE_DESTROYED(fw
))
3287 /****** cleanup ******/
3298 * RestoreWithdrawnLocation
3300 * Puts windows back where they were before fvwm took over
3303 void RestoreWithdrawnLocation(
3304 FvwmWindow
*fw
, Bool is_restart_or_recapture
, Window parent
)
3310 rectangle unshaded_g
;
3311 XSetWindowAttributes xswa
;
3318 /* always get the latest size hints in case the application changed
3319 * the gravity and we do not yet know about it */
3321 GetWindowSizeHints(fw
);
3322 SET_HAS_NEW_WM_NORMAL_HINTS(fw
, 0);
3323 get_unshaded_geometry(fw
, &unshaded_g
);
3324 gravity_get_naked_geometry(
3325 fw
->hints
.win_gravity
, fw
, &naked_g
, &unshaded_g
);
3326 gravity_translate_to_northwest_geometry(
3327 fw
->hints
.win_gravity
, fw
, &naked_g
, &naked_g
);
3330 xwc
.width
= naked_g
.width
;
3331 xwc
.height
= naked_g
.height
;
3332 xwc
.border_width
= fw
->attr_backup
.border_width
;
3333 mask
= (CWX
| CWY
| CWWidth
| CWHeight
| CWBorderWidth
);
3335 /* We can not assume that the window is currently on the screen.
3336 * Although this is normally the case, it is not always true. The
3337 * most common example is when the user does something in an
3338 * application which will, after some amount of computational delay,
3339 * cause the window to be unmapped, but then switches screens before
3340 * this happens. The XTranslateCoordinates call above will set the
3341 * window coordinates to either be larger than the screen, or negative.
3342 * This will result in the window being placed in odd, or even
3343 * unviewable locations when the window is remapped. The following
3344 * code forces the "relative" location to be within the bounds of the
3349 * Unfortunately, this does horrendous things during re-starts,
3350 * hence the "if (restart)" clause (RN)
3352 * Also, fixed so that it only does this stuff if a window is more than
3353 * half off the screen. (RN)
3356 if (!is_restart_or_recapture
)
3358 /* Don't mess with it if its partially on the screen now */
3359 if (unshaded_g
.x
< 0 || unshaded_g
.y
< 0 ||
3360 unshaded_g
.x
>= Scr
.MyDisplayWidth
||
3361 unshaded_g
.y
>= Scr
.MyDisplayHeight
)
3363 w2
= (unshaded_g
.width
>> 1);
3364 h2
= (unshaded_g
.height
>> 1);
3365 if ( xwc
.x
< -w2
|| xwc
.x
> Scr
.MyDisplayWidth
- w2
)
3367 xwc
.x
= xwc
.x
% Scr
.MyDisplayWidth
;
3370 xwc
.x
+= Scr
.MyDisplayWidth
;
3373 if (xwc
.y
< -h2
|| xwc
.y
> Scr
.MyDisplayHeight
- h2
)
3375 xwc
.y
= xwc
.y
% Scr
.MyDisplayHeight
;
3378 xwc
.y
+= Scr
.MyDisplayHeight
;
3384 /* restore initial backing store setting on window */
3385 xswa
.backing_store
= fw
->attr_backup
.backing_store
;
3386 XChangeWindowAttributes(dpy
, FW_W(fw
), CWBackingStore
, &xswa
);
3387 /* reparent to root window */
3389 dpy
, FW_W(fw
), (parent
== None
) ? Scr
.Root
: parent
, xwc
.x
,
3392 if (IS_ICONIFIED(fw
) && !IS_ICON_SUPPRESSED(fw
))
3394 if (FW_W_ICON_TITLE(fw
))
3396 XUnmapWindow(dpy
, FW_W_ICON_TITLE(fw
));
3398 if (FW_W_ICON_PIXMAP(fw
))
3400 XUnmapWindow(dpy
, FW_W_ICON_PIXMAP(fw
));
3404 XConfigureWindow(dpy
, FW_W(fw
), mask
, &xwc
);
3405 if (!is_restart_or_recapture
)
3407 /* must be initial capture */
3418 * Reborder - Removes fvwm border windows
3425 /* put a border back around all windows */
3426 MyXGrabServer (dpy
);
3428 /* force reinstall */
3429 InstallWindowColormaps (&Scr
.FvwmRoot
);
3432 * Grab the last window and work backwards: preserve stacking order on
3434 for (fw
= get_prev_window_in_stack_ring(&Scr
.FvwmRoot
);
3435 fw
!= &Scr
.FvwmRoot
; fw
= get_prev_window_in_stack_ring(fw
))
3437 if (!IS_ICONIFIED(fw
) && Scr
.CurrentDesk
!= fw
->Desk
)
3439 XMapWindow(dpy
, FW_W(fw
));
3440 SetMapStateProp(fw
, NormalState
);
3442 RestoreWithdrawnLocation (fw
, True
, Scr
.Root
);
3443 XUnmapWindow(dpy
,FW_W_FRAME(fw
));
3444 XDestroyWindow(dpy
,FW_W_FRAME(fw
));
3447 MyXUngrabServer (dpy
);
3454 void CaptureAllWindows(const exec_context_t
*exc
, Bool is_recapture
)
3457 unsigned int nchildren
;
3458 Window root
, parent
, *children
;
3459 initial_window_options_t win_opts
;
3463 if (!XQueryTree(dpy
, Scr
.Root
, &root
, &parent
, &children
, &nchildren
))
3465 MyXUngrabServer(dpy
);
3468 memset(&win_opts
, 0, sizeof(win_opts
));
3469 win_opts
.flags
.do_override_ppos
= 1;
3470 win_opts
.flags
.is_recapture
= 1;
3471 if (!(Scr
.flags
.are_windows_captured
)) /* initial capture? */
3474 exec_context_changes_t ecc
;
3477 /* weed out icon windows */
3478 for (i
= 0; i
< nchildren
; i
++)
3482 XWMHints
*wmhintsp
= XGetWMHints(
3486 wmhintsp
->flags
& IconWindowHint
)
3488 for (j
= 0; j
< nchildren
; j
++)
3491 wmhintsp
->icon_window
)
3500 XFree ((char *) wmhintsp
);
3504 /* map all of the non-override, non-icon windows */
3505 e
.type
= MapRequest
;
3506 ecc
.x
.etrigger
= &e
;
3507 for (i
= 0; i
< nchildren
; i
++)
3511 MappedNotOverride(children
[i
], &win_opts
))
3513 XUnmapWindow(dpy
, children
[i
]);
3514 e
.xmaprequest
.window
= children
[i
];
3515 e
.xmaprequest
.parent
= Scr
.Root
;
3517 ecc
.w
.w
= children
[i
];
3518 ecc
.w
.wcontext
= C_ROOT
;
3519 ea
.exc
= exc_clone_context(
3520 exc
, &ecc
, ECC_ETRIGGER
| ECC_FW
|
3521 ECC_W
| ECC_WCONTEXT
);
3522 HandleMapRequestKeepRaised(
3523 &ea
, None
, NULL
, &win_opts
);
3524 exc_destroy_context(ea
.exc
);
3527 Scr
.flags
.are_windows_captured
= 1;
3529 else /* must be recapture */
3531 Window keep_on_top_win
;
3536 t
= get_focus_window();
3537 focus_w
= (t
) ? FW_W(t
) : None
;
3538 hide_screen(True
, &keep_on_top_win
, &parent_win
);
3539 /* reborder all windows */
3540 for (i
=0;i
<nchildren
;i
++)
3543 dpy
, children
[i
], FvwmContext
,
3544 (caddr_t
*)&fw
) != XCNOENT
)
3547 exc
, fw
, children
[i
], keep_on_top_win
,
3548 parent_win
, is_recapture
);
3551 hide_screen(False
, NULL
, NULL
);
3552 /* find the window that had the focus and focus it again */
3555 for (t
= Scr
.FvwmRoot
.next
; t
&& FW_W(t
) != focus_w
;
3562 SetFocusWindow(t
, True
, FOCUS_SET_FORCE
);
3568 XFree((char *)children
);
3570 MyXUngrabServer(dpy
);
3575 /* ---------------------------- builtin commands --------------------------- */
3577 void CMD_Recapture(F_CMD_ARGS
)
3579 do_recapture(F_PASS_ARGS
, False
);
3584 void CMD_RecaptureWindow(F_CMD_ARGS
)
3586 do_recapture(F_PASS_ARGS
, True
);