13 /* GData of GSList*'s of PointerBinding*'s. */
14 static GData
*bound_contexts
;
16 static gboolean grabbed
;
18 struct mbind_foreach_grab_temp
{
29 static gboolean
translate(char *str
, guint
*state
, guint
*button
)
36 parsed
= g_strsplit(str
, "-", -1);
38 /* first, find the button (last token) */
40 for (i
= 0; parsed
[i
] != NULL
; ++i
)
43 goto translation_fail
;
45 /* figure out the mod mask */
47 for (i
= 0; parsed
[i
] != l
; ++i
) {
48 guint m
= kbind_translate_modifier(parsed
[i
]);
49 if (!m
) goto translation_fail
;
53 /* figure out the button */
56 g_warning("Invalid button '%s' in pointer binding.", l
);
57 goto translation_fail
;
67 void grab_button(Client
*client
, guint state
, guint button
, GQuark context
,
71 int mode
= GrabModeAsync
;
74 if (context
== g_quark_try_string("frame")) {
75 win
= client
->frame
->window
;
76 mask
= ButtonPressMask
| ButtonMotionMask
| ButtonReleaseMask
;
77 } else if (context
== g_quark_try_string("client")) {
78 win
= client
->frame
->plate
;
79 mode
= GrabModeSync
; /* this is handled in mbind_fire */
80 mask
= ButtonPressMask
; /* can't catch more than this with Sync mode
81 the release event is manufactured in
86 XGrabButton(ob_display
, button
, state
, win
, FALSE
, mask
, mode
,
87 GrabModeAsync
, None
, None
);
89 XUngrabButton(ob_display
, button
, state
, win
);
92 static void mbind_foreach_grab(GQuark key
, gpointer data
, gpointer user_data
)
94 struct mbind_foreach_grab_temp
*d
= user_data
;
95 PointerBinding
*b
= ((GSList
*)data
)->data
;
97 grab_button(d
->client
, b
->state
, b
->button
, key
, d
->grab
);
100 void mbind_grab_all(Client
*client
, gboolean grab
)
102 struct mbind_foreach_grab_temp bt
;
105 g_datalist_foreach(&bound_contexts
, mbind_foreach_grab
, &bt
);
108 void grab_all_clients(gboolean grab
)
112 for (it
= client_list
; it
!= NULL
; it
= it
->next
)
113 mbind_grab_all(it
->data
, grab
);
119 g_datalist_init(&bound_contexts
);
122 void mbind_shutdown()
125 mbind_grab_pointer(FALSE
);
127 g_datalist_clear(&bound_contexts
);
130 gboolean
mbind_add(char *name
, GQuark context
)
136 if (!translate(name
, &state
, &button
))
139 for (it
= g_datalist_id_get_data(&bound_contexts
, context
);
140 it
!= NULL
; it
= it
->next
){
142 if (b
->state
== state
&& b
->button
== button
)
143 return TRUE
; /* already bound */
146 grab_all_clients(FALSE
);
148 /* add the binding */
149 b
= g_new(PointerBinding
, 1);
152 b
->name
= g_strdup(name
);
153 g_datalist_id_set_data(&bound_contexts
, context
,
154 g_slist_append(g_datalist_id_get_data(&bound_contexts
, context
), b
));
155 grab_all_clients(TRUE
);
160 static void mbind_foreach_clear(GQuark key
, gpointer data
, gpointer user_data
)
163 user_data
= user_data
;
164 for (it
= data
; it
!= NULL
; it
= it
->next
) {
165 PointerBinding
*b
= it
->data
;
171 void mbind_clearall()
173 grab_all_clients(FALSE
);
174 g_datalist_foreach(&bound_contexts
, mbind_foreach_clear
, NULL
);
177 void mbind_fire(guint state
, guint button
, GQuark context
, EventType type
,
178 Client
*client
, int xroot
, int yroot
)
184 data
= eventdata_new_pointer(type
, context
, client
, state
, button
,
186 g_assert(data
!= NULL
);
187 hooks_fire_pointer(data
);
188 eventdata_free(data
);
192 for (it
= g_datalist_id_get_data(&bound_contexts
, context
);
193 it
!= NULL
; it
= it
->next
){
194 PointerBinding
*b
= it
->data
;
195 if (b
->state
== state
&& b
->button
== button
) {
197 data
= eventdata_new_pointer(type
, context
, client
, state
, button
,
198 b
->name
, xroot
, yroot
);
199 g_assert(data
!= NULL
);
201 eventdata_free(data
);
207 gboolean
mbind_grab_pointer(gboolean grab
)
211 ret
= XGrabPointer(ob_display
, ob_root
, FALSE
, (ButtonPressMask
|
215 GrabModeAsync
, GrabModeAsync
, None
, None
,
216 CurrentTime
) == GrabSuccess
;
218 XUngrabPointer(ob_display
, CurrentTime
);