summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
Diffstat (limited to 'openbox')
-rw-r--r--openbox/action.c17
-rw-r--r--openbox/client.c29
-rw-r--r--openbox/event.c92
-rw-r--r--openbox/focus.c2
-rw-r--r--openbox/frame.c84
-rw-r--r--openbox/frame.h10
-rw-r--r--openbox/moveresize.c4
-rw-r--r--openbox/place.c3
-rw-r--r--openbox/resist.c4
9 files changed, 147 insertions, 98 deletions
diff --git a/openbox/action.c b/openbox/action.c
index b54e888e..2e348c7c 100644
--- a/openbox/action.c
+++ b/openbox/action.c
@@ -48,19 +48,8 @@ inline void client_action_start(union ActionData *data)
inline void client_action_end(union ActionData *data)
{
if (config_focus_follow)
- if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
- if (!data->any.button) {
- grab_pointer(FALSE, FALSE, OB_CURSOR_NONE);
- } else {
- ObClient *c;
-
- /* usually this is sorta redundant, but with a press action
- the enter event will come as a GrabNotify which is
- ignored, so this will handle that case */
- if ((c = client_under_pointer()))
- event_enter_client(c);
- }
- }
+ if (data->any.context != OB_FRAME_CONTEXT_CLIENT && !data->any.button)
+ grab_pointer(FALSE, FALSE, OB_CURSOR_NONE);
}
typedef struct
@@ -1275,7 +1264,7 @@ void action_raiselower(union ActionData *data)
if (cit == c) break;
if (client_normal(cit) == client_normal(c) &&
cit->layer == c->layer &&
- cit->frame->visible &&
+ frame_visible(cit->frame) &&
!client_search_transient(c, cit))
{
if (RECT_INTERSECTS_RECT(cit->frame->area, c->frame->area)) {
diff --git a/openbox/client.c b/openbox/client.c
index 658b05db..02bd74b4 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -2061,7 +2061,7 @@ static void client_change_wm_state(ObClient *self)
old = self->wmstate;
- if (self->shaded || self->iconic || !self->frame->visible)
+ if (self->shaded || self->iconic || !frame_visible(self->frame))
self->wmstate = IconicState;
else
self->wmstate = NormalState;
@@ -2731,15 +2731,19 @@ static void client_iconify_recursive(ObClient *self,
(self->frame, iconic,
(ObFrameIconifyAnimateFunc)client_showhide, self);
/* but focus a new window now please */
- focus_fallback(TRUE);
+ focus_fallback(FALSE);
} else
client_showhide(self);
} else {
if (config_animate_iconify)
- /* start the animation then show it, this way the whole window
- doesnt get shown, just the first step of the animation */
- frame_begin_iconify_animation(self->frame, iconic, NULL, NULL);
- client_showhide(self);
+ /* the animation will show the window when it is hidden,
+ but the window state needs to be adjusted after the
+ animation finishes, so call showhide when it's done to make
+ sure everything is updated appropriately
+ */
+ frame_begin_iconify_animation
+ (self->frame, iconic,
+ (ObFrameIconifyAnimateFunc)client_showhide, self);
}
}
@@ -3184,7 +3188,7 @@ gboolean client_can_focus(ObClient *self)
/* choose the correct target */
self = client_focus_target(self);
- if (!self->frame->visible)
+ if (!frame_visible(self->frame))
return FALSE;
if (!(self->can_focus || self->focus_notify))
@@ -3217,7 +3221,7 @@ gboolean client_focus(ObClient *self)
self = client_focus_target(self);
if (!client_can_focus(self)) {
- if (!self->frame->visible) {
+ if (!frame_visible(self->frame)) {
/* update the focus lists */
focus_order_to_top(self);
}
@@ -3302,7 +3306,7 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
client_set_desktop(self, screen_desktop, FALSE);
else
screen_set_desktop(self->desktop);
- } else if (!self->frame->visible)
+ } else if (!frame_visible(self->frame))
/* if its not visible for other reasons, then don't mess
with it */
return;
@@ -3729,8 +3733,11 @@ ObClient* client_under_pointer()
for (it = stacking_list; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
- if (c->frame->visible &&
- RECT_CONTAINS(c->frame->area, x, y)) {
+ if (frame_visible(c->frame) &&
+ /* ignore all animating windows */
+ !frame_iconify_animating(c->frame) &&
+ RECT_CONTAINS(c->frame->area, x, y))
+ {
ret = c;
break;
}
diff --git a/openbox/event.c b/openbox/event.c
index a0202bf3..ec0789d1 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -83,6 +83,7 @@ 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_group(ObGroup *g, XEvent *e);
+static void event_handle_user_input(ObClient *client, XEvent *e);
static void focus_delay_dest(gpointer data);
static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
@@ -530,49 +531,13 @@ static void event_process(const XEvent *ec, gpointer data)
}
#endif
- /* user input (action-bound) events */
if (e->type == ButtonPress || e->type == ButtonRelease ||
e->type == MotionNotify || e->type == KeyPress ||
e->type == KeyRelease)
{
- gboolean useevent = TRUE;
-
- if (menu_frame_visible) {
- if (event_handle_menu(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 */
- useevent = FALSE;
- }
-
- if (useevent) {
- /* if the keyboard interactive action uses the event then dont
- use it for bindings. likewise is moveresize uses the event. */
- if (!keyboard_process_interactive_grab(e, &client) &&
- !(moveresize_in_progress && moveresize_event(e)))
- {
- if (moveresize_in_progress)
- /* make further actions work on the client being
- moved/resized */
- client = moveresize_client;
-
-
- menu_can_hide = FALSE;
- ob_main_loop_timeout_add(ob_main_loop,
- config_menu_hide_delay * 1000,
- menu_hide_delay_func,
- NULL, g_direct_equal, NULL);
-
- if (e->type == ButtonPress || e->type == ButtonRelease ||
- e->type == MotionNotify) {
- mouse_event(client, e);
- } else if (e->type == KeyPress) {
- keyboard_event((focus_cycle_target ? focus_cycle_target :
- (client ? client : focus_client)), e);
- }
- }
- }
+ event_handle_user_input(client, e);
}
+
/* if something happens and it's not from an XEvent, then we don't know
the time */
event_curtime = CurrentTime;
@@ -732,6 +697,12 @@ static void event_handle_client(ObClient *client, XEvent *e)
frame_adjust_state(client->frame);
break;
case OB_FRAME_CONTEXT_FRAME:
+ /* When the mouse leaves an animating window, don't use the
+ corresponding enter events. Pretend like the animating window
+ doesn't even exist..! */
+ if (frame_iconify_animating(client->frame))
+ event_ignore_queued_enters();
+
ob_debug_type(OB_DEBUG_FOCUS,
"%sNotify mode %d detail %d on %lx\n",
(e->type == EnterNotify ? "Enter" : "Leave"),
@@ -1379,6 +1350,51 @@ static gboolean event_handle_menu(XEvent *ev)
return ret;
}
+static void event_handle_user_input(ObClient *client, XEvent *e)
+{
+ g_assert(e->type == ButtonPress || e->type == ButtonRelease ||
+ e->type == MotionNotify || e->type == KeyPress ||
+ e->type == KeyRelease);
+
+ if (menu_frame_visible) {
+ if (event_handle_menu(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;
+ }
+
+ /* if the keyboard interactive action uses the event then dont
+ use it for bindings. likewise is moveresize uses the event. */
+ if (!keyboard_process_interactive_grab(e, &client) &&
+ !(moveresize_in_progress && moveresize_event(e)))
+ {
+ if (moveresize_in_progress)
+ /* make further actions work on the client being
+ moved/resized */
+ client = moveresize_client;
+
+ menu_can_hide = FALSE;
+ ob_main_loop_timeout_add(ob_main_loop,
+ config_menu_hide_delay * 1000,
+ menu_hide_delay_func,
+ NULL, g_direct_equal, NULL);
+
+ 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_visible(client->frame))
+ mouse_event(client, e);
+ } else if (e->type == KeyPress) {
+ keyboard_event((focus_cycle_target ? focus_cycle_target :
+ (client ? client : focus_client)), e);
+ }
+ }
+}
+
static gboolean menu_hide_delay_func(gpointer data)
{
menu_can_hide = TRUE;
diff --git a/openbox/focus.c b/openbox/focus.c
index 823435c9..94257205 100644
--- a/openbox/focus.c
+++ b/openbox/focus.c
@@ -499,7 +499,7 @@ static gboolean valid_focus_target(ObClient *ft, gboolean dock_windows)
for (it = ft->transients; it; it = g_slist_next(it)) {
ObClient *c = it->data;
- if (c->frame->visible)
+ if (frame_visible(c->frame))
return FALSE;
}
return TRUE;
diff --git a/openbox/frame.c b/openbox/frame.c
index 6c4241aa..3af354c3 100644
--- a/openbox/frame.c
+++ b/openbox/frame.c
@@ -42,7 +42,8 @@
from the frame. */
#define INNER_EVENTMASK (ButtonPressMask)
-#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+//#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+#define FRAME_ANIMATE_ICONIFY_TIME 2000000
#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 30) /* 30 Hz */
#define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
@@ -481,17 +482,18 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
self->client->area.height);
}
- if (!fake && !self->iconify_animation_going) {
- /* move and resize the top level frame.
- shading can change without being moved or resized.
-
- but don't do this during an iconify animation. it will be
- reflected afterwards.
- */
- XMoveResizeWindow(ob_display, self->window,
- self->area.x, self->area.y,
- self->area.width - self->bwidth * 2,
- self->area.height - self->bwidth * 2);
+ if (!fake) {
+ if (!frame_iconify_animating(self))
+ /* move and resize the top level frame.
+ shading can change without being moved or resized.
+
+ but don't do this during an iconify animation. it will be
+ reflected afterwards.
+ */
+ XMoveResizeWindow(ob_display, self->window,
+ self->area.x, self->area.y,
+ self->area.width - self->bwidth * 2,
+ self->area.height - self->bwidth * 2);
if (resized) {
framerender_frame(self);
@@ -839,10 +841,6 @@ ObFrameContext frame_context(ObClient *client, Window win)
if (win == RootWindow(ob_display, ob_screen))
return OB_FRAME_CONTEXT_DESKTOP;
if (client == NULL) return OB_FRAME_CONTEXT_NONE;
-
- self = client->frame;
- if (self->iconify_animation_going) return OB_FRAME_CONTEXT_NONE;
-
if (win == client->window) {
/* conceptually, this is the desktop, as far as users are
concerned */
@@ -851,6 +849,7 @@ ObFrameContext frame_context(ObClient *client, Window win)
return OB_FRAME_CONTEXT_CLIENT;
}
+ self = client->frame;
if (win == self->inner || win == self->plate) {
/* conceptually, this is the desktop, as far as users are
concerned */
@@ -1108,27 +1107,41 @@ static gboolean frame_animate_iconify(gpointer p)
h = self->innersize.top; /* just the titlebar */
}
- if (time == 0) {
- /* call the callback when it's done */
- if (self->iconify_animation_cb)
- self->iconify_animation_cb(self->iconify_animation_data);
- /* we're not animating any more ! */
- self->iconify_animation_going = 0;
+ if (time == 0)
+ frame_end_iconify_animation(self);
+ else {
+ XMoveResizeWindow(ob_display, self->window, x, y, w, h);
+ XFlush(ob_display);
}
- /* move to the next spot (after the callback for the animation ending) */
- XMoveResizeWindow(ob_display, self->window, x, y, w, h);
- XFlush(ob_display);
-
return time > 0; /* repeat until we're out of time */
}
+void frame_end_iconify_animation(ObFrame *self)
+{
+ /* see if there is an animation going */
+ if (self->iconify_animation_going == 0) return;
+
+ /* call the callback when it's done */
+ if (self->iconify_animation_cb)
+ self->iconify_animation_cb(self->iconify_animation_data);
+ /* we're not animating any more ! */
+ self->iconify_animation_going = 0;
+
+ /* move after the callback for the animation ending */
+ XMoveResizeWindow(ob_display, self->window,
+ self->area.x, self->area.y,
+ self->area.width - self->bwidth * 2,
+ self->area.height - self->bwidth * 2);
+ XFlush(ob_display);
+}
+
void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying,
ObFrameIconifyAnimateFunc callback,
gpointer data)
{
gulong time;
- gboolean start_timer = TRUE;
+ gboolean new_anim = FALSE;
gboolean set_end = TRUE;
GTimeVal now;
@@ -1151,8 +1164,8 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying,
} else
/* animation was already going in the same direction */
set_end = FALSE;
- start_timer = FALSE;
- }
+ } else
+ new_anim = TRUE;
self->iconify_animation_going = iconifying ? 1 : -1;
self->iconify_animation_cb = callback;
@@ -1165,14 +1178,25 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying,
g_time_val_add(&self->iconify_animation_end, time);
}
- if (start_timer) {
+ if (new_anim) {
ob_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
self, FALSE);
ob_main_loop_timeout_add(ob_main_loop,
FRAME_ANIMATE_ICONIFY_STEP_TIME,
frame_animate_iconify, self,
g_direct_equal, NULL);
+
/* do the first step */
frame_animate_iconify(self);
+
+ if (!self->visible)
+ frame_show(self);
}
}
+
+gboolean frame_visible(ObFrame *self)
+{
+ /* if it is animating back from iconic state then it is considered
+ visible. but if it is iconifying then it is not visible. */
+ return self->visible && self->iconify_animation_going <= 0;
+}
diff --git a/openbox/frame.h b/openbox/frame.h
index 4ffc7df2..5f31b8c9 100644
--- a/openbox/frame.h
+++ b/openbox/frame.h
@@ -77,6 +77,9 @@ struct _ObFrame
Strut size;
Rect area;
+ /*! Is the frame visible? Don't read this directly ! Use frame_visible()
+ instead, because that takes into account if the frame is visible but
+ animating to the iconic (invisible) state. */
gboolean visible;
guint decorations;
@@ -195,5 +198,12 @@ void frame_flash_stop(ObFrame *self);
void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying,
ObFrameIconifyAnimateFunc callback,
gpointer data);
+void frame_end_iconify_animation(ObFrame *self);
+
+/* Returns true if the frame is visible (but false if it is only visible
+ because it is animating */
+gboolean frame_visible(ObFrame *self);
+
+#define frame_iconify_animating(f) (f->iconify_animation_going != 0)
#endif
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index 868c0c25..9f9d4dfd 100644
--- a/openbox/moveresize.c
+++ b/openbox/moveresize.c
@@ -153,12 +153,14 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
moving = (cnr == prop_atoms.net_wm_moveresize_move ||
cnr == prop_atoms.net_wm_moveresize_move_keyboard);
- if (moveresize_in_progress || !c->frame->visible ||
+ if (moveresize_in_progress || !frame_visible(c->frame) ||
!(moving ?
(c->functions & OB_CLIENT_FUNC_MOVE) :
(c->functions & OB_CLIENT_FUNC_RESIZE)))
return;
+ frame_end_iconify_animation(c->frame);
+
moveresize_client = c;
start_cx = c->area.x;
start_cy = c->area.y;
diff --git a/openbox/place.c b/openbox/place.c
index 8003270e..eada385f 100644
--- a/openbox/place.c
+++ b/openbox/place.c
@@ -251,7 +251,8 @@ typedef enum
} ObSmartType;
#define SMART_IGNORE(placer, c) \
- (placer == c || !c->frame->visible || c->shaded || !client_normal(c) || \
+ (placer == c || c->shaded || !client_normal(c) || \
+ !frame_visible(c->frame) || \
(c->desktop != DESKTOP_ALL && \
c->desktop != (placer->desktop == DESKTOP_ALL ? \
screen_desktop : placer->desktop)))
diff --git a/openbox/resist.c b/openbox/resist.c
index fc293446..0c7ec87e 100644
--- a/openbox/resist.c
+++ b/openbox/resist.c
@@ -57,7 +57,7 @@ void resist_move_windows(ObClient *c, gint *x, gint *y)
target = it->data;
/* don't snap to self or non-visibles */
- if (!target->frame->visible || target == c) continue;
+ if (!frame_visible(target->frame) || target == c) continue;
/* don't snap to windows in layers beneath */
if(target->layer < c->layer && !config_resist_layers_below)
@@ -199,7 +199,7 @@ void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn)
target = it->data;
/* don't snap to invisibles or ourself */
- if (!target->frame->visible || target == c) continue;
+ if (!frame_visible(target->frame) || target == c) continue;
/* don't snap to windows in layers beneath */
if(target->layer < c->layer && !config_resist_layers_below)