Fix segfault when creating a tearoff menu using a Pixmap background.
[fvwm.git] / fvwm / colormaps.c
blobe91d1213d5c71972aed9ed9864a42bd06d8fcf15
1 /* -*-c-*- */
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
17 /* This module is all new
18 * by Rob Nation
20 * This code handles colormaps for fvwm.
22 * Copyright 1994 Robert Nation. No restrictions are placed on this code,
23 * as long as the copyright notice is preserved . No guarantees or
24 * warrantees of any sort whatsoever are given or implied or anything.
27 /* ---------------------------- included header files ---------------------- */
29 #include "config.h"
31 #include <stdio.h>
33 #include "libs/fvwmlib.h"
34 #include "fvwm.h"
35 #include "externs.h"
36 #include "cursor.h"
37 #include "execcontext.h"
38 #include "eventhandler.h"
39 #include "functions.h"
40 #include "bindings.h"
41 #include "misc.h"
42 #include "screen.h"
43 #include "colormaps.h"
45 /* ---------------------------- local definitions -------------------------- */
47 /* ---------------------------- local macros ------------------------------- */
49 /* ---------------------------- imports ------------------------------------ */
51 /* ---------------------------- included code files ------------------------ */
53 /* ---------------------------- local types -------------------------------- */
55 /* ---------------------------- forward declarations ----------------------- */
57 /* ---------------------------- local variables ---------------------------- */
59 static Bool client_controls_colormaps = False;
60 static Colormap last_cmap = None;
62 /* ---------------------------- exported variables (globals) --------------- */
64 const FvwmWindow *colormap_win;
66 /* ---------------------------- local functions ---------------------------- */
68 /* ---------------------------- interface functions ------------------------ */
70 void set_client_controls_colormaps(Bool flag)
72 client_controls_colormaps = flag;
74 return;
77 /* HandleColormapNotify - colormap notify event handler
79 * This procedure handles both a client changing its own colormap, and
80 * a client explicitly installing its colormap itself (only the window
81 * manager should do that, so we must set it correctly).
83 void colormap_handle_colormap_notify(const evh_args_t *ea)
85 XEvent evdummy;
86 XColormapEvent *cevent = (XColormapEvent *)ea->exc->x.etrigger;
87 Bool ReInstall = False;
88 XWindowAttributes attr;
89 FvwmWindow *fw = ea->exc->w.fw;
91 if (!fw)
93 return;
95 if (cevent->new)
97 if (XGetWindowAttributes(dpy, FW_W(fw), &attr) != 0)
99 fw->attr_backup.colormap = attr.colormap;
100 if (fw == colormap_win &&
101 fw->number_cmap_windows == 0)
103 last_cmap = attr.colormap;
105 ReInstall = True;
108 else if ((cevent->state == ColormapUninstalled)&&
109 (last_cmap == cevent->colormap))
111 /* Some window installed its colormap, change it back */
112 ReInstall = True;
115 while (FCheckTypedEvent(dpy, ColormapNotify, &evdummy))
117 if (XFindContext(
118 dpy, cevent->window, FvwmContext,
119 (caddr_t *) &fw) == XCNOENT)
121 fw = NULL;
123 if ((fw)&&(cevent->new))
125 if (XGetWindowAttributes(dpy, FW_W(fw), &attr) != 0)
127 fw->attr_backup.colormap = attr.colormap;
128 if (fw == colormap_win &&
129 fw->number_cmap_windows == 0)
131 last_cmap = attr.colormap;
133 ReInstall = True;
136 else if ((fw)&&
137 (cevent->state == ColormapUninstalled)&&
138 (last_cmap == cevent->colormap))
140 /* Some window installed its colormap, change it back */
141 ReInstall = True;
143 else if ((fw)&&
144 (cevent->state == ColormapInstalled)&&
145 (last_cmap == cevent->colormap))
147 /* The last color map installed was the correct one.
148 * Do not change anything */
149 ReInstall = False;
153 /* Reinstall the colormap that we think should be installed,
154 * UNLESS and unrecognized window has the focus - it might be
155 * an override-redirect window that has its own colormap. */
156 if (ReInstall && Scr.UnknownWinFocused == None &&
157 !client_controls_colormaps)
159 XInstallColormap(dpy,last_cmap);
162 return;
165 /* Re-Install the active colormap */
166 void ReInstallActiveColormap(void)
168 InstallWindowColormaps(colormap_win);
170 return;
173 /* Procedure:
174 * InstallWindowColormaps - install the colormaps for one fvwm window
176 * Inputs:
177 * type - type of event that caused the installation
178 * tmp - for a subset of event types, the address of the
179 * window structure, whose colormaps are to be installed.
181 void InstallWindowColormaps(const FvwmWindow *fw)
183 int i;
184 XWindowAttributes attributes;
185 Window w;
186 Bool ThisWinInstalled = False;
188 /* If no window, then install fvwm colormap */
189 if (!fw)
191 fw = &Scr.FvwmRoot;
194 colormap_win = fw;
195 /* Save the colormap to be loaded for when force loading of
196 * root colormap(s) ends.
198 Scr.pushed_window = fw;
199 /* Don't load any new colormap if root/fvwm colormap(s) has been
200 * force loaded.
202 if (Scr.root_pushes || Scr.fvwm_pushes || client_controls_colormaps)
204 return;
207 if (fw->number_cmap_windows > 0)
209 for (i=fw->number_cmap_windows -1; i>=0;i--)
211 w = fw->cmap_windows[i];
212 if (w == FW_W(fw))
214 ThisWinInstalled = True;
216 if (!XGetWindowAttributes(dpy,w,&attributes))
218 attributes.colormap = last_cmap;
222 * On Sun X servers, don't install 24 bit TrueColor
223 * colourmaps. Despite what the server says, these
224 * colourmaps are always installed. */
225 if (last_cmap != attributes.colormap
226 #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED)
227 && !(attributes.depth == 24 &&
228 attributes.visual->class == TrueColor)
229 #endif
232 last_cmap = attributes.colormap;
233 XInstallColormap(dpy, last_cmap);
238 if (!ThisWinInstalled)
240 if (last_cmap != fw->attr_backup.colormap
241 #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED)
242 && !(fw->attr_backup.depth == 24 &&
243 fw->attr_backup.visual->class == TrueColor)
244 #endif
247 last_cmap = fw->attr_backup.colormap;
248 XInstallColormap(dpy, last_cmap);
252 return;
256 /* Force (un)loads root colormap(s)
258 * These matching routines provide a mechanism to insure that
259 * the root colormap(s) is installed during operations like
260 * rubber banding that require colors from
261 * that colormap. Calls may be nested arbitrarily deeply,
262 * as long as there is one UninstallRootColormap call per
263 * InstallRootColormap call.
265 * {Uni,I}nstall{Root,Fvwm}Colormap calls may be freely intermixed
267 void InstallRootColormap(void)
269 if (last_cmap != DefaultColormap(dpy, Scr.screen))
271 last_cmap = DefaultColormap(dpy, Scr.screen);
272 XInstallColormap(dpy, last_cmap);
274 Scr.root_pushes++;
276 return;
279 /* Unstacks one layer of root colormap pushing
280 * If we peel off the last layer, re-install the application colormap
281 * or the fvwm colormap if fvwm has a menu posted
283 void UninstallRootColormap(void)
285 if (Scr.root_pushes)
287 Scr.root_pushes--;
290 if (!Scr.root_pushes)
292 if (!Scr.fvwm_pushes)
294 InstallWindowColormaps(Scr.pushed_window);
296 else if (last_cmap != Pcmap)
298 last_cmap = Pcmap;
299 XInstallColormap(dpy, last_cmap);
303 return;
306 /* Procedures:
307 * {Uni/I}nstallFvwmColormap - Force (un)loads fvwm colormap(s)
308 * This is used to ensure the fvwm colormap is installed during
309 * menu operations
311 void InstallFvwmColormap(void)
313 if (last_cmap != Pcmap)
315 last_cmap = Pcmap;
316 XInstallColormap(dpy, last_cmap);
318 Scr.fvwm_pushes++;
320 return;
323 void UninstallFvwmColormap(void)
325 if (Scr.fvwm_pushes)
327 Scr.fvwm_pushes--;
330 if (!Scr.fvwm_pushes)
332 if (!Scr.root_pushes)
334 InstallWindowColormaps(Scr.pushed_window);
336 else if (last_cmap != DefaultColormap(dpy, Scr.screen))
338 last_cmap = DefaultColormap(dpy, Scr.screen);
339 XInstallColormap(dpy, last_cmap);
343 return;
346 /* Gets the WM_COLORMAP_WINDOWS property from the window
348 * This property typically doesn't exist, but a few applications
349 * use it. These seem to occur mostly on SGI machines.
351 void FetchWmColormapWindows (FvwmWindow *fw)
353 XWindowAttributes getattribs;
354 XSetWindowAttributes setattribs;
355 long i;
356 unsigned long valuemask;
358 if (fw->cmap_windows != (Window *)NULL)
360 XFree((void *)fw->cmap_windows);
363 if (!XGetWMColormapWindows (dpy, FW_W(fw), &(fw->cmap_windows),
364 &(fw->number_cmap_windows)))
366 fw->number_cmap_windows = 0;
367 fw->cmap_windows = NULL;
369 /* we need to be notified of Enter events into these subwindows
370 * so we can set their colormaps */
371 if (fw->number_cmap_windows != 0)
373 for (i = 0; i < fw->number_cmap_windows; i++)
375 if (XGetWindowAttributes(
376 dpy, fw->cmap_windows[i], &getattribs))
378 valuemask = CWEventMask;
379 setattribs.event_mask =
380 getattribs.your_event_mask |
381 EnterWindowMask | LeaveWindowMask;
382 XChangeWindowAttributes(
383 dpy, fw->cmap_windows[i], valuemask,
384 &setattribs);
388 return;
391 /* Looks through the window list for any matching COLORMAP_WINDOWS
392 * windows and installs the colormap if one exists.
394 void EnterSubWindowColormap(Window win)
396 FvwmWindow *t;
397 long i;
398 XWindowAttributes attribs;
400 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
402 if (t->number_cmap_windows != 0)
404 for (i = 0; i < t->number_cmap_windows; i++)
406 if (t->cmap_windows[i] == win)
408 if (XGetWindowAttributes(
409 dpy,win,&attribs))
411 last_cmap = attribs.colormap;
412 XInstallColormap(
413 dpy, last_cmap);
415 return;
421 return;
424 void LeaveSubWindowColormap(Window win)
426 FvwmWindow *t;
427 long i;
428 int bWinInList, bParentInList;
430 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
432 if (t->number_cmap_windows != 0)
434 bWinInList = 0;
435 bParentInList = 0;
436 for (i=0;i<t->number_cmap_windows;i++)
438 if (t->cmap_windows[i] == win)
440 bWinInList = 1;
442 if (t->cmap_windows[i] == FW_W(t))
444 bParentInList = 1;
447 if (bWinInList)
449 if (bParentInList)
451 InstallWindowColormaps(t);
453 else
455 InstallWindowColormaps(NULL);
457 return;
462 return;