]> Dogcows Code - chaz/openbox/commitdiff
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

22 files changed:
Makefile.am
data/rc.xml
data/xsession/openbox-gnome-session.in
debian/control
doc/obxprop.1.in [new file with mode: 0644]
doc/obxprop.1.sgml [new file with mode: 0644]
doc/openbox-gnome-session.1.in
doc/openbox-gnome-session.1.sgml
doc/openbox-kde-session.1.in
doc/openbox-kde-session.1.sgml
doc/openbox-session.1.in
doc/openbox-session.1.sgml
doc/openbox.1.in
doc/openbox.1.sgml
openbox/actions/focus.c
openbox/config.c
openbox/config.h
openbox/event.c
openbox/focus_cycle.c
openbox/menuframe.c
openbox/menuframe.h
tools/obxprop/obxprop.c

index 45a3bd2f9d66c04be5001840c2b020c27b21ef7d..9617a1ca4738acd7b01275934662162052f2920f 100644 (file)
@@ -501,6 +501,8 @@ dist_noinst_DATA = \
        doc/openbox-gnome-session.1.in \
        doc/openbox-kde-session.1.sgml \
        doc/openbox-kde-session.1.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 \
index e5eb9178a8bd0789fbbada31e1cf502be2a0f6ee..f5f3712f048abeb808dabe0cada04205ea812441 100644 (file)
        menu is hidden again -->
   <middle>no</middle>
   <!-- center submenus vertically about the parent entry -->
-  <submenuShowDelay>100</submenuShowDelay>
-  <!-- this one is easy, time to delay before showing a submenu after hovering
-       over the parent entry -->
+  <submenuShowDelay>200</submenuShowDelay>
+  <!-- time to delay before showing a submenu after hovering over the parent
+       entry.
+       if this is a negative value, then the delay is infinite and the
+       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 -->
+       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>
   <!-- controls if icons appear in the client-list-(combined-)menu -->
   <manageDesktops>yes</manageDesktops>
index de46bec534476029cb6567e269bb5c9e7cc80345..6765ae82b21bb066e25b3d8bb9d95cc620641830 100644 (file)
@@ -46,7 +46,7 @@ else
   OB_SESSION=$(gconftool-2 -g $SPATH/openbox_session 2> /dev/null)
 
   # update the GNOME/Openbox session if needed
-  if x$OB_SESSION != x$SESSION; then
+  if test x$OB_SESSION != x$SESSION; then
       # the default session changed or we didn't run GNOME/Openbox before
       gconftool-2 -t list --list-type=strings -s $SPATH/openbox_session \
         "$SESSION" 2> /dev/null
index 0a15a7716a025d8e09b85a72b5d7bb425ef1790d..61f72ccf65ed56e78f3570aaa63f27adb7fb0a79 100644 (file)
@@ -13,4 +13,4 @@ Suggests: menu, x-display-manager, ksmserver | gnome-session, kdm | gdm
 Conflicts: menu (<< 2.1.12)
 Provides: x-window-manager
 Description: A minimalistic, highly configurable, next generation window manager with extensive standards support.
- http://icculus.org/openbox/
+ http://openbox.org/
diff --git a/doc/obxprop.1.in b/doc/obxprop.1.in
new file mode 100644 (file)
index 0000000..f3ac096
--- /dev/null
@@ -0,0 +1,42 @@
+.TH "OBXPROP" "1" 
+.SH "NAME" 
+openbox \(em A minimalistic, highly configurable, next generation window 
+manager with extensive standards support. 
+.SH "SYNOPSIS" 
+.PP 
+\fBopenbox\fR [\fB\-\-help\fP]  [\fB\-\-display\fP]  [DISPLAY]  [\fB\-\-id\fP]  [ID]  [\fB\-\-root\fP]  
+.SH "DESCRIPTION" 
+.PP 
+obxprop is a tool for displaying the properties on an x 
+window. 
+.PP 
+This tool has a similar functionality to \fBxprop\fR, 
+but obxprop allows you to see UTF-8 strings as text. 
+.PP 
+You may use the \fB\-\-id\fR option to specify a window 
+identifier, otherwise obxprop will allow you to select a window by 
+clicking on it. 
+.PP 
+Primarily, this tool exists for Openbox users to see the value of the 
+_OB_NAME, _OB_CLASS, and _OB_ROLE properties, which Openbox uses for 
+matching windows against user-defined application rules. 
+.SH "OPTIONS" 
+.PP 
+These are the possible options that \fBopenbox\fR accepts: 
+.IP "\fB\-\-help\fP" 10 
+Show a summary of the options available. 
+.IP "\fB\-\-display\fP" 10 
+.IP "DISPLAY" 10 
+Specify the X display to use. 
+.IP "\fB\-\-id\fP" 10 
+.IP "ID" 10 
+Specify the window identifier for the window whose properties 
+will be displayed. 
+.SH "SEE ALSO" 
+.PP 
+openbox (1), openbox-session(1), openbox-gnome-session(1), 
+openbox-kde-session(1). 
+.PP 
+Please report bugs to: \fBhttp://bugzilla.icculus.org/ 
+\fP 
+.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40 
diff --git a/doc/obxprop.1.sgml b/doc/obxprop.1.sgml
new file mode 100644 (file)
index 0000000..06e7817
--- /dev/null
@@ -0,0 +1,116 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+     page: `docbook-to-man manpage.sgml > manpage.1'.  You may view
+     the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+     less'.  A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+       docbook-to-man $< > $@
+
+    
+       The docbook-to-man binary is found in the docbook-to-man package.
+       Please remember that if you create the nroff version in one of the
+       debian/rules file targets (such as build), you will need to include
+       docbook-to-man in your Build-Depends control field.
+
+  -->
+
+  <!ENTITY dhsection   "<manvolnum>1</manvolnum>">
+  <!ENTITY dhucpackage "<refentrytitle>OBXPROP</refentrytitle>">
+  <!ENTITY dhpackage   "openbox">
+]>
+
+<refentry>
+  <refmeta>
+    &dhucpackage;
+
+    &dhsection;
+  </refmeta>
+  <refnamediv>
+    <refname>&dhpackage;</refname>
+
+    <refpurpose>A minimalistic, highly configurable, next generation window
+      manager with extensive standards support.</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg><option>--help</option></arg>
+      <arg><option>--display</option></arg><arg>DISPLAY</arg>
+      <arg><option>--id</option></arg><arg>ID</arg>
+      <arg><option>--root</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>DESCRIPTION</title>
+
+    <para>obxprop is a tool for displaying the properties on an x
+      window.</para>
+
+    <para>This tool has a similar functionality to <command>xprop</command>,
+      but obxprop allows you to see UTF-8 strings as text.</para>
+
+    <para>You may use the <command>--id</command> option to specify a window
+      identifier, otherwise obxprop will allow you to select a window by
+      clicking on it.</para>
+
+    <para>Primarily, this tool exists for Openbox users to see the value of the
+      _OB_NAME, _OB_CLASS, and _OB_ROLE properties, which Openbox uses for
+      matching windows against user-defined application rules.</para>
+  </refsect1>
+  <refsect1>
+    <title>OPTIONS</title>
+
+    <para>These are the possible options that <command>&dhpackage;</command> accepts:</para>
+    <variablelist>
+      <varlistentry>
+        <term><option>--help</option></term>
+        <listitem>
+          <para>Show a summary of the options available.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--display</option></term><term>DISPLAY</term>
+        <listitem>
+          <para>Specify the X display to use.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--id</option></term><term>ID</term>
+        <listitem>
+          <para>Specify the window identifier for the window whose properties
+            will be displayed.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>SEE ALSO</title>
+
+    <para>openbox (1), openbox-session(1), openbox-gnome-session(1),
+      openbox-kde-session(1).</para>
+
+    <para>Please report bugs to: <literal>http://bugzilla.icculus.org/
+      </literal></para>
+  </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
+
+
index f38c9bf64c7094dbfb1bf70669cdb0f3a77686cb..7256874ba91489462e593db8d41bfbb0457ae450 100644 (file)
@@ -15,8 +15,8 @@ openbox(1), openbox-kde-session(1), openbox-session(1).
  
 .PP 
 The program's full documentation is available on the website: 
-\fBhttp://icculus.org/openbox/\fP 
+\fBhttp://openbox.org/\fP 
 .PP 
 Please report bugs to: \fBhttp://bugzilla.icculus.org/ 
 \fP 
-.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 
+.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40 
index c72865a75f72a2f8c4baa0d42ef8d492b622efe9..66add1b3c538b850ea2edfedf0d71ef77aa5f47d 100644 (file)
@@ -49,7 +49,7 @@ manpage.1: manpage.sgml
       </para>
 
     <para>The program's full documentation is available on the website:
-      <literal>http://icculus.org/openbox/</literal></para>
+      <literal>http://openbox.org/</literal></para>
 
     <para>Please report bugs to: <literal>http://bugzilla.icculus.org/
       </literal></para>
index d46d14b4899324333e1db3e57534b7fed9c13ece..9a96275d946fa99211e20bf42b9ab95e89989ac9 100644 (file)
@@ -15,8 +15,8 @@ openbox(1), openbox-gnome-session(1), openbox-session(1).
  
 .PP 
 The program's full documentation is available on the website: 
-\fBhttp://icculus.org/openbox/\fP 
+\fBhttp://openbox.org/\fP 
 .PP 
 Please report bugs to: \fBhttp://bugzilla.icculus.org/ 
 \fP 
-.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 
+.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40 
index e4f049db4c25c7dd27b5ccb3ff3c336a13660d29..70c5117e69a01698081f3eb207d1e8f5012dfd96 100644 (file)
@@ -49,7 +49,7 @@ manpage.1: manpage.sgml
       </para>
 
     <para>The program's full documentation is available on the website:
-      <literal>http://icculus.org/openbox/</literal></para>
+      <literal>http://openbox.org/</literal></para>
 
     <para>Please report bugs to: <literal>http://bugzilla.icculus.org/
       </literal></para>
index 262324743584469498f047df4659beb0a868161d..483cdfdab2733bc51c76470f72579ee1b765e118 100644 (file)
@@ -35,8 +35,8 @@ openbox(1), openbox-session(1), openbox-gnome-session(1).
  
 .PP 
 The program's full documentation is available on the website: 
-\fBhttp://icculus.org/openbox/\fP 
+\fBhttp://openbox.org/\fP 
 .PP 
 Please report bugs to: \fBhttp://bugzilla.icculus.org/ 
 \fP 
-.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 
+.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40 
index 3c31755e7b18f959894b30e51452190a01d6a5d5..ccece7a2bfce4c0a63fb0c796a5f0dd7f0a70d9b 100644 (file)
@@ -66,7 +66,7 @@ manpage.1: manpage.sgml
       </para>
 
     <para>The program's full documentation is available on the website:
-      <literal>http://icculus.org/openbox/</literal></para>
+      <literal>http://openbox.org/</literal></para>
 
     <para>Please report bugs to: <literal>http://bugzilla.icculus.org/
       </literal></para>
index 2a5446f3c21eba6b4a64645d7ea9ae270cd5d0af..d508e8c699e09a9404cb88fbcadbd4810bd8a05a 100644 (file)
@@ -88,8 +88,8 @@ obconf (1), openbox-session(1), openbox-gnome-session(1),
 openbox-kde-session(1). 
 .PP 
 The program's full documentation is available on the website: 
-\fBhttp://icculus.org/openbox/\fP 
+\fBhttp://openbox.org/\fP 
 .PP 
 Please report bugs to: \fBhttp://bugzilla.icculus.org/ 
 \fP 
-.\" created by instant / docbook-to-man, Tue 22 May 2007, 00:06 
+.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40 
index 6921a66618bd5f07980a110ec4608bbf04a807ec..275c3246ee075516d239e5477b272374707663b8 100644 (file)
@@ -177,7 +177,7 @@ manpage.1: manpage.sgml
       openbox-kde-session(1).</para>
 
     <para>The program's full documentation is available on the website:
-      <literal>http://icculus.org/openbox/</literal></para>
+      <literal>http://openbox.org/</literal></para>
 
     <para>Please report bugs to: <literal>http://bugzilla.icculus.org/
       </literal></para>
index 40c2c80d5c68506a0170769edf84e11e98ee3bf1..8bae49c7a1aaf0778aa142d789f4a43b0366682f 100644 (file)
@@ -6,6 +6,7 @@
 
 typedef struct {
     gboolean here;
+    gboolean stop_int;
 } Options;
 
 static gpointer setup_func(xmlNodePtr node);
@@ -22,9 +23,12 @@ static gpointer setup_func(xmlNodePtr node)
     Options *o;
 
     o = g_new0(Options, 1);
+    o->stop_int = TRUE;
 
     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;
 }
 
@@ -44,11 +48,17 @@ static gboolean run_func(ObActionsData *data, gpointer options)
             (data->context != OB_FRAME_CONTEXT_CLIENT &&
              data->context != OB_FRAME_CONTEXT_FRAME))
         {
+            if (o->stop_int)
+                actions_interactive_cancel_act();
+
             actions_client_move(data, TRUE);
             client_activate(data->client, TRUE, o->here, FALSE, FALSE, TRUE);
             actions_client_move(data, FALSE);
         }
     } else if (data->context == OB_FRAME_CONTEXT_DESKTOP) {
+        if (o->stop_int)
+            actions_interactive_cancel_act();
+
         /* focus action on the root window. make keybindings work for this
            openbox instance, but don't focus any specific client */
         focus_nothing();
index 92445517b77b708d0b434ca10d468142c7152961..0241e3f49f4a022add8526d9572145d84f6864c3 100644 (file)
@@ -93,6 +93,7 @@ gint config_mouse_screenedgetime;
 guint    config_menu_hide_delay;
 gboolean config_menu_middle;
 guint    config_submenu_show_delay;
+guint    config_submenu_hide_delay;
 gboolean config_menu_client_list_icons;
 gboolean config_menu_manage_desktops;
 
@@ -813,6 +814,8 @@ static void parse_menu(xmlNodePtr node, gpointer d)
         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")))
@@ -1017,7 +1020,8 @@ void config_startup(ObtXmlInst *i)
 
     config_menu_hide_delay = 250;
     config_menu_middle = FALSE;
-    config_submenu_show_delay = 0;
+    config_submenu_show_delay = 200;
+    config_submenu_hide_delay = 400;
     config_menu_client_list_icons = TRUE;
     config_menu_manage_desktops = TRUE;
     config_menu_files = NULL;
index d6295f527c2bddc88b60dab5274ef08584786c43..89c4c6f6807ab79ac0423b2a17dce49bcf35ff47 100644 (file)
@@ -191,6 +191,8 @@ extern guint    config_menu_hide_delay;
 extern gboolean config_menu_middle;
 /*! Delay before opening a submenu in milliseconds */
 extern guint    config_submenu_show_delay;
+/*! Delay before closing a submenu in milliseconds */
+extern guint    config_submenu_hide_delay;
 /*! Show icons in client_list_menu */
 extern gboolean config_menu_client_list_icons;
 /*! Show manage desktops in client_list_menu */
index 2f853fbbc40d8a0a52e8d9a775a132e8a2ba3b9e..5127c28f972740c890ff6cfde2506b7e1648b11a 100644 (file)
@@ -1802,8 +1802,13 @@ static gboolean event_handle_menu_input(XEvent *ev)
 
             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;
             }
 
@@ -1903,6 +1908,15 @@ static gboolean event_handle_menu_input(XEvent *ev)
     return ret;
 }
 
+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;
@@ -1925,14 +1939,16 @@ static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
         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(obt_display, &ce, event_look_for_menu_enter,
+                              (XPointer)e->frame))
+                XPutBackEvent(obt_display, &ce);
+            else
                 menu_frame_select(e->frame, NULL, FALSE);
         }
         break;
index a616db64b2de0c86121c848cf86a5b489453dae4..a70151fdce236ea31ae0e6798217f93b461bdf09 100644 (file)
@@ -54,9 +54,10 @@ void focus_cycle_stop(ObClient *ifclient)
 {
     /* stop focus cycling if the given client is a valid focus target,
        and so the cycling is being disrupted */
-    if (focus_cycle_target && ifclient &&
-        (ifclient == focus_cycle_target ||
-         focus_cycle_popup_is_showing(ifclient)))
+    if (focus_cycle_target &&
+        ((ifclient && (ifclient == focus_cycle_target ||
+                       focus_cycle_popup_is_showing(ifclient))) ||
+         !ifclient))
     {
         focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,TRUE);
         focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
index ee374de5e538e81ec913fce5085625ec8943b2a3..57f2943886767a15a4a11a2f842faf8431897766 100644 (file)
@@ -48,10 +48,11 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
                                               ObMenuFrame *frame);
 static void menu_entry_frame_free(ObMenuEntryFrame *self);
 static void menu_frame_update(ObMenuFrame *self);
-static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data);
-static gboolean menu_entry_frame_submenu_show_timeout(gpointer data);
+static gboolean submenu_show_timeout(gpointer data);
 static void menu_frame_hide(ObMenuFrame *self);
 
+static gboolean submenu_hide_timeout(gpointer data);
+
 static Window createWindow(Window parent, gulong mask,
                            XSetWindowAttributes *attrib)
 {
@@ -95,7 +96,6 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
     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 +985,15 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
     return TRUE;
 }
 
+/*! 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)
 {
@@ -997,12 +1006,14 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
     self->monitor = parent->monitor;
     self->parent = parent;
     self->parent_entry = parent_entry;
-    parent->open_submenu = parent_entry;
 
     /* set up parent's child to be us */
-    if (parent->child)
-        menu_frame_hide(parent->child);
-    parent->child = self;
+    if ((parent->child) != self) {
+        if (parent->child)
+            menu_frame_hide(parent->child);
+        parent->child = self;
+        parent->child_entry = parent_entry;
+    }
 
     if (!menu_frame_show(self))
         return FALSE;
@@ -1043,9 +1054,11 @@ static void menu_frame_hide(ObMenuFrame *self)
     if (self->child)
         menu_frame_hide(self->child);
 
-    if (self->parent && self->parent->child == self) {
+    if (self->parent) {
+        remove_submenu_hide_timeout(self);
+
         self->parent->child = NULL;
-        self->parent->open_submenu = NULL;
+        self->parent->child_entry = NULL;
     }
     self->parent = NULL;
     self->parent_entry = NULL;
@@ -1071,11 +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);
+        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 +1098,8 @@ void menu_frame_hide_all_client(ObClient *client)
         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);
+                obt_main_loop_timeout_remove(ob_main_loop,
+                                             submenu_show_timeout);
             }
             menu_frame_hide(f);
         }
@@ -1130,6 +1134,7 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y)
 
         for (it = frame->entries; it; it = g_list_next(it)) {
             ObMenuEntryFrame *e = it->data;
+
             if (RECT_CONTAINS(e->area, x, y)) {
                 ret = e;
                 break;
@@ -1139,18 +1144,17 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y)
     return ret;
 }
 
-static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data)
+static gboolean submenu_show_timeout(gpointer data)
 {
     g_assert(menu_frame_visible);
-    g_assert(((ObMenuFrame*)data)->parent != NULL);
-    menu_frame_hide((ObMenuFrame*)data);
+    menu_entry_frame_show_submenu((ObMenuEntryFrame*)data);
     return FALSE;
 }
 
-static gboolean menu_entry_frame_submenu_show_timeout(gpointer data)
+static gboolean submenu_hide_timeout(gpointer data)
 {
     g_assert(menu_frame_visible);
-    menu_entry_frame_show_submenu((ObMenuEntryFrame*)data);
+    menu_frame_hide((ObMenuFrame*)data);
     return FALSE;
 }
 
@@ -1159,27 +1163,25 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
 {
     ObMenuEntryFrame *old = self->selected;
     ObMenuFrame *oldchild = self->child;
+    ObMenuEntryFrame *oldchild_entry = self->child_entry;
 
+    /* if the user selected a separator, ignore it and reselect what we had
+       selected before */
     if (entry && entry->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR)
         entry = old;
 
-    if (old == entry) return;
+    if (old == entry &&
+        (!old || old->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU))
+        return;
+
+    /* if the user left this menu but we have a submenu open, move the
+       selection back to that submenu */
+    if (!entry && oldchild_entry)
+        entry = oldchild_entry;
 
     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);
+        obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
     }
 
     self->selected = entry;
@@ -1187,50 +1189,47 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *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)
+                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)
+                    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);
             }
         }
     }
index 87a718e79fbf377bb44492ce618a75a1f547dcf1..a57b0dcbda2fe3ff4eaf0d04b4585141219d5a56 100644 (file)
@@ -50,12 +50,10 @@ struct _ObMenuFrame
     ObMenuFrame *parent;
     ObMenuEntryFrame *parent_entry;
     ObMenuFrame *child;
+    ObMenuEntryFrame *child_entry;
 
     GList *entries;
     ObMenuEntryFrame *selected;
-    /* if a submenu was selected, then this holds the entry for that submenu
-       until it is closed */
-    ObMenuEntryFrame *open_submenu;
 
     /* show entries from the menu starting at this index */
     guint show_from;
index 268515440683c03374d7cac6d79fc9ee4133f1a4..6ea8a4d3861641a1dab01857cf0cc21a4a3514ca 100644 (file)
@@ -16,7 +16,8 @@ gint fail(const gchar *s) {
              "Options:\n"
              "    --help              Display this help and exit\n"
              "    --display DISPLAY   Connect to this X display\n"
-             "    --id ID             Show the properties for this window\n");
+             "    --id ID             Show the properties for this window\n"
+             "    --root              Show the properties for the root window\n");
     return 1;
 }
 
@@ -256,11 +257,14 @@ int main(int argc, char **argv)
     Window id, userid = None;
     int i;
     char *dname = NULL;
+    gboolean root = FALSE;
 
     for (i = 1; i < argc; ++i) {
         if (!strcmp(argv[i], "--help")) {
             return fail(0);
         }
+        else if (!strcmp(argv[i], "--root"))
+            root = TRUE;
         else if (!strcmp(argv[i], "--id")) {
             if (++i == argc)
                 return fail(0);
@@ -287,6 +291,9 @@ int main(int argc, char **argv)
                     "Ensure you have permission to connect to the display.");
     }
 
+    if (root)
+        userid = RootWindow(d, DefaultScreen(d));
+
     if (userid == None) {
         i = XGrabPointer(d, RootWindow(d, DefaultScreen(d)),
                          False, ButtonPressMask,
This page took 0.046895 seconds and 4 git commands to generate.