]> Dogcows Code - chaz/openbox/commitdiff
Merge branch 'master' into chaz
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 26 Oct 2012 19:03:24 +0000 (13:03 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 26 Oct 2012 19:03:24 +0000 (13:03 -0600)
Conflicts:
openbox/config.c

1  2 
data/rc.xml
data/rc.xsd
openbox/client.c
openbox/client.h
openbox/config.c
openbox/config.h
openbox/frame.c
openbox/moveresize.c

diff --combined data/rc.xml
index 70ad9bf9c39bdc72fc83caa0d1c2f2726e2995f8,932521b7095dfe6603d4dc6addb1e8a65d38e643..ce1e8fc1f8d0775f323c1cef3231ae2d9d2cb789
@@@ -33,9 -33,6 +33,6 @@@
  <placement>
    <policy>Smart</policy>
    <!-- 'Smart' or 'UnderMouse' -->
-   <center>yes</center>
-   <!-- whether to place windows in the center of the free area found or
-        the top left corner -->
    <monitor>Primary</monitor>
    <!-- with Smart placement on a multi-monitor system, try to place new windows
         on: 'Any' - any monitor, 'Mouse' - where the mouse is, 'Active' - where
@@@ -63,8 -60,6 +60,8 @@@
    -->
    <keepBorder>yes</keepBorder>
    <animateIconify>yes</animateIconify>
 +  <flashFrameDelay>600</flashFrameDelay>
 +  <flashFrameDuration>5000</flashFrameDuration>
    <font place="ActiveWindow">
      <name>sans</name>
      <size>8</size>
         submenu will not be shown until it is clicked on -->
    <submenuHideDelay>400</submenuHideDelay>
    <!-- time to delay before hiding a submenu when selecting another
-        entry in parent menu -->
+        entry in parent menu
         if this is a negative value, then the delay is infinite and the
         submenu will not be hidden until a different submenu is opened -->
-   <applicationIcons>yes</applicationIcons>
+   <showIcons>yes</showIcons>
    <!-- controls if icons appear in the client-list-(combined-)menu -->
    <manageDesktops>yes</manageDesktops>
    <!-- show the manage desktops section in the client-list-(combined-)menu -->
  
    <application name="the window's _OB_APP_NAME property (see obxprop)"
                class="the window's _OB_APP_CLASS property (see obxprop)"
+           groupname="the window's _OB_APP_GROUP_NAME property (see obxprop)"
+          groupclass="the window's _OB_APP_GROUP_CLASS property (see obxprop)"
                 role="the window's _OB_APP_ROLE property (see obxprop)"
                title="the window's _OB_APP_TITLE property (see obxprop)"
                 type="the window's _OB_APP_TYPE property (see obxprob)..
        # applications who refuse to behave
        <x>center</x>
        # a number like 50, or 'center' to center on screen. use a negative number
-       # to start from the right (or bottom for <y>), ie -50 is 50 pixels from the
-       # right edge (or bottom).
+       # to start from the right (or bottom for <y>), ie -50 is 50 pixels from
+       # the right edge (or bottom). use 'default' to specify using value
+       # provided by the application, or chosen by openbox, instead.
        <y>200</y>
        <monitor>1</monitor>
        # specifies the monitor in a xinerama setup.
        # 1 is the first head, or 'mouse' for wherever the mouse is
      </position>
  
+     <size>
+       # the size to make the window.
+       <width>20</width>
+       # a number like 20, or 'default' to use the size given by the application.
+       # you can use fractions such as 1/2 or percentages such as 75% in which
+       # case the value is relative to the size of the monitor that the window
+       # appears on.
+       <height>30%</height>
+     </size>
      <focus>yes</focus>
      # if the window should try be given focus when it appears. if this is set
      # to yes it doesn't guarantee the window will be given focus. some
  
      <maximized>true</maximized>
      # 'Horizontal', 'Vertical' or boolean (yes/no)
 +
 +    <opacity>255</opacity>
 +    # make the window semi-transparent
 +    # value between 0 and 255, inclusive; 0 invisible, 255 fully opaque
    </application>
  
    # end of the example
diff --combined data/rc.xsd
index 4585f7cc461fcbf36fc9f8fdd7c6578581fb8d86,425d53c9fd3fd6e2f4abaaa10df1cc5aa98ba7d3..0fd98ffb87c01c0df645f813c5b772ad5ee48699
@@@ -70,9 -70,8 +70,8 @@@
          </xsd:annotation>
          <xsd:sequence>
              <xsd:element minOccurs="0" name="policy" type="ob:placementpolicy"/>
-             <xsd:element minOccurs="0" name="center" type="ob:bool"/>
              <xsd:element minOccurs="0" name="monitor" type="ob:placementmonitor"/>
-             <xsd:element minOccurs="0" name="monitor" type="ob:primarymonitor"/>
+             <xsd:element minOccurs="0" name="primaryMonitor" type="ob:primarymonitor"/>
          </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="margins">
@@@ -92,8 -91,6 +91,8 @@@
              <xsd:element minOccurs="0" name="titleLayout" type="xsd:string"/>
              <xsd:element minOccurs="0" name="keepBorder" type="ob:bool"/>
              <xsd:element minOccurs="0" name="animateIconify" type="ob:bool"/>
 +            <xsd:element minOccurs="0" name="flashFrameDelay" type="ob:integer"/>
 +            <xsd:element minOccurs="0" name="flashFrameDuration" type="ob:integer"/>
              <xsd:element minOccurs="0" maxOccurs="unbounded" name="font" type="ob:font"/>
          </xsd:sequence>
      </xsd:complexType>
          </xsd:all>
          <xsd:attribute name="force" type="ob:bool"/>
      </xsd:complexType>
+     <xsd:complexType name="window_size">
+         <xsd:all>
+             <xsd:element name="width" type="ob:size_value"/>
+             <xsd:element name="height" type="ob:size_value"/>
+         </xsd:all>
+     </xsd:complexType>
      <xsd:complexType name="application">
          <xsd:all>
              <xsd:element minOccurs="0" name="decor" type="ob:bool"/>
              <xsd:element minOccurs="0" name="shade" type="ob:bool"/>
              <xsd:element minOccurs="0" name="position" type="ob:window_position"/>
+             <xsd:element minOccurs="0" name="size" type="ob:window_size"/>
              <xsd:element minOccurs="0" name="focus" type="xsd:string"/>
              <xsd:element minOccurs="0" name="desktop" type="xsd:integer"/>
              <xsd:element minOccurs="0" name="layer" type="ob:layer"/>
              <xsd:element minOccurs="0" name="skip_taskbar" type="ob:bool"/>
              <xsd:element minOccurs="0" name="fullscreen" type="ob:bool"/>
              <xsd:element minOccurs="0" name="maximized" type="ob:maximization"/>
 +            <xsd:element minOccurs="0" name="opacity" type="xsd:unsignedByte"/>
          </xsd:all>
          <!-- at least one of these must be present -->
          <xsd:attribute name="role" type="xsd:string"/>
              <xsd:enumeration value="InactiveWindow"/>
              <xsd:enumeration value="MenuHeader"/>
              <xsd:enumeration value="MenuItem"/>
-             <xsd:enumeration value="OnScreenDisplay"/>
+             <xsd:enumeration value="ActiveOnScreenDisplay"/>
+             <xsd:enumeration value="InactiveOnScreenDisplay"/>
          </xsd:restriction>
      </xsd:simpleType>
      <xsd:simpleType name="fontweight">
          <xsd:restriction base="xsd:string">
              <!-- ob: atoi($_) unless $_ eq 'center'; -->
              <!-- I think the regexp DTRT WRT atoi. -->
-             <xsd:pattern value="center|-?(0|[1-9][0-9]*)"/>
+             <xsd:pattern value="default|center|-?(0|[1-9][0-9]*)(|%|/[1-9][0-9]*)"/>
+         </xsd:restriction>
+     </xsd:simpleType>
+     <xsd:simpleType name="size_value">
+         <xsd:restriction base="xsd:string">
+             <xsd:pattern value="default|([1-9][0-9]*)(|%|/[1-9][0-9]*)"/>
          </xsd:restriction>
      </xsd:simpleType>
      <xsd:simpleType name="mouse_or_int">
          <xsd:restriction base="xsd:string">
              <xsd:enumeration value="Mouse"/>
              <xsd:enumeration value="Active"/>
-             <xsd:enumeration value="[0-9][0-9][0-9][0-9][0-9]"/>
+             <xsd:pattern value="[0-9][0-9][0-9][0-9][0-9]"/>
          </xsd:restriction>
      </xsd:simpleType>
      <xsd:simpleType name="popupposition">
diff --combined openbox/client.c
index 46162c319791a118aab0b2c8bcf1f057d3480152,b6cc4a879300fa824f0d6c8be694829e023a8bc4..1478d840f832265471d208fac1fead0b3199ec64
@@@ -167,6 -167,21 +167,21 @@@ void client_remove_destroy_notify(ObCli
      }
  }
  
+ void client_remove_destroy_notify_data(ObClientCallback func, gpointer data)
+ {
+     GSList *it;
+     for (it = client_destroy_notifies; it; it = g_slist_next(it)) {
+         ClientCallback *d = it->data;
+         if (d->func == func && d->data == data) {
+             g_slice_free(ClientCallback, d);
+             client_destroy_notifies =
+                 g_slist_delete_link(client_destroy_notifies, it);
+             break;
+         }
+     }
+ }
  void client_set_list(void)
  {
      Window *windows, *win_it;
@@@ -203,6 -218,7 +218,7 @@@ void client_manage(Window window, ObPro
      Time launch_time;
      guint32 user_time;
      gboolean obplaced;
+     gulong ignore_start;
  
      ob_debug("Managing window: 0x%lx", window);
  
      ob_debug("Window group: 0x%x", self->group?self->group->leader:0);
      ob_debug("Window name: %s class: %s role: %s title: %s",
               self->name, self->class, self->role, self->title);
+     ob_debug("Window group name: %s group class: %s",
+              self->group_name, self->group_class);
  
      /* per-app settings override stuff from client_get_all, and return the
         settings for other uses too. the returned settings is a shallow copy,
                       "program + user specified" :
                       "BADNESS !?")))), place.width, place.height);
  
-         obplaced = place_client(self, do_activate, &place.x, &place.y,
-                                 settings);
+         obplaced = place_client(self, do_activate, &place, settings);
  
          /* watch for buggy apps that ask to be placed at (0,0) when there is
             a strut there */
      /* grab mouse bindings before showing the window */
      mouse_grab_for_client(self, TRUE);
  
+     if (!config_focus_under_mouse)
+         ignore_start = event_start_ignore_all_enters();
      /* this has to happen before we try focus the window, but we want it to
         happen after the client's stacking has been determined or it looks bad
      */
-     {
-         gulong ignore_start;
-         if (!config_focus_under_mouse)
-             ignore_start = event_start_ignore_all_enters();
-         client_show(self);
-         if (!config_focus_under_mouse)
-             event_end_ignore_all_enters(ignore_start);
-     }
+     client_show(self);
  
      /* activate/hilight/raise the window */
      if (try_activate) {
              stacking_raise(CLIENT_AS_WINDOW(self));
      }
  
+     if (!config_focus_under_mouse)
+         event_end_ignore_all_enters(ignore_start);
      /* add to client list/map */
      client_list = g_list_append(client_list, self);
      window_add(&self->window, CLIENT_AS_WINDOW(self));
@@@ -710,6 -724,8 +724,8 @@@ void client_unmanage(ObClient *self
      g_free(self->name);
      g_free(self->class);
      g_free(self->role);
+     g_free(self->group_name);
+     g_free(self->group_class);
      g_free(self->client_machine);
      g_free(self->sm_client_id);
      g_slice_free(ObClient, self);
@@@ -902,15 -918,25 +918,25 @@@ static ObAppSettings *client_get_settin
  
          g_assert(app->name != NULL || app->class != NULL ||
                   app->role != NULL || app->title != NULL ||
+                  app->group_name != NULL || app->group_class != NULL ||
                   (signed)app->type >= 0);
  
          if (app->name &&
              !g_pattern_match(app->name, strlen(self->name), self->name, NULL))
              match = FALSE;
+         else if (app->group_name &&
+             !g_pattern_match(app->group_name,
+                              strlen(self->group_name), self->group_name, NULL))
+             match = FALSE;
          else if (app->class &&
                   !g_pattern_match(app->class,
                                    strlen(self->class), self->class, NULL))
              match = FALSE;
+         else if (app->group_class &&
+                  !g_pattern_match(app->group_class,
+                                   strlen(self->group_class), self->group_class,
+                                   NULL))
+             match = FALSE;
          else if (app->role &&
                   !g_pattern_match(app->role,
                                    strlen(self->role), self->role, NULL))
              self->desktop = settings->desktop - 1;
      }
  
 +    if (settings->opacity != -1)
 +      self->opacity = settings->opacity;
 +
      if (settings->layer == -1) {
          self->below = TRUE;
          self->above = FALSE;
@@@ -1020,8 -1043,6 +1046,8 @@@ static void client_restore_session_stat
      self->max_horz = self->session->max_horz;
      self->max_vert = self->session->max_vert;
      self->undecorated = self->session->undecorated;
 +
 +    self->opacity = self->session->opacity;
  }
  
  static gboolean client_restore_session_stacking(ObClient *self)
@@@ -1202,13 -1223,15 +1228,15 @@@ static void client_get_all(ObClient *se
         from per-app settings */
      client_get_session_ids(self);
  
-     /* now we got everything that can affect the decorations */
+     /* get this early so we have it for debugging, also this can be used
+      by app rule matching */
+     client_update_title(self);
+     /* now we got everything that can affect the decorations or app rule
+        matching */
      if (!real)
          return;
  
-     /* get this early so we have it for debugging */
-     client_update_title(self);
      /* save the values of the variables used for app rule matching */
      client_save_app_rule_values(self);
  
@@@ -2357,6 -2380,25 +2385,25 @@@ static void client_get_session_ids(ObCl
      if (self->name == NULL) self->name = g_strdup("");
      if (self->class == NULL) self->class = g_strdup("");
  
+     /* get the WM_CLASS (name and class) from the group leader. make them "" if
+        they are not provided */
+     if (leader)
+         got = OBT_PROP_GETSS_TYPE(leader, WM_CLASS, STRING_NO_CC, &ss);
+     else
+         got = FALSE;
+     if (got) {
+         if (ss[0]) {
+             self->group_name = g_strdup(ss[0]);
+             if (ss[1])
+                 self->group_class = g_strdup(ss[1]);
+         }
+         g_strfreev(ss);
+     }
+     if (self->group_name == NULL) self->group_name = g_strdup("");
+     if (self->group_class == NULL) self->group_class = g_strdup("");
      /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
      got = OBT_PROP_GETS_XPCS(self->window, WM_WINDOW_ROLE, &s);
  
@@@ -2426,6 -2468,8 +2473,8 @@@ static void client_save_app_rule_values
      OBT_PROP_SETS(self->window, OB_APP_ROLE, self->role);
      OBT_PROP_SETS(self->window, OB_APP_NAME, self->name);
      OBT_PROP_SETS(self->window, OB_APP_CLASS, self->class);
+     OBT_PROP_SETS(self->window, OB_APP_GROUP_NAME, self->group_name);
+     OBT_PROP_SETS(self->window, OB_APP_GROUP_CLASS, self->group_class);
      OBT_PROP_SETS(self->window, OB_APP_TITLE, self->original_title);
  
      switch (self->type) {
@@@ -2766,6 -2810,12 +2815,12 @@@ gboolean client_helper(ObClient *self
              self->type == OB_CLIENT_TYPE_TOOLBAR);
  }
  
+ gboolean client_occupies_space(ObClient *self)
+ {
+     return !(self->type == OB_CLIENT_TYPE_DESKTOP ||
+              self->type == OB_CLIENT_TYPE_SPLASH);
+ }
  gboolean client_mouse_focusable(ObClient *self)
  {
      return !(self->type == OB_CLIENT_TYPE_MENU ||
@@@ -2792,7 -2842,6 +2847,7 @@@ static void client_apply_startup_state(
      gboolean demands_attention = self->demands_attention;
      gboolean max_horz = self->max_horz;
      gboolean max_vert = self->max_vert;
 +    guint8   opacity = self->opacity;
      Rect oldarea;
      gint l;
  
      /* make sure client_setup_decor_and_functions() is called at least once */
      client_setup_decor_and_functions(self, FALSE);
  
 +    /* make the client semi-transparent */
 +    client_set_opacity(self, opacity);
 +
      /* 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
@@@ -3733,12 -3779,6 +3788,12 @@@ void client_set_desktop(ObClient *self
      focus_cycle_addremove(NULL, TRUE);
  }
  
 +void client_set_opacity(ObClient *self, guint8 opacity)
 +{
 +    OBT_PROP_SET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL, 
 +          opacity * 16777216);
 +}
 +
  gboolean client_is_direct_child(ObClient *parent, ObClient *child)
  {
      while (child != parent && (child = client_direct_parent(child)));
diff --combined openbox/client.h
index 99fdfd053fc3a99811bc3a16c23c38a32658b9de,d68d3035a3b20e54921bc6e5b4cb2f0295391f0c..a946f274bc906a19cab39ca66dfa7f8251eb3de3
@@@ -127,6 -127,10 +127,10 @@@ struct _ObClien
      gchar *class;
      /*! The specified role of the window, used for identification */
      gchar *role;
+     /*! The application that created the window's group. */
+     gchar *group_name;
+     /*! The class of the window's group, can used for grouping */
+     gchar *group_class;
      /*! The session client id for the window. *This can be NULL!* */
      gchar *sm_client_id;
  
      gboolean max_vert;
      /*! The window is maximized to fill the screen horizontally */
      gboolean max_horz;
 +    /*! The window is semi-transparent */
 +    guint8 opacity;
      /*! The window should not be displayed by pagers */
      gboolean skip_pager;
      /*! The window should not be displayed by taskbars */
@@@ -328,6 -330,7 +332,7 @@@ typedef void (*ObClientCallback)(ObClie
  /*! Get notified when the client is unmanaged */
  void client_add_destroy_notify(ObClientCallback func, gpointer data);
  void client_remove_destroy_notify(ObClientCallback func);
+ void client_remove_destroy_notify_data(ObClientCallback func, gpointer data);
  
  /*! Manages a given window
    @param prompt This specifies an ObPrompt which is being managed.  It is
@@@ -364,6 -367,10 +369,10 @@@ gboolean client_normal(ObClient *self)
    (utilty, menu, etc) */
  gboolean client_helper(ObClient *self);
  
+ /*! Returns true if the window occupies space in the monitor conceptually, or
+   false if it does not and its presence should be ignored when possible. */
+ gboolean client_occupies_space(ObClient *self);
  /*! Return if the client is a type which should be given focus from mouse
    presses on the *client* window. This doesn't affect clicking on the
    decorations. This doesn't count for focus cycling, different rules apply to
@@@ -495,7 -502,7 +504,7 @@@ void client_fullscreen(ObClient *self, 
  /*! Determine if the window, using the given client-area, would be considered
    as an "oldschool fullscreen" window, that is, if it is filling a whole
    monitor. */
- gboolean client_is_oldfullscreen(const ObClient const *self, const Rect *area);
+ gboolean client_is_oldfullscreen(const ObClient *self, const Rect *area);
  
  /*! Iconifies or uniconifies the client window
    @param iconic true if the window should be iconified; false if it should be
@@@ -541,9 -548,6 +550,9 @@@ void client_kill(ObClient *self)
  void client_set_desktop(ObClient *self, guint target, gboolean donthide,
                          gboolean dontraise);
  
 +/*! Adjust the client opacity */
 +void client_set_opacity(ObClient *self, guint8 opacity);
 +
  /*! Show the client if it should be shown. Returns if the window is shown. */
  gboolean client_show(ObClient *self);
  
diff --combined openbox/config.c
index f0f6c7b3de73d7fa25f938aff22a3eeaff55dcb9,03fc96b35bafc937f8fef9e4caf7411af1f03a7a..c21b47d88554162d189ebc6f2ff66c0ba90265c0
@@@ -37,7 -37,6 +37,6 @@@ gboolean config_focus_under_mouse
  gboolean config_unfocus_leave;
  
  ObPlacePolicy  config_place_policy;
- gboolean       config_place_center;
  ObPlaceMonitor config_place_monitor;
  
  guint          config_primary_monitor_index;
@@@ -48,8 -47,6 +47,8 @@@ StrutPartial config_margins
  gchar   *config_theme;
  gboolean config_theme_keepborder;
  guint    config_theme_window_list_icon_size;
 +guint    config_frame_flash_delay;
 +guint    config_frame_flash_duration;
  
  gchar   *config_title_layout;
  
@@@ -124,7 -121,6 +123,7 @@@ ObAppSettings* config_create_app_settin
      settings->fullscreen = -1;
      settings->max_horz = -1;
      settings->max_vert = -1;
 +    settings->opacity = -1;
      return settings;
  }
  
@@@ -150,7 -146,6 +149,7 @@@ void config_app_settings_copy_non_defau
      copy_if(fullscreen, -1);
      copy_if(max_horz, -1);
      copy_if(max_vert, -1);
 +    copy_if(opacity, -1);
  
      if (src->pos_given) {
          dst->pos_given = TRUE;
          dst->position = src->position;
          /* monitor is copied above */
      }
+     if (src->size_given) {
+         dst->size_given = TRUE;
+         dst->width_num = src->width_num;
+         dst->width_denom = src->width_denom;
+         dst->height_num = src->height_num;
+         dst->height_denom = src->height_denom;
+     }
  }
  
  void config_parse_relative_number(gchar *s, gint *num, gint *denom)
@@@ -204,6 -207,144 +211,148 @@@ void config_parse_gravity_coord(xmlNode
    </applications>
  */
  
+ static void parse_single_per_app_settings(xmlNodePtr app,
+                                           ObAppSettings *settings)
+ {
+     xmlNodePtr n, c;
+     gboolean x_pos_given = FALSE;
+     gboolean width_given = FALSE;
+     if ((n = obt_xml_find_node(app->children, "decor")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->decor = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "shade")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->shade = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "position"))) {
+         if ((c = obt_xml_find_node(n->children, "x"))) {
+             if (!obt_xml_node_contains(c, "default")) {
+                 config_parse_gravity_coord(c, &settings->position.x);
+                 x_pos_given = TRUE;
+             }
+         }
+         if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
+             if (!obt_xml_node_contains(c, "default")) {
+                 config_parse_gravity_coord(c, &settings->position.y);
+                 settings->pos_given = TRUE;
+             }
+         }
+         /* monitor can be set without setting x or y */
+         if ((c = obt_xml_find_node(n->children, "monitor"))) {
+             if (!obt_xml_node_contains(c, "default")) {
+                 gchar *s = obt_xml_node_string(c);
+                 if (!g_ascii_strcasecmp(s, "mouse"))
+                     settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
+                 else if (!g_ascii_strcasecmp(s, "active"))
+                     settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
+                 else if (!g_ascii_strcasecmp(s, "primary"))
+                     settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
+                 else
+                     settings->monitor = obt_xml_node_int(c);
+                 g_free(s);
+             }
+         }
+         obt_xml_attr_bool(n, "force", &settings->pos_force);
+     }
+     if ((n = obt_xml_find_node(app->children, "size"))) {
+         if ((c = obt_xml_find_node(n->children, "width"))) {
+             if (!obt_xml_node_contains(c, "default")) {
+                 gchar *s = obt_xml_node_string(c);
+                 config_parse_relative_number(s,
+                                              &settings->width_num,
+                                              &settings->width_denom);
+                 if (settings->width_num > 0 && settings->width_denom >= 0)
+                     width_given = TRUE;
+                 g_free(s);
+             }
+         }
+         if (width_given && (c = obt_xml_find_node(n->children, "height"))) {
+             gchar *s = obt_xml_node_string(c);
+             config_parse_relative_number(s,
+                                          &settings->height_num,
+                                          &settings->height_denom);
+             if (settings->height_num > 0 && settings->height_denom >= 0)
+                 settings->size_given = TRUE;
+             g_free(s);
+         }
+     }
+     if ((n = obt_xml_find_node(app->children, "focus"))) {
+         if (!obt_xml_node_contains(n, "default"))
+             settings->focus = obt_xml_node_bool(n);
+     }
+     if ((n = obt_xml_find_node(app->children, "desktop"))) {
+         if (!obt_xml_node_contains(n, "default")) {
+             gchar *s = obt_xml_node_string(n);
+             if (!g_ascii_strcasecmp(s, "all"))
+                 settings->desktop = DESKTOP_ALL;
+             else {
+                 gint i = obt_xml_node_int(n);
+                 if (i > 0)
+                     settings->desktop = i;
+             }
+             g_free(s);
+         }
+     }
+     if ((n = obt_xml_find_node(app->children, "layer"))) {
+         if (!obt_xml_node_contains(n, "default")) {
+             gchar *s = obt_xml_node_string(n);
+             if (!g_ascii_strcasecmp(s, "above"))
+                 settings->layer = 1;
+             else if (!g_ascii_strcasecmp(s, "below"))
+                 settings->layer = -1;
+             else
+                 settings->layer = 0;
+             g_free(s);
+         }
+     }
+     if ((n = obt_xml_find_node(app->children, "iconic")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->iconic = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "skip_pager")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->skip_pager = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->skip_taskbar = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "fullscreen")))
+         if (!obt_xml_node_contains(n, "default"))
+             settings->fullscreen = obt_xml_node_bool(n);
+     if ((n = obt_xml_find_node(app->children, "maximized"))) {
+         if (!obt_xml_node_contains(n, "default")) {
+             gchar *s = obt_xml_node_string(n);
+             if (!g_ascii_strcasecmp(s, "horizontal")) {
+                 settings->max_horz = TRUE;
+                 settings->max_vert = FALSE;
+             } else if (!g_ascii_strcasecmp(s, "vertical")) {
+                 settings->max_horz = FALSE;
+                 settings->max_vert = TRUE;
+             } else
+                 settings->max_horz = settings->max_vert =
+                     obt_xml_node_bool(n);
+             g_free(s);
+         }
+     }
++
++    if ((n = obt_xml_find_node(app->children, "opacity")))
++        if (!obt_xml_node_contains(n, "default"))
++            settings->opacity = obt_xml_node_int(n);
+ }
  /* Manages settings for individual applications.
     Some notes: monitor is the screen number in a multi monitor
     (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
  static void parse_per_app_settings(xmlNodePtr node, gpointer d)
  {
      xmlNodePtr app = obt_xml_find_node(node->children, "application");
-     gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
-         *type_str = NULL;
-     gboolean name_set, class_set, type_set, role_set, title_set;
-     ObClientType type;
-     gboolean x_pos_given;
+     for (; app; app = obt_xml_find_node(app->next, "application")) {
+         ObAppSettings *settings;
  
-     while (app) {
-         x_pos_given = FALSE;
+         gboolean name_set, class_set, role_set, title_set,
+             type_set, group_name_set, group_class_set;
+         gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
+             *type_str = NULL, *group_name = NULL, *group_class = NULL;
+         ObClientType type;
  
          class_set = obt_xml_attr_string(app, "class", &class);
          name_set = obt_xml_attr_string(app, "name", &name);
+         group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
+         group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
          type_set = obt_xml_attr_string(app, "type", &type_str);
          role_set = obt_xml_attr_string(app, "role", &role);
          title_set = obt_xml_attr_string(app, "title", &title);
                  type_set = FALSE; /* not valid! */
          }
  
-         if (class_set || name_set || role_set || title_set || type_set) {
-             xmlNodePtr n, c;
-             ObAppSettings *settings = config_create_app_settings();
-             if (name_set)
-                 settings->name = g_pattern_spec_new(name);
-             if (class_set)
-                 settings->class = g_pattern_spec_new(class);
-             if (role_set)
-                 settings->role = g_pattern_spec_new(role);
-             if (title_set)
-                 settings->title = g_pattern_spec_new(title);
-             if (type_set)
-                 settings->type = type;
-             if ((n = obt_xml_find_node(app->children, "decor")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->decor = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "shade")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->shade = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "position"))) {
-                 if ((c = obt_xml_find_node(n->children, "x")))
-                     if (!obt_xml_node_contains(c, "default")) {
-                         config_parse_gravity_coord(c, &settings->position.x);
-                         x_pos_given = TRUE;
-                     }
-                 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
-                     if (!obt_xml_node_contains(c, "default")) {
-                         config_parse_gravity_coord(c, &settings->position.y);
-                         settings->pos_given = TRUE;
-                     }
-                 /* monitor can be set without setting x or y */
-                 if ((c = obt_xml_find_node(n->children, "monitor")))
-                     if (!obt_xml_node_contains(c, "default")) {
-                         gchar *s = obt_xml_node_string(c);
-                         if (!g_ascii_strcasecmp(s, "mouse"))
-                             settings->monitor_type =
-                                     OB_PLACE_MONITOR_MOUSE;
-                         else if (!g_ascii_strcasecmp(s, "active"))
-                             settings->monitor_type =
-                                     OB_PLACE_MONITOR_ACTIVE;
-                         else if (!g_ascii_strcasecmp(s, "primary"))
-                             settings->monitor_type =
-                                     OB_PLACE_MONITOR_PRIMARY;
-                         else
-                             settings->monitor = obt_xml_node_int(c);
-                         g_free(s);
-                     }
-                 obt_xml_attr_bool(n, "force", &settings->pos_force);
-             }
-             if ((n = obt_xml_find_node(app->children, "focus")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->focus = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "desktop"))) {
-                 if (!obt_xml_node_contains(n, "default")) {
-                     gchar *s = obt_xml_node_string(n);
-                     if (!g_ascii_strcasecmp(s, "all"))
-                         settings->desktop = DESKTOP_ALL;
-                     else {
-                         gint i = obt_xml_node_int(n);
-                         if (i > 0)
-                             settings->desktop = i;
-                     }
-                     g_free(s);
-                 }
-             }
+         if (!(class_set || name_set || role_set || title_set ||
+               type_set || group_class_set || group_name_set))
+             continue;
+         settings = config_create_app_settings();
+         if (name_set)
+             settings->name = g_pattern_spec_new(name);
+         if (class_set)
+             settings->class = g_pattern_spec_new(class);
+         if (group_name_set)
+             settings->group_name = g_pattern_spec_new(group_name);
+         if (group_class_set)
+             settings->group_class = g_pattern_spec_new(group_class);
+         if (role_set)
+             settings->role = g_pattern_spec_new(role);
+         if (title_set)
+             settings->title = g_pattern_spec_new(title);
+         if (type_set)
+             settings->type = type;
  
-             if ((n = obt_xml_find_node(app->children, "layer")))
-                 if (!obt_xml_node_contains(n, "default")) {
-                     gchar *s = obt_xml_node_string(n);
-                     if (!g_ascii_strcasecmp(s, "above"))
-                         settings->layer = 1;
-                     else if (!g_ascii_strcasecmp(s, "below"))
-                         settings->layer = -1;
-                     else
-                         settings->layer = 0;
-                     g_free(s);
-                 }
-             if ((n = obt_xml_find_node(app->children, "iconic")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->iconic = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "skip_pager")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->skip_pager = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->skip_taskbar = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "fullscreen")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->fullscreen = obt_xml_node_bool(n);
-             if ((n = obt_xml_find_node(app->children, "maximized")))
-                 if (!obt_xml_node_contains(n, "default")) {
-                     gchar *s = obt_xml_node_string(n);
-                     if (!g_ascii_strcasecmp(s, "horizontal")) {
-                         settings->max_horz = TRUE;
-                         settings->max_vert = FALSE;
-                     } else if (!g_ascii_strcasecmp(s, "vertical")) {
-                         settings->max_horz = FALSE;
-                         settings->max_vert = TRUE;
-                     } else
-                         settings->max_horz = settings->max_vert =
-                             obt_xml_node_bool(n);
-                     g_free(s);
-                 }
-             if ((n = obt_xml_find_node(app->children, "opacity")))
-                 if (!obt_xml_node_contains(n, "default"))
-                     settings->opacity = obt_xml_node_int(n);
-             config_per_app_settings = g_slist_append(config_per_app_settings,
-                                                      (gpointer) settings);
-             g_free(name);
-             g_free(class);
-             g_free(role);
-             g_free(title);
-             g_free(type_str);
-             name = class = role = title = type_str = NULL;
-         }
-         app = obt_xml_find_node(app->next, "application");
+         g_free(name);
+         g_free(class);
+         g_free(group_name);
+         g_free(group_class);
+         g_free(role);
+         g_free(title);
+         g_free(type_str);
+         parse_single_per_app_settings(app, settings);
+         config_per_app_settings = g_slist_append(config_per_app_settings,
+                                                  (gpointer)settings);
      }
  }
  
@@@ -592,8 -630,6 +638,6 @@@ static void parse_placement(xmlNodePtr 
      if ((n = obt_xml_find_node(node, "policy")))
          if (obt_xml_node_contains(n, "UnderMouse"))
              config_place_policy = OB_PLACE_POLICY_MOUSE;
-     if ((n = obt_xml_find_node(node, "center")))
-         config_place_center = obt_xml_node_bool(n);
      if ((n = obt_xml_find_node(node, "monitor"))) {
          if (obt_xml_node_contains(n, "active"))
              config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
@@@ -663,10 -699,6 +707,10 @@@ static void parse_theme(xmlNodePtr node
          else if (config_theme_window_list_icon_size > 96)
              config_theme_window_list_icon_size = 96;
      }
 +    if ((n = obt_xml_find_node(node, "flashFrameDelay")))
 +        config_frame_flash_delay = obt_xml_node_int(n);
 +    if ((n = obt_xml_find_node(node, "flashFrameDuration")))
 +        config_frame_flash_duration = obt_xml_node_int(n);
  
      n = obt_xml_find_node(node, "font");
      while (n) {
@@@ -1025,7 -1057,6 +1069,6 @@@ void config_startup(ObtXmlInst *i
      obt_xml_register(i, "focus", parse_focus, NULL);
  
      config_place_policy = OB_PLACE_POLICY_SMART;
-     config_place_center = TRUE;
      config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
  
      config_primary_monitor_index = 1;
      config_title_layout = g_strdup("NLIMC");
      config_theme_keepborder = TRUE;
      config_theme_window_list_icon_size = 36;
 +    config_frame_flash_delay = 600;
 +    config_frame_flash_duration = 5000;
  
      config_font_activewindow = NULL;
      config_font_inactivewindow = NULL;
@@@ -1146,10 -1175,12 +1189,12 @@@ void config_shutdown(void
  
      for (it = config_per_app_settings; it; it = g_slist_next(it)) {
          ObAppSettings *itd = (ObAppSettings *)it->data;
-         if (itd->name)  g_pattern_spec_free(itd->name);
-         if (itd->role)  g_pattern_spec_free(itd->role);
+         if (itd->name) g_pattern_spec_free(itd->name);
+         if (itd->role) g_pattern_spec_free(itd->role);
          if (itd->title) g_pattern_spec_free(itd->title);
          if (itd->class) g_pattern_spec_free(itd->class);
+         if (itd->group_name) g_pattern_spec_free(itd->group_name);
+         if (itd->group_class) g_pattern_spec_free(itd->group_class);
          g_slice_free(ObAppSettings, it->data);
      }
      g_slist_free(config_per_app_settings);
diff --combined openbox/config.h
index beb54be4e6393102c23e521a9aeb12774efa5c75,87662ab9d27955fa86d073d4fef1f6f7c2e8c5ff..c09a1f4f1cfb5335add5a71c4a6cef14eb5a06f6
@@@ -38,6 -38,8 +38,8 @@@ struct _ObAppSetting
      GPatternSpec *class;
      GPatternSpec *name;
      GPatternSpec *role;
+     GPatternSpec *group_class;
+     GPatternSpec *group_name;
      GPatternSpec *title;
      ObClientType  type;
  
      gboolean pos_given;
      gboolean pos_force;
  
+     gint width_num;
+     gint width_denom;
+     gint height_num;
+     gint height_denom;
+     gboolean size_given;
      guint desktop;
      gint shade;
      gint decor;
@@@ -57,9 -65,8 +65,9 @@@
      gint max_horz;
      gint max_vert;
      gint fullscreen;
 -
      gint layer;
 +
 +    guint8 opacity;
  };
  
  /*! Should new windows be focused */
@@@ -82,8 -89,6 +90,6 @@@ extern gboolean config_unfocus_leave
  
  /*! The algorithm to use for placing new windows */
  extern ObPlacePolicy config_place_policy;
- /*! Place windows in the center of the free area */
- extern gboolean config_place_center;
  /*! Place windows on the active monitor (unless they are part of an application
    already on another monitor) */
  extern ObPlaceMonitor config_place_monitor;
@@@ -146,10 -151,6 +152,10 @@@ extern gchar *config_title_layout
  extern gboolean config_animate_iconify;
  /*! Size of icons in focus switching dialogs */
  extern guint config_theme_window_list_icon_size;
 +/*! Amount of time between flashes (0 to disable flashing) */
 +extern guint config_frame_flash_delay;
 +/*! How long (ms) to flash the window's frame (0 to flash forever) */
 +extern guint config_frame_flash_duration;
  
  /*! The font for the active window's title */
  extern RrFont *config_font_activewindow;
diff --combined openbox/frame.c
index 4468e1910bf75d33ef3e5da5cc24f4b2bc966561,24d3eb535a93ae3f3eaa428298df54585ffefa65..0f2d56ebaf7ce37c6e55c445444f7328afe94ced
@@@ -378,13 -378,22 +378,22 @@@ void frame_adjust_area(ObFrame *self, g
  
          STRUT_SET(self->size,
                    self->cbwidth_l + (!self->max_horz ? self->bwidth : 0),
-                   self->cbwidth_t + self->bwidth,
+                   self->cbwidth_t +
+                   (!self->max_horz || !self->max_vert ? self->bwidth : 0),
                    self->cbwidth_r + (!self->max_horz ? self->bwidth : 0),
                    self->cbwidth_b +
                    (!self->max_horz || !self->max_vert ? self->bwidth : 0));
  
          if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
              self->size.top += ob_rr_theme->title_height + self->bwidth;
+         else if (self->max_horz && self->max_vert) {
+             /* A maximized and undecorated window needs a small border on the
+                top of the window to let the user still undecorate/unmaximize the
+                window via the client menu. */
+             /* XXX This size should probably be a theme option. */
+             self->size.top += 1;
+         }
          if (self->decorations & OB_FRAME_DECOR_HANDLE &&
              ob_rr_theme->handle_height > 0)
          {
@@@ -1665,13 -1674,11 +1674,13 @@@ static gboolean flash_timeout(gpointer 
      ObFrame *self = data;
      GTimeVal now;
  
 -    g_get_current_time(&now);
 -    if (now.tv_sec > self->flash_end.tv_sec ||
 -        (now.tv_sec == self->flash_end.tv_sec &&
 -         now.tv_usec >= self->flash_end.tv_usec))
 -        self->flashing = FALSE;
 +    if (config_frame_flash_duration != 0) {
 +        g_get_current_time(&now);
 +        if (now.tv_sec > self->flash_end.tv_sec ||
 +            (now.tv_sec == self->flash_end.tv_sec &&
 +             now.tv_usec >= self->flash_end.tv_usec))
 +            self->flashing = FALSE;
 +    }
  
      if (!self->flashing)
          return FALSE; /* we are done */
  
  void frame_flash_start(ObFrame *self)
  {
 +    if (config_frame_flash_delay == 0) return;
 +
      self->flash_on = self->focused;
  
      if (!self->flashing)
          self->flash_timer = g_timeout_add_full(G_PRIORITY_DEFAULT,
 -                                               600, flash_timeout, self,
 +                                               config_frame_flash_delay, flash_timeout, self,
                                                 flash_done);
 -    g_get_current_time(&self->flash_end);
 -    g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
 +
 +    if (config_frame_flash_duration != 0) {
 +        g_get_current_time(&self->flash_end);
 +        g_time_val_add(&self->flash_end, 1000 * config_frame_flash_duration);
 +    }
  
      self->flashing = TRUE;
  }
diff --combined openbox/moveresize.c
index d700da9ebd66a0ecacb8d10c4e15bc0a2b75c4f2,1625ccf01ccddd7aa5d0fc9036ab4c7ed5fdde14..ffed909315037ae4b6882f92b391dbc3b0dc8a7d
@@@ -583,16 -583,16 +583,16 @@@ static void edge_warp_move_ptr(void
  
      switch (edge_warp_dir) {
        case OB_DIRECTION_NORTH:
 -          y = a->height - 1;
 +          y = a->height - 2;
            break;
        case OB_DIRECTION_EAST:
 -          x = a->x;
 +          x = a->x + 1;
            break;
        case OB_DIRECTION_SOUTH:
 -          y = a->y;
 +          y = a->y + 1;
            break;
        case OB_DIRECTION_WEST:
 -          x = a->width - 1;
 +          x = a->width - 2;
            break;
        default:
          g_assert_not_reached();
@@@ -630,6 -630,10 +630,10 @@@ static void do_edge_warp(gint x, gint y
  
      for (i = 0; i < screen_num_monitors; ++i) {
          const Rect *a = screen_physical_area_monitor(i);
+         if (!RECT_CONTAINS(*a, x, y))
+             continue;
          if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
          if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
          if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
This page took 0.053807 seconds and 4 git commands to generate.