]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
Add MoveFromEdge* actions, shorten client_directional_edge_search with some handy...
[chaz/openbox] / openbox / client.c
index a8db51d3eca3cc0a760759f79d53fbc16b3a5be2..2fa7728ac35bf549fc4b456b94e3a183082a1b53 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
    
    client.c for the Openbox window manager
-   Copyright (c) 2004        Mikael Magnusson
+   Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003        Ben Jansens
 
    This program is free software; you can redistribute it and/or modify
@@ -204,8 +204,6 @@ void client_manage_all()
     XFree(children);
 }
 
-/* This should possibly do something more interesting than just match
- * against WM_CLASS literally. */
 static ObAppSettings *get_settings(ObClient *client)
 {
     GSList *a = config_per_app_settings;
@@ -213,7 +211,12 @@ static ObAppSettings *get_settings(ObClient *client)
     while (a) {
         ObAppSettings *app = (ObAppSettings *) a->data;
         
-        if (!strcmp(app->name, client->name)) {
+        if (
+            (app->name && !app->class && !strcmp(app->name, client->name))
+            || (app->class && !app->name && !strcmp(app->class, client->class))
+            || (app->class && app->name && !strcmp(app->class, client->class)
+                && !strcmp(app->name, client->name))
+            ) {
             ob_debug("Window matching: %s\n", app->name);
             /* Match if no role was specified in the per app setting, or if the string
              * matches the beginning of the role, since apps like to set the role to
@@ -319,6 +322,9 @@ void client_manage(Window window)
     /* get and set application level settings */
     settings = get_settings(self);
 
+    stacking_add(CLIENT_AS_WINDOW(self));
+    client_restore_session_stacking(self);
+
     if (settings) {
         /* Don't worry, we won't actually both shade and undecorate the
          * window when push comes to shove. */
@@ -327,21 +333,25 @@ void client_manage(Window window)
         if (settings->decor != -1)
             client_set_undecorated(self, !settings->decor);
         if (settings->iconic != -1)
-            client_iconify(self, settings->iconic);
-        if (settings->skip_pager != -1)
-            client->skip_pager = !!settings->skip_pager;
-        if (settings->skip_taskbar != -1)
-            client->skip_taskbar = !!settings->skip_taskbar;
+            client_iconify(self, settings->iconic, FALSE);
+        if (settings->skip_pager != -1) {
+            self->skip_pager = !!settings->skip_pager;
+            client_change_state(self);
+        }
+        if (settings->skip_taskbar != -1) {
+            self->skip_taskbar = !!settings->skip_taskbar;
+            client_change_state(self);
+        }
 
         /* 1 && -1 shouldn't be possible by the code in config.c */
-        if (settings->max_vert == 1 && self->max_horz == 1)
+        if (settings->max_vert == 1 && settings->max_horz == 1)
             client_maximize(self, TRUE, 0, TRUE);
-        else if (settings->max_vert == 0 && self->max_horz == 0)
+        else if (settings->max_vert == 0 && settings->max_horz == 0)
             client_maximize(self, FALSE, 0, TRUE);
-        else if (settings->max_vert == 1 && self->max_horz == 0) {
+        else if (settings->max_vert == 1 && settings->max_horz == 0) {
             client_maximize(self, TRUE, 2, TRUE);
             client_maximize(self, FALSE, 1, TRUE);
-        } else if (settings->max_vert == 0 && self->max_horz == 1) {
+        } else if (settings->max_vert == 0 && settings->max_horz == 1) {
             client_maximize(self, TRUE, 1, TRUE);
             client_maximize(self, FALSE, 2, TRUE);
         }
@@ -349,17 +359,15 @@ void client_manage(Window window)
         if (settings->fullscreen != -1)
             client_fullscreen(self, !!settings->fullscreen, TRUE);
 
-        if (settings->desktop < screen_num_desktops)
-            client_set_desktop(self, settings->desktop, FALSE);
+        if (settings->desktop < screen_num_desktops
+            || settings->desktop == DESKTOP_ALL)
+            client_set_desktop(self, settings->desktop, TRUE);
 
         if (settings->layer > -2 && settings->layer < 2)
             client_set_layer(self, settings->layer);
 
     }
 
-    stacking_add(CLIENT_AS_WINDOW(self));
-    client_restore_session_stacking(self);
-
     /* focus the new window? */
     if (ob_state() != OB_STATE_STARTING &&
         (config_focus_new || client_search_focus_parent(self)) ||
@@ -407,8 +415,9 @@ void client_manage(Window window)
     if (ob_state() == OB_STATE_RUNNING) {
         gint x = self->area.x, ox = x;
         gint y = self->area.y, oy = y;
+        gboolean transient;
 
-        place_client(self, &x, &y, settings);
+        transient = place_client(self, &x, &y, settings);
 
         /* make sure the window is visible. */
         client_find_onscreen(self, &x, &y,
@@ -424,10 +433,11 @@ void client_manage(Window window)
                                 off-screen and on xinerama divides (ie,
                                 it is up to the placement routines to avoid
                                 the xinerama divides) */
-                             ((self->positioned & PPosition) &&
-                              !(self->positioned & USPosition)) &&
-                             client_normal(self) &&
-                             !self->session);
+                             transient ||
+                             (((self->positioned & PPosition) &&
+                               !(self->positioned & USPosition)) &&
+                              client_normal(self) &&
+                              !self->session));
         if (x != ox || y != oy)         
             client_move(self, x, y);
     }
@@ -1227,7 +1237,7 @@ void client_update_normal_hints(ObClient *self)
         if (size.flags & PBaseSize)
             SIZE_SET(self->base_size, size.base_width, size.base_height);
     
-        if (size.flags & PResizeInc)
+        if (size.flags & PResizeInc && size.width_inc && size.height_inc)
             SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
     }
 }
@@ -1237,7 +1247,7 @@ void client_setup_decor_and_functions(ObClient *self)
     /* start with everything (cept fullscreen) */
     self->decorations =
         (OB_FRAME_DECOR_TITLEBAR |
-         (ob_rr_theme->show_handle ? OB_FRAME_DECOR_HANDLE : 0) |
+         OB_FRAME_DECOR_HANDLE |
          OB_FRAME_DECOR_GRIPS |
          OB_FRAME_DECOR_BORDER |
          OB_FRAME_DECOR_ICON |
@@ -1293,8 +1303,12 @@ void client_setup_decor_and_functions(ObClient *self)
             if (! ((self->mwmhints.decorations & OB_MWM_DECOR_HANDLE) ||
                    (self->mwmhints.decorations & OB_MWM_DECOR_TITLE)))
                 /* if the mwm hints request no handle or title, then all
-                   decorations are disabled */
-                self->decorations = config_theme_keepborder ? OB_FRAME_DECOR_BORDER : 0;
+                   decorations are disabled, but keep the border if that's
+                   specified */
+                if (self->mwmhints.decorations & OB_MWM_DECOR_BORDER)
+                    self->decorations = OB_FRAME_DECOR_BORDER;
+                else
+                    self->decorations = 0;
         }
     }
 
@@ -1528,7 +1542,8 @@ void client_update_title(ObClient *self)
     /* try netwm */
     if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
         /* try old x stuff */
-        if (!PROP_GETS(self->window, wm_name, locale, &data)) {
+        if (!(PROP_GETS(self->window, wm_name, locale, &data)
+              || PROP_GETS(self->window, wm_name, utf8, &data))) {
             // http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
             if (self->transient) {
                 data = g_strdup("");
@@ -1538,35 +1553,39 @@ void client_update_title(ObClient *self)
         }
     }
 
-    /* did the title change? then reset the title_count */
-    if (old_title && 0 != strncmp(old_title, data, strlen(data)))
-        self->title_count = 1;
+    if (config_title_number) {
 
-    /* look for duplicates and append a number */
-    nums = 0;
-    for (it = client_list; it; it = g_list_next(it))
-        if (it->data != self) {
-            ObClient *c = it->data;
-            if (0 == strncmp(c->title, data, strlen(data)))
-                nums |= 1 << c->title_count;
-        }
-    /* find first free number */
-    for (i = 1; i <= 32; ++i)
-        if (!(nums & (1 << i))) {
-            if (self->title_count == 1 || i == 1)
-                self->title_count = i;
-            break;
+        /* did the title change? then reset the title_count */
+        if (old_title && 0 != strncmp(old_title, data, strlen(data)))
+            self->title_count = 1;
+
+        /* look for duplicates and append a number */
+        nums = 0;
+        for (it = client_list; it; it = g_list_next(it))
+            if (it->data != self) {
+                ObClient *c = it->data;
+                if (0 == strncmp(c->title, data, strlen(data)))
+                    nums |= 1 << c->title_count;
+            }
+        /* find first free number */
+        for (i = 1; i <= 32; ++i)
+            if (!(nums & (1 << i))) {
+                if (self->title_count == 1 || i == 1)
+                    self->title_count = i;
+                break;
+            }
+        /* dont display the number for the first window */
+        if (self->title_count > 1) {
+            gchar *ndata;
+            ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
+            g_free(data);
+            data = ndata;
         }
-    /* dont display the number for the first window */
-    if (self->title_count > 1) {
-        gchar *ndata;
-        ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
-        g_free(data);
-        data = ndata;
-    }
+    } else
+        self->title_count = 1;
 
-    PROP_SETS(self->window, net_wm_visible_name, data);
 no_number:
+    PROP_SETS(self->window, net_wm_visible_name, data);
     self->title = data;
 
     if (self->frame)
@@ -1582,12 +1601,15 @@ no_number:
     /* try netwm */
     if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
         /* try old x stuff */
-        if (!PROP_GETS(self->window, wm_icon_name, locale, &data)) {
+        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data)
+              || PROP_GETS(self->window, wm_icon_name, utf8, &data))) {
             data = g_strdup(self->title);
             read_title = FALSE;
         }
 
-    /* append the title count, dont display the number for the first window */
+    /* append the title count, dont display the number for the first window.
+     * We don't need to check for config_title_number here since title_count
+     * is not set above 1 then. */
     if (read_title && self->title_count > 1) {
         gchar *vdata, *ndata;
         ndata = g_strdup_printf(" - [%u]", self->title_count);
@@ -2026,35 +2048,16 @@ void client_configure_full(ObClient *self, ObCorner anchor,
 
     /* set the size and position if fullscreen */
     if (self->fullscreen) {
-#ifdef VIDMODE
-        gint dot;
-        XF86VidModeModeLine mode;
-#endif
         Rect *a;
         guint i;
 
         i = client_monitor(self);
         a = screen_physical_area_monitor(i);
 
-#ifdef VIDMODE
-        if (i == 0 && /* primary head */
-            extensions_vidmode &&
-            XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y) &&
-            /* get the mode last so the mode.privsize isnt freed incorrectly */
-            XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) {
-            x += a->x;
-            y += a->y;
-            w = mode.hdisplay;
-            h = mode.vdisplay;
-            if (mode.privsize) XFree(mode.private);
-        } else
-#endif
-        {
-            x = a->x;
-            y = a->y;
-            w = a->width;
-            h = a->height;
-        }
+        x = a->x;
+        y = a->y;
+        w = a->width;
+        h = a->height;
 
         user = FALSE; /* ignore that increment etc shit when in fullscreen */
     } else {
@@ -2338,12 +2341,6 @@ static void client_iconify_recursive(ObClient *self,
             focus_order_remove(self);
             focus_order_add_new(self);
 
-            /* this is here cuz with the VIDMODE extension, the viewport can
-               change while a fullscreen window is iconic, and when it
-               uniconifies, it would be nice if it did so to the new position
-               of the viewport */
-            client_reconfigure(self);
-
             changed = TRUE;
         }
     }
@@ -2851,21 +2848,20 @@ gboolean client_focus(ObClient *self)
     return TRUE;
 }
 
+/* Used when the current client is closed, focus_last will then prevent
+ * focus from going to the mouse pointer */
 void client_unfocus(ObClient *self)
 {
     if (focus_client == self) {
 #ifdef DEBUG_FOCUS
         ob_debug("client_unfocus for %lx\n", self->window);
 #endif
-        focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING);
+        focus_fallback(OB_FOCUS_FALLBACK_CLOSED);
     }
 }
 
 void client_activate(ObClient *self, gboolean here)
 {
-    /* This check is for the client_list_menu trying to activate
-     * a closed client. */
-    if (!g_list_find(client_list, self)) return;
     if (client_normal(self) && screen_showing_desktop)
         screen_show_desktop(FALSE);
     if (self->iconic)
@@ -3220,11 +3216,30 @@ void client_update_sm_client_id(ObClient *self)
                   &self->sm_client_id);
 }
 
+#define WANT_EDGE(cur, c) \
+            if(cur == c)                                                      \
+                continue;                                                     \
+            if(!client_normal_or_dock(cur))                                   \
+                continue;                                                     \
+            if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \
+                continue;                                                     \
+            if(cur->iconic)                                                   \
+                continue;                                                     \
+            if(cur->layer < c->layer && !config_resist_layers_below)          \
+                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)
+gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
 {
     gint dest, monitor_dest;
     gint my_edge_start, my_edge_end, my_offset;
@@ -3241,11 +3256,11 @@ gint client_directional_edge_search(ObClient *c, ObDirection 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;
+        my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
         
         /* default: top of screen */
-        dest = a->y;
-        monitor_dest = monitor->y;
+        dest = a->y + (hang ? c->frame->area.height : 0);
+        monitor_dest = monitor->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)
@@ -3255,45 +3270,29 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
             gint his_edge_start, his_edge_end, his_offset;
             ObClient *cur = it->data;
 
-            if(cur == c)
-                continue;
-            if(!client_normal(cur))
-                continue;
-            if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
-                continue;
-            if(cur->iconic)
-                continue;
-            if(cur->layer < c->layer && !config_resist_layers_below)
-                continue;
+            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 + cur->frame->area.height;
+            his_offset = cur->frame->area.y + (hang ? 0 : cur->frame->area.height);
 
             if(his_offset + 1 > my_offset)
                 continue;
 
             if(his_offset < dest)
                 continue;
-            
-            if(his_edge_start >= my_edge_start &&
-               his_edge_start <= my_edge_end)
-                dest = his_offset;
-
-            if(my_edge_start >= his_edge_start &&
-               my_edge_start <= his_edge_end)
-                dest = his_offset;
 
+            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
         }
         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 + c->frame->area.height;
+        my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
 
         /* default: bottom of screen */
-        dest = a->y + a->height;
-        monitor_dest = monitor->y + monitor->height;
+        dest = a->y + a->height - (hang ? c->frame->area.height : 0);
+        monitor_dest = monitor->y + monitor->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)
@@ -3303,20 +3302,11 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
             gint his_edge_start, his_edge_end, his_offset;
             ObClient *cur = it->data;
 
-            if(cur == c)
-                continue;
-            if(!client_normal(cur))
-                continue;
-            if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
-                continue;
-            if(cur->iconic)
-                continue;
-            if(cur->layer < c->layer && !config_resist_layers_below)
-                continue;
+            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;
+            his_offset = cur->frame->area.y + (hang ? cur->frame->area.height : 0);
 
 
             if(his_offset - 1 < my_offset)
@@ -3324,25 +3314,18 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
             
             if(his_offset > dest)
                 continue;
-            
-            if(his_edge_start >= my_edge_start &&
-               his_edge_start <= my_edge_end)
-                dest = his_offset;
-
-            if(my_edge_start >= his_edge_start &&
-               my_edge_start <= his_edge_end)
-                dest = his_offset;
 
+            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
         }
         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;
+        my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
 
         /* default: leftmost egde of screen */
-        dest = a->x;
-        monitor_dest = monitor->x;
+        dest = a->x + (hang ? c->frame->area.width : 0);
+        monitor_dest = monitor->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)
@@ -3352,46 +3335,29 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
             gint his_edge_start, his_edge_end, his_offset;
             ObClient *cur = it->data;
 
-            if(cur == c)
-                continue;
-            if(!client_normal(cur))
-                continue;
-            if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
-                continue;
-            if(cur->iconic)
-                continue;
-            if(cur->layer < c->layer && !config_resist_layers_below)
-                continue;
+            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 + cur->frame->area.width;
+            his_offset = cur->frame->area.x + (hang ? 0 : cur->frame->area.width);
 
             if(his_offset + 1 > my_offset)
                 continue;
-            
+
             if(his_offset < dest)
                 continue;
-            
-            if(his_edge_start >= my_edge_start &&
-               his_edge_start <= my_edge_end)
-                dest = his_offset;
-
-            if(my_edge_start >= his_edge_start &&
-               my_edge_start <= his_edge_end)
-                dest = his_offset;
-                
 
+            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
         }
-        break;
+       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 + c->frame->area.width;
+        my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
         
         /* default: rightmost edge of screen */
-        dest = a->x + a->width;
-        monitor_dest = monitor->x + monitor->width;
+        dest = a->x + a->width - (hang ? c->frame->area.width : 0);
+        monitor_dest = monitor->x + monitor->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)
@@ -3401,35 +3367,19 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
             gint his_edge_start, his_edge_end, his_offset;
             ObClient *cur = it->data;
 
-            if(cur == c)
-                continue;
-            if(!client_normal(cur))
-                continue;
-            if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
-                continue;
-            if(cur->iconic)
-                continue;
-            if(cur->layer < c->layer && !config_resist_layers_below)
-                continue;
+            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;
+            his_offset = cur->frame->area.x + (hang ? cur->frame->area.width : 0);
 
             if(his_offset - 1 < my_offset)
                 continue;
             
             if(his_offset > dest)
                 continue;
-            
-            if(his_edge_start >= my_edge_start &&
-               his_edge_start <= my_edge_end)
-                dest = his_offset;
-
-            if(my_edge_start >= his_edge_start &&
-               my_edge_start <= his_edge_end)
-                dest = his_offset;
 
+            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
         }
         break;
     case OB_DIRECTION_NORTHEAST:
This page took 0.036005 seconds and 4 git commands to generate.