]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
don't focus helper windows that map unless there are no other valid targets in the...
[chaz/openbox] / openbox / client.c
index d65ce4a193c0711cb8c4ce49f49b294ad9c4c24f..4383bc7d64028795829c34dca2a70b33b9aa7316 100644 (file)
@@ -274,6 +274,9 @@ void client_manage(Window window)
     /* get all the stuff off the window */
     client_get_all(self, TRUE);
 
+    ob_debug("Window type: %d\n", self->type);
+    ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
+
     /* specify that if we exit, the window should not be destroyed and
        should be reparented back to root automatically */
     XChangeSaveSet(ob_display, window, SetModeInsert);
@@ -320,7 +323,7 @@ void client_manage(Window window)
          client_search_focus_tree_full(self)) &&
         /* this checks for focus=false for the window */
         (!settings || settings->focus != 0) &&
-        focus_valid_target(self, FALSE, TRUE, FALSE, FALSE))
+        focus_valid_target(self, FALSE, FALSE, TRUE, FALSE, FALSE))
     {
         activate = TRUE;
     }
@@ -933,7 +936,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     frame_rect_to_frame(self->frame, &desired);
 
     /* get where the frame would be */
-    frame_client_gravity(self->frame, x, y, w, h);
+    frame_client_gravity(self->frame, x, y);
 
     /* get the requested size of the window with decorations */
     fw = self->frame->size.left + w + self->frame->size.right;
@@ -1021,7 +1024,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     }
 
     /* get where the client should be */
-    frame_frame_gravity(self->frame, x, y, w, h);
+    frame_frame_gravity(self->frame, x, y);
 
     return ox != *x || oy != *y;
 }
@@ -2613,11 +2616,18 @@ static void client_apply_startup_state(ObClient *self,
     else if (max_horz)
         client_maximize(self, TRUE, 1);
 
-    /* if the window hasn't been configured yet, then do so now */
-    if (!fullscreen && !max_vert && !max_horz) {
-        self->area = oldarea;
-        client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
-    }
+    /* if the window hasn't been configured yet, then do so now, in fact the
+       x,y,w,h may _not_ be the same as the area rect, which can end up
+       meaning that the client isn't properly moved/resized by the fullscreen
+       function
+       pho can cause this because it maps at size of the screen but not 0,0
+       so openbox moves it on screen to 0,0 (thus x,y=0,0 and area.x,y don't).
+       then fullscreen'ing makes it go to 0,0 which it thinks it already is at
+       cuz thats where the pre-fullscreen will be. however the actual area is
+       not, so this needs to be called even if we have fullscreened/maxed
+    */
+    self->area = oldarea;
+    client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
 
     /* set the desktop hint, to make sure that it always exists */
     PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
@@ -2702,7 +2712,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
     /* gets the frame's position */
-    frame_client_gravity(self->frame, x, y, *w, *h);
+    frame_client_gravity(self->frame, x, y);
 
     /* these positions are frame positions, not client positions */
 
@@ -2749,7 +2759,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     }
 
     /* gets the client's position */
-    frame_frame_gravity(self->frame, x, y, *w, *h);
+    frame_frame_gravity(self->frame, x, y);
 
     /* work within the prefered sizes given by the window */
     if (!(*w == self->area.width && *h == self->area.height)) {
@@ -3029,6 +3039,9 @@ void client_fullscreen(ObClient *self, gboolean fs)
         RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
     }
 
+    ob_debug("Window %s going fullscreen (%d)\n",
+             self->title, self->fullscreen);
+
     client_setup_decor_and_functions(self, FALSE);
     client_move_resize(self, x, y, w, h);
 
@@ -3864,188 +3877,216 @@ ObClient *client_search_transient(ObClient *self, ObClient *search)
     return NULL;
 }
 
-#define WANT_EDGE(cur, c) \
-            if (cur == c)                                                     \
-                continue;                                                     \
-            if (c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&  \
-                cur->desktop != screen_desktop)                               \
-                continue;                                                     \
-            if (cur->iconic)                                                  \
-                continue;
-
-#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
-            if ((his_edge_start >= my_edge_start && \
-                 his_edge_start <= my_edge_end) ||  \
-                (my_edge_start >= his_edge_start && \
-                 my_edge_start <= his_edge_end))    \
-                dest = his_offset;
-
-/* finds the nearest edge in the given direction from the current client
- * note to self: the edge is the -frame- edge (the actual one), not the
- * client edge.
- */
-gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
+void client_find_edge_directional(ObClient *self, ObDirection dir,
+                                  gint my_head, gint my_size,
+                                  gint my_edge_start, gint my_edge_size,
+                                  gint *dest, gboolean *near_edge)
 {
-    gint dest, monitor_dest;
-    gint my_edge_start, my_edge_end, my_offset;
     GList *it;
     Rect *a, *mon;
-    
-    if(!client_list)
-        return -1;
+    gint edge;
 
-    a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
-    mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area);
+    a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS,
+                    &self->frame->area);
+    mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR,
+                      &self->frame->area);
 
     switch(dir) {
     case OB_DIRECTION_NORTH:
-        my_edge_start = c->frame->area.x;
-        my_edge_end = c->frame->area.x + c->frame->area.width;
-        my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
-        
-        /* default: top of screen */
-        dest = a->y + (hang ? c->frame->area.height : 0);
-        monitor_dest = mon->y + (hang ? c->frame->area.height : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset > monitor_dest)
-            dest = monitor_dest; 
-
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
-
-            WANT_EDGE(cur, c)
-
-            his_edge_start = cur->frame->area.x;
-            his_edge_end = cur->frame->area.x + cur->frame->area.width;
-            his_offset = cur->frame->area.y + 
-                         (hang ? 0 : cur->frame->area.height);
-
-            if(his_offset + 1 > my_offset)
-                continue;
-
-            if(his_offset < dest)
-                continue;
-
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
-        }
+        if (my_head >= RECT_TOP(*mon))
+            edge = RECT_TOP(*mon) - 1;
+        else
+            edge = RECT_TOP(*a) - 1;
         break;
     case OB_DIRECTION_SOUTH:
-        my_edge_start = c->frame->area.x;
-        my_edge_end = c->frame->area.x + c->frame->area.width;
-        my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
-
-        /* default: bottom of screen */
-        dest = a->y + a->height - (hang ? c->frame->area.height : 0);
-        monitor_dest = mon->y + mon->height -
-                       (hang ? c->frame->area.height : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset < monitor_dest)
-            dest = monitor_dest; 
-
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
-
-            WANT_EDGE(cur, c)
-
-            his_edge_start = cur->frame->area.x;
-            his_edge_end = cur->frame->area.x + cur->frame->area.width;
-            his_offset = cur->frame->area.y +
-                         (hang ? cur->frame->area.height : 0);
-
-
-            if(his_offset - 1 < my_offset)
-                continue;
-            
-            if(his_offset > dest)
-                continue;
-
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
-        }
+        if (my_head <= RECT_BOTTOM(*mon))
+            edge = RECT_BOTTOM(*mon) + 1;
+        else
+            edge = RECT_BOTTOM(*a) + 1;
+        break;
+    case OB_DIRECTION_EAST:
+        if (my_head <= RECT_RIGHT(*mon))
+            edge = RECT_RIGHT(*mon) + 1;
+        else
+            edge = RECT_RIGHT(*a) + 1;
         break;
     case OB_DIRECTION_WEST:
-        my_edge_start = c->frame->area.y;
-        my_edge_end = c->frame->area.y + c->frame->area.height;
-        my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
+        if (my_head >= RECT_LEFT(*mon))
+            edge = RECT_LEFT(*mon) - 1;
+        else
+            edge = RECT_LEFT(*a) - 1;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    /* default to the far edge, then narrow it down */
+    *dest = edge;
+    *near_edge = TRUE;
 
-        /* default: leftmost egde of screen */
-        dest = a->x + (hang ? c->frame->area.width : 0);
-        monitor_dest = mon->x + (hang ? c->frame->area.width : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset > monitor_dest)
-            dest = monitor_dest;            
+    for(it = client_list; it; it = g_list_next(it)) {
+        ObClient *cur = it->data;
+        gint edge_start, edge_size, head, tail;
+        gboolean skip_head = FALSE, skip_tail = FALSE;
 
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
+        /* skip windows to not bump into */
+        if (cur == self)
+            continue;
+        if (cur->iconic)
+            continue;
+        if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&
+            cur->desktop != screen_desktop)
+            continue;
 
-            WANT_EDGE(cur, c)
+        ob_debug("trying window %s\n", cur->title);
 
-            his_edge_start = cur->frame->area.y;
-            his_edge_end = cur->frame->area.y + cur->frame->area.height;
-            his_offset = cur->frame->area.x +
-                         (hang ? 0 : cur->frame->area.width);
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+        case OB_DIRECTION_SOUTH:
+            edge_start = cur->frame->area.x;
+            edge_size = cur->frame->area.width;
+            break;
+        case OB_DIRECTION_EAST:
+        case OB_DIRECTION_WEST:
+            edge_start = cur->frame->area.y;
+            edge_size = cur->frame->area.height;
+            break;
+        default:
+            g_assert_not_reached();
+        }
 
-            if(his_offset + 1 > my_offset)
-                continue;
+        /* do we collide with this window? */
+        if (!RANGES_INTERSECT(my_edge_start, my_edge_size,
+                              edge_start, edge_size))
+            continue;
 
-            if(his_offset < dest)
-                continue;
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+            head = RECT_BOTTOM(cur->frame->area);
+            tail = RECT_TOP(cur->frame->area);
+            break;
+        case OB_DIRECTION_SOUTH:
+            head = RECT_TOP(cur->frame->area);
+            tail = RECT_BOTTOM(cur->frame->area);
+            break;
+        case OB_DIRECTION_EAST:
+            head = RECT_LEFT(cur->frame->area);
+            tail = RECT_RIGHT(cur->frame->area);
+            break;
+        case OB_DIRECTION_WEST:
+            head = RECT_RIGHT(cur->frame->area);
+            tail = RECT_LEFT(cur->frame->area);
+            break;
+        default:
+            g_assert_not_reached();
+        }
 
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+        case OB_DIRECTION_WEST:
+            if (my_head <= head + 1)
+                skip_head = TRUE;
+            if (my_head + my_size - 1 <= tail + 1)
+                skip_tail = TRUE;
+            if (head < *dest)
+                skip_head = TRUE;
+            if (tail - my_size < *dest)
+                skip_tail = TRUE;
+            break;
+        case OB_DIRECTION_SOUTH:
+        case OB_DIRECTION_EAST:
+            if (my_head >= head - 1)
+                skip_head = TRUE;
+            if (my_head - my_size + 1 >= tail - 1)
+                skip_tail = TRUE;
+            if (head > *dest)
+                skip_head = TRUE;
+            if (tail + my_size > *dest)
+                skip_tail = TRUE;
+            break;
+        default:
+            g_assert_not_reached();
         }
-       break;
-    case OB_DIRECTION_EAST:
-        my_edge_start = c->frame->area.y;
-        my_edge_end = c->frame->area.y + c->frame->area.height;
-        my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
-        
-        /* default: rightmost edge of screen */
-        dest = a->x + a->width - (hang ? c->frame->area.width : 0);
-        monitor_dest = mon->x + mon->width -
-                       (hang ? c->frame->area.width : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset < monitor_dest)
-            dest = monitor_dest;            
-
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
-
-            WANT_EDGE(cur, c)
-
-            his_edge_start = cur->frame->area.y;
-            his_edge_end = cur->frame->area.y + cur->frame->area.height;
-            his_offset = cur->frame->area.x +
-                         (hang ? cur->frame->area.width : 0);
-
-            if(his_offset - 1 < my_offset)
-                continue;
-            
-            if(his_offset > dest)
-                continue;
 
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
+        ob_debug("my head %d size %d\n", my_head, my_size);
+        ob_debug("head %d tail %d deest %d\n", head, tail, *dest);
+        if (!skip_head) {
+            ob_debug("using near edge %d\n", head);
+            *dest = head;
+            *near_edge = TRUE;
         }
+        else if (!skip_tail) {
+            ob_debug("using far edge %d\n", tail);
+            *dest = tail;
+            *near_edge = FALSE;
+        }
+    }
+}
+
+void client_find_move_directional(ObClient *self, ObDirection dir,
+                                  gint *x, gint *y)
+{
+    gint head, size;
+    gint e, e_start, e_size;
+    gboolean near;
+
+    switch (dir) {
+    case OB_DIRECTION_EAST:
+        head = RECT_RIGHT(self->frame->area);
+        size = self->frame->area.width;
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        break;
+    case OB_DIRECTION_WEST:
+        head = RECT_LEFT(self->frame->area);
+        size = self->frame->area.width;
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        break;
+    case OB_DIRECTION_NORTH:
+        head = RECT_TOP(self->frame->area);
+        size = self->frame->area.height;
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
+        break;
+    case OB_DIRECTION_SOUTH:
+        head = RECT_BOTTOM(self->frame->area);
+        size = self->frame->area.height;
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
         break;
-    case OB_DIRECTION_NORTHEAST:
-    case OB_DIRECTION_SOUTHEAST:
-    case OB_DIRECTION_NORTHWEST:
-    case OB_DIRECTION_SOUTHWEST:
-        /* not implemented */
     default:
         g_assert_not_reached();
-        dest = 0; /* suppress warning */
     }
 
-    g_free(a);
-    g_free(mon);
-    return dest;
+    client_find_edge_directional(self, dir, head, size,
+                                 e_start, e_size, &e, &near);
+    *x = self->frame->area.x;
+    *y = self->frame->area.y;
+    switch (dir) {
+    case OB_DIRECTION_EAST:
+        if (near) e -= self->frame->area.width;
+        else      e++;
+        *x = e;
+        break;
+    case OB_DIRECTION_WEST:
+        if (near) e++;
+        else      e -= self->frame->area.width;
+        *x = e;
+        break;
+    case OB_DIRECTION_NORTH:
+        if (near) e++;
+        else      e -= self->frame->area.height;
+        *y = e;
+        break;
+    case OB_DIRECTION_SOUTH:
+        if (near) e -= self->frame->area.height;
+        else      e++;
+        *y = e;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    frame_frame_gravity(self->frame, x, y);
 }
 
 ObClient* client_under_pointer()
This page took 0.030063 seconds and 4 git commands to generate.