merge r5765-r5772 from trunk (this was non-trivial)
authorDana Jansens <danakj@orodu.net>
Sun, 22 Apr 2007 04:28:43 +0000 (04:28 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 22 Apr 2007 04:28:43 +0000 (04:28 +0000)
openbox/dock.c
openbox/event.c
openbox/frame.c
openbox/keyboard.c
openbox/mainloop.c
openbox/mainloop.h
openbox/menuframe.c
openbox/menuframe.h
openbox/startupnotify.c
render/theme.c
render/theme.h

index 53c791396a1d7254d89d885dc9cdfaba75e19c80..70e1127290657c54558e6ce23bbae33ccdf5c4be 100644 (file)
@@ -616,14 +616,14 @@ void dock_hide(gboolean hide)
     if (!hide) {
         if (dock->hidden && config_dock_hide) {
             ob_main_loop_timeout_add(ob_main_loop, config_dock_show_delay,
-                                 show_timeout, NULL, NULL);
+                                 show_timeout, NULL, g_direct_equal, NULL);
         } else if (!dock->hidden && config_dock_hide) {
             ob_main_loop_timeout_remove(ob_main_loop, hide_timeout);
         }
     } else {
         if (!dock->hidden && config_dock_hide) {
             ob_main_loop_timeout_add(ob_main_loop, config_dock_hide_delay,
-                                 hide_timeout, NULL, NULL);
+                                 hide_timeout, NULL, g_direct_equal, NULL);
         } else if (dock->hidden && config_dock_hide) {
             ob_main_loop_timeout_remove(ob_main_loop, show_timeout);
         }
index 1f5bae13287b6427cc29cc0b2e17dcc1fc33db89..9a1e13dc831becd6c2baf1282d2033a7a32d93b7 100644 (file)
@@ -64,6 +64,12 @@ typedef struct
     gboolean ignored;
 } ObEventData;
 
+typedef struct
+{
+    ObClient *client;
+    Time time;
+} ObFocusDelayData;
+
 static void event_process(const XEvent *e, gpointer data);
 static void event_client_dest(ObClient *client, gpointer data);
 static void event_handle_root(XEvent *e);
@@ -73,6 +79,8 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e);
 static void event_handle_client(ObClient *c, XEvent *e);
 static void event_handle_group(ObGroup *g, XEvent *e);
 
+static void focus_delay_dest(gpointer data);
+static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
 static gboolean focus_delay_func(gpointer data);
 static void focus_delay_client_dest(ObClient *client, gpointer data);
 
@@ -531,7 +539,7 @@ static void event_process(const XEvent *ec, gpointer data)
                 ob_main_loop_timeout_add(ob_main_loop,
                                          config_menu_hide_delay * 1000,
                                          menu_hide_delay_func,
-                                         NULL, NULL);
+                                         NULL, g_direct_equal, NULL);
 
                 if (e->type == ButtonPress || e->type == ButtonRelease ||
                     e->type == MotionNotify)
@@ -616,13 +624,24 @@ void event_enter_client(ObClient *client)
 
     if (client_normal(client) && client_can_focus(client)) {
         if (config_focus_delay) {
+            ObFocusDelayData *data;
+
             ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
+
+            data = g_new(ObFocusDelayData, 1);
+            data->client = client;
+            data->time = event_curtime;
+
             ob_main_loop_timeout_add(ob_main_loop,
                                      config_focus_delay,
                                      focus_delay_func,
-                                     client, NULL);
-        } else
-            focus_delay_func(client);
+                                     data, focus_delay_cmp, focus_delay_dest);
+        } else {
+            ObFocusDelayData data;
+            data.client = client;
+            data.time = event_curtime;
+            focus_delay_func(&data);
+        }
     }
 }
 
@@ -745,7 +764,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             if (config_focus_follow && config_focus_delay)
                 ob_main_loop_timeout_remove_data(ob_main_loop,
                                                  focus_delay_func,
-                                                 client, TRUE);
+                                                 client, FALSE);
             break;
         default:
             break;
@@ -1281,6 +1300,11 @@ static void event_handle_menu(XEvent *ev)
         {
             menu_frame_select(e->frame, NULL);
         }
+    case MotionNotify:   
+        if ((e = menu_entry_frame_under(ev->xmotion.x_root,   
+                                        ev->xmotion.y_root)))
+            menu_frame_select(e->frame, e);   
+        break;
     case KeyPress:
         if (ev->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
             menu_frame_hide_all();
@@ -1316,21 +1340,35 @@ static gboolean menu_hide_delay_func(gpointer data)
     return FALSE; /* no repeat */
 }
 
+static void focus_delay_dest(gpointer data)
+{
+    g_free(data);
+}
+
+static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2)
+{
+    const ObFocusDelayData *f1 = d1, *f2 = d2;
+    return f1->client == f2->client;
+}
+
 static gboolean focus_delay_func(gpointer data)
 {
-    ObClient *c = data;
+    ObFocusDelayData *d = data;
+    Time old = event_curtime;
 
-    if (focus_client != c) {
-        if (client_focus(c) && config_focus_raise)
-            client_raise(c);
+    event_curtime = d->time;
+    if (focus_client != d->client) {
+        if (client_focus(d->client) && config_focus_raise)
+            client_raise(d->client);
     }
+    event_curtime = old;
     return FALSE; /* no repeat */
 }
 
 static void focus_delay_client_dest(ObClient *client, gpointer data)
 {
     ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
-                                     client, TRUE);
+                                     client, FALSE);
 }
 
 static void event_client_dest(ObClient *client, gpointer data)
index 554e7b55fda8a7bbf4c1507ac34eeaa71158bcf5..052f12df8d44e33613c0b52494d58411974deead 100644 (file)
@@ -977,6 +977,7 @@ void frame_flash_start(ObFrame *self)
                                  G_USEC_PER_SEC * 0.6,
                                  flash_timeout,
                                  self,
+                                 g_direct_equal,
                                  flash_done);
     g_get_current_time(&self->flash_end);
     g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
index b95b0805b00083cbb9a6ed57cea46cdf11b9f6c4..01b54b4c10a9325d602bf87767e4ab8f3c185368 100644 (file)
@@ -271,7 +271,8 @@ void keyboard_event(ObClient *client, const XEvent *e)
                 ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
                 /* 5 second timeout for chains */
                 ob_main_loop_timeout_add(ob_main_loop, 5 * G_USEC_PER_SEC,
-                                         chain_timeout, NULL, NULL);
+                                         chain_timeout, NULL,
+                                         g_direct_equal, NULL);
                 grab_keys(FALSE);
                 curpos = p;
                 grab_keys(TRUE);
index e6914f89e8f446b26f71cf3eee0973163262a5f9..62261dde0af6e52dd2b215aea6a12f8c659e8cd2 100644 (file)
@@ -99,6 +99,7 @@ struct _ObMainLoopTimer
     gulong delay;
     GSourceFunc func;
     gpointer data;
+    GEqualFunc equal;
     GDestroyNotify destroy;
 
     /* The timer needs to be freed */
@@ -585,12 +586,14 @@ void ob_main_loop_timeout_add(ObMainLoop *loop,
                               gulong microseconds,
                               GSourceFunc handler,
                               gpointer data,
+                              GEqualFunc cmp,
                               GDestroyNotify notify)
 {
     ObMainLoopTimer *t = g_new(ObMainLoopTimer, 1);
     t->delay = microseconds;
     t->func = handler;
     t->data = data;
+    t->equal = cmp;
     t->destroy = notify;
     t->del_me = FALSE;
     g_get_current_time(&loop->now);
@@ -619,7 +622,7 @@ void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
 
     for (it = loop->timers; it; it = g_slist_next(it)) {
         ObMainLoopTimer *t = it->data;
-        if (t->func == handler && t->data == data) {
+        if (t->func == handler && t->equal(t->data, data)) {
             t->del_me = TRUE;
             if (cancel_dest)
                 t->destroy = NULL;
index 9530f2a60c15d718b434abbf1f6aeedffa8cc654..475918501f3fb2f2666c193e02ab9de4606009b8 100644 (file)
@@ -61,6 +61,7 @@ void ob_main_loop_timeout_add(ObMainLoop *loop,
                               gulong microseconds,
                               GSourceFunc handler,
                               gpointer data,
+                              GEqualFunc cmp,
                               GDestroyNotify notify);
 void ob_main_loop_timeout_remove(ObMainLoop *loop,
                                  GSourceFunc handler);
index fd7e95200cef7437a87929edb5cbfa1ca7f3d257..f359c9852ee091b0c14e2793de5584fbc427b124 100644 (file)
@@ -163,6 +163,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
         RrAppearanceCopy(ob_rr_theme->a_menu_text_disabled);
     self->a_text_selected =
         RrAppearanceCopy(ob_rr_theme->a_menu_text_selected);
+    self->a_text_title =
+        RrAppearanceCopy(ob_rr_theme->a_menu_text_title);
 
     return self;
 }
@@ -193,6 +195,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
         RrAppearanceFree(self->a_text_normal);
         RrAppearanceFree(self->a_text_disabled);
         RrAppearanceFree(self->a_text_selected);
+        RrAppearanceFree(self->a_text_title);
         RrAppearanceFree(self->a_bullet_normal);
         RrAppearanceFree(self->a_bullet_selected);
 
@@ -290,9 +293,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
     case OB_MENU_ENTRY_TYPE_SEPARATOR:
         if (self->entry->data.separator.label) {
             item_a = self->frame->a_title;
-            item_a->texture[0].data.text.string =
-                self->entry->data.separator.label;
-            th = self->frame->title_h;
+            th = ob_rr_theme->menu_title_height;
         } else {
             item_a = self->a_normal;
             th = SEPARATOR_HEIGHT + 2*PADDING;
@@ -326,7 +327,10 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
         text_a->texture[0].data.text.string = sub ? sub->title : "";
         break;
     case OB_MENU_ENTRY_TYPE_SEPARATOR:
-        text_a = self->a_text_normal;
+        if (self->entry->data.separator.label != NULL)
+            text_a = self->a_text_title;
+        else
+            text_a = self->a_text_normal;
         break;
     }
 
@@ -354,7 +358,22 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                 self->frame->item_h - 2*PADDING);
         break;
     case OB_MENU_ENTRY_TYPE_SEPARATOR:
-        if (self->entry->data.separator.label == NULL) {
+        if (self->entry->data.separator.label != NULL) {
+            /* labeled separator */
+            XMoveResizeWindow(ob_display, self->text,
+                              ob_rr_theme->paddingx, ob_rr_theme->paddingy,
+                              self->area.width - 2*ob_rr_theme->paddingx,
+                              ob_rr_theme->menu_title_height -
+                              2*ob_rr_theme->paddingy);
+            text_a->surface.parent = item_a;
+            text_a->surface.parentx = ob_rr_theme->paddingx;
+            text_a->surface.parenty = ob_rr_theme->paddingy;
+            RrPaint(text_a, self->text,
+                    self->area.width - 2*ob_rr_theme->paddingx,
+                    ob_rr_theme->menu_title_height -
+                    2*ob_rr_theme->paddingy);
+        } else {
+            /* unlabeled separaator */
             XMoveResizeWindow(ob_display, self->text, PADDING, PADDING,
                               self->area.width - 2*PADDING, SEPARATOR_HEIGHT);
             self->a_separator->surface.parent = item_a;
@@ -463,6 +482,7 @@ static void menu_frame_render(ObMenuFrame *self)
     GList *it;
     gboolean has_icon = FALSE;
     ObMenu *sub;
+    ObMenuEntryFrame *e;
 
     XSetWindowBorderWidth(ob_display, self->window, ob_rr_theme->mbwidth);
     XSetWindowBorder(ob_display, self->window,
@@ -482,12 +502,6 @@ static void menu_frame_render(ObMenuFrame *self)
         th += 2*PADDING;
         self->item_h = th;
 
-        self->a_title->texture[0].data.text.string = "";
-        RrMinsize(self->a_title, &tw, &th);
-        tw += 2*PADDING;
-        th += 2*PADDING;
-        self->title_h = th;
-
         RrMargins(e->a_normal, &l, &t, &r, &b);
         STRUT_SET(self->item_margin,
                   MAX(self->item_margin.left, l),
@@ -513,10 +527,28 @@ static void menu_frame_render(ObMenuFrame *self)
 
     for (it = self->entries; it; it = g_list_next(it)) {
         RrAppearance *text_a;
-        ObMenuEntryFrame *e = it->data;
+        e = it->data;
+
+        /* if the first entry is a labeled separator, then make its border
+           overlap with the menu's outside border */
+        if (it == self->entries &&
+            e->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR &&
+            e->entry->data.separator.label)
+        {
+            h -= ob_rr_theme->mbwidth;
+        }
+
+        if (e->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR &&
+            e->entry->data.separator.label)
+        {
+            e->border = ob_rr_theme->mbwidth;
+        }
 
-        RECT_SET_POINT(e->area, 0, h);
-        XMoveWindow(ob_display, e->window, 0, e->area.y);
+        RECT_SET_POINT(e->area, 0, h+e->border);
+        XMoveWindow(ob_display, e->window, e->area.x-e->border, e->area.y-e->border);
+        XSetWindowBorderWidth(ob_display, e->window, e->border);
+        XSetWindowBorder(ob_display, e->window,
+                         RrColorPixel(ob_rr_theme->menu_b_color));
 
         text_a = ((e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
                    !e->entry->data.normal.enabled) ?
@@ -548,10 +580,12 @@ static void menu_frame_render(ObMenuFrame *self)
             break;
         case OB_MENU_ENTRY_TYPE_SEPARATOR:
             if (e->entry->data.separator.label != NULL) {
-                self->a_title->texture[0].data.text.string =
+                e->a_text_title->texture[0].data.text.string =
                     e->entry->data.separator.label;
-                RrMinsize(self->a_title, &tw, &th);
+                RrMinsize(e->a_text_title, &tw, &th);
                 tw = MIN(tw, MAX_MENU_WIDTH);
+                th = ob_rr_theme->menu_title_height +
+                    (ob_rr_theme->mbwidth - PADDING) *2;
             } else {
                 tw = 0;
                 th = SEPARATOR_HEIGHT;
@@ -564,6 +598,16 @@ static void menu_frame_render(ObMenuFrame *self)
         h += th;
     }
 
+    /* if the last entry is a labeled separator, then make its border
+       overlap with the menu's outside border */
+    it = g_list_last(self->entries);
+    e = it ? it->data : NULL;
+    if (e && e->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR &&
+        e->entry->data.separator.label)
+    {
+        h -= ob_rr_theme->mbwidth;
+    }
+
     self->text_x = PADDING;
     self->text_w = w;
 
@@ -874,7 +918,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry)
                 ob_main_loop_timeout_add(ob_main_loop,
                                          config_submenu_show_delay * 1000,
                                          menu_entry_frame_submenu_timeout,
-                                         self->selected,
+                                         self->selected, g_direct_equal,
                                          NULL);
             } else {
                 menu_entry_frame_show_submenu(self->selected);
index 9bc1bdc4543a377774306b7a13fa4ef9d73e788b..016700a74ae7e6fad32967f1916cf05aa2eab939 100644 (file)
@@ -80,6 +80,7 @@ struct _ObMenuEntryFrame
     guint ignore_enters;
 
     Rect area;
+    gint border;
 
     Window window;
     Window icon;
@@ -98,6 +99,7 @@ struct _ObMenuEntryFrame
     RrAppearance *a_text_normal;
     RrAppearance *a_text_disabled;
     RrAppearance *a_text_selected;
+    RrAppearance *a_text_title;
 };
 
 extern GHashTable *menu_frame_map;
index bf1f44ac3fa94fb9fbc41720fc93f9834c7220de..5b5723e591ecf545597273e32e64b95582a1224a 100644 (file)
@@ -144,6 +144,7 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data)
            have a timeout */
         ob_main_loop_timeout_add(ob_main_loop, 30 * G_USEC_PER_SEC,
                                  sn_wait_timeout, seq,
+                                 g_direct_equal,
                                  (GDestroyNotify)sn_startup_sequence_unref);
         change = TRUE;
         break;
@@ -256,6 +257,7 @@ void sn_setup_spawn_environment(gchar *program, gchar *name,
     sn_launcher_context_ref(sn_launcher);
     ob_main_loop_timeout_add(ob_main_loop, 30 * G_USEC_PER_SEC,
                              sn_launch_wait_timeout, sn_launcher,
+                             g_direct_equal,
                              (GDestroyNotify)sn_launcher_context_unref);
 
     setenv("DESKTOP_STARTUP_ID", id, TRUE);
index 13a62cfd06ab283e65c72f0043db6c3d07980b01..c03449856cf3325225e7d53d69f88260f3a6a792 100644 (file)
@@ -80,7 +80,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
     theme->a_focused_handle = RrAppearanceNew(inst, 0);
     theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
     theme->a_menu = RrAppearanceNew(inst, 0);
-    theme->a_menu_title = RrAppearanceNew(inst, 1);
+    theme->a_menu_title = RrAppearanceNew(inst, 0);
+    theme->a_menu_text_title = RrAppearanceNew(inst, 1);
     theme->a_menu_normal = RrAppearanceNew(inst, 0);
     theme->a_menu_disabled = RrAppearanceNew(inst, 0);
     theme->a_menu_selected = RrAppearanceNew(inst, 0);
@@ -473,7 +474,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
         set_default_appearance(theme->a_menu);
     if (!read_appearance(db, inst,
                          "menu.title.bg", theme->a_menu_title,
-                         FALSE))
+                         TRUE))
         set_default_appearance(theme->a_menu_title);
     if (!read_appearance(db, inst,
                          "menu.items.active.bg", theme->a_menu_selected,
@@ -636,6 +637,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
     theme->a_icon->surface.grad =
         theme->a_clear->surface.grad =
         theme->a_clear_tex->surface.grad =
+        theme->a_menu_text_title->surface.grad =
         theme->a_menu_normal->surface.grad =
         theme->a_menu_disabled->surface.grad =
         theme->a_menu_text_normal->surface.grad =
@@ -736,10 +738,12 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
     theme->a_unfocused_label->texture[0].data.text.shadow_alpha =
         theme->title_unfocused_shadow_alpha;
 
-    theme->a_menu_title->texture[0].type = RR_TEXTURE_TEXT;
-    theme->a_menu_title->texture[0].data.text.justify = mtitlejust;
-    theme->a_menu_title->texture[0].data.text.font = theme->menu_title_font;
-    theme->a_menu_title->texture[0].data.text.color = theme->menu_title_color;
+    theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
+    theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
+    theme->a_menu_text_title->texture[0].data.text.font =
+        theme->menu_title_font;
+    theme->a_menu_text_title->texture[0].data.text.color =
+        theme->menu_title_color;
 
     if (read_string(db, "menu.title.text.font", &str)) {
         char *p;
@@ -750,8 +754,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
                 i = parse_inline_number(p + strlen("shadowoffset="));
             else
                 i = 1;
-            theme->a_menu_title->texture[0].data.text.shadow_offset_x = i;
-            theme->a_menu_title->texture[0].data.text.shadow_offset_y = i;
+            theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
+            theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
         }
         if ((p = strstr(str, "shadowtint=")))
         {
@@ -767,9 +771,9 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
         }
     }
 
-    theme->a_menu_title->texture[0].data.text.shadow_color =
+    theme->a_menu_text_title->texture[0].data.text.shadow_color =
         theme->menu_title_shadow_color;
-    theme->a_menu_title->texture[0].data.text.shadow_alpha =
+    theme->a_menu_text_title->texture[0].data.text.shadow_alpha =
         theme->menu_title_shadow_alpha;
 
     theme->a_menu_text_normal->texture[0].type =
@@ -1042,7 +1046,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, gchar *name,
              theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
     theme->menu_title_font_height = RrFontHeight
         (theme->menu_title_font,
-         theme->a_menu_title->texture[0].data.text.shadow_offset_y);
+         theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
     theme->menu_font_height = RrFontHeight
         (theme->menu_font,
          theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
@@ -1199,6 +1203,7 @@ void RrThemeFree(RrTheme *theme)
         RrAppearanceFree(theme->a_unfocused_handle);
         RrAppearanceFree(theme->a_menu);
         RrAppearanceFree(theme->a_menu_title);
+        RrAppearanceFree(theme->a_menu_text_title);
         RrAppearanceFree(theme->a_menu_normal);
         RrAppearanceFree(theme->a_menu_disabled);
         RrAppearanceFree(theme->a_menu_selected);
index acceaf5fd01d0580ceb2ed3956e4a921f0b7a5ec..1960f43f2d416a679b3d8e75ec3111f9276cc7fd 100644 (file)
@@ -179,6 +179,7 @@ struct _RrTheme {
     RrAppearance *a_icon;
     RrAppearance *a_focused_handle;
     RrAppearance *a_unfocused_handle;
+    RrAppearance *a_menu_text_title;
     RrAppearance *a_menu_title;
     RrAppearance *a_menu;
     RrAppearance *a_menu_normal;