emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r99925: Don't redraw lucid menus more


From: Jan D
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r99925: Don't redraw lucid menus more than needed. Use double buffer to reduce flicker.
Date: Sat, 17 Apr 2010 19:49:18 +0200
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 99925 [merge]
committer: Jan D <address@hidden>
branch nick: trunk
timestamp: Sat 2010-04-17 19:49:18 +0200
message:
  Don't redraw lucid menus more than needed.  Use double buffer to reduce 
flicker.
    
  * xlwmenu.c: Include Shell.h, remove duplicate declaration of
  XlwMenuRedisplay.
  (display_menu_item): Replace ws->window with ws->pixmap, remove
  call to XftDrawRect.
  (display_menu): Remove this and that argument.  Remove
  just_compute_this_one_p. Fill pixmap at start and copy it to window
  at end.
  (expose_cb): New function.
  (make_windows_if_needed): Replace XCreateWindow with XtCreatePopup.
  Add eventhandler for expose to expose_cb.  Remove creation of
  xft_draw.
  (create_pixmap_for_menu): New function.
  (remap_menubar): Pop down menus that aren't the same as in old_stack.
  Set width, heigh, x, y on widget with XtVaSetValues.  Call
  create_pixmap_for_menu.
  Replace XUnmapWindow with XtPopdown.
  Remowe two last parameters to display_menu.
  (map_event_to_widget_value, XlwMenuRedisplay, Key, Select)
  (pop_up_menu): Remowe two last parameters to display_menu.
  (XlwMenuRealize): Call create_pixmap_for_menu, set w and pixmap.
  Remove call to XftDrawCreate.
  (XlwMenuDestroy): Free pixmap.  Call XtDestroyWidget instead of
  XDestroyWindow.
  (handle_motion_event): Only call handle_single_motion_event once.
  
  * xlwmenuP.h (window_state): Add pixmap and w.
modified:
  lwlib/ChangeLog
  lwlib/xlwmenu.c
  lwlib/xlwmenuP.h
=== modified file 'lwlib/ChangeLog'
--- a/lwlib/ChangeLog   2010-04-16 01:08:29 +0000
+++ b/lwlib/ChangeLog   2010-04-17 17:43:03 +0000
@@ -1,3 +1,32 @@
+2010-04-17  Jan Djärv  <address@hidden>
+
+       * xlwmenu.c: Include Shell.h, remove duplicate declaration of
+       XlwMenuRedisplay.
+       (display_menu_item): Replace ws->window with ws->pixmap, remove
+       call to XftDrawRect.
+       (display_menu): Remove this and that argument.  Remove
+       just_compute_this_one_p. Fill pixmap at start and copy it to window
+       at end.
+       (expose_cb): New function.
+       (make_windows_if_needed): Replace XCreateWindow with XtCreatePopup.
+       Add eventhandler for expose to expose_cb.  Remove creation of
+       xft_draw.
+       (create_pixmap_for_menu): New function.
+       (remap_menubar): Pop down menus that aren't the same as in old_stack.
+       Set width, heigh, x, y on widget with XtVaSetValues.  Call
+       create_pixmap_for_menu.
+       Replace XUnmapWindow with XtPopdown.
+       Remowe two last parameters to display_menu.
+       (map_event_to_widget_value, XlwMenuRedisplay, Key, Select)
+       (pop_up_menu): Remowe two last parameters to display_menu.
+       (XlwMenuRealize): Call create_pixmap_for_menu, set w and pixmap.
+       Remove call to XftDrawCreate.
+       (XlwMenuDestroy): Free pixmap.  Call XtDestroyWidget instead of
+       XDestroyWindow.
+       (handle_motion_event): Only call handle_single_motion_event once.
+
+       * xlwmenuP.h (window_state): Add pixmap and w.
+
 2010-04-16  YAMAMOTO Mitsuharu  <address@hidden>
 
        * xlwmenu.c (facename_changed): Put function in #ifdef HAVE_XFT.

=== modified file 'lwlib/xlwmenu.c'
--- a/lwlib/xlwmenu.c   2010-04-16 01:08:29 +0000
+++ b/lwlib/xlwmenu.c   2010-04-17 17:43:03 +0000
@@ -44,6 +44,7 @@
 #include <X11/ObjectP.h>
 #include <X11/StringDefs.h>
 #include <X11/cursorfont.h>
+#include <X11/Shell.h>
 #include "xlwmenuP.h"
 
 #ifdef emacs
@@ -186,7 +187,6 @@
 
 static Boolean XlwMenuSetValues();
 static void XlwMenuRealize();
-static void XlwMenuRedisplay();
 static void XlwMenuResize();
 static void XlwMenuInitialize();
 static void XlwMenuRedisplay();
@@ -1067,13 +1067,13 @@
 
       if (separator_p)
        {
-         draw_separator (mw, ws->window, x, y, width, separator);
+         draw_separator (mw, ws->pixmap, x, y, width, separator);
        }
       else
        {
          int x_offset = x + h_spacing + shadow;
          char* display_string = resource_widget_value (mw, val);
-         draw_shadow_rectangle (mw, ws->window, x, y, width, height, True,
+         draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height, True,
                                 False);
 
          /* Deal with centering a menu title. */
@@ -1092,9 +1092,6 @@
           if (ws->xft_draw)
             {
               int draw_y = y + v_spacing + shadow;
-              XftDrawRect (ws->xft_draw, &mw->menu.xft_bg,
-                           x_offset, draw_y,
-                           ws->width, font_height);
               XftDrawStringUtf8 (ws->xft_draw, xftfg,
                                  mw->menu.xft_font,
                                  x_offset, draw_y + font_ascent,
@@ -1105,13 +1102,13 @@
 #endif
 #ifdef HAVE_X_I18N
           if (mw->menu.fontSet)
-            XmbDrawString (XtDisplay (mw), ws->window, mw->menu.fontSet,
+            XmbDrawString (XtDisplay (mw), ws->pixmap, mw->menu.fontSet,
                            text_gc, x_offset,
                            y + v_spacing + shadow + font_ascent,
                            display_string, strlen (display_string));
           else
 #endif
-          XDrawString (XtDisplay (mw), ws->window,
+          XDrawString (XtDisplay (mw), ws->pixmap,
                       text_gc, x_offset,
                       y + v_spacing + shadow + font_ascent,
                       display_string, strlen (display_string));
@@ -1119,16 +1116,16 @@
          if (!horizontal_p)
            {
              if (val->button_type == BUTTON_TYPE_TOGGLE)
-               draw_toggle (mw, ws->window, x, y + v_spacing + shadow,
+               draw_toggle (mw, ws->pixmap, x, y + v_spacing + shadow,
                             val->selected);
              else if (val->button_type == BUTTON_TYPE_RADIO)
-               draw_radio (mw, ws->window, x, y + v_spacing + shadow,
+               draw_radio (mw, ws->pixmap, x, y + v_spacing + shadow,
                            val->selected);
 
              if (val->contents)
                {
                  int a_w = arrow_width (mw);
-                 draw_arrow (mw, ws->window, deco_gc,
+                 draw_arrow (mw, ws->pixmap, deco_gc,
                              x + width - a_w
                              - mw->menu.horizontal_spacing
                              - mw->menu.shadow_thickness,
@@ -1154,7 +1151,7 @@
 #endif
 #ifdef HAVE_X_I18N
                   if (mw->menu.fontSet)
-                    XmbDrawString (XtDisplay (mw), ws->window,
+                    XmbDrawString (XtDisplay (mw), ws->pixmap,
                                    mw->menu.fontSet,
                                    text_gc,
                                    x + label_width + mw->menu.arrow_spacing,
@@ -1162,7 +1159,7 @@
                                    val->key, strlen (val->key));
                   else
 #endif
-                 XDrawString (XtDisplay (mw), ws->window,
+                 XDrawString (XtDisplay (mw), ws->pixmap,
                               text_gc,
                               x + label_width + mw->menu.arrow_spacing,
                               y + v_spacing + shadow + font_ascent,
@@ -1171,17 +1168,17 @@
            }
          else
            {
-             XDrawRectangle (XtDisplay (mw), ws->window,
+             XDrawRectangle (XtDisplay (mw), ws->pixmap,
                              mw->menu.background_gc,
                              x + shadow, y + shadow,
                              label_width + h_spacing - 1,
                              font_height + 2 * v_spacing - 1);
-             draw_shadow_rectangle (mw, ws->window, x, y, width, height,
+             draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height,
                                     True, False);
            }
 
          if (highlighted_p)
-           draw_shadow_rectangle (mw, ws->window, x, y, width, height, False,
+           draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height, False,
                                   False);
        }
     }
@@ -1191,16 +1188,13 @@
 }
 
 static void
-display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
-             this, that)
+display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return)
      XlwMenuWidget mw;
      int level;
      Boolean just_compute_p;
      XPoint* highlighted_pos;
      XPoint* hit;
      widget_value** hit_return;
-     widget_value* this;
-     widget_value* that;
 {
   widget_value*        val;
   widget_value* following_item;
@@ -1208,9 +1202,6 @@
   XPoint       where;
   int horizontal_p = mw->menu.horizontal && (level == 0);
   int highlighted_p;
-  int just_compute_this_one_p;
-  /* This is set nonzero if the element containing HIGHLIGHTED_POS
-     is disabled, so that we do not return any subsequent element either.  */
   int no_return = 0;
   enum menu_separator separator;
 
@@ -1229,6 +1220,11 @@
   where.y = 0;
 
   ws = &mw->menu.windows [level];
+
+  if (!just_compute_p)
+    XFillRectangle (XtDisplay (mw), ws->pixmap, mw->menu.background_gc,
+                    0, 0, ws->width, ws->height);
+
   for (val = mw->menu.old_stack [level]->contents; val; val = val->next)
     {
       highlighted_p = val == following_item;
@@ -1240,11 +1236,8 @@
            highlighted_pos->y = where.y;
        }
 
-      just_compute_this_one_p =
-       just_compute_p || ((this || that) && val != this &&  val != that);
-
       display_menu_item (mw, val, ws, &where, highlighted_p, horizontal_p,
-                        just_compute_this_one_p);
+                        just_compute_p);
 
       if (highlighted_p && highlighted_pos)
        {
@@ -1282,8 +1275,12 @@
     }
 
   if (!just_compute_p)
-    draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height,
-                          False, False);
+    {
+      draw_shadow_rectangle (mw, ws->pixmap, 0, 0, ws->width, ws->height,
+                             False, False);
+      XCopyArea (XtDisplay (mw), ws->pixmap, ws->window,
+                 mw->menu.foreground_gc, 0, 0, ws->width, ws->height, 0, 0);
+    }
 }
 
 /* Motion code */
@@ -1302,15 +1299,28 @@
 }
 
 static void
+expose_cb (Widget widget,
+           XtPointer closure,
+           XEvent* event,
+           Boolean* continue_to_dispatch)
+{
+  *continue_to_dispatch = False;
+  XlwMenuWidget mw = (XlwMenuWidget) closure;
+  int i;
+
+  for (i = 0; i < mw->menu.windows_length; ++i)
+    if (mw->menu.windows [i].w == widget) break;
+  if (i < mw->menu.windows_length && i < mw->menu.old_depth)
+    display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
+}
+
+static void
 make_windows_if_needed (mw, n)
      XlwMenuWidget mw;
      int n;
 {
   int i;
   int start_at;
-  XSetWindowAttributes xswa;
-  int mask;
-  Window root = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
   window_state* windows;
 #ifdef HAVE_XFT
   int screen = XScreenNumberOfScreen (mw->core.screen);
@@ -1319,17 +1329,6 @@
   if (mw->menu.windows_length >= n)
     return;
 
-  xswa.save_under = True;
-  xswa.override_redirect = True;
-  xswa.background_pixel = mw->core.background_pixel;
-  xswa.border_pixel = mw->core.border_pixel;
-  xswa.event_mask =
-    ExposureMask | PointerMotionMask | PointerMotionHintMask
-      | ButtonReleaseMask | ButtonPressMask;
-  xswa.cursor = mw->menu.cursor_shape;
-  mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel
-    | CWEventMask | CWCursor;
-
   if (!mw->menu.windows)
     {
       mw->menu.windows =
@@ -1349,23 +1348,29 @@
 
   for (i = start_at; i < n; i++)
    {
+     Arg av[10];
+     int ac = 0;
      windows [i].x = 0;
      windows [i].y = 0;
      windows [i].width = 1;
      windows [i].height = 1;
      windows [i].max_rest_width = 0;
-     windows [i].window =
-       XCreateWindow (XtDisplay (mw), root, 0, 0, 1, 1,
-                     0, 0, CopyFromParent, CopyFromParent, mask, &xswa);
+     XtSetArg (av[ac], XtNwidth, 1); ++ac;
+     XtSetArg (av[ac], XtNheight, 1); ++ac;
+     XtSetArg (av[ac], XtNsaveUnder, True); ++ac;
+     XtSetArg (av[ac], XtNbackground, mw->core.background_pixel); ++ac;
+     XtSetArg (av[ac], XtNborderColor, mw->core.border_pixel); ++ac;
+     XtSetArg (av[ac], XtNborderWidth, mw->core.border_width); ++ac;
+     XtSetArg (av[ac], XtNcursor, mw->menu.cursor_shape); ++ac;
+     windows [i].w =
+       XtCreatePopupShell ("sub", overrideShellWidgetClass,
+                           (Widget) mw, av, ac);
+     XtRealizeWidget (windows [i].w);
+     XtAddEventHandler (windows [i].w, ExposureMask, False, expose_cb, mw);
+     windows [i].window = XtWindow (windows [i].w);
+     windows [i].pixmap = None;
 #ifdef HAVE_XFT
-     if (mw->menu.xft_font)
-       mw->menu.windows [i].xft_draw
-         = XftDrawCreate (XtDisplay (mw),
-                          windows [i].window,
-                          DefaultVisual (XtDisplay (mw), screen),
-                          mw->core.colormap);
-     else
-       mw->menu.windows [i].xft_draw = 0;
+     windows [i].xft_draw = 0;
 #endif
    }
 }
@@ -1445,6 +1450,33 @@
     }
 }
 
+static void
+create_pixmap_for_menu (window_state* ws, XlwMenuWidget mw)
+{
+  if (ws->pixmap != None) 
+    {
+      XFreePixmap (XtDisplay (ws->w), ws->pixmap);
+      ws->pixmap = None;
+    }
+  ws->pixmap = XCreatePixmap (XtDisplay (ws->w), ws->window,
+                              ws->width, ws->height,
+                              DefaultDepthOfScreen (XtScreen (ws->w)));
+#ifdef HAVE_XFT
+  if (ws->xft_draw)
+    XftDrawDestroy (ws->xft_draw);
+  if (mw->menu.xft_font)
+    {
+      int screen = XScreenNumberOfScreen (mw->core.screen);
+      ws->xft_draw = XftDrawCreate (XtDisplay (ws->w),
+                                    ws->pixmap,
+                                    DefaultVisual (XtDisplay (ws->w), screen),
+                                    mw->core.colormap);
+    }
+  else
+    ws->xft_draw = 0;
+#endif
+}
+
 /* Updates old_stack from new_stack and redisplays. */
 static void
 remap_menubar (mw)
@@ -1490,14 +1522,17 @@
   /* updates old_state from new_state.  It has to be done now because
      display_menu (called below) uses the old_stack to know what to display. */
   for (i = last_same + 1; i < new_depth; i++)
-    old_stack [i] = new_stack [i];
+    {
+      XtPopdown (mw->menu.windows [i].w);
+      old_stack [i] = new_stack [i];
+    }
   mw->menu.old_depth = new_depth;
 
   /* refresh the last selection */
   selection_position.x = 0;
   selection_position.y = 0;
   display_menu (mw, last_same, new_selection == old_selection,
-               &selection_position, NULL, NULL, old_selection, new_selection);
+               &selection_position, NULL, NULL);
 
   /* Now place the new menus.  */
   for (i = last_same + 1; i < new_depth && new_stack[i]->contents; i++)
@@ -1524,17 +1559,17 @@
 
       fit_to_screen (mw, ws, previous_ws, mw->menu.horizontal && i == 1);
 
-      XClearWindow (XtDisplay (mw), ws->window);
-      XMoveResizeWindow (XtDisplay (mw), ws->window, ws->x, ws->y,
-                        ws->width, ws->height);
-      XMapRaised (XtDisplay (mw), ws->window);
-      display_menu (mw, i, False, &selection_position, NULL, NULL, NULL, NULL);
+      XtVaSetValues (ws->w, XtNwidth, ws->width, XtNheight, ws->height,
+                     XtNx, ws->x, XtNy, ws->y, NULL);
+      create_pixmap_for_menu (ws, mw);
+      XtPopup (ws->w, XtGrabNone);
+      display_menu (mw, i, False, &selection_position, NULL, NULL);
     }
 
   /* unmap the menus that popped down */
   for (i = new_depth - 1; i < old_depth; i++)
     if (i >= new_depth || (i > 0 && !new_stack[i]->contents))
-      XUnmapWindow (XtDisplay (mw), windows[i].window);
+      XtPopdown (windows[i].w);
 }
 
 static Boolean
@@ -1575,7 +1610,7 @@
       if (ws && motion_event_is_in_menu (mw, ev, i, &relative_pos))
        {
           inside = 1;
-         display_menu (mw, i, True, NULL, &relative_pos, val, NULL, NULL);
+         display_menu (mw, i, True, NULL, &relative_pos, val);
 
          if (*val)
            {
@@ -1954,6 +1989,7 @@
   mw->menu.windows [0].width = 0;
   mw->menu.windows [0].height = 0;
   mw->menu.windows [0].max_rest_width = 0;
+  mw->menu.windows [0].pixmap = None;
 #ifdef HAVE_XFT
   mw->menu.windows [0].xft_draw = 0;
 #endif
@@ -1996,22 +2032,19 @@
   x_uncatch_errors ();
 #endif
 
+  mw->menu.windows [0].w = w;
   mw->menu.windows [0].window = XtWindow (w);
   mw->menu.windows [0].x = w->core.x;
   mw->menu.windows [0].y = w->core.y;
   mw->menu.windows [0].width = w->core.width;
   mw->menu.windows [0].height = w->core.height;
 
+  create_pixmap_for_menu (&mw->menu.windows [0], mw);
+
 #ifdef HAVE_XFT
   if (mw->menu.xft_font)
     {
       XColor colors[3];
-      int screen = XScreenNumberOfScreen (mw->core.screen);
-      mw->menu.windows [0].xft_draw
-        = XftDrawCreate (XtDisplay (w),
-                         mw->menu.windows [0].window,
-                         DefaultVisual (XtDisplay (w), screen),
-                         mw->core.colormap);
       colors[0].pixel = mw->menu.xft_fg.pixel = mw->menu.foreground;
       colors[1].pixel = mw->menu.xft_bg.pixel = mw->core.background_pixel;
       colors[2].pixel = mw->menu.xft_disabled_fg.pixel
@@ -2030,8 +2063,6 @@
       mw->menu.xft_disabled_fg.color.green = colors[2].green;
       mw->menu.xft_disabled_fg.color.blue = colors[2].blue;
     }
-  else
-    mw->menu.windows [0].xft_draw = 0;
 #endif
 }
 
@@ -2055,8 +2086,7 @@
       submenu_destroyed = 0;
     }
 
-  for (i = 0; i < mw->menu.old_depth; i++)
-    display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
+  display_menu (mw, 0, False, NULL, NULL, NULL);
 }
 
 
@@ -2121,10 +2151,14 @@
     XftFontClose (XtDisplay (mw), mw->menu.xft_font);
 #endif
 
+  if (mw->menu.windows [0].pixmap != None) 
+    XFreePixmap (XtDisplay (mw), mw->menu.windows [0].pixmap);
   /* start from 1 because the one in slot 0 is w->core.window */
   for (i = 1; i < mw->menu.windows_length; i++)
     {
-      XDestroyWindow (XtDisplay (mw), mw->menu.windows [i].window);
+      if (mw->menu.windows [i].pixmap != None) 
+        XFreePixmap (XtDisplay (mw), mw->menu.windows [i].pixmap);
+      XtDestroyWidget (mw->menu.windows [i].w);
 #ifdef HAVE_XFT
       if (mw->menu.windows [i].xft_draw)
         XftDrawDestroy (mw->menu.windows [i].xft_draw);
@@ -2140,7 +2174,7 @@
 facename_changed (XlwMenuWidget newmw,
                   XlwMenuWidget oldmw)
 {
-  /* This will fore a new XftFont even if the same sting is set.
+  /* This will fore a new XftFont even if the same string is set.
      This is good, as rendering parameters may have changed and
      we just want to do a redisplay.  */
   return newmw->menu.faceName != oldmw->menu.faceName;
@@ -2250,13 +2284,14 @@
       /* Don't allow the popup menu to resize itself.  */
       mw->core.width = mw->menu.windows [0].width;
       mw->core.height = mw->menu.windows [0].height;
-      mw->core.parent->core.width = mw->core.width ;
-      mw->core.parent->core.height = mw->core.height ;
+      mw->core.parent->core.width = mw->core.width;
+      mw->core.parent->core.height = mw->core.height;
     }
   else
     {
       mw->menu.windows [0].width = mw->core.width;
       mw->menu.windows [0].height = mw->core.height;
+      create_pixmap_for_menu (&mw->menu.windows [0], mw);
     }
 }
 
@@ -2287,8 +2322,7 @@
   int x = ev->x_root;
   int y = ev->y_root;
   int state = ev->state;
-
-  handle_single_motion_event (mw, ev);
+  XMotionEvent oldev = *ev;
 
   /* allow motion events to be generated again */
   if (ev->is_hint
@@ -2300,6 +2334,8 @@
       && ev->state == state
       && (ev->x_root != x || ev->y_root != y))
     handle_single_motion_event (mw, ev);
+  else
+    handle_single_motion_event (mw, &oldev);
 }
 
 static void
@@ -2609,7 +2645,7 @@
       else
        {
          XtRemoveGrab ((Widget) mw);
-         display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
+         display_menu (mw, 0, False, NULL, NULL, NULL);
        }
     }
 
@@ -2650,7 +2686,7 @@
       else
        {
          XtRemoveGrab ((Widget) mw);
-         display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
+         display_menu (mw, 0, False, NULL, NULL, NULL);
        }
     }
 
@@ -2701,7 +2737,7 @@
       XtConfigureWidget (XtParent ((Widget)mw), x, y, w, h,
                         XtParent ((Widget)mw)->core.border_width);
       XtPopup (XtParent ((Widget)mw), XtGrabExclusive);
-      display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
+      display_menu (mw, 0, False, NULL, NULL, NULL);
       mw->menu.windows [0].x = x + borderwidth;
       mw->menu.windows [0].y = y + borderwidth;
       mw->menu.top_depth = 1;  /* Popup menus don't have a bar so top is 1  */

=== modified file 'lwlib/xlwmenuP.h'
--- a/lwlib/xlwmenuP.h  2010-04-08 16:20:32 +0000
+++ b/lwlib/xlwmenuP.h  2010-04-17 17:43:03 +0000
@@ -32,7 +32,9 @@
 /* Elements in the stack arrays. */
 typedef struct _window_state
 {
+  Widget        w;
   Window       window;
+  Pixmap        pixmap;
   Position     x;
   Position     y;
   Dimension    width;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]