1 /*
2  * Copyright (C) 1993 Rob Nation
3  * Copyright (C) 1995 Bo Yang
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  */
20 
21 /**************************************************************************
22  *
23  * Assorted odds and ends
24  *
25  **************************************************************************/
26 #define LOCAL_DEBUG
27 
28 #include "../../configure.h"
29 
30 #include "asinternals.h"
31 
32 /****************************************************************************/
33 /* window management specifics - button ungrabbing convinience functions:   */
34 /****************************************************************************/
ungrab_window_buttons(Window w)35 inline void ungrab_window_buttons (Window w)
36 {
37 	LOCAL_DEBUG_OUT ("w = %lX", w);
38 	XUngrabButton (dpy, AnyButton, AnyModifier, w);
39 }
40 
ungrab_window_keys(Window w)41 inline void ungrab_window_keys (Window w)
42 {
43 	XUngrabKey (dpy, AnyKey, AnyModifier, w);
44 }
45 
46 /******************************************************************************
47  * Versions of grab primitives that circumvent modifier problems
48  *****************************************************************************/
49 void
MyXGrabButton(unsigned button,unsigned modifiers,Window grab_window,Bool owner_events,unsigned event_mask,int pointer_mode,int keyboard_mode,Window confine_to,Cursor cursor)50 MyXGrabButton (unsigned button, unsigned modifiers,
51 							 Window grab_window, Bool owner_events, unsigned event_mask,
52 							 int pointer_mode, int keyboard_mode, Window confine_to,
53 							 Cursor cursor)
54 {
55 	LOCAL_DEBUG_CALLER_OUT ("button = %d, w = %lX modifiers = %X", button,
56 													grab_window, modifiers);
57 	if (modifiers == AnyModifier)
58 		XGrabButton (dpy, button, AnyModifier, grab_window,
59 								 owner_events, event_mask, pointer_mode, keyboard_mode,
60 								 confine_to, cursor);
61 	else {
62 		register int i = 0;
63 		do {
64 /*			LOCAL_DEBUG_OUT( "grabbing button %d with mod %lX on window %lX", button, modifiers | lock_mods[i], grab_window ); */
65 			XGrabButton (dpy, button, modifiers | lock_mods[i], grab_window,
66 									 owner_events, event_mask, pointer_mode, keyboard_mode,
67 									 confine_to, cursor);
68 			if (lock_mods[i] == 0)
69 				break;
70 		} while (++i < MAX_LOCK_MODS);
71 	}
72 }
73 
74 void
MyXUngrabButton(unsigned button,unsigned modifiers,Window grab_window)75 MyXUngrabButton (unsigned button, unsigned modifiers, Window grab_window)
76 {
77 	LOCAL_DEBUG_CALLER_OUT ("w = %lX", grab_window);
78 	if (modifiers == AnyModifier)
79 		XUngrabButton (dpy, button, AnyModifier, grab_window);
80 	else {
81 		register int i = 0;
82 		do {
83 			XUngrabButton (dpy, button, modifiers | lock_mods[i], grab_window);
84 			if (lock_mods[i] == 0)
85 				break;
86 		} while (++i < MAX_LOCK_MODS);
87 	}
88 }
89 
grab_window_buttons(Window w,ASFlagType context_mask)90 void grab_window_buttons (Window w, ASFlagType context_mask)
91 {
92 	register MouseButton *MouseEntry;
93 	LOCAL_DEBUG_OUT ("w = %lX, context = 0x%lX", w, context_mask);
94 	for (MouseEntry = Scr.Feel.MouseButtonRoot; MouseEntry;
95 			 MouseEntry = MouseEntry->NextButton) {
96 		if (MouseEntry->fdata && get_flags (MouseEntry->Context, context_mask)) {
97 			LOCAL_DEBUG_OUT
98 					("mouse fdata %p button %d + modifier %X has context %lx",
99 					 MouseEntry->fdata, MouseEntry->Button, MouseEntry->Modifier,
100 					 get_flags (MouseEntry->Context, context_mask));
101 			if (MouseEntry->Button > 0)
102 				MyXGrabButton (MouseEntry->Button, MouseEntry->Modifier, w,
103 											 True, ButtonPressMask | ButtonReleaseMask,
104 											 GrabModeAsync, GrabModeAsync, None,
105 											 Scr.Feel.cursors[ASCUR_Default]);
106 			else {
107 				register int i = MAX_MOUSE_BUTTONS + 1;
108 				while (--i > 0)
109 					MyXGrabButton (i, MouseEntry->Modifier, w,
110 												 True, ButtonPressMask | ButtonReleaseMask,
111 												 GrabModeAsync, GrabModeAsync, None,
112 												 Scr.Feel.cursors[ASCUR_Default]);
113 			}
114 		}
115 	}
116 }
117 
118 
grab_focus_click(Window w)119 void grab_focus_click (Window w)
120 {
121 	int i;
122 	LOCAL_DEBUG_CALLER_OUT ("w = %lX", w);
123 	if (w) {											/* need to grab all buttons for window that we are about to unfocus */
124 		for (i = 0; i < MAX_MOUSE_BUTTONS; i++)
125 			if (Scr.Feel.buttons2grab & (0x01 << i)) {
126 				MyXGrabButton (i + 1, 0, w, True, ButtonPressMask, GrabModeSync,
127 											 GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Sys]);
128 			}
129 	}
130 }
131 
ungrab_focus_click(Window w)132 void ungrab_focus_click (Window w)
133 {
134 	LOCAL_DEBUG_CALLER_OUT ("w = %lX", w);
135 	if (w) {											/* if we do click to focus, remove the grab on mouse events that
136 																 * was made to detect the focus change */
137 		register int i = 0;
138 #if 0
139 		register ASFlagType grab_btn_mask = Scr.Feel.buttons2grab << 1;
140 		while (++i <= MAX_MOUSE_BUTTONS)
141 			if (grab_btn_mask & (1 << i)) {
142 				MyXUngrabButton (i, 0, w);
143 			}
144 #else
145 		for (i = 0; i < MAX_MOUSE_BUTTONS; i++)
146 			if (Scr.Feel.buttons2grab & (0x01 << i)) {
147 				MyXUngrabButton (i + 1, 0, w);
148 			}
149 #endif
150 	}
151 }
152 
153 
154 /***********************************************************************
155  * Key grabbing :
156  ***********************************************************************/
grab_window_keys(Window w,ASFlagType context_mask)157 void grab_window_keys (Window w, ASFlagType context_mask)
158 {
159 	FuncKey *tmp;
160 	for (tmp = Scr.Feel.FuncKeyRoot; tmp != NULL; tmp = tmp->next)
161 		if (get_flags (tmp->cont, context_mask)) {
162 			if (tmp->mods == AnyModifier)
163 				XGrabKey (dpy, tmp->keycode, AnyModifier, w, True, GrabModeAsync,
164 									GrabModeAsync);
165 			else {
166 				register int i = 0;
167 				do {										/* combining modifiers with <Lock> keys,
168 																 * so to enable things like ScrollLock+Alt+A to work the same as Alt+A */
169 					XGrabKey (dpy, tmp->keycode, tmp->mods | lock_mods[i], w, True,
170 										GrabModeAsync, GrabModeAsync);
171 					if (lock_mods[i] == 0)
172 						break;
173 				} while (++i < MAX_LOCK_MODS);
174 			}
175 		}
176 }
177 
178 
179 
180 /******************************************************************************
181  *
182  * Grab ClickToRaise button press events for a window
183  *
184  *****************************************************************************/
GrabRaiseClick(ASWindow * t)185 void GrabRaiseClick (ASWindow * t)
186 {
187 	int b;
188 
189 	for (b = 1; b <= MAX_MOUSE_BUTTONS; b++) {
190 		if (Scr.Feel.RaiseButtons & (1 << b))
191 			MyXGrabButton (b, 0, t->w, True, ButtonPressMask, GrabModeSync,
192 										 GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Title]);
193 	}
194 }
195 
196 /******************************************************************************
197  *
198  * Ungrab ClickToRaise button press events to allow their use in applications
199  *
200  *****************************************************************************/
UngrabRaiseClick(ASWindow * t)201 void UngrabRaiseClick (ASWindow * t)
202 {
203 	int b;
204 
205 	for (b = 1; b <= MAX_MOUSE_BUTTONS; b++) {
206 		if (Scr.Feel.RaiseButtons & (1 << b))
207 			MyXUngrabButton (b, 0, t->w);
208 	}
209 }
210 
211 /******************************************************************************
212  *
213  * Recalculate the visibility flags
214  *
215  *****************************************************************************/
216 
UpdateVisibility(void)217 void UpdateVisibility (void)
218 {
219 #if 0
220 	ASWindow *t, *s, *tbase;
221 
222 	tbase = Scr.ASRoot.next;
223 	for (t = Scr.ASRoot.next; t != NULL; t = t->next) {
224 		int visible = 0;
225 		int tx1, ty1, tx2, ty2;
226 
227 		if (t->flags & MAPPED) {
228 			tx1 = t->frame_x;
229 			ty1 = t->frame_y;
230 			if (t->flags & SHADED) {
231 				tx2 = t->frame_x + t->title_width;
232 				ty2 = t->frame_y + t->title_height;
233 			} else {
234 				tx2 = t->frame_x + t->frame_width;
235 				ty2 = t->frame_y + t->frame_height;
236 			}
237 		} else if (t->flags & ICONIFIED) {
238 			tx1 = t->icon_p_x;
239 			ty1 = t->icon_p_y;
240 			tx2 = t->icon_p_x + t->icon_p_width;
241 			ty2 = t->icon_p_y + t->icon_p_height;
242 		} else
243 			continue;
244 
245 		if ((tx2 > 0) && (tx1 < Scr.MyDisplayWidth) && (ty2 > 0)
246 				&& (ty1 < Scr.MyDisplayHeight)) {
247 			visible = VISIBLE;
248 			for (s = Scr.ASRoot.next; s != t; s = s->next) {
249 				if (get_flags (s->hints->flags, AS_Transient)
250 						&& (s->hints->transient_for == t->w))
251 					continue;
252 				else if (s->status->layer != t->status->layer)
253 					continue;
254 
255 				if (s->flags & MAPPED) {
256 					if ((tx2 > s->frame_x) && (tx1 < s->frame_x + s->frame_width) &&
257 							(ty2 > s->frame_y) && (ty1 < s->frame_y + s->frame_height)) {
258 						visible = 0;
259 						break;
260 					}
261 				} else if (s->flags & ICONIFIED) {
262 					if ((tx2 > s->icon_p_x) && (tx1 < s->icon_p_x + s->icon_p_width)
263 							&& (ty2 > s->icon_p_y)
264 							&& (ty1 < s->icon_p_y + s->icon_p_height)) {
265 						visible = 0;
266 						break;
267 					}
268 				} else if (s->flags & SHADED) {
269 					if ((tx2 > s->frame_x) && (tx1 < s->frame_x + s->title_width) &&
270 							(ty2 > s->frame_y) && (ty1 < s->frame_y + s->title_height)) {
271 						visible = 0;
272 						break;
273 					}
274 				}
275 			}
276 		}
277 		if ((t->flags & VISIBLE) != visible) {
278 			t->flags ^= VISIBLE;
279 			if ((Scr.flags & ClickToRaise) && !(Scr.flags & ClickToFocus)
280 					&& (t->flags & MAPPED)) {
281 				if (visible)
282 					UngrabRaiseClick (t);
283 				else
284 					GrabRaiseClick (t);
285 			}
286 		}
287 	}
288 #endif
289 }
290