+
+gboolean prompt_key_event(ObPrompt *self, XEvent *e)
+{
+ gboolean shift;
+ guint shift_mask;
+
+ if (e->type != KeyPress) return FALSE;
+
+ shift_mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT);
+ shift = !!(e->xkey.state & shift_mask);
+
+ /* only accept shift */
+ if (e->xkey.state != 0 && e->xkey.state != shift_mask)
+ return FALSE;
+
+ if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
+ prompt_cancel(self);
+ else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) ||
+ e->xkey.keycode == ob_keycode(OB_KEY_SPACE))
+ {
+ if (self->func) self->func(self, self->focus->result, self->data);
+ prompt_hide(self);
+ }
+ else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) ||
+ e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
+ e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
+ {
+ gint i;
+ gboolean left;
+ ObPromptElement *oldfocus;
+
+ left = e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
+ (e->xkey.keycode == ob_keycode(OB_KEY_TAB) && shift);
+ oldfocus = self->focus;
+
+ for (i = 0; i < self->n_buttons; ++i)
+ if (self->focus == &self->button[i]) break;
+ i += (left ? -1 : 1);
+ if (i < 0) i = self->n_buttons - 1;
+ else if (i >= self->n_buttons) i = 0;
+ self->focus = &self->button[i];
+
+ if (oldfocus != self->focus) render_button(self, oldfocus);
+ render_button(self, self->focus);
+ }
+ return TRUE;
+}
+
+gboolean prompt_mouse_event(ObPrompt *self, XEvent *e)
+{
+ gint i;
+ ObPromptElement *but;
+
+ if (e->type != ButtonPress && e->type != ButtonRelease &&
+ e->type != MotionNotify) return FALSE;
+
+ /* find the button */
+ but = NULL;
+ for (i = 0; i < self->n_buttons; ++i)
+ if (self->button[i].window ==
+ (e->type == MotionNotify ? e->xmotion.window : e->xbutton.window))
+ {
+ but = &self->button[i];
+ break;
+ }
+ if (!but) return FALSE;
+
+ if (e->type == ButtonPress) {
+ ObPromptElement *oldfocus;
+
+ oldfocus = self->focus;
+
+ but->pressed = TRUE;
+ self->focus = but;
+
+ if (oldfocus != but) render_button(self, oldfocus);
+ render_button(self, but);
+ }
+ else if (e->type == ButtonRelease) {
+ if (but->pressed) {
+ if (self->func) self->func(self, but->result, self->data);
+ prompt_hide(self);
+ }
+ }
+ else if (e->type == MotionNotify) {
+ gboolean press;
+
+ press = (e->xmotion.x >= 0 && e->xmotion.y >= 0 &&
+ e->xmotion.x < but->width && e->xmotion.y < but->height);
+
+ if (press != but->pressed) {
+ but->pressed = press;
+ render_button(self, but);
+ }
+ }
+ return TRUE;
+}
+
+void prompt_cancel(ObPrompt *self)
+{
+ if (self->func) self->func(self, self->cancel_result, self->data);
+ prompt_hide(self);
+}