Don't handle input events on prompts if they should be used for a binding/menu instead.
Also, be more careful about making the prompt buttons look pressed, don't make them pressed from a motion notify event if they didnt first handle the press.
This commit is contained in:
parent
73575c10ce
commit
3368b91d54
7 changed files with 80 additions and 65 deletions
|
@ -90,7 +90,7 @@ static gboolean event_handle_prompt(ObPrompt *p, XEvent *e);
|
|||
static void event_handle_dock(ObDock *s, XEvent *e);
|
||||
static void event_handle_dockapp(ObDockApp *app, XEvent *e);
|
||||
static void event_handle_client(ObClient *c, XEvent *e);
|
||||
static void event_handle_user_input(ObClient *client, XEvent *e);
|
||||
static gboolean event_handle_user_input(ObClient *client, XEvent *e);
|
||||
static gboolean is_enter_focus_event_ignored(gulong serial);
|
||||
static void event_ignore_enter_range(gulong start, gulong end);
|
||||
|
||||
|
@ -472,6 +472,7 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
ObWindow *obwin = NULL;
|
||||
ObMenuFrame *menu = NULL;
|
||||
ObPrompt *prompt = NULL;
|
||||
gboolean used;
|
||||
|
||||
/* make a copy we can mangle */
|
||||
ee = *ec;
|
||||
|
@ -717,15 +718,13 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (prompt && event_handle_prompt(prompt, e))
|
||||
;
|
||||
else if (e->type == ButtonPress || e->type == ButtonRelease) {
|
||||
if (e->type == ButtonPress || e->type == ButtonRelease) {
|
||||
/* If the button press was on some non-root window, or was physically
|
||||
on the root window, then process it */
|
||||
if (window != obt_root(ob_screen) ||
|
||||
e->xbutton.subwindow == None)
|
||||
{
|
||||
event_handle_user_input(client, e);
|
||||
used = event_handle_user_input(client, e);
|
||||
}
|
||||
/* Otherwise only process it if it was physically on an openbox
|
||||
internal window */
|
||||
|
@ -735,13 +734,16 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
if ((w = window_find(e->xbutton.subwindow)) &&
|
||||
WINDOW_IS_INTERNAL(w))
|
||||
{
|
||||
event_handle_user_input(client, e);
|
||||
used = event_handle_user_input(client, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e->type == KeyPress || e->type == KeyRelease ||
|
||||
e->type == MotionNotify)
|
||||
event_handle_user_input(client, e);
|
||||
used = event_handle_user_input(client, e);
|
||||
|
||||
if (prompt && !used)
|
||||
used = event_handle_prompt(prompt, e);
|
||||
|
||||
/* if something happens and it's not from an XEvent, then we don't know
|
||||
the time */
|
||||
|
@ -1955,7 +1957,7 @@ static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
|
|||
}
|
||||
}
|
||||
|
||||
static void event_handle_user_input(ObClient *client, XEvent *e)
|
||||
static gboolean event_handle_user_input(ObClient *client, XEvent *e)
|
||||
{
|
||||
g_assert(e->type == ButtonPress || e->type == ButtonRelease ||
|
||||
e->type == MotionNotify || e->type == KeyPress ||
|
||||
|
@ -1966,29 +1968,32 @@ static void event_handle_user_input(ObClient *client, XEvent *e)
|
|||
/* don't use the event if the menu used it, but if the menu
|
||||
didn't use it and it's a keypress that is bound, it will
|
||||
close the menu and be used */
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* if the keyboard interactive action uses the event then dont
|
||||
use it for bindings. likewise is moveresize uses the event. */
|
||||
if (!actions_interactive_input_event(e) && !moveresize_event(e)) {
|
||||
if (moveresize_in_progress)
|
||||
/* make further actions work on the client being
|
||||
moved/resized */
|
||||
client = moveresize_client;
|
||||
if (actions_interactive_input_event(e) || moveresize_event(e))
|
||||
return TRUE;
|
||||
|
||||
if (e->type == ButtonPress ||
|
||||
e->type == ButtonRelease ||
|
||||
e->type == MotionNotify)
|
||||
{
|
||||
/* the frame may not be "visible" but they can still click on it
|
||||
in the case where it is animating before disappearing */
|
||||
if (!client || !frame_iconify_animating(client->frame))
|
||||
mouse_event(client, e);
|
||||
} else
|
||||
keyboard_event((focus_cycle_target ? focus_cycle_target :
|
||||
(client ? client : focus_client)), e);
|
||||
}
|
||||
if (moveresize_in_progress)
|
||||
/* make further actions work on the client being
|
||||
moved/resized */
|
||||
client = moveresize_client;
|
||||
|
||||
if (e->type == ButtonPress ||
|
||||
e->type == ButtonRelease ||
|
||||
e->type == MotionNotify)
|
||||
{
|
||||
/* the frame may not be "visible" but they can still click on it
|
||||
in the case where it is animating before disappearing */
|
||||
if (!client || !frame_iconify_animating(client->frame))
|
||||
return mouse_event(client, e);
|
||||
} else
|
||||
return keyboard_event((focus_cycle_target ? focus_cycle_target :
|
||||
(client ? client : focus_client)), e);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void focus_delay_dest(gpointer data)
|
||||
|
|
|
@ -204,13 +204,14 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client)
|
|||
}
|
||||
#endif
|
||||
|
||||
void keyboard_event(ObClient *client, const XEvent *e)
|
||||
gboolean keyboard_event(ObClient *client, const XEvent *e)
|
||||
{
|
||||
KeyBindingTree *p;
|
||||
gboolean used;
|
||||
|
||||
if (e->type == KeyRelease) {
|
||||
grab_key_passive_count(-1);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert(e->type == KeyPress);
|
||||
|
@ -221,9 +222,10 @@ void keyboard_event(ObClient *client, const XEvent *e)
|
|||
{
|
||||
obt_main_loop_timeout_remove(ob_main_loop, chain_timeout);
|
||||
keyboard_reset_chains(-1);
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
used = FALSE;
|
||||
if (curpos == NULL)
|
||||
p = keyboard_firstnode;
|
||||
else
|
||||
|
@ -258,9 +260,11 @@ void keyboard_event(ObClient *client, const XEvent *e)
|
|||
0, OB_FRAME_CONTEXT_NONE, client);
|
||||
}
|
||||
break;
|
||||
used = TRUE;
|
||||
}
|
||||
p = p->next_sibling;
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
static void node_rebind(KeyBindingTree *node)
|
||||
|
|
|
@ -40,7 +40,7 @@ void keyboard_chroot(GList *keylist);
|
|||
gboolean keyboard_bind(GList *keylist, struct _ObActionsAct *action);
|
||||
void keyboard_unbind_all(void);
|
||||
|
||||
void keyboard_event(struct _ObClient *client, const XEvent *e);
|
||||
gboolean keyboard_event(struct _ObClient *client, const XEvent *e);
|
||||
/*! @param break_chroots how many chroots to break. -1 means to break them ALL!
|
||||
*/
|
||||
void keyboard_reset_chains(gint break_chroots);
|
||||
|
|
|
@ -205,12 +205,13 @@ void mouse_replay_pointer(void)
|
|||
}
|
||||
}
|
||||
|
||||
void mouse_event(ObClient *client, XEvent *e)
|
||||
gboolean mouse_event(ObClient *client, XEvent *e)
|
||||
{
|
||||
static Time ltime;
|
||||
static guint button = 0, state = 0, lbutton = 0;
|
||||
static Window lwindow = None;
|
||||
static gint px, py, pwx = -1, pwy = -1;
|
||||
gboolean used = FALSE;
|
||||
|
||||
ObFrameContext context;
|
||||
gboolean click = FALSE;
|
||||
|
@ -246,10 +247,10 @@ void mouse_event(ObClient *client, XEvent *e)
|
|||
if (CLIENT_CONTEXT(context, client))
|
||||
replay_pointer_needed = TRUE;
|
||||
|
||||
fire_binding(OB_MOUSE_ACTION_PRESS, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root, e->xbutton.y_root);
|
||||
used = fire_binding(OB_MOUSE_ACTION_PRESS, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root, e->xbutton.y_root) || used;
|
||||
|
||||
/* if the bindings grab the pointer, there won't be a ButtonRelease
|
||||
event for us */
|
||||
|
@ -311,23 +312,23 @@ void mouse_event(ObClient *client, XEvent *e)
|
|||
state = 0;
|
||||
ltime = e->xbutton.time;
|
||||
}
|
||||
fire_binding(OB_MOUSE_ACTION_RELEASE, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root);
|
||||
used = fire_binding(OB_MOUSE_ACTION_RELEASE, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root) || used;
|
||||
if (click)
|
||||
fire_binding(OB_MOUSE_ACTION_CLICK, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root);
|
||||
used = fire_binding(OB_MOUSE_ACTION_CLICK, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root) || used;
|
||||
if (dclick)
|
||||
fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root);
|
||||
used = fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
|
||||
client, e->xbutton.state,
|
||||
e->xbutton.button,
|
||||
e->xbutton.x_root,
|
||||
e->xbutton.y_root) || used;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
|
@ -347,8 +348,8 @@ void mouse_event(ObClient *client, XEvent *e)
|
|||
context == OB_FRAME_CONTEXT_CLOSE)
|
||||
break;
|
||||
|
||||
fire_binding(OB_MOUSE_ACTION_MOTION, context,
|
||||
client, state, button, px, py);
|
||||
used = fire_binding(OB_MOUSE_ACTION_MOTION, context,
|
||||
client, state, button, px, py);
|
||||
button = 0;
|
||||
state = 0;
|
||||
}
|
||||
|
@ -358,6 +359,7 @@ void mouse_event(ObClient *client, XEvent *e)
|
|||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
gboolean mouse_bind(const gchar *buttonstr, const gchar *contextstr,
|
||||
|
|
|
@ -33,7 +33,7 @@ gboolean mouse_bind(const gchar *buttonstr, const gchar *contextstr,
|
|||
ObMouseAction mact, struct _ObActionsAct *action);
|
||||
void mouse_unbind_all(void);
|
||||
|
||||
void mouse_event(struct _ObClient *client, XEvent *e);
|
||||
gboolean mouse_event(struct _ObClient *client, XEvent *e);
|
||||
|
||||
void mouse_grab_for_client(struct _ObClient *client, gboolean grab);
|
||||
|
||||
|
|
|
@ -411,10 +411,10 @@ static void render_button(ObPrompt *self, ObPromptElement *e)
|
|||
{
|
||||
RrAppearance *a;
|
||||
|
||||
if (e->pressed && self->focus == e) a = prompt_a_pfocus;
|
||||
else if (self->focus == e) a = prompt_a_focus;
|
||||
else if (e->pressed) a = prompt_a_press;
|
||||
else a = prompt_a_button;
|
||||
if (e->hover && self->focus == e) a = prompt_a_pfocus;
|
||||
else if (self->focus == e) a = prompt_a_focus;
|
||||
else if (e->pressed) a = prompt_a_press;
|
||||
else a = prompt_a_button;
|
||||
|
||||
a->surface.parent = prompt_a_bg;
|
||||
a->surface.parentx = e->x;
|
||||
|
@ -587,25 +587,28 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e)
|
|||
|
||||
oldfocus = self->focus;
|
||||
|
||||
but->pressed = TRUE;
|
||||
but->pressed = but->hover = TRUE;
|
||||
self->focus = but;
|
||||
|
||||
if (oldfocus != but) render_button(self, oldfocus);
|
||||
render_button(self, but);
|
||||
}
|
||||
else if (e->type == ButtonRelease) {
|
||||
if (but->pressed)
|
||||
if (but->hover)
|
||||
prompt_run_callback(self, but->result);
|
||||
but->pressed = FALSE;
|
||||
}
|
||||
else if (e->type == MotionNotify) {
|
||||
gboolean press;
|
||||
if (but->pressed) {
|
||||
gboolean hover;
|
||||
|
||||
press = (e->xmotion.x >= 0 && e->xmotion.y >= 0 &&
|
||||
e->xmotion.x < but->width && e->xmotion.y < but->height);
|
||||
hover = (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);
|
||||
if (hover != but->hover) {
|
||||
but->hover = hover;
|
||||
render_button(self, but);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
|
|
@ -38,6 +38,7 @@ struct _ObPromptElement {
|
|||
|
||||
gint x, y, width, height;
|
||||
gboolean pressed;
|
||||
gboolean hover;
|
||||
gint result;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue