From 3b14b587ef8131cbeb2afb2c11240f50c5f5d02b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 24 Mar 2003 04:56:46 +0000 Subject: [PATCH] more focus improvements. everything seems to work! --- openbox/client.c | 53 ++++++++++++++++++++++++++++-------------- openbox/client.h | 5 ++++ openbox/dispatch.h | 6 +++-- openbox/event.c | 57 ++++++++++++++++------------------------------ openbox/focus.c | 6 ++--- 5 files changed, 67 insertions(+), 60 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 7a5bc3d7..7d20abb9 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -239,17 +239,6 @@ void client_unmanage(Client *client) engine_frame_hide(client->frame); - /* dispatch the unmapped event */ - dispatch_client(Event_Client_Unmapped, client, 0, 0); - g_assert(client != NULL); - - /* give the client its border back */ - client_toggle_border(client, TRUE); - - /* reparent the window out of the frame, and free the frame */ - engine_frame_release_client(client->frame, client); - client->frame = NULL; - client_list = g_slist_remove(client_list, client); stacking_list = g_list_remove(stacking_list, client); g_hash_table_remove(client_map, (gpointer)client->window); @@ -278,11 +267,22 @@ void client_unmanage(Client *client) client_calc_layer(it->data); } + /* dispatch the unmapped event */ + dispatch_client(Event_Client_Unmapped, client, 0, 0); + g_assert(client != NULL); + /* unfocus the client (dispatchs the focus event) (we're out of the transient lists already, so being modal doesn't matter) */ if (client_focused(client)) client_unfocus(client); + /* give the client its border back */ + client_toggle_border(client, TRUE); + + /* reparent the window out of the frame, and free the frame */ + engine_frame_release_client(client->frame, client); + client->frame = NULL; + if (ob_state != State_Exiting) { /* these values should not be persisted across a window unmapping/mapping */ @@ -1511,6 +1511,9 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk) client_change_state(self); client_showhide(self); screen_update_struts(); + + dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped, + self, 0, 0); } void client_maximize(Client *self, gboolean max, int dir, gboolean savearea) @@ -1650,7 +1653,7 @@ void client_close(Client *self) ce.xclient.window = self->window; ce.xclient.format = 32; ce.xclient.data.l[0] = prop_atoms.wm_delete_window; - ce.xclient.data.l[1] = CurrentTime; + ce.xclient.data.l[1] = event_lasttime; ce.xclient.data.l[2] = 0l; ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; @@ -1902,11 +1905,11 @@ gboolean client_focus(Client *self) } } - if (client_focused(self)) - return TRUE; + g_message("** focusing %lx", self->window); if (self->can_focus) - XSetInputFocus(ob_display, self->window, RevertToNone, CurrentTime); + XSetInputFocus(ob_display, self->window, RevertToNone, + CurrentTime); if (self->focus_notify) { XEvent ce; @@ -1916,7 +1919,7 @@ gboolean client_focus(Client *self) ce.xclient.window = self->window; ce.xclient.format = 32; ce.xclient.data.l[0] = prop_atoms.wm_take_focus; - ce.xclient.data.l[1] = event_lasttime; + ce.xclient.data.l[1] = CurrentTime; ce.xclient.data.l[2] = 0l; ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; @@ -1930,10 +1933,26 @@ gboolean client_focus(Client *self) void client_unfocus(Client *self) { g_assert(focus_client == self); - focus_set_client(NULL); + client_set_focused(self, FALSE); } gboolean client_focused(Client *self) { return self == focus_client; } + +void client_set_focused(Client *self, gboolean focused) +{ + if (focused) { + if (focus_client != self) + focus_set_client(self); + } else { + if (focus_client == self) + focus_set_client(NULL); + } + + /* focus state can affect the stacking layer */ + client_calc_layer(self); + + engine_frame_adjust_focus(self->frame); +} diff --git a/openbox/client.h b/openbox/client.h index e51315c0..808f4e5f 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -320,6 +320,11 @@ gboolean client_normal(Client *self); /* Returns if the window is focused */ gboolean client_focused(Client *self); +/*! Sets the client to a focused or unfocused state. This does not actually + change the input focus, but rather is used once focus has been moved to tell + the client that it is so. */ +void client_set_focused(Client *self, gboolean focused); + /*! Move and/or resize the window. This also maintains things like the client's minsize, and size increments. @param anchor The corner to keep in the same position when resizing. diff --git a/openbox/dispatch.h b/openbox/dispatch.h index 31116c5c..412e135e 100644 --- a/openbox/dispatch.h +++ b/openbox/dispatch.h @@ -18,9 +18,11 @@ typedef enum { Event_X_Bell = 1 << 7, /* an XKB bell event */ Event_Client_New = 1 << 8, /* new window, before mapping */ - Event_Client_Mapped = 1 << 9, /* new window, after mapping */ + Event_Client_Mapped = 1 << 9, /* new window, after mapping + or uniconified */ Event_Client_Destroy = 1 << 10, /* unmanaged */ - Event_Client_Unmapped = 1 << 11, /* unmanaged, after unmapping */ + Event_Client_Unmapped = 1 << 11, /* unmanaged, after unmapping + or iconified */ Event_Client_Focus = 1 << 12, /* focused */ Event_Client_Unfocus = 1 << 13, /* unfocused */ Event_Client_Urgent = 1 << 14, /* entered/left urgent state */ diff --git a/openbox/event.c b/openbox/event.c index ab0f8d8b..88db5e9e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -219,36 +219,31 @@ void event_process(XEvent *e) event_lasttime = e->xproperty.time; break; case FocusIn: - if (e->xfocus.mode == NotifyGrab) return; -/* if (e->type == FocusIn && window == focus_backup && focus_client != NULL) { -*/ - /* Something's focused but we got a focus event for the backup - window. this means that something unfocused before we received - the new FocusIn. Just ignore it, and refocus what should be - focused! */ -/* client_focus(focus_client); + if (e->xfocus.mode == NotifyGrab || + !(e->xfocus.detail == NotifyNonlinearVirtual || + e->xfocus.detail == NotifyNonlinear)) return; - } -*/ + g_message("FOCUS IN %lx", window); break; case FocusOut: - if (e->xfocus.mode == NotifyGrab) return; - /*|| e.xfocus.mode == NotifyUngrab ||*/ - /* From Metacity, from WindowMaker, ignore all funky pointer - root events. Its commented out cuz I don't think we need this - at all. If problems arise we can look into it */ - /*e.xfocus.detail > NotifyNonlinearVirtual) */ + if (e->xfocus.mode == NotifyGrab || + !(e->xfocus.detail == NotifyNonlinearVirtual || + e->xfocus.detail == NotifyNonlinear)) + return; /* FocusOut events just make us look for FocusIn events. They are mostly ignored otherwise. */ { XEvent fi; if (XCheckTypedEvent(ob_display, FocusIn, &fi)) { + g_message("FOCUS OUT %lx IN %lx", e->xfocus.window, fi.xfocus.window); event_process(&fi); - /* dont unfocus the window we just focused! */ - if (fi.xfocus.window == e->xfocus.window) - return; - } + + if (fi.xfocus.window == e->xfocus.window) + return; + } else { + g_message("FOCUS OUT %lx IN 0x0", e->xfocus.window); + } } break; case EnterNotify: @@ -334,22 +329,8 @@ static void event_handle_client(Client *client, XEvent *e) switch (e->type) { case FocusIn: - if (focus_client != client) - focus_set_client(client); - - /* focus state can affect the stacking layer */ - client_calc_layer(client); - - engine_frame_adjust_focus(client->frame); - break; case FocusOut: - if (focus_client == client) - focus_set_client(NULL); - - /* focus state can affect the stacking layer */ - client_calc_layer(client); - - engine_frame_adjust_focus(client->frame); + client_set_focused(client, e->type == FocusIn); break; case ConfigureRequest: g_message("ConfigureRequest for window %lx", client->window); @@ -508,7 +489,7 @@ static void event_handle_client(Client *client, XEvent *e) client_set_desktop(client, e->xclient.data.l[0]); } else if (msgtype == prop_atoms.net_wm_state) { /* can't compress these */ - g_message("net_wm_state %s %ld %ld for 0x%lx\n", + g_message("net_wm_state %s %ld %ld for 0x%lx", (e->xclient.data.l[0] == 0 ? "Remove" : e->xclient.data.l[0] == 1 ? "Add" : e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"), @@ -517,10 +498,10 @@ static void event_handle_client(Client *client, XEvent *e) client_set_state(client, e->xclient.data.l[0], e->xclient.data.l[1], e->xclient.data.l[2]); } else if (msgtype == prop_atoms.net_close_window) { - g_message("net_close_window for 0x%lx\n", client->window); + g_message("net_close_window for 0x%lx", client->window); client_close(client); } else if (msgtype == prop_atoms.net_active_window) { - g_message("net_active_window for 0x%lx\n", client->window); + g_message("net_active_window for 0x%lx", client->window); if (screen_showing_desktop) screen_show_desktop(FALSE); if (client->iconic) diff --git a/openbox/focus.c b/openbox/focus.c index 75bd6bcd..9b6eead2 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -1,8 +1,10 @@ +#include "event.h" #include "openbox.h" #include "client.h" #include "screen.h" #include "prop.h" #include "dispatch.h" +#include "focus.h" #include #include @@ -13,8 +15,6 @@ GList **focus_order = NULL; /* these lists are created when screen_startup Window focus_backup = None; -void focus_set_client(Client *client); - void focus_startup() { /* create the window which gets focus when no clients get it. Have to @@ -62,7 +62,7 @@ void focus_set_client(Client *client) if (client == NULL) { /* when nothing will be focused, send focus to the backup target */ - XSetInputFocus(ob_display, focus_backup, RevertToNone, CurrentTime); + XSetInputFocus(ob_display, focus_backup, RevertToNone, event_lasttime); } old = focus_client; -- 2.44.0