]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
fix window gravity..
[chaz/openbox] / openbox / client.c
index cfe2958be32b916021d987efc08b58e6dd27fcad..557909a1da2954fc1c26d08654abc4605e5ee077 100644 (file)
@@ -241,6 +241,7 @@ void client_manage(Window window)
     XWMHints *wmhint;
     gboolean activate = FALSE;
     ObAppSettings *settings;
+    gint placex, placey;
 
     grab_server(TRUE);
 
@@ -314,7 +315,8 @@ void client_manage(Window window)
     grab_server(FALSE);
 
     /* per-app settings override stuff from client_get_all, and return the
-       settings for other uses too */
+       settings for other uses too. the returned settings is a shallow copy,
+       that needs to be freed with g_free(). */
     settings = client_get_settings_state(self);
     /* the session should get the last say thought */
     client_restore_session_state(self);
@@ -358,6 +360,15 @@ void client_manage(Window window)
         activate = TRUE;
     }
 
+    /* adjust the frame to the client's size before showing or placing
+       the window */
+    frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+    frame_adjust_client_area(self->frame);
+
+    /* where the frame was placed is where the window was originally */
+    placex = self->area.x;
+    placey = self->area.y;
+
     /* figure out placement for the window */
     if (ob_state() == OB_STATE_RUNNING) {
         gboolean transient;
@@ -368,10 +379,10 @@ void client_manage(Window window)
                    (self->positioned == USPosition ? "user specified" :
                     "BADNESS !?"))), self->area.x, self->area.y);
 
-        transient = place_client(self, &self->area.x, &self->area.y, settings);
+        transient = place_client(self, &placex, &placey, settings);
 
         /* make sure the window is visible. */
-        client_find_onscreen(self, &self->area.x, &self->area.y,
+        client_find_onscreen(self, &placex, &placey,
                              self->area.width, self->area.height,
                              /* non-normal clients has less rules, and
                                 windows that are being restored from a
@@ -391,31 +402,32 @@ void client_manage(Window window)
     }
 
     ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
-             self->window, self->area.x, self->area.y,
+             self->window, placex, placey,
              self->area.width, self->area.height);
     if (self->session)
         ob_debug("  but session requested %d %d instead, overriding\n",
                  self->session->x, self->session->y);
 
-    /* adjust the frame to the client's size before showing the window */
-    frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
-    frame_adjust_client_area(self->frame);
-
+    /* do this after the window is placed, so the premax/prefullscreen numbers
+       won't be all wacko!!
+       also, this moves the window to the position where it has been placed
+    */
+    client_apply_startup_state(self);
 
     /* move the client to its placed position, or it it's already there,
        generate a ConfigureNotify telling the client where it is.
 
        do this after adjusting the frame. otherwise it gets all weird and
-       clients don't work right */
-    client_configure_full(self, self->area.x, self->area.y,
-                          self->area.width, self->area.height,
-                          FALSE, TRUE);
+       clients don't work right
 
-    /* do this after the window is placed, so the premax/prefullscreen numbers
-       won't be all wacko!!
-       also, this moves the window to the position where it has been placed
+       also do this after applying the startup state so maximize and fullscreen
+       will get the right sizes and positions if the client is starting with
+       those states
     */
-    client_apply_startup_state(self);
+    client_configure(self, placex, placey,
+                     self->area.width, self->area.height,
+                     FALSE, TRUE);
+
 
     if (activate) {
         guint32 last_time = focus_client ?
@@ -506,6 +518,9 @@ void client_manage(Window window)
     /* update the list hints */
     client_set_list();
 
+    /* free the ObAppSettings shallow copy */
+    g_free(settings);
+
     ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
              window, self->frame->plate, self->class);
 
@@ -527,7 +542,7 @@ ObClient *client_fake_manage(Window window)
 
     client_get_all(self, FALSE);
     /* per-app settings override stuff, and return the settings for other
-       uses too */
+       uses too. this returns a shallow copy that needs to be freed */
     settings = client_get_settings_state(self);
 
     client_setup_decor_and_functions(self);
@@ -535,6 +550,10 @@ ObClient *client_fake_manage(Window window)
     /* create the decoration frame for the client window and adjust its size */
     self->frame = frame_new(self);
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
+
+    /* free the ObAppSettings shallow copy */
+    g_free(settings);
+
     return self;
 }
 
@@ -565,7 +584,7 @@ void client_unmanage(ObClient *self)
 
     /* ignore enter events from the unmap so it doesnt mess with the
        focus */
-    event_ignore_queued_enters();
+    event_ignore_all_queued_enters();
 
     mouse_grab_for_client(self, FALSE);
 
@@ -641,6 +660,8 @@ void client_unmanage(ObClient *self)
         }
 
         self->fullscreen = self->max_horz = self->max_vert = FALSE;
+        /* let it be moved and resized no matter what */
+        self->functions = OB_CLIENT_FUNC_MOVE | OB_CLIENT_FUNC_RESIZE;
         self->decorations = 0; /* unmanaged windows have no decor */
 
         client_move_resize(self, a.x, a.y, a.width, a.height);
@@ -694,73 +715,82 @@ void client_fake_unmanage(ObClient *self)
     g_free(self);
 }
 
+/*! Returns a new structure containing the per-app settings for this client.
+  The returned structure needs to be freed with g_free. */
 static ObAppSettings *client_get_settings_state(ObClient *self)
 {
-    ObAppSettings *settings = NULL;
+    ObAppSettings *settings;
     GSList *it;
 
+    settings = config_create_app_settings();
+
     for (it = config_per_app_settings; it; it = g_slist_next(it)) {
         ObAppSettings *app = it->data;
-        
-        if ((app->name && !app->class && !strcmp(app->name, self->name))
-            || (app->class && !app->name && !strcmp(app->class, self->class))
-            || (app->class && app->name && !strcmp(app->class, self->class)
-                && !strcmp(app->name, self->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 things like browser-window-23c4b2f */
-            if (!app->role
-                || !strncmp(app->role, self->role, strlen(app->role)))
-            {
-                ob_debug("Window matching: %s\n", app->name);
-                /* use this one */
-                settings = app;
-                break;
-            }
-        }
+        gboolean match = TRUE;
+
+        g_assert(app->name != NULL || app->class != NULL);
+
+        /* we know that either name or class is not NULL so it will have to
+           match to use the rule */
+        if (app->name &&
+            !g_pattern_match(app->name, strlen(self->name), self->name, NULL))
+            match = FALSE;
+        else if (app->class &&
+                !g_pattern_match(app->class,
+                                 strlen(self->class), self->class, NULL))
+            match = FALSE;
+        else if (app->role &&
+                 !g_pattern_match(app->role,
+                                  strlen(self->role), self->role, NULL))
+            match = FALSE;
+
+        if (match) {
+            ob_debug("Window matching: %s\n", app->name);
+
+            /* copy the settings to our struct, overriding the existing
+               settings if they are not defaults */
+            config_app_settings_copy_non_defaults(app, settings);
+        }
+    }
+
+    if (settings->shade != -1)
+        self->shaded = !!settings->shade;
+    if (settings->decor != -1)
+        self->undecorated = !settings->decor;
+    if (settings->iconic != -1)
+        self->iconic = !!settings->iconic;
+    if (settings->skip_pager != -1)
+        self->skip_pager = !!settings->skip_pager;
+    if (settings->skip_taskbar != -1)
+        self->skip_taskbar = !!settings->skip_taskbar;
+
+    if (settings->max_vert != -1)
+        self->max_vert = !!settings->max_vert;
+    if (settings->max_horz != -1)
+        self->max_horz = !!settings->max_horz;
+
+    if (settings->fullscreen != -1)
+        self->fullscreen = !!settings->fullscreen;
+
+    if (settings->desktop) {
+        if (settings->desktop == DESKTOP_ALL)
+            self->desktop = settings->desktop;
+        else if (settings->desktop > 0 &&
+                 settings->desktop <= screen_num_desktops)
+            self->desktop = settings->desktop - 1;
+    }
+
+    if (settings->layer == -1) {
+        self->below = TRUE;
+        self->above = FALSE;
     }
-
-    if (settings) {
-        if (settings->shade != -1)
-            self->shaded = !!settings->shade;
-        if (settings->decor != -1)
-            self->undecorated = !settings->decor;
-        if (settings->iconic != -1)
-            self->iconic = !!settings->iconic;
-        if (settings->skip_pager != -1)
-            self->skip_pager = !!settings->skip_pager;
-        if (settings->skip_taskbar != -1)
-            self->skip_taskbar = !!settings->skip_taskbar;
-
-        if (settings->max_vert != -1)
-            self->max_vert = !!settings->max_vert;
-        if (settings->max_horz != -1)
-            self->max_horz = !!settings->max_horz;
-
-        if (settings->fullscreen != -1)
-            self->fullscreen = !!settings->fullscreen;
-
-        if (settings->desktop) {
-            if (settings->desktop == DESKTOP_ALL)
-                self->desktop = settings->desktop;
-            else if (settings->desktop > 0 &&
-                     settings->desktop <= screen_num_desktops)
-                self->desktop = settings->desktop - 1;
-        }
-
-        if (settings->layer == -1) {
-            self->below = TRUE;
-            self->above = FALSE;
-        }
-        else if (settings->layer == 0) {
-            self->below = FALSE;
-            self->above = FALSE;
-        }
-        else if (settings->layer == 1) {
-            self->below = FALSE;
-            self->above = TRUE;
-        }
+    else if (settings->layer == 0) {
+        self->below = FALSE;
+        self->above = FALSE;
+    }
+    else if (settings->layer == 1) {
+        self->below = FALSE;
+        self->above = TRUE;
     }
     return settings;
 }
@@ -853,9 +883,11 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     gint ox = *x, oy = *y;
     gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude;
     gint fw, fh;
+    Rect desired;
 
+    RECT_SET(desired, *x, *y, w, h);
     all_a = screen_area(self->desktop);
-    mon_a = screen_area_monitor(self->desktop, client_monitor(self));
+    mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired));
 
     /* get where the frame would be */
     frame_client_gravity(self->frame, x, y, w, h);
@@ -905,10 +937,10 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
         POINT_SET(newbl, newtl.x, newbr.y);
 
         /* is it moving or just resizing from some corner? */
-        stationary_l = oldtl.x == oldtl.x;
-        stationary_r = oldtr.x == oldtr.x;
-        stationary_t = oldtl.y == oldtl.y;
-        stationary_b = oldbl.y == oldbl.y;
+        stationary_l = oldtl.x == newtl.x;
+        stationary_r = oldtr.x == newtr.x;
+        stationary_t = oldtl.y == newtl.y;
+        stationary_b = oldbl.y == newbl.y;
 
         /* if left edge is growing and didnt move right edge */
         if (stationary_r && newtl.x < oldtl.x)
@@ -1563,6 +1595,8 @@ void client_update_normal_hints(ObClient *self)
     }
 }
 
+/*! This needs to be followed by a call to client_configure to make
+  the changes show */
 void client_setup_decor_and_functions(ObClient *self)
 {
     /* start with everything (cept fullscreen) */
@@ -1585,7 +1619,8 @@ void client_setup_decor_and_functions(ObClient *self)
          OB_CLIENT_FUNC_SHADE |
          OB_CLIENT_FUNC_CLOSE |
          OB_CLIENT_FUNC_BELOW |
-         OB_CLIENT_FUNC_ABOVE);
+         OB_CLIENT_FUNC_ABOVE |
+         OB_CLIENT_FUNC_UNDECORATE);
 
     if (!(self->min_size.width < self->max_size.width ||
           self->min_size.height < self->max_size.height))
@@ -1615,11 +1650,13 @@ void client_setup_decor_and_functions(ObClient *self)
            do with them is move them */
         self->decorations = 0;
         self->functions = OB_CLIENT_FUNC_MOVE;
+        break;
 
     case OB_CLIENT_TYPE_DESKTOP:
         /* these windows are not manipulated by the window manager */
         self->decorations = 0;
         self->functions = 0;
+        break;
 
     case OB_CLIENT_TYPE_DOCK:
         /* these windows are not manipulated by the window manager, but they
@@ -1680,10 +1717,15 @@ void client_setup_decor_and_functions(ObClient *self)
         self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE;
     }
 
-    /* kill the handle on fully maxed windows */
-    if (self->max_vert && self->max_horz)
+    if (self->max_horz && self->max_vert)
+        /* kill the handle on fully maxed windows */
         self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS);
 
+    /* If there are no decorations to remove, don't allow the user to try
+       toggle the state */
+    if (self->decorations == 0)
+        self->functions &= ~OB_CLIENT_FUNC_UNDECORATE;
+
     /* finally, the user can have requested no decorations, which overrides
        everything (but doesnt give it a border if it doesnt have one) */
     if (self->undecorated) {
@@ -1706,16 +1748,11 @@ void client_setup_decor_and_functions(ObClient *self)
     }
 
     client_change_allowed_actions(self);
-
-    if (self->frame) {
-        /* adjust the client's decorations, etc. */
-        client_reconfigure(self);
-    }
 }
 
 static void client_change_allowed_actions(ObClient *self)
 {
-    gulong actions[11];
+    gulong actions[12];
     gint num = 0;
 
     /* desktop windows are kept on all desktops */
@@ -1742,6 +1779,8 @@ static void client_change_allowed_actions(ObClient *self)
         actions[num++] = prop_atoms.net_wm_action_above;
     if (self->functions & OB_CLIENT_FUNC_BELOW)
         actions[num++] = prop_atoms.net_wm_action_below;
+    if (self->functions & OB_CLIENT_FUNC_UNDECORATE)
+        actions[num++] = prop_atoms.ob_wm_action_undecorate;
 
     PROP_SETA32(self->window, net_wm_allowed_actions, atom, actions, num);
 
@@ -2407,13 +2446,13 @@ gboolean client_show(ObClient *self)
     if (client_should_show(self)) {
         frame_show(self->frame);
         show = TRUE;
-    }
 
-    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
-       needs to be in IconicState. This includes when it is on another
-       desktop!
-    */
-    client_change_wm_state(self);
+        /* According to the ICCCM (sec 4.1.3.1) when a window is not visible,
+           it needs to be in IconicState. This includes when it is on another
+           desktop!
+        */
+        client_change_wm_state(self);
+    }
     return show;
 }
 
@@ -2436,13 +2475,13 @@ gboolean client_hide(ObClient *self)
 
         frame_hide(self->frame);
         hide = TRUE;
-    }
 
-    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
-       needs to be in IconicState. This includes when it is on another
-       desktop!
-    */
-    client_change_wm_state(self);
+        /* According to the ICCCM (sec 4.1.3.1) when a window is not visible,
+           it needs to be in IconicState. This includes when it is on another
+           desktop!
+        */
+        client_change_wm_state(self);
+    }
     return hide;
 }
 
@@ -2450,12 +2489,6 @@ void client_showhide(ObClient *self)
 {
     if (!client_show(self))
         client_hide(self);
-
-    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
-       needs to be in IconicState. This includes when it is on another
-       desktop!
-    */
-    client_change_wm_state(self);
 }
 
 gboolean client_normal(ObClient *self) {
@@ -2558,7 +2591,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     /* make the frame recalculate its dimentions n shit without changing
        anything visible for real, this way the constraints below can work with
        the updated frame dimensions. */
-    frame_adjust_area(self->frame, TRUE, TRUE, TRUE);
+    frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
     /* work within the prefered sizes given by the window */
     if (!(*w == self->area.width && *h == self->area.height)) {
@@ -2704,14 +2737,16 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 }
 
 
-void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
-                           gboolean user, gboolean final)
+void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
+                      gboolean user, gboolean final)
 {
     gint oldw, oldh;
     gboolean send_resize_client;
     gboolean moved = FALSE, resized = FALSE;
+    gboolean fmoved, fresized;
     guint fdecor = self->frame->decorations;
     gboolean fhorz = self->frame->max_horz;
+    gboolean fvert = self->frame->max_vert;
     gint logicalw, logicalh;
 
     /* find the new x, y, width, and height (and logical size) */
@@ -2745,10 +2780,19 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
     }
 
     /* find the frame's dimensions and move/resize it */
-    if (self->decorations != fdecor || self->max_horz != fhorz)
-        moved = resized = TRUE;
-    if (moved || resized)
-        frame_adjust_area(self->frame, moved, resized, FALSE);
+    fmoved = moved;
+    fresized = resized;
+
+    /* if decorations changed, then readjust everything for the frame */
+    if (self->decorations != fdecor ||
+        self->max_horz != fhorz || self->max_vert != fvert)
+    {
+        fmoved = fresized = TRUE;
+    }
+
+    /* adjust the frame */
+    if (fmoved || fresized)
+        frame_adjust_area(self->frame, fmoved, fresized, FALSE);
 
     if ((!user || (user && final)) && !resized)
     {
@@ -3056,7 +3100,7 @@ void client_set_desktop_recursive(ObClient *self,
     guint old;
     GSList *it;
 
-    if (target != self->desktop) {
+    if (target != self->desktop && self->type != OB_CLIENT_TYPE_DESKTOP) {
 
         ob_debug("Setting desktop %u\n", target+1);
 
@@ -3269,10 +3313,6 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         }
     }
 
-    /* Grab pointer across these, so it is the same as actions. Enter events
-       won't be generated by the windows moving around */
-    grab_pointer(FALSE, FALSE, OB_CURSOR_NONE);
-
     if (max_horz != self->max_horz || max_vert != self->max_vert) {
         if (max_horz != self->max_horz && max_vert != self->max_vert) {
             /* toggling both */
@@ -3304,19 +3344,18 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         client_calc_layer(self);
     }
 
-    /* These things below can change focus so we can't grab pointer for them */
-    ungrab_pointer();
-
     if (modal != self->modal) {
         self->modal = modal;
         /* when a window changes modality, then its stacking order with its
            transients needs to change */
         stacking_raise(CLIENT_AS_WINDOW(self));
+
         /* it also may get focused. if something is focused that shouldn't
            be focused anymore, then move the focus */
         if (focus_client && client_focus_target(focus_client) != focus_client)
             client_focus(focus_client);
     }
+
     if (iconic != self->iconic)
         client_iconify(self, iconic, FALSE, FALSE);
 
@@ -3463,12 +3502,9 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
                   self->window, event_curtime, last_time,
                   (user ? "user" : "application"), allow);
 
-    if (allow) {
-        if (event_curtime != CurrentTime)
-            self->user_time = event_curtime;
-
+    if (allow)
         client_present(self, here, TRUE);
-    else
+    else
         /* don't focus it but tell the user it wants attention */
         client_hilite(self, TRUE);
 }
@@ -3573,16 +3609,14 @@ void client_set_layer(ObClient *self, gint layer)
 
 void client_set_undecorated(ObClient *self, gboolean undecorated)
 {
-    if (self->undecorated != undecorated) {
+    if (self->undecorated != undecorated &&
+        /* don't let it undecorate if the function is missing, but let 
+           it redecorate */
+        (self->functions & OB_CLIENT_FUNC_UNDECORATE || !undecorated))
+    {
         self->undecorated = undecorated;
         client_setup_decor_and_functions(self);
-        /* Make sure the client knows it might have moved. Maybe there is a
-         * better way of doing this so only one client_configure is sent, but
-         * since 125 of these are sent per second when moving the window (with
-         * user = FALSE) i doubt it matters much.
-         */
-        client_configure(self, self->area.x, self->area.y,
-                         self->area.width, self->area.height, TRUE, TRUE);
+        client_reconfigure(self); /* show the lack of decorations */
         client_change_state(self); /* reflect this in the state hints */
     }
 }
This page took 0.03827 seconds and 4 git commands to generate.