remove focus-stealing-prevention stuff, don't use user_time crap at all. it is broken in every application that has ever used it. ever. ever. \^_^/;;;

This commit is contained in:
Dana Jansens 2007-08-01 23:35:31 -04:00
parent bfb0c91671
commit dacc9dac7a
10 changed files with 37 additions and 351 deletions

View file

@ -249,8 +249,6 @@ openbox_openbox_SOURCES = \
openbox/popup.h \
openbox/prop.c \
openbox/prop.h \
openbox/propwin.c \
openbox/propwin.h \
openbox/resist.c \
openbox/resist.h \
openbox/screen.c \

View file

@ -32,7 +32,6 @@
#include "event.h"
#include "grab.h"
#include "focus.h"
#include "propwin.h"
#include "stacking.h"
#include "openbox.h"
#include "group.h"
@ -215,6 +214,7 @@ void client_manage(Window window)
ObAppSettings *settings;
gboolean transient = FALSE;
Rect place, *monitor;
Time map_time;
grab_server(TRUE);
@ -269,7 +269,6 @@ void client_manage(Window window)
self->wmstate = WithdrawnState; /* make sure it gets updated first time */
self->gravity = NorthWestGravity;
self->desktop = screen_num_desktops; /* always an invalid value */
self->user_time = focus_client ? focus_client->user_time : CurrentTime;
/* get all the stuff off the window */
client_get_all(self, TRUE);
@ -300,10 +299,8 @@ void client_manage(Window window)
/* now we have all of the window's information so we can set this up */
client_setup_decor_and_functions(self, FALSE);
{
Time t = sn_app_started(self->startup_id, self->class);
if (t) self->user_time = t;
}
/* tell startup notification that this app started */
map_time = sn_app_started(self->startup_id, self->class);
/* do this after we have a frame.. it uses the frame to help determine the
WM_STATE to apply. */
@ -453,14 +450,6 @@ void client_manage(Window window)
if (activate) {
gboolean raise = FALSE;
guint32 last_time = focus_client ?
focus_client->user_time : CurrentTime;
/* This is focus stealing prevention */
ob_debug_type(OB_DEBUG_FOCUS,
"Want to focus new window 0x%x with time %u "
"(last time %u)\n",
self->window, self->user_time, last_time);
if (menu_frame_visible || moveresize_in_progress) {
activate = FALSE;
@ -475,8 +464,8 @@ void client_manage(Window window)
else if (!(self->desktop == screen_desktop ||
self->desktop == DESKTOP_ALL) &&
/* the timestamp is from before you changed desktops */
self->user_time && screen_desktop_user_time &&
!event_time_after(self->user_time, screen_desktop_user_time))
map_time && screen_desktop_user_time &&
!event_time_after(map_time, screen_desktop_user_time))
{
activate = FALSE;
raise = TRUE;
@ -488,26 +477,15 @@ void client_manage(Window window)
else if (focus_client && client_search_focus_tree_full(self) == NULL &&
client_search_focus_group_full(self) == NULL)
{
/* If time stamp is old, don't steal focus */
if (self->user_time && last_time &&
!event_time_after(self->user_time, last_time))
{
activate = FALSE;
ob_debug_type(OB_DEBUG_FOCUS,
"Not focusing the window because the time is "
"too old\n");
}
/* If its a transient (and parents aren't focused) and the time
is ambiguous (either the current focus target doesn't have
a timestamp, or they are the same (we probably inherited it
from them) */
else if (client_has_parent(self) &&
(!last_time || self->user_time == last_time))
{
if (client_has_parent(self)) {
activate = FALSE;
ob_debug_type(OB_DEBUG_FOCUS,
"Not focusing the window because it is a "
"transient, and the time is very ambiguous\n");
"transient, and its relatives aren't focused\n");
}
/* Don't steal focus from globally active clients.
I stole this idea from KWin. It seems nice.
@ -532,10 +510,6 @@ void client_manage(Window window)
}
if (!activate) {
ob_debug_type(OB_DEBUG_FOCUS,
"Focus stealing prevention activated for %s with "
"time %u (last time %u)\n",
self->title, self->user_time, last_time);
/* if the client isn't focused, then hilite it so the user
knows it is there */
client_hilite(self, TRUE);
@ -669,9 +643,6 @@ void client_unmanage(ObClient *self)
/* remove the window from our save set */
XChangeSaveSet(ob_display, self->window, SetModeDelete);
/* kill the property windows */
propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
/* update the focus lists */
focus_order_remove(self);
if (client_focused(self)) {
@ -1111,9 +1082,6 @@ static void client_get_all(ObClient *self, gboolean real)
client_get_colormap(self);
client_update_strut(self);
client_update_icons(self);
client_update_user_time_window(self);
if (!self->user_time_window) /* check if this would have been called */
client_update_user_time(self);
client_update_icon_geometry(self);
}
@ -2114,62 +2082,6 @@ void client_update_icons(ObClient *self)
frame_adjust_icon(self->frame);
}
void client_update_user_time(ObClient *self)
{
guint32 time;
gboolean got = FALSE;
if (self->user_time_window)
got = PROP_GET32(self->user_time_window,
net_wm_user_time, cardinal, &time);
if (!got)
got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time);
if (got) {
/* we set this every time, not just when it grows, because in practice
sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes
backward we don't want all windows to stop focusing. we'll just
assume noone is setting times older than the last one, cuz that
would be pretty stupid anyways
*/
self->user_time = time;
/*ob_debug("window %s user time %u\n", self->title, time);*/
}
}
void client_update_user_time_window(ObClient *self)
{
guint32 w;
if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w))
w = None;
if (w != self->user_time_window) {
/* remove the old window */
propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
self->user_time_window = None;
if (self->group && self->group->leader == w) {
ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
"_NET_WM_USER_TYPE_WINDOW to its group leader\n");
/* do it anyways..? */
}
else if (w == self->window) {
ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
"_NET_WM_USER_TIME_WINDOW to itself\n");
w = None; /* don't do it */
}
/* add the new window */
propwin_add(w, OB_PROPWIN_USER_TIME, self);
self->user_time_window = w;
/* and update from it */
client_update_user_time(self);
}
}
void client_update_icon_geometry(ObClient *self)
{
guint num;
@ -3651,34 +3563,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise,
void client_activate(ObClient *self, gboolean here, gboolean raise,
gboolean unshade, gboolean user)
{
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
gboolean allow = FALSE;
/* if the currently focused app doesn't set a user_time, then it can't
benefit from any focus stealing prevention.
if the timestamp is missing in the request then let it go through
even if it is source=app, because EVERY APPLICATION DOES THIS because
GTK IS VERY BUGGY AND HARDCODES source=application... WHY!?
*/
if (!last_time || !event_curtime)
allow = TRUE;
/* otherwise, if they didn't give a time stamp or if it is too old, they
don't get focus */
else
allow = event_time_after(event_curtime, last_time);
ob_debug_type(OB_DEBUG_FOCUS,
"Want to activate window 0x%x with time %u (last time %u), "
"source=%s allowing? %d\n",
self->window, event_curtime, last_time,
(user ? "user" : "application"), allow);
if (allow)
client_present(self, here, raise, unshade);
else
/* don't focus it but tell the user it wants attention */
client_hilite(self, TRUE);
client_present(self, here, raise, unshade);
}
static void client_bring_windows_recursive(ObClient *self,

View file

@ -289,15 +289,9 @@ struct _ObClient
/*! Where the window should iconify to/from */
Rect icon_geometry;
/*! The time when the client last received user interaction */
guint32 user_time;
/*! A separate window for the client to update it's user_time on */
Window user_time_window;
};
extern GList *client_list;
extern GHashTable *client_user_time_window_map;
void client_startup(gboolean reconfig);
void client_shutdown(gboolean reconfig);
@ -606,10 +600,6 @@ void client_update_title(ObClient *self);
void client_update_strut(ObClient *self);
/*! Updates the window's icons */
void client_update_icons(ObClient *self);
/*! Updates the window's user time */
void client_update_user_time(ObClient *self);
/*! Updates the window's user time window */
void client_update_user_time_window(ObClient *self);
/*! Updates the window's icon geometry (where to iconify to/from) */
void client_update_icon_geometry(ObClient *self);

View file

@ -34,7 +34,6 @@
#include "menuframe.h"
#include "keyboard.h"
#include "modkeys.h"
#include "propwin.h"
#include "mouse.h"
#include "mainloop.h"
#include "focus.h"
@ -90,7 +89,6 @@ static gboolean event_handle_menu(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_time_window_clients(GSList *l, XEvent *e);
static void event_handle_user_input(ObClient *client, XEvent *e);
static gboolean is_enter_focus_event_ignored(XEvent *e);
@ -433,7 +431,6 @@ static void event_process(const XEvent *ec, gpointer data)
ObDock *dock = NULL;
ObDockApp *dockapp = NULL;
ObWindow *obwin = NULL;
GSList *timewinclients = NULL;
XEvent ee, *e;
ObEventData *ed = data;
@ -442,27 +439,24 @@ static void event_process(const XEvent *ec, gpointer data)
e = ⅇ
window = event_get_window(e);
if (e->type != PropertyNotify ||
!(timewinclients = propwin_get_clients(window,
OB_PROPWIN_USER_TIME)))
if ((obwin = g_hash_table_lookup(window_map, &window))) {
switch (obwin->type) {
case Window_Dock:
dock = WINDOW_AS_DOCK(obwin);
break;
case Window_DockApp:
dockapp = WINDOW_AS_DOCKAPP(obwin);
break;
case Window_Client:
client = WINDOW_AS_CLIENT(obwin);
break;
case Window_Menu:
case Window_Internal:
/* not to be used for events */
g_assert_not_reached();
break;
}
if ((obwin = g_hash_table_lookup(window_map, &window))) {
switch (obwin->type) {
case Window_Dock:
dock = WINDOW_AS_DOCK(obwin);
break;
case Window_DockApp:
dockapp = WINDOW_AS_DOCKAPP(obwin);
break;
case Window_Client:
client = WINDOW_AS_CLIENT(obwin);
break;
case Window_Menu:
case Window_Internal:
/* not to be used for events */
g_assert_not_reached();
break;
}
}
event_set_curtime(e);
event_hack_mods(e);
@ -607,8 +601,7 @@ static void event_process(const XEvent *ec, gpointer data)
section or by focus_fallback */
client_calc_layer(client);
}
} else if (timewinclients)
event_handle_user_time_window_clients(timewinclients, e);
}
else if (client)
event_handle_client(client, e);
else if (dockapp)
@ -766,15 +759,6 @@ void event_enter_client(ObClient *client)
}
}
static void event_handle_user_time_window_clients(GSList *l, XEvent *e)
{
g_assert(e->type == PropertyNotify);
if (e->xproperty.atom == prop_atoms.net_wm_user_time) {
for (; l; l = g_slist_next(l))
client_update_user_time(l->data);
}
}
static void event_handle_client(ObClient *client, XEvent *e)
{
XEvent ce;
@ -1288,8 +1272,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
(e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
/* XXX make use of data.l[2] !? */
if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) {
event_curtime = e->xclient.data.l[1];
if (event_curtime == 0)
/* don't use the user's timestamp for client_focus, cuz if it's
an old broken timestamp (happens all the time) then focus
won't move even though we're trying to move it
event_curtime = e->xclient.data.l[1];*/
if (e->xclient.data.l[1] == 0)
ob_debug_type(OB_DEBUG_APP_BUGS,
"_NET_ACTIVE_WINDOW message for window %s is"
" missing a timestamp\n", client->title);
@ -1509,12 +1496,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
else if (msgtype == prop_atoms.net_wm_icon_geometry) {
client_update_icon_geometry(client);
}
else if (msgtype == prop_atoms.net_wm_user_time) {
client_update_user_time(client);
}
else if (msgtype == prop_atoms.net_wm_user_time_window) {
client_update_user_time_window(client);
}
#ifdef SYNC
else if (msgtype == prop_atoms.net_wm_sync_request_counter) {
client_update_sync_request_counter(client);

View file

@ -42,7 +42,6 @@
#include "menuframe.h"
#include "grab.h"
#include "group.h"
#include "propwin.h"
#include "config.h"
#include "mainloop.h"
#include "gettext.h"
@ -301,7 +300,6 @@ gint main(gint argc, gchar **argv)
sn_startup(reconfigure);
screen_startup(reconfigure);
grab_startup(reconfigure);
propwin_startup(reconfigure);
group_startup(reconfigure);
client_startup(reconfigure);
dock_startup(reconfigure);
@ -363,7 +361,6 @@ gint main(gint argc, gchar **argv)
dock_shutdown(reconfigure);
client_shutdown(reconfigure);
group_shutdown(reconfigure);
propwin_shutdown(reconfigure);
grab_shutdown(reconfigure);
screen_shutdown(reconfigure);
focus_cycle_popup_shutdown(reconfigure);

View file

@ -93,8 +93,8 @@ void prop_startup()
CREATE(net_wm_icon_geometry, "_NET_WM_ICON_GEOMETRY");
/* CREATE(net_wm_pid, "_NET_WM_PID"); */
CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
CREATE(net_wm_user_time, "_NET_WM_USER_TIME");
CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW");
/* CREATE(net_wm_user_time, "_NET_WM_USER_TIME"); */
/* CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW"); */
CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT");
CREATE(net_frame_extents, "_NET_FRAME_EXTENTS");

View file

@ -131,8 +131,8 @@ typedef struct Atoms {
Atom net_wm_icon_geometry;
/* Atom net_wm_pid; */
Atom net_wm_allowed_actions;
Atom net_wm_user_time;
Atom net_wm_user_time_window;
/* Atom net_wm_user_time; */
/* Atom net_wm_user_time_window; */
Atom net_frame_extents;
/* application protocols */

View file

@ -1,127 +0,0 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
propwin.c for the Openbox window manager
Copyright (c) 2006 Mikael Magnusson
Copyright (c) 2003-2007 Dana Jansens
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file for a copy of the GNU General Public License.
*/
#include "propwin.h"
#include "openbox.h"
#include "client.h"
#include "debug.h"
typedef struct _ObPropWin ObPropWin;
typedef struct _ObPropWinData ObPropWinData;
struct _ObPropWinData
{
GSList *clients;
};
struct _ObPropWin
{
Window win;
ObPropWinData data[OB_NUM_PROPWIN_TYPES];
};
/*! A hash table that maps a window to an ObPropWin */
static GHashTable *propwin_map;
static guint window_hash(Window *w) { return *w; }
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
void propwin_startup(gboolean reconfig)
{
if (!reconfig)
propwin_map = g_hash_table_new_full((GHashFunc)window_hash,
(GEqualFunc)window_comp,
NULL,
g_free);
}
void propwin_shutdown(gboolean reconfig)
{
if (!reconfig)
g_hash_table_destroy(propwin_map);
else
g_assert(g_hash_table_size(propwin_map) == 0);
}
void propwin_add(Window win, ObPropWinType type, ObClient *client)
{
ObPropWin *p;
if (!win) return;
g_assert(client);
g_assert(type < OB_NUM_PROPWIN_TYPES);
p = g_hash_table_lookup(propwin_map, &win);
if (!p) {
p = g_new0(ObPropWin, 1);
p->win = win;
g_hash_table_insert(propwin_map, &p->win, p);
/* get property changes on this window */
XSelectInput(ob_display, win, PropertyChangeMask);
} else
g_assert(g_slist_find(p->data[type].clients, client) == NULL);
if (p->data[type].clients != NULL)
ob_debug("Client %s is using a property window 0x%x that is already "
"in use\n", client->title, win);
/* add it to the clients list */
p->data[type].clients = g_slist_prepend(p->data[type].clients, client);
}
void propwin_remove(Window win, ObPropWinType type, ObClient *client)
{
ObPropWin *p;
if (!win) return;
p = g_hash_table_lookup(propwin_map, &win);
g_assert(p);
/* remove it to the clients list */
g_assert(g_slist_find(p->data[type].clients, client) != NULL);
p->data[type].clients = g_slist_remove(p->data[type].clients, client);
/* no more clients left for this type */
if (p->data[type].clients == NULL) {
guint i;
gboolean none = TRUE;
for (i = 0; i < OB_NUM_PROPWIN_TYPES; ++i)
if (p->data[i].clients != NULL)
none = FALSE; /* another type still has a client for this
window */
if (none) {
/* don't get events for this window any more */
XSelectInput(ob_display, win, NoEventMask);
g_hash_table_remove(propwin_map, &win);
}
}
}
GSList* propwin_get_clients(Window win, ObPropWinType type)
{
ObPropWin *p = g_hash_table_lookup(propwin_map, &win);
if (p)
return p->data[type].clients;
else
return NULL;
}

View file

@ -1,40 +0,0 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
propwin.h for the Openbox window manager
Copyright (c) 2007 Dana Jansens
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file for a copy of the GNU General Public License.
*/
#ifndef __propwin_h
#define __propwin_h
#include <glib.h>
#include <X11/Xlib.h>
struct _ObClient;
typedef enum {
OB_PROPWIN_USER_TIME,
OB_NUM_PROPWIN_TYPES
} ObPropWinType;
void propwin_startup(gboolean reconfig);
void propwin_shutdown(gboolean reconfig);
void propwin_add(Window win, ObPropWinType type, struct _ObClient *client);
void propwin_remove(Window win, ObPropWinType type, struct _ObClient *client);
GSList* propwin_get_clients(Window win, ObPropWinType type);
#endif

View file

@ -282,8 +282,10 @@ gboolean screen_annex()
supported[i++] = prop_atoms.net_wm_state_demands_attention;
supported[i++] = prop_atoms.net_moveresize_window;
supported[i++] = prop_atoms.net_wm_moveresize;
/*
supported[i++] = prop_atoms.net_wm_user_time;
supported[i++] = prop_atoms.net_wm_user_time_window;
*/
supported[i++] = prop_atoms.net_frame_extents;
supported[i++] = prop_atoms.net_request_frame_extents;
supported[i++] = prop_atoms.net_restack_window;