#include "menuframe.h"
#include "keyboard.h"
#include "mouse.h"
+#include "mainloop.h"
#include "framerender.h"
#include "focus.h"
#include "moveresize.h"
#include "stacking.h"
#include "extensions.h"
-#include "timer.h"
#include "event.h"
#include <X11/Xlib.h>
#include <X11/ICE/ICElib.h>
#endif
-static void event_process(XEvent *e);
+static void event_process(const XEvent *e, gpointer data);
static void event_handle_root(XEvent *e);
static void 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 fd_event_handle();
-#ifdef USE_SM
-static void ice_watch(IceConn conn, IcePointer data, Bool opening,
- IcePointer *watch_data);
-#endif
-static void find_max_fd();
+
+static gboolean focus_delay_func(gpointer data);
+static void focus_delay_client_dest(gpointer data);
#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
(e)->xfocus.detail == NotifyAncestor || \
};
static int mask_table_size;
-static fd_set selset, allset;
#ifdef USE_SM
-static IceConn ice_conn;
-static int ice_fd;
-#endif
-static int max_fd, x_fd;
-static GData *fd_handler_list;
-
+static void ice_handler(int fd, gpointer conn)
+{
+ Bool b;
+ IceProcessMessages(conn, NULL, &b);
+}
-#ifdef USE_SM
static void ice_watch(IceConn conn, IcePointer data, Bool opening,
IcePointer *watch_data)
{
+ static gint fd = -1;
+
if (opening) {
- g_assert (ice_fd < 0);
- ice_conn = conn;
- ice_fd = IceConnectionNumber(conn);
- FD_SET(ice_fd, &allset);
+ fd = IceConnectionNumber(conn);
+ ob_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
} else {
- FD_CLR(ice_fd, &allset);
- ice_fd = -1;
+ ob_main_loop_fd_remove(ob_main_loop, fd);
+ fd = -1;
}
- find_max_fd();
}
#endif
+#ifdef USE_LIBSN
+static void sn_handler(const XEvent *e, gpointer display)
+{
+ XEvent ec;
+ ec = *e;
+ sn_display_process_event(display, &ec);
+}
+#endif
+
+
void event_startup()
{
mask_table_size = sizeof(mask_table) / sizeof(mask_table[0]);
}
}
- FD_ZERO(&allset);
- max_fd = x_fd = ConnectionNumber(ob_display);
- FD_SET(x_fd, &allset);
+ ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
#ifdef USE_SM
- ice_fd = -1;
IceAddConnectionWatch(ice_watch, NULL);
#endif
- g_datalist_init(&fd_handler_list);
+#ifdef USE_LIBSN
+ ob_main_loop_x_add(ob_main_loop, sn_handler, ob_sn_display, NULL);
+#endif
+
+ client_add_destructor(focus_delay_client_dest);
}
void event_shutdown()
{
+ client_remove_destructor(focus_delay_client_dest);
XFreeModifiermap(modmap);
- g_datalist_clear(&fd_handler_list);
-}
-
-void event_loop()
-{
- XEvent e;
- struct timeval *wait;
- gboolean had_event = FALSE;
-
- while (XPending(ob_display)) {
- XNextEvent(ob_display, &e);
-
-#ifdef USE_LIBSN
- sn_display_process_event(ob_sn_display, &e);
-#endif
-
- event_process(&e);
- had_event = TRUE;
- }
-
- if (!had_event) {
- timer_dispatch((GTimeVal**)&wait);
- selset = allset;
- select(max_fd + 1, &selset, NULL, NULL, wait);
-
- /* handle the X events as soon as possible? */
- if (FD_ISSET(x_fd, &selset))
- return;
-
-#ifdef USE_SM
- if (ice_fd >= 0 && FD_ISSET(ice_fd, &selset)) {
- Bool b;
- IceProcessMessages(ice_conn, NULL, &b);
- }
-#endif
-
- fd_event_handle();
- }
}
static Window event_get_window(XEvent *e)
break;
case MotionNotify:
STRIP_MODS(e->xmotion.state);
-#if 0
/* compress events */
{
XEvent ce;
e->xmotion.y_root = ce.xmotion.y_root;
}
}
-#endif
break;
}
}
gboolean fallback = TRUE;
while (TRUE) {
- if (!XCheckTypedWindowEvent(ob_display, FocusOut,
- e->xfocus.window,&fe))
+ if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window,
+ FocusOut, &fe))
if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
break;
if (fe.type == FocusOut) {
#endif
return TRUE;
} else {
- event_process(&fe);
+ event_process(&fe, NULL);
#ifdef DEBUG_FOCUS
ob_debug("focused window got an Out/In back to "
"itself but focus_client was null "
/* once all the FocusOut's have been dealt with, if there
is a FocusIn still left and it is valid, then use it */
- event_process(&fe);
+ event_process(&fe, NULL);
/* secret magic way of event_process telling us that no
client was found for the FocusIn event. ^_^ */
if (fe.xfocus.window != None) {
return FALSE;
}
-static void event_process(XEvent *e)
+static void event_process(const XEvent *ec, gpointer data)
{
Window window;
ObClient *client = NULL;
ObDock *dock = NULL;
ObDockApp *dockapp = NULL;
ObWindow *obwin = NULL;
+ XEvent ee, *e;
+
+ /* make a copy we can mangle */
+ ee = *ec;
+ e = ⅇ
window = event_get_window(e);
if ((obwin = g_hash_table_lookup(window_map, &window))) {
client->frame->close_hover = FALSE;
frame_adjust_state(client->frame);
break;
+ case OB_FRAME_CONTEXT_FRAME:
+ /* XXX if doing a 'reconfigure' make sure you kill this timer,
+ maybe all timers.. */
+ if (config_focus_delay)
+ ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
default:
break;
}
ob_debug("EnterNotify on %lx, focusing window\n",
client->window);
#endif
- client_focus(client);
+ if (config_focus_delay) {
+ ob_main_loop_timeout_add(ob_main_loop,
+ config_focus_delay,
+ focus_delay_func,
+ client,
+ NULL);
+ } else
+ client_focus(client);
}
}
break;
msgtype = e->xclient.message_type;
if (msgtype == prop_atoms.wm_change_state) {
/* compress changes into a single change */
- while (XCheckTypedWindowEvent(ob_display, e->type,
- client->window, &ce)) {
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
/* XXX: it would be nice to compress ALL messages of a
type, not just messages in a row without other
message types between. */
client_set_wm_state(client, e->xclient.data.l[0]);
} else if (msgtype == prop_atoms.net_wm_desktop) {
/* compress changes into a single change */
- while (XCheckTypedWindowEvent(ob_display, e->type,
- client->window, &ce)) {
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
/* XXX: it would be nice to compress ALL messages of a
type, not just messages in a row without other
message types between. */
if (!client_validate(client)) break;
/* compress changes to a single property into a single change */
- while (XCheckTypedWindowEvent(ob_display, e->type,
- client->window, &ce)) {
- /* XXX: it would be nice to compress ALL changes to a property,
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
+ Atom a, b;
+
+ /* XXX: it would be nice to compress ALL changes to a property,
not just changes in a row without other props between. */
- if (ce.xproperty.atom != e->xproperty.atom) {
- XPutBackEvent(ob_display, &ce);
- break;
- }
+
+ a = ce.xproperty.atom;
+ b = e->xproperty.atom;
+
+ if (a == b)
+ continue;
+ if ((a == prop_atoms.net_wm_name ||
+ a == prop_atoms.wm_name ||
+ a == prop_atoms.net_wm_icon_name ||
+ a == prop_atoms.wm_icon_name)
+ &&
+ (b == prop_atoms.net_wm_name ||
+ b == prop_atoms.wm_name ||
+ b == prop_atoms.net_wm_icon_name ||
+ b == prop_atoms.wm_icon_name)) {
+ continue;
+ }
+ if ((a == prop_atoms.net_wm_icon ||
+ a == prop_atoms.kwm_win_icon)
+ &&
+ (b == prop_atoms.net_wm_icon ||
+ b == prop_atoms.kwm_win_icon))
+ continue;
+
+ XPutBackEvent(ob_display, &ce);
+ break;
}
msgtype = e->xproperty.atom;
client_update_normal_hints(client);
/* normal hints can make a window non-resizable */
client_setup_decor_and_functions(client);
- }
- else if (msgtype == XA_WM_HINTS)
+ } else if (msgtype == XA_WM_HINTS) {
client_update_wmhints(client);
- else if (msgtype == XA_WM_TRANSIENT_FOR) {
+ } else if (msgtype == XA_WM_TRANSIENT_FOR) {
client_update_transient_for(client);
client_get_type(client);
/* type may have changed, so update the layer */
client_calc_layer(client);
client_setup_decor_and_functions(client);
- }
- else if (msgtype == prop_atoms.net_wm_name ||
- msgtype == prop_atoms.wm_name ||
- msgtype == prop_atoms.net_wm_icon_name ||
- msgtype == prop_atoms.wm_icon_name)
+ } else if (msgtype == prop_atoms.net_wm_name ||
+ msgtype == prop_atoms.wm_name ||
+ msgtype == prop_atoms.net_wm_icon_name ||
+ msgtype == prop_atoms.wm_icon_name) {
client_update_title(client);
- else if (msgtype == prop_atoms.wm_class)
+ } else if (msgtype == prop_atoms.wm_class) {
client_update_class(client);
- else if (msgtype == prop_atoms.wm_protocols) {
+ } else if (msgtype == prop_atoms.wm_protocols) {
client_update_protocols(client);
client_setup_decor_and_functions(client);
}
client_update_strut(client);
}
else if (msgtype == prop_atoms.net_wm_icon ||
- msgtype == prop_atoms.kwm_win_icon)
+ msgtype == prop_atoms.kwm_win_icon) {
client_update_icons(client);
+ }
default:
;
#ifdef SHAPE
}
}
-void event_add_fd_handler(event_fd_handler *h) {
- g_datalist_id_set_data(&fd_handler_list, h->fd, h);
- FD_SET(h->fd, &allset);
- max_fd = MAX(max_fd, h->fd);
-}
-
-static void find_max_fd_foreach(GQuark n, gpointer data, gpointer max)
-{
- *((unsigned int *)max) = MAX(*((unsigned int *)max), n);
-}
-
-static void find_max_fd()
-{
- int tmpmax = -1;
- g_datalist_foreach(&fd_handler_list, find_max_fd_foreach,
- (gpointer)&tmpmax);
- max_fd = MAX(x_fd, tmpmax);
-#ifdef USE_SM
- max_fd = MAX(ice_fd, max_fd);
-#endif
-}
-
-void event_remove_fd(gint n)
-{
- FD_CLR(n, &allset);
- g_datalist_id_remove_data(&fd_handler_list, (GQuark)n);
- find_max_fd();
-}
-
-static void fd_event_handle_foreach(GQuark n,
- gpointer data, gpointer user_data)
-{
- if (FD_ISSET( (int)n, &selset)) {
- event_fd_handler *h = (event_fd_handler *)data;
- g_assert(h->fd == (int)n);
- h->handler(h->fd, h->data);
- }
-}
-
-static void fd_event_handle()
-{
- g_datalist_foreach(&fd_handler_list, fd_event_handle_foreach, NULL);
-}
-
static void event_handle_dock(ObDock *s, XEvent *e)
{
switch (e->type) {
}
}
+ObMenuFrame* find_active_menu()
+{
+ GList *it;
+ ObMenuFrame *f;
+
+ for (it = menu_frame_visible; it; it = g_list_next(it)) {
+ f = it->data;
+ if (f->selected)
+ break;
+ }
+ return it ? it->data : NULL;
+}
+
static void event_handle_menu(XEvent *ev)
{
ObMenuFrame *f;
menu_frame_select(f, e);
}
break;
+ case KeyPress:
+ if (ev->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
+ menu_frame_hide_all();
+ else if (ev->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
+ ObMenuFrame *f;
+ if ((f = find_active_menu()))
+ menu_entry_frame_execute(f->selected,
+ !(ev->xkey.state & ControlMask));
+ } else if (ev->xkey.keycode == ob_keycode(OB_KEY_LEFT)) {
+ ObMenuFrame *f;
+ if ((f = find_active_menu()) && f->parent)
+ menu_frame_select(f, NULL);
+ } else if (ev->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) {
+ ObMenuFrame *f;
+ if ((f = find_active_menu()) && f->child)
+ menu_frame_select_next(f->child);
+ } else if (ev->xkey.keycode == ob_keycode(OB_KEY_UP)) {
+ ObMenuFrame *f;
+ if ((f = find_active_menu()))
+ menu_frame_select_previous(f);
+ } else if (ev->xkey.keycode == ob_keycode(OB_KEY_DOWN)) {
+ ObMenuFrame *f;
+ if ((f = find_active_menu()))
+ menu_frame_select_next(f);
+ }
+ break;
}
}
+
+static gboolean focus_delay_func(gpointer data)
+{
+ ObClient *c = data;
+ client_focus(c);
+ return FALSE; /* no repeat */
+}
+
+static void focus_delay_client_dest(gpointer data)
+{
+ ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
+}