Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Fri, 8 Jan 2010 15:22:30 +0000 (10:22 -0500)
committerDana Jansens <danakj@orodu.net>
Fri, 8 Jan 2010 15:22:30 +0000 (10:22 -0500)
Conflicts:

Makefile.am
openbox/actions/focus.c
openbox/config.c
openbox/event.c
openbox/menuframe.c

1  2 
Makefile.am
data/rc.xml
openbox/actions/focus.c
openbox/config.c
openbox/config.h
openbox/event.c
openbox/focus_cycle.c
openbox/menuframe.c
openbox/menuframe.h

diff --cc Makefile.am
@@@ -501,10 -493,10 +501,12 @@@ dist_noinst_DATA = 
        doc/openbox-gnome-session.1.in \
        doc/openbox-kde-session.1.sgml \
        doc/openbox-kde-session.1.in \
 -      render/obrender-3.0.pc.in \
 -      parser/obparser-3.0.pc.in \
+       doc/obxprop.1.sgml \
+       doc/obxprop.1.in \
 +      obrender/version.h.in \
 +      obrender/obrender-3.5.pc.in \
 +      obt/obt-3.5.pc.in \
 +      obt/version.h.in \
        tools/themeupdate/themeupdate.py \
        tests/hideshow.py \
        tests/Makefile \
diff --cc data/rc.xml
Simple merge
@@@ -6,9 -6,11 +6,10 @@@
  
  typedef struct {
      gboolean here;
+     gboolean stop_int;
  } Options;
  
 -static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
 -static void     free_func(gpointer options);
 +static gpointer setup_func(xmlNodePtr node);
  static gboolean run_func(ObActionsData *data, gpointer options);
  
  void action_focus_startup(void)
@@@ -22,9 -28,12 +23,12 @@@ static gpointer setup_func(xmlNodePtr n
      Options *o;
  
      o = g_new0(Options, 1);
+     o->stop_int = TRUE;
  
 -    if ((n = parse_find_node("here", node)))
 -        o->here = parse_bool(doc, n);
 -    if ((n = parse_find_node("stopInteractive", node)))
 -        o->stop_int = parse_bool(doc, n);
 +    if ((n = obt_xml_find_node(node, "here")))
 +        o->here = obt_xml_node_bool(n);
++    if ((n = obt_xml_find_node(node, "stopInteractive")))
++        o->stop_int = obt_xml_node_bool(n);
      return o;
  }
  
@@@ -807,21 -807,23 +808,23 @@@ static void parse_menu(xmlNodePtr node
      xmlNodePtr n;
      node = node->children;
  
 -    if ((n = parse_find_node("hideDelay", node)))
 -        config_menu_hide_delay = parse_int(doc, n);
 -    if ((n = parse_find_node("middle", node)))
 -        config_menu_middle = parse_bool(doc, n);
 -    if ((n = parse_find_node("submenuShowDelay", node)))
 -        config_submenu_show_delay = parse_int(doc, n);
 -    if ((n = parse_find_node("submenuHideDelay", node)))
 -        config_submenu_hide_delay = parse_int(doc, n);
 -    if ((n = parse_find_node("applicationIcons", node)))
 -        config_menu_client_list_icons = parse_bool(doc, n);
 -    if ((n = parse_find_node("manageDesktops", node)))
 -        config_menu_manage_desktops = parse_bool(doc, n);
 -
 -    while ((node = parse_find_node("file", node))) {
 -            gchar *c = parse_string(doc, node);
 +    if ((n = obt_xml_find_node(node, "hideDelay")))
 +        config_menu_hide_delay = obt_xml_node_int(n);
 +    if ((n = obt_xml_find_node(node, "middle")))
 +        config_menu_middle = obt_xml_node_bool(n);
 +    if ((n = obt_xml_find_node(node, "submenuShowDelay")))
 +        config_submenu_show_delay = obt_xml_node_int(n);
++    if ((n = obt_xml_find_node(node, "submenuHideDelay")))
++        config_submenu_hide_delay = obt_xml_node_int(n);
 +    if ((n = obt_xml_find_node(node, "applicationIcons")))
 +        config_menu_client_list_icons = obt_xml_node_bool(n);
 +    if ((n = obt_xml_find_node(node, "manageDesktops")))
 +        config_menu_manage_desktops = obt_xml_node_bool(n);
 +
 +    while ((node = obt_xml_find_node(node, "file"))) {
 +            gchar *c = obt_xml_node_string(node);
              config_menu_files = g_slist_append(config_menu_files,
 -                                               parse_expand_tilde(c));
 +                                               obt_paths_expand_tilde(c));
              g_free(c);
              node = node->next;
      }
Simple merge
diff --cc openbox/event.c
@@@ -1742,160 -1674,130 +1742,165 @@@ static gboolean event_handle_prompt(ObP
      return FALSE;
  }
  
 -static gboolean event_handle_menu_keyboard(XEvent *ev)
 +static gboolean event_handle_menu_input(XEvent *ev)
  {
 -    guint keycode, state;
 -    gunichar unikey;
 -    ObMenuFrame *frame;
      gboolean ret = FALSE;
  
 -    keycode = ev->xkey.keycode;
 -    state = ev->xkey.state;
 -    unikey = translate_unichar(keycode);
 +    if (ev->type == ButtonRelease || ev->type == ButtonPress) {
 +        ObMenuEntryFrame *e;
  
 -    frame = find_active_or_last_menu();
 -    if (frame == NULL)
 -        g_assert_not_reached(); /* there is no active menu */
 +        if (menu_hide_delay_reached() &&
 +            (ev->xbutton.button < 4 || ev->xbutton.button > 5))
 +        {
 +            if ((e = menu_entry_frame_under(ev->xbutton.x_root,
 +                                            ev->xbutton.y_root)))
 +            {
 +                if (ev->type == ButtonPress && e->frame->child)
 +                    menu_frame_select(e->frame->child, NULL, TRUE);
 +                menu_frame_select(e->frame, e, TRUE);
 +                if (ev->type == ButtonRelease)
 +                    menu_entry_frame_execute(e, ev->xbutton.state);
 +            }
 +            else if (ev->type == ButtonRelease)
 +                menu_frame_hide_all();
 +        }
 +        ret = TRUE;
 +    }
 +    else if (ev->type == MotionNotify) {
 +        ObMenuFrame *f;
 +        ObMenuEntryFrame *e;
  
 -    /* Allow control while going thru the menu */
 -    else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
 -        frame->got_press = TRUE;
 +        if ((e = menu_entry_frame_under(ev->xmotion.x_root,
 +                                        ev->xmotion.y_root)))
 +            if (!(f = find_active_menu()) ||
 +                f == e->frame ||
 +                f->parent == e->frame ||
 +                f->child == e->frame)
 +                menu_frame_select(e->frame, e, FALSE);
 +    }
 +    else if (ev->type == KeyPress || ev->type == KeyRelease) {
 +        guint keycode, state;
 +        gunichar unikey;
 +        ObMenuFrame *frame;
  
 -        if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
 -            menu_frame_hide_all();
 -            ret = TRUE;
 -        }
 +        keycode = ev->xkey.keycode;
 +        state = ev->xkey.state;
 +        unikey = obt_keyboard_keycode_to_unichar(keycode);
 +
 +        frame = find_active_or_last_menu();
 +        if (frame == NULL)
 +            g_assert_not_reached(); /* there is no active menu */
  
 -        else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
 -            /* Left goes to the parent menu */
 -            if (frame->parent) {
 -                /* remove focus from the child */
 -                menu_frame_select(frame, NULL, TRUE);
 -                /* and put it in the parent */
 -                menu_frame_select(frame->parent, frame->parent->selected,
 -                                  TRUE);
 +        /* Allow control while going thru the menu */
 +        else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
 +            frame->got_press = TRUE;
 +
 +            if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
 +                menu_frame_hide_all();
 +                ret = TRUE;
              }
 -            ret = TRUE;
 -        }
  
 -        else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
 -            /* Right goes to the selected submenu */
 -            if (frame->child) menu_frame_select_next(frame->child);
 -            ret = TRUE;
 -        }
 +            else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
 +                /* Left goes to the parent menu */
-                 if (frame->parent)
++                if (frame->parent) {
++                    /* remove focus from the child */
 +                    menu_frame_select(frame, NULL, TRUE);
++                    /* and put it in the parent */
++                    menu_frame_select(frame->parent, frame->parent->selected,
++                                      TRUE);
++                }
 +                ret = TRUE;
 +            }
  
 -        else if (ob_keycode_match(keycode, OB_KEY_UP)) {
 -            menu_frame_select_previous(frame);
 -            ret = TRUE;
 -        }
 +            else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
 +                /* Right goes to the selected submenu */
 +                if (frame->child) menu_frame_select_next(frame->child);
 +                ret = TRUE;
 +            }
 +
 +            else if (ob_keycode_match(keycode, OB_KEY_UP)) {
 +                menu_frame_select_previous(frame);
 +                ret = TRUE;
 +            }
  
 -        else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
 -            menu_frame_select_next(frame);
 -            ret = TRUE;
 +            else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
 +                menu_frame_select_next(frame);
 +                ret = TRUE;
 +            }
          }
 -    }
  
 -    /* Use KeyRelease events for running things so that the key release doesn't
 -       get sent to the focused application.
 +        /* Use KeyRelease events for running things so that the key release
 +           doesn't get sent to the focused application.
  
 -       Allow ControlMask only, and don't bother if the menu is empty */
 -    else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
 -             frame->entries && frame->got_press)
 -    {
 -        if (ob_keycode_match(keycode, OB_KEY_RETURN)) {
 -            /* Enter runs the active item or goes into the submenu.
 -               Control-Enter runs it without closing the menu. */
 -            if (frame->child)
 -                menu_frame_select_next(frame->child);
 -            else if (frame->selected)
 -                menu_entry_frame_execute(frame->selected, state);
 -
 -            ret = TRUE;
 -        }
 +           Allow ControlMask only, and don't bother if the menu is empty */
 +        else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
 +                 frame->entries && frame->got_press)
 +        {
 +            if (ob_keycode_match(keycode, OB_KEY_RETURN)) {
 +                /* Enter runs the active item or goes into the submenu.
 +                   Control-Enter runs it without closing the menu. */
 +                if (frame->child)
 +                    menu_frame_select_next(frame->child);
 +                else if (frame->selected)
 +                    menu_entry_frame_execute(frame->selected, state);
  
 -        /* keyboard accelerator shortcuts. (if it was a valid key) */
 -        else if (unikey != 0) {
 -            GList *start;
 -            GList *it;
 -            ObMenuEntryFrame *found = NULL;
 -            guint num_found = 0;
 -
 -            /* start after the selected one */
 -            start = frame->entries;
 -            if (frame->selected) {
 -                for (it = start; frame->selected != it->data;
 -                     it = g_list_next(it))
 -                    g_assert(it != NULL); /* nothing was selected? */
 -                /* next with wraparound */
 -                start = g_list_next(it);
 -                if (start == NULL) start = frame->entries;
 +                ret = TRUE;
              }
  
 -            it = start;
 -            do {
 -                ObMenuEntryFrame *e = it->data;
 -                gunichar entrykey = 0;
 +            /* keyboard accelerator shortcuts. (if it was a valid key) */
 +            else if (unikey != 0) {
 +                GList *start;
 +                GList *it;
 +                ObMenuEntryFrame *found = NULL;
 +                guint num_found = 0;
 +
 +                /* start after the selected one */
 +                start = frame->entries;
 +                if (frame->selected) {
 +                    for (it = start; frame->selected != it->data;
 +                         it = g_list_next(it))
 +                        g_assert(it != NULL); /* nothing was selected? */
 +                    /* next with wraparound */
 +                    start = g_list_next(it);
 +                    if (start == NULL) start = frame->entries;
 +                }
 +
 +                it = start;
 +                do {
 +                    ObMenuEntryFrame *e = it->data;
 +                    gunichar entrykey = 0;
  
 -                if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
 -                    entrykey = e->entry->data.normal.shortcut;
 -                else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
 -                    entrykey = e->entry->data.submenu.submenu->shortcut;
 +                    if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
 +                        entrykey = e->entry->data.normal.shortcut;
 +                    else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
 +                        entrykey = e->entry->data.submenu.submenu->shortcut;
  
 -                if (unikey == entrykey) {
 -                    if (found == NULL) found = e;
 -                    ++num_found;
 -                }
 +                    if (unikey == entrykey) {
 +                        if (found == NULL) found = e;
 +                        ++num_found;
 +                    }
  
 -                /* next with wraparound */
 -                it = g_list_next(it);
 -                if (it == NULL) it = frame->entries;
 -            } while (it != start);
 +                    /* next with wraparound */
 +                    it = g_list_next(it);
 +                    if (it == NULL) it = frame->entries;
 +                } while (it != start);
  
 -            if (found) {
 -                if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
 -                    num_found == 1)
 -                {
 -                    menu_frame_select(frame, found, TRUE);
 -                    usleep(50000); /* highlight the item for a short bit so the
 -                                      user can see what happened */
 -                    menu_entry_frame_execute(found, state);
 -                } else {
 -                    menu_frame_select(frame, found, TRUE);
 -                    if (num_found == 1)
 -                        menu_frame_select_next(frame->child);
 -                }
 +                if (found) {
 +                    if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
 +                        num_found == 1)
 +                    {
 +                        menu_frame_select(frame, found, TRUE);
 +                        usleep(50000); /* highlight the item for a short bit so
 +                                          the user can see what happened */
 +                        menu_entry_frame_execute(found, state);
 +                    } else {
 +                        menu_frame_select(frame, found, TRUE);
 +                        if (num_found == 1)
 +                            menu_frame_select_next(frame->child);
 +                    }
  
 -                ret = TRUE;
 +                    ret = TRUE;
 +                }
              }
          }
      }
      return ret;
  }
  
 -static gboolean event_handle_menu(XEvent *ev)
+ static Bool event_look_for_menu_enter(Display *d, XEvent *ev, XPointer arg)
+ {
+     ObMenuFrame *f = (ObMenuFrame*)arg;
+     ObMenuEntryFrame *e;
+     return ev->type == EnterNotify &&
+         (e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
+         !e->ignore_enters && e->frame == f;
+ }
 +static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
  {
      ObMenuFrame *f;
      ObMenuEntryFrame *e;
          if (ev->xcrossing.detail == NotifyInferior)
              break;
  
-         if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
-             (f = find_active_menu()) && f->selected == e)
+         if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)))
          {
-             ObMenuEntryFrame *u = menu_entry_frame_under(ev->xcrossing.x_root,
-                                                          ev->xcrossing.y_root);
-             /* if we're just going from one entry in the menu to the next,
-                don't unselect stuff first */
-             if (!u || e->frame != u->frame)
+             XEvent ce;
+             /* check if an EnterNotify event is coming, and if not, then select
+                nothing in the menu */
 -            if (XCheckIfEvent(ob_display, &ce, event_look_for_menu_enter,
++            if (XCheckIfEvent(obt_display, &ce, event_look_for_menu_enter,
+                               (XPointer)e->frame))
 -                XPutBackEvent(ob_display, &ce);
++                XPutBackEvent(obt_display, &ce);
+             else
                  menu_frame_select(e->frame, NULL, FALSE);
          }
          break;
Simple merge
@@@ -92,10 -94,9 +93,9 @@@ ObMenuFrame* menu_frame_new(ObMenu *men
      XSetWindowAttributes attr;
  
      self = g_new0(ObMenuFrame, 1);
 -    self->type = Window_Menu;
 +    self->obwin.type = OB_WINDOW_CLASS_MENUFRAME;
      self->menu = menu;
      self->selected = NULL;
-     self->open_submenu = NULL;
      self->client = client;
      self->direction_right = TRUE;
      self->show_from = show_from;
@@@ -985,6 -974,15 +985,15 @@@ gboolean menu_frame_show_topmenu(ObMenu
      return TRUE;
  }
  
 -    ob_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout,
 -                                     child, FALSE);
+ /*! Stop hiding an open submenu.
+     @child The OnMenuFrame of the submenu to be hidden
+ */
+ static void remove_submenu_hide_timeout(ObMenuFrame *child)
+ {
++    obt_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout,
++                                      child, FALSE);
+ }
  gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
                                   ObMenuEntryFrame *parent_entry)
  {
@@@ -1071,11 -1073,7 +1084,7 @@@ void menu_frame_hide_all(void
  
      if (config_submenu_show_delay) {
          /* remove any submenu open requests */
-         obt_main_loop_timeout_remove(ob_main_loop,
-                                      menu_entry_frame_submenu_show_timeout);
-         /* remove any submenu close delays */
-         obt_main_loop_timeout_remove(ob_main_loop,
-                                      menu_entry_frame_submenu_hide_timeout);
 -        ob_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
++        obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
      }
      if ((it = g_list_last(menu_frame_visible)))
          menu_frame_hide(it->data);
@@@ -1089,13 -1087,8 +1098,8 @@@ void menu_frame_hide_all_client(ObClien
          if (f->client == client) {
              if (config_submenu_show_delay) {
                  /* remove any submenu open requests */
-                 obt_main_loop_timeout_remove
-                     (ob_main_loop,
-                      menu_entry_frame_submenu_show_timeout);
-                 /* remove any submenu close delays */
-                 obt_main_loop_timeout_remove
-                     (ob_main_loop,
-                      menu_entry_frame_submenu_hide_timeout);
 -                ob_main_loop_timeout_remove(ob_main_loop,
 -                                            submenu_show_timeout);
++                obt_main_loop_timeout_remove(ob_main_loop,
++                                             submenu_show_timeout);
              }
              menu_frame_hide(f);
          }
@@@ -1167,19 -1170,7 +1181,7 @@@ void menu_frame_select(ObMenuFrame *sel
  
      if (config_submenu_show_delay) {
          /* remove any submenu open requests */
-         obt_main_loop_timeout_remove(ob_main_loop,
-                                      menu_entry_frame_submenu_show_timeout);
-     }
-     if (!entry && self->open_submenu) {
-         /* we moved out of the menu, so move the selection back to the open
-            submenu */
-         entry = self->open_submenu;
-         oldchild = NULL;
-         /* remove any submenu close delays */
-         obt_main_loop_timeout_remove(ob_main_loop,
-                                      menu_entry_frame_submenu_hide_timeout);
 -        ob_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
++        obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
      }
  
      self->selected = entry;
      if (old)
          menu_entry_frame_render(old);
  
-     if (oldchild) {
-         /* there is an open submenu */
-         if (config_submenu_show_delay && !immediate) {
-             if (entry == self->open_submenu) {
-                 /* we moved onto the entry that has an open submenu, so stop
-                    trying to close the submenu */
-                 obt_main_loop_timeout_remove
-                     (ob_main_loop,
-                      menu_entry_frame_submenu_hide_timeout);
-             }
-             else if (old == self->open_submenu) {
-                 /* we just moved off the entry with an open submenu, so
-                    close the open submenu after a delay */
-                 obt_main_loop_timeout_add
-                     (ob_main_loop,
-                      config_submenu_show_delay * 1000,
-                      menu_entry_frame_submenu_hide_timeout,
-                      self->child, g_direct_equal,
-                      NULL);
-             }
+     if (oldchild_entry) {
+         /* There is an open submenu */
+         if (oldchild_entry == self->selected) {
+             /* The open submenu has been reselected, so stop hiding the
+                submenu */
+             remove_submenu_hide_timeout(oldchild);
+         }
+         else if (oldchild_entry == old) {
+             /* The open submenu was selected and is no longer, so hide the
+                submenu */
+             if (immediate || config_submenu_hide_delay == 0)
+                 menu_frame_hide(oldchild);
+             else if (config_submenu_hide_delay > 0)
 -                ob_main_loop_timeout_add(ob_main_loop,
 -                                         config_submenu_hide_delay * 1000,
 -                                         submenu_hide_timeout,
 -                                         oldchild, g_direct_equal,
 -                                         NULL);
++                obt_main_loop_timeout_add(ob_main_loop,
++                                          config_submenu_hide_delay * 1000,
++                                          submenu_hide_timeout,
++                                          oldchild, g_direct_equal,
++                                          NULL);
          }
-         else
-             menu_frame_hide(oldchild);
      }
  
      if (self->selected) {
          menu_entry_frame_render(self->selected);
  
-         /* if we've selected a submenu and it wasn't already open, then
-            show it */
-         if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU &&
-             self->selected != self->open_submenu)
-         {
-             if (config_submenu_show_delay && !immediate) {
-                 /* initiate a new submenu open request */
-                 obt_main_loop_timeout_add
-                     (ob_main_loop,
-                      config_submenu_show_delay * 1000,
-                      menu_entry_frame_submenu_show_timeout,
-                      self->selected, g_direct_equal,
-                      NULL);
-             } else {
-                 menu_entry_frame_show_submenu(self->selected);
+         if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
+             /* only show if the submenu isn't already showing */
+             if (oldchild_entry != self->selected) {
+                 if (immediate || config_submenu_hide_delay == 0)
+                     menu_entry_frame_show_submenu(self->selected);
+                 else if (config_submenu_hide_delay > 0)
 -                    ob_main_loop_timeout_add(ob_main_loop,
 -                                             config_submenu_show_delay * 1000,
 -                                             submenu_show_timeout,
 -                                             self->selected, g_direct_equal,
 -                                             NULL);
++                    obt_main_loop_timeout_add(ob_main_loop,
++                                              config_submenu_show_delay * 1000,
++                                              submenu_show_timeout,
++                                              self->selected, g_direct_equal,
++                                              NULL);
+             }
+             /* hide the grandchildren of this menu. and move the cursor to
+                the current menu */
+             else if (immediate && self->child && self->child->child) {
+                 menu_frame_hide(self->child->child);
+                 menu_frame_select(self->child, NULL, TRUE);
              }
          }
      }
Simple merge