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);
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 */
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)
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;
}
}
- 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;
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;
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);
+}
/* 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.
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 */
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:
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);
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"),
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)
+#include "event.h"
#include "openbox.h"
#include "client.h"
#include "screen.h"
#include "prop.h"
#include "dispatch.h"
+#include "focus.h"
#include <X11/Xlib.h>
#include <glib.h>
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
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;