Detect input shapes
[mikachu/openbox.git] / openbox / client.c
index 2fbd020..bdf1258 100644 (file)
@@ -1384,6 +1384,7 @@ static void client_get_state(ObClient *self)
 static void client_get_shaped(ObClient *self)
 {
     self->shaped = FALSE;
+    self->shaped_input = FALSE;
 #ifdef SHAPE
     if (obt_display_extension_shape) {
         gint foo;
@@ -1396,6 +1397,23 @@ static void client_get_shaped(ObClient *self)
                            &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo,
                            &ufoo);
         self->shaped = !!s;
+#ifdef ShapeInput
+        { /* when some smart people added ShapeInput they forgot to update XShapeQueryExtents or
+             add a new one for input shapes, so we get to do this instead, yay! */
+            int nrects, ordering;
+            XRectangle *input_rect = XShapeGetRectangles(obt_display, self->window,
+                                                         ShapeInput, &nrects, &ordering);
+            if (nrects == 1 && input_rect->width == self->area.width &&
+                               input_rect->height == self->area.height &&
+                               /* openbox sets the border width of client windows to 0 */
+                               input_rect->x == 0 && input_rect->y == 0) {
+                self->shaped_input = FALSE;
+            } else {
+                self->shaped_input = TRUE;
+            }
+            XFree(input_rect);
+        }
+#endif
     }
 #endif
 }
@@ -1717,18 +1735,21 @@ void client_update_opacity(ObClient *self)
         OBT_PROP_ERASE(self->frame->window, NET_WM_WINDOW_OPACITY);
 }
 
-void client_update_normal_hints(ObClient *self)
+void client_update_normal_hints(ObClient *realself)
 {
-    XSizeHints size;
+    XSizeHints size = {0};
     glong ret;
+    ObClient *self = g_new(ObClient, 1);
 
     /* defaults */
-    self->min_ratio = 0.0f;
-    self->max_ratio = 0.0f;
-    SIZE_SET(self->size_inc, 1, 1);
-    SIZE_SET(self->base_size, -1, -1);
-    SIZE_SET(self->min_size, 0, 0);
-    SIZE_SET(self->max_size, G_MAXINT, G_MAXINT);
+    realself->min_ratio = 0.0f;
+    realself->max_ratio = 0.0f;
+    SIZE_SET(realself->size_inc, 1, 1);
+    SIZE_SET(realself->base_size, -1, -1);
+    SIZE_SET(realself->min_size, 0, 0);
+    SIZE_SET(realself->max_size, G_MAXINT, G_MAXINT);
+
+    memcpy(self, realself, sizeof(ObClient));
 
     /* get the hints from the window */
     if (XGetWMNormalHints(obt_display, self->window, &size, &ret)) {
@@ -1742,6 +1763,9 @@ void client_update_normal_hints(ObClient *self)
             self->gravity = size.win_gravity;
 
         if (size.flags & PAspect) {
+            if ((unsigned int)size.min_aspect.x > 4096 ||
+                (unsigned int)size.min_aspect.y > 4096)
+                goto invalid_hints;
             if (size.min_aspect.y)
                 self->min_ratio =
                     (gfloat) size.min_aspect.x / size.min_aspect.y;
@@ -1750,17 +1774,33 @@ void client_update_normal_hints(ObClient *self)
                     (gfloat) size.max_aspect.x / size.max_aspect.y;
         }
 
-        if (size.flags & PMinSize)
+        if (size.flags & PMinSize) {
+            if ((unsigned int)size.min_width > 4096 ||
+                (unsigned int)size.min_height > 4096)
+                goto invalid_hints;
             SIZE_SET(self->min_size, size.min_width, size.min_height);
+        }
 
-        if (size.flags & PMaxSize)
+        if (size.flags & PMaxSize) {
+            if ((unsigned int)size.max_width > 4096 ||
+                (unsigned int)size.max_height > 4096)
+                goto invalid_hints;
             SIZE_SET(self->max_size, size.max_width, size.max_height);
+        }
 
-        if (size.flags & PBaseSize)
+        if (size.flags & PBaseSize) {
+            if ((unsigned int)size.base_width > 4096 ||
+                (unsigned int)size.base_height > 4096)
+                goto invalid_hints;
             SIZE_SET(self->base_size, size.base_width, size.base_height);
+        }
 
-        if (size.flags & PResizeInc && size.width_inc && size.height_inc)
+        if (size.flags & PResizeInc && size.width_inc && size.height_inc) {
+            if ((unsigned int)size.width_inc > 4096 ||
+                (unsigned int)size.width_inc > 4096)
+                goto invalid_hints;
             SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
+        }
 
         ob_debug("Normal hints: min size (%d %d) max size (%d %d)",
                  self->min_size.width, self->min_size.height,
@@ -1771,6 +1811,11 @@ void client_update_normal_hints(ObClient *self)
     }
     else
         ob_debug("Normal hints: not set");
+    memcpy(realself, self, sizeof(ObClient));
+    g_free(self);
+    return;
+invalid_hints:
+    ob_debug("Normal hints: corruption detected, not setting anything");
 }
 
 static void client_setup_default_decor_and_functions(ObClient *self)
@@ -1939,6 +1984,7 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
     /* now we need to check against rules for the client's current state */
     if (self->fullscreen) {
         self->functions &= (OB_CLIENT_FUNC_CLOSE |
+                            OB_CLIENT_FUNC_MOVE |
                             OB_CLIENT_FUNC_FULLSCREEN |
                             OB_CLIENT_FUNC_ICONIFY);
         self->decorations = 0;