]> Dogcows Code - chaz/openbox/blobdiff - openbox/event.c
when a window is fully maxed, make clicking on the titlebar past the edge buttons...
[chaz/openbox] / openbox / event.c
index 9a1ebb2f9add26369f0212c43d55eeffbe94e13d..ef320afd0ae8c3ee2dc81203cac7864dd64d9757 100644 (file)
@@ -32,6 +32,7 @@
 #include "menuframe.h"
 #include "keyboard.h"
 #include "modkeys.h"
+#include "propwin.h"
 #include "mouse.h"
 #include "mainloop.h"
 #include "framerender.h"
@@ -43,7 +44,6 @@
 #include "translate.h"
 
 #include <X11/Xlib.h>
-#include <X11/keysym.h>
 #include <X11/Xatom.h>
 #include <glib.h>
 
@@ -82,7 +82,7 @@ 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_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);
@@ -407,11 +407,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
 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;
 
@@ -420,8 +420,9 @@ static void event_process(const XEvent *ec, gpointer data)
     e = &ee;
 
     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:
@@ -504,7 +505,7 @@ static void event_process(const XEvent *ec, gpointer data)
             frame_adjust_focus(client->frame, TRUE);
             focus_set_client(client);
             client_calc_layer(client);
-            client_bring_non_application_windows(client);
+            client_bring_helper_windows(client);
         }
     } else if (e->type == FocusOut) {
         gboolean nomove = FALSE;
@@ -555,8 +556,8 @@ static void event_process(const XEvent *ec, gpointer data)
             /* 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)
@@ -567,8 +568,32 @@ static void event_process(const XEvent *ec, gpointer data)
         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;
 
@@ -663,21 +688,11 @@ static void event_handle_root(XEvent *e)
     }
 }
 
-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;
 
@@ -700,14 +715,27 @@ 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;
     Atom msgtype;
     ObFrameContext con;
+    static gint px = -1, py = -1;
      
     switch (e->type) {
     case ButtonPress:
+        /* save where the press occured for the first button pressed */
+        if (px == -1) px = e->xbutton.x;
+        if (py == -1) 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.
@@ -719,8 +747,13 @@ static void event_handle_client(ObClient *client, XEvent *e)
             !keyboard_interactively_grabbed() &&
             !menu_frame_visible)
         {
-            con = frame_context(client, e->xbutton.window);
+            /* 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)
+                px = py = -1;
+
             switch (con) {
             case OB_FRAME_CONTEXT_MAXIMIZE:
                 client->frame->max_press = (e->type == ButtonPress);
@@ -749,7 +782,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
         }
         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;
@@ -809,7 +843,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
             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;
@@ -1025,7 +1060,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             if ((unsigned)e->xclient.data.l[0] < screen_num_desktops ||
                 (unsigned)e->xclient.data.l[0] == DESKTOP_ALL)
                 client_set_desktop(client, (unsigned)e->xclient.data.l[0],
-                                   FALSE, FALSE);
+                                   FALSE);
         } else if (msgtype == prop_atoms.net_wm_state) {
             /* can't compress these */
             ob_debug("net_wm_state %s %ld %ld for 0x%lx\n",
@@ -1047,9 +1082,10 @@ static void event_handle_client(ObClient *client, XEvent *e)
                        (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));
@@ -1166,7 +1202,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             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);
@@ -1191,6 +1227,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
         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);
This page took 0.025661 seconds and 4 git commands to generate.