#include "menuframe.h"
#include "keyboard.h"
#include "modkeys.h"
+#include "propwin.h"
#include "mouse.h"
#include "mainloop.h"
#include "framerender.h"
#include "translate.h"
#include <X11/Xlib.h>
-#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <glib.h>
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_time_window_clients(GSList *l, XEvent *e);
static void event_handle_user_input(ObClient *client, XEvent *e);
static void focus_delay_dest(gpointer data);
static void event_process(const XEvent *ec, gpointer data)
{
Window window;
- ObGroup *group = NULL;
ObClient *client = NULL;
ObDock *dock = NULL;
ObDockApp *dockapp = NULL;
ObWindow *obwin = NULL;
+ GSList *timewinclients = NULL;
XEvent ee, *e;
ObEventData *ed = data;
e = ⅇ
window = event_get_window(e);
- if (!(e->type == PropertyNotify &&
- (group = g_hash_table_lookup(group_map, &window))))
+ 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:
frame_adjust_focus(client->frame, TRUE);
focus_set_client(client);
client_calc_layer(client);
+ client_bring_helper_windows(client);
}
} else if (e->type == FocusOut) {
gboolean nomove = FALSE;
/* focus_set_client has already been called for sure */
client_calc_layer(client);
}
- } else if (group)
- event_handle_group(group, e);
+ } else if (timewinclients)
+ event_handle_user_time_window_clients(timewinclients, e);
else if (client)
event_handle_client(client, e);
else if (dockapp)
event_handle_root(e);
else if (e->type == MapRequest)
client_manage(window);
+ else if (e->type == ClientMessage) {
+ /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
+ windows that are not managed yet. */
+ if (e->xclient.message_type == prop_atoms.net_request_frame_extents) {
+ /* Pretend to manage the client, getting information used to
+ determine its decorations */
+ ObClient *c = client_fake_manage(e->xclient.window);
+ gulong vals[4];
+
+ /* adjust the decorations so we know the sizes */
+ frame_adjust_area(c->frame, FALSE, TRUE, TRUE);
+
+ /* set the frame extents on the window */
+ vals[0] = c->frame->size.left;
+ vals[1] = c->frame->size.right;
+ vals[2] = c->frame->size.top;
+ vals[3] = c->frame->size.bottom;
+ PROP_SETA32(e->xclient.window, net_frame_extents,
+ cardinal, vals, 4);
+
+ /* Free the pretend client */
+ client_fake_unmanage(c);
+ }
+ }
else if (e->type == ConfigureRequest) {
- /* unhandled configure requests must be used to configure the
+ /* unhandled config5Aure requests must be used to configure the
window directly */
XWindowChanges xwc;
}
}
-static void event_handle_group(ObGroup *group, XEvent *e)
-{
- GSList *it;
-
- g_assert(e->type == PropertyNotify);
-
- for (it = group->members; it; it = g_slist_next(it))
- event_handle_client(it->data, e);
-}
-
void event_enter_client(ObClient *client)
{
g_assert(config_focus_follow);
- if (client_normal(client) && client_can_focus(client)) {
+ if (client_enter_focusable(client) && client_can_focus(client)) {
if (config_focus_delay) {
ObFocusDelayData *data;
}
}
+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;
Atom msgtype;
ObFrameContext con;
+ static gint px = -1, py = -1;
+ static guint pb = 0;
switch (e->type) {
case ButtonPress:
+ /* save where the press occured for the first button pressed */
+ if (!pb) {
+ pb = e->xbutton.button;
+ px = e->xbutton.x;
+ py = e->xbutton.y;
+ }
case ButtonRelease:
/* Wheel buttons don't draw because they are an instant click, so it
- is a waste of resources to go drawing it. */
- if (!(e->xbutton.button == 4 || e->xbutton.button == 5)) {
- con = frame_context(client, e->xbutton.window);
+ is a waste of resources to go drawing it.
+ if the user is doing an intereactive thing, or has a menu open then
+ the mouse is grabbed (possibly) and if we get these events we don't
+ want to deal with them
+ */
+ if (!(e->xbutton.button == 4 || e->xbutton.button == 5) &&
+ !keyboard_interactively_grabbed() &&
+ !menu_frame_visible)
+ {
+ /* use where the press occured */
+ con = frame_context(client, e->xbutton.window, px, py);
con = mouse_button_frame_context(con, e->xbutton.button);
+
+ if (e->type == ButtonRelease && e->xbutton.button == pb)
+ pb = 0, px = py = -1;
+
switch (con) {
case OB_FRAME_CONTEXT_MAXIMIZE:
client->frame->max_press = (e->type == ButtonPress);
}
}
break;
+ case MotionNotify:
+ con = frame_context(client, e->xmotion.window,
+ e->xmotion.x, e->xmotion.y);
+ switch (con) {
+ case OB_FRAME_CONTEXT_TITLEBAR:
+ /* we've left the button area inside the titlebar */
+ if (client->frame->max_hover || client->frame->desk_hover ||
+ client->frame->shade_hover || client->frame->iconify_hover ||
+ client->frame->close_hover)
+ {
+ client->frame->max_hover = FALSE;
+ client->frame->desk_hover = FALSE;
+ client->frame->shade_hover = FALSE;
+ client->frame->iconify_hover = FALSE;
+ client->frame->close_hover = FALSE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ case OB_FRAME_CONTEXT_MAXIMIZE:
+ if (!client->frame->max_hover) {
+ client->frame->max_hover = TRUE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ case OB_FRAME_CONTEXT_ALLDESKTOPS:
+ if (!client->frame->desk_hover) {
+ client->frame->desk_hover = TRUE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ case OB_FRAME_CONTEXT_SHADE:
+ if (!client->frame->shade_hover) {
+ client->frame->shade_hover = TRUE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ case OB_FRAME_CONTEXT_ICONIFY:
+ if (!client->frame->iconify_hover) {
+ client->frame->iconify_hover = TRUE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ case OB_FRAME_CONTEXT_CLOSE:
+ if (!client->frame->close_hover) {
+ client->frame->close_hover = TRUE;
+ frame_adjust_state(client->frame);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
case LeaveNotify:
- con = frame_context(client, e->xcrossing.window);
+ con = frame_context(client, e->xcrossing.window,
+ e->xcrossing.x, e->xcrossing.y);
switch (con) {
case OB_FRAME_CONTEXT_MAXIMIZE:
client->frame->max_hover = FALSE;
nofocus = TRUE;
}
- con = frame_context(client, e->xcrossing.window);
+ con = frame_context(client, e->xcrossing.window,
+ e->xcrossing.x, e->xcrossing.y);
switch (con) {
case OB_FRAME_CONTEXT_MAXIMIZE:
client->frame->max_hover = TRUE;
(e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
/* XXX make use of data.l[2] !? */
event_curtime = e->xclient.data.l[1];
- ob_debug_type(OB_DEBUG_APP_BUGS,
- "_NET_ACTIVE_WINDOW message for window %s is "
- "missing a timestamp\n", client->title);
+ if (event_curtime == 0)
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_ACTIVE_WINDOW message for window %s is "
+ "missing a timestamp\n", client->title);
client_activate(client, FALSE,
(e->xclient.data.l[0] == 0 ||
e->xclient.data.l[0] == 2));
client_update_wmhints(client);
} else if (msgtype == XA_WM_TRANSIENT_FOR) {
client_update_transient_for(client);
- client_get_type(client);
+ client_get_type_and_transientness(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_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);