theme-viewer.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* Metacity theme viewer and test app main() */
00004 
00005 /*
00006  * Copyright (C) 2002 Havoc Pennington
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00021  * 02111-1307, USA.
00022  */
00023 
00024 #include <config.h>
00025 #include "util.h"
00026 #include "theme.h"
00027 #include "theme-parser.h"
00028 #include "preview-widget.h"
00029 #include <gtk/gtk.h>
00030 #include <time.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include <libintl.h>
00035 #define _(x) dgettext (GETTEXT_PACKAGE, x)
00036 #define N_(x) x
00037 
00038 /* We need to compute all different button arrangements
00039  * in terms of button location. We don't care about
00040  * different arrangements in terms of button function.
00041  *
00042  * So if dups are allowed, from 0-4 buttons on the left, from 0-4 on
00043  * the right, 5x5=25 combinations.
00044  *
00045  * If no dups, 0-4 on left determines the number on the right plus
00046  * we have a special case for the "no buttons on either side" case.
00047  */
00048 #ifndef ALLOW_DUPLICATE_BUTTONS
00049 #define BUTTON_LAYOUT_COMBINATIONS (MAX_BUTTONS_PER_CORNER + 1 + 1)
00050 #else
00051 #define BUTTON_LAYOUT_COMBINATIONS ((MAX_BUTTONS_PER_CORNER+1)*(MAX_BUTTONS_PER_CORNER+1))
00052 #endif
00053 
00054 enum
00055 {
00056   FONT_SIZE_SMALL,
00057   FONT_SIZE_NORMAL,
00058   FONT_SIZE_LARGE,
00059   FONT_SIZE_LAST
00060 };
00061 
00062 static MetaTheme *global_theme = NULL;
00063 static GtkWidget *previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + BUTTON_LAYOUT_COMBINATIONS] = { NULL, };
00064 static double milliseconds_to_draw_frame = 0.0;
00065 
00066 static void run_position_expression_tests (void);
00067 #if 0
00068 static void run_position_expression_timings (void);
00069 #endif
00070 static void run_theme_benchmark (void);
00071 
00072 
00073 static GtkItemFactoryEntry menu_items[] =
00074 {
00075   { N_("/_Windows"),              NULL,         NULL,                     0, "<Branch>" },
00076   { N_("/Windows/tearoff"),       NULL,         NULL,                     0, "<Tearoff>" },
00077   { N_("/Windows/_Dialog"),       "<control>d",  NULL,               0, NULL },
00078   { N_("/Windows/_Modal dialog"), NULL,          NULL,         0, NULL },
00079   { N_("/Windows/_Utility"),      "<control>u",  NULL,              0, NULL },
00080   { N_("/Windows/_Splashscreen"), "<control>s",  NULL,         0, NULL },
00081   { N_("/Windows/_Top dock"),     NULL,          NULL,                 0, NULL },
00082   { N_("/Windows/_Bottom dock"),  NULL,          NULL,                 0, NULL },
00083   { N_("/Windows/_Left dock"),    NULL,          NULL,                 0, NULL },
00084   { N_("/Windows/_Right dock"),   NULL,          NULL,                 0, NULL },
00085   { N_("/Windows/_All docks"),    NULL,          NULL,                 0, NULL },
00086   { N_("/Windows/Des_ktop"),      NULL,          NULL,              0, NULL }
00087 };
00088 
00089 static GtkWidget *
00090 normal_contents (void)
00091 {
00092   GtkWidget *table;
00093   GtkWidget *toolbar;
00094   GtkWidget *handlebox;
00095   GtkWidget *statusbar;
00096   GtkWidget *contents;
00097   GtkWidget *sw;
00098   GtkItemFactory *item_factory;
00099       
00100   table = gtk_table_new (1, 4, FALSE);
00101   
00102   /* Create the menubar
00103    */
00104       
00105   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", NULL);
00106 
00107   gtk_item_factory_set_translate_func(item_factory,
00108                                       (GtkTranslateFunc)gettext, NULL, NULL);
00109 
00110   /* Set up item factory to go away */
00111   g_object_ref (item_factory);
00112   gtk_object_sink (GTK_OBJECT (item_factory));
00113   g_object_set_data_full (G_OBJECT (table),
00114                           "<main>",
00115                           item_factory,
00116                           (GDestroyNotify) g_object_unref);
00117 
00118   /* create menu items */
00119   gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items),
00120                                  menu_items, NULL);
00121 
00122   gtk_table_attach (GTK_TABLE (table),
00123                     gtk_item_factory_get_widget (item_factory, "<main>"),
00124                     /* X direction */          /* Y direction */
00125                     0, 1,                      0, 1,
00126                     GTK_EXPAND | GTK_FILL,     0,
00127                     0,                         0);
00128 
00129   /* Create the toolbar
00130    */
00131   toolbar = gtk_toolbar_new ();
00132 
00133   gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
00134                             GTK_STOCK_NEW,
00135                             _("Open another one of these windows"),
00136                             NULL,
00137                             NULL, NULL,
00138                             -1);  /* -1 means "append" */
00139   
00140   gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
00141                             GTK_STOCK_OPEN,
00142                             _("This is a demo button with an 'open' icon"),
00143                             NULL,
00144                             NULL, NULL,
00145                             -1);  /* -1 means "append" */
00146 
00147   gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
00148                             GTK_STOCK_QUIT,
00149                             _("This is a demo button with a 'quit' icon"),
00150                             NULL,
00151                             NULL, NULL,
00152                             -1);  /* -1 means "append" */
00153 
00154   handlebox = gtk_handle_box_new ();
00155 
00156   gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
00157       
00158   gtk_table_attach (GTK_TABLE (table),
00159                     handlebox,
00160                     /* X direction */       /* Y direction */
00161                     0, 1,                   1, 2,
00162                     GTK_EXPAND | GTK_FILL,  0,
00163                     0,                      0);
00164 
00165   /* Create document
00166    */
00167 
00168   sw = gtk_scrolled_window_new (NULL, NULL);
00169 
00170   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
00171                                   GTK_POLICY_AUTOMATIC,
00172                                   GTK_POLICY_AUTOMATIC);
00173 
00174   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
00175                                        GTK_SHADOW_IN);
00176       
00177   gtk_table_attach (GTK_TABLE (table),
00178                     sw,
00179                     /* X direction */       /* Y direction */
00180                     0, 1,                   2, 3,
00181                     GTK_EXPAND | GTK_FILL,  GTK_EXPAND | GTK_FILL,
00182                     0,                      0);
00183       
00184   contents = gtk_text_view_new ();
00185   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents),
00186                                PANGO_WRAP_WORD);
00187       
00188   gtk_container_add (GTK_CONTAINER (sw),
00189                      contents);
00190 
00191   /* Create statusbar */
00192 
00193   statusbar = gtk_statusbar_new ();
00194   gtk_table_attach (GTK_TABLE (table),
00195                     statusbar,
00196                     /* X direction */       /* Y direction */
00197                     0, 1,                   3, 4,
00198                     GTK_EXPAND | GTK_FILL,  0,
00199                     0,                      0);
00200 
00201   gtk_widget_show_all (table);
00202 
00203   return table;
00204 }
00205 
00206 static void
00207 update_spacings (GtkWidget *vbox,
00208                  GtkWidget *action_area)
00209 {
00210   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
00211   gtk_box_set_spacing (GTK_BOX (action_area), 10);
00212   gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
00213 }
00214 
00215 static GtkWidget*
00216 dialog_contents (void)
00217 {
00218   GtkWidget *vbox;
00219   GtkWidget *hbox;
00220   GtkWidget *action_area;
00221   GtkWidget *label;
00222   GtkWidget *image;
00223   GtkWidget *button;
00224   
00225   vbox = gtk_vbox_new (FALSE, 0);
00226 
00227   action_area = gtk_hbutton_box_new ();
00228 
00229   gtk_button_box_set_layout (GTK_BUTTON_BOX (action_area),
00230                              GTK_BUTTONBOX_END);  
00231 
00232   button = gtk_button_new_from_stock (GTK_STOCK_OK);
00233   gtk_box_pack_end (GTK_BOX (action_area),
00234                     button,
00235                     FALSE, TRUE, 0);
00236   
00237   gtk_box_pack_end (GTK_BOX (vbox), action_area,
00238                     FALSE, TRUE, 0);
00239 
00240   update_spacings (vbox, action_area);
00241 
00242   label = gtk_label_new (_("This is a sample message in a sample dialog"));
00243   image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO,
00244                                     GTK_ICON_SIZE_DIALOG);
00245   gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
00246   
00247   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
00248   gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00249   
00250   hbox = gtk_hbox_new (FALSE, 6);
00251 
00252   gtk_box_pack_start (GTK_BOX (hbox), image,
00253                       FALSE, FALSE, 0);
00254 
00255   gtk_box_pack_start (GTK_BOX (hbox), label,
00256                       TRUE, TRUE, 0);
00257 
00258   gtk_box_pack_start (GTK_BOX (vbox),
00259                       hbox,
00260                       FALSE, FALSE, 0);
00261 
00262   gtk_widget_show_all (vbox);
00263 
00264   return vbox;
00265 }
00266 
00267 static GtkWidget*
00268 utility_contents (void)
00269 {
00270   GtkWidget *table;
00271   GtkWidget *button;
00272   int i, j;
00273 
00274   table = gtk_table_new (3, 4, FALSE);
00275 
00276   i = 0;
00277   while (i < 3)
00278     {
00279       j = 0;
00280       while (j < 4)
00281         {
00282           char *str;
00283 
00284           str = g_strdup_printf ("_%c", (char) ('A' + 4*i + j));
00285           
00286           button = gtk_button_new_with_mnemonic (str);
00287 
00288           g_free (str);
00289           
00290           gtk_table_attach (GTK_TABLE (table),
00291                             button,
00292                             /* X direction */       /* Y direction */
00293                             i, i+1,                   j, j+1,
00294                             GTK_EXPAND | GTK_FILL,  GTK_EXPAND | GTK_FILL,
00295                             0,                      0);
00296 
00297           ++j;
00298         }
00299 
00300       ++i;
00301     }
00302 
00303   gtk_widget_show_all (table);
00304   
00305   return table;
00306 }
00307 
00308 static GtkWidget*
00309 menu_contents (void)
00310 {
00311   GtkWidget *vbox;
00312   GtkWidget *mi;  
00313   int i;
00314   GtkWidget *frame;
00315 
00316   frame = gtk_frame_new (NULL);
00317   gtk_frame_set_shadow_type (GTK_FRAME (frame),
00318                              GTK_SHADOW_OUT);
00319 
00320   vbox = gtk_vbox_new (FALSE, 0);
00321 
00322   i = 0;
00323   while (i < 10)
00324     {
00325       char *str = g_strdup_printf (_("Fake menu item %d\n"), i + 1);
00326       mi = gtk_label_new (str);
00327       gtk_misc_set_alignment (GTK_MISC (mi), 0.0, 0.5);
00328       g_free (str);
00329       gtk_box_pack_start (GTK_BOX (vbox), mi, FALSE, FALSE, 0);
00330       
00331       ++i;
00332     }
00333 
00334   gtk_container_add (GTK_CONTAINER (frame), vbox);
00335   
00336   gtk_widget_show_all (frame);
00337   
00338   return frame;
00339 }
00340 
00341 static GtkWidget*
00342 border_only_contents (void)
00343 {
00344   GtkWidget *event_box;
00345   GtkWidget *vbox;
00346   GtkWidget *w;
00347   GdkColor color;
00348 
00349   event_box = gtk_event_box_new ();
00350 
00351   color.red = 40000;
00352   color.green = 0;
00353   color.blue = 40000;
00354   gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color);
00355   
00356   vbox = gtk_vbox_new (FALSE, 0);
00357   gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
00358   
00359   w = gtk_label_new (_("Border-only window"));
00360   gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
00361   w = gtk_button_new_with_label (_("Bar"));
00362   gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
00363 
00364   gtk_container_add (GTK_CONTAINER (event_box), vbox);
00365   
00366   gtk_widget_show_all (event_box);
00367   
00368   return event_box;
00369 }
00370 
00371 static GtkWidget*
00372 get_window_contents (MetaFrameType  type,
00373                      const char   **title)
00374 {
00375   switch (type)
00376     {
00377     case META_FRAME_TYPE_NORMAL:
00378       *title = _("Normal Application Window");
00379       return normal_contents ();
00380 
00381     case META_FRAME_TYPE_DIALOG:
00382       *title = _("Dialog Box");
00383       return dialog_contents ();
00384 
00385     case META_FRAME_TYPE_MODAL_DIALOG:
00386       *title = _("Modal Dialog Box");
00387       return dialog_contents ();
00388 
00389     case META_FRAME_TYPE_UTILITY:
00390       *title = _("Utility Palette");
00391       return utility_contents ();
00392 
00393     case META_FRAME_TYPE_MENU:
00394       *title = _("Torn-off Menu");
00395       return menu_contents ();
00396 
00397     case META_FRAME_TYPE_BORDER:
00398       *title = _("Border");
00399       return border_only_contents ();
00400       
00401     case META_FRAME_TYPE_LAST:
00402       g_assert_not_reached ();
00403       break;
00404     }
00405 
00406   return NULL;
00407 }
00408 
00409 static MetaFrameFlags
00410 get_window_flags (MetaFrameType type)
00411 {
00412   MetaFrameFlags flags;
00413 
00414   flags = META_FRAME_ALLOWS_DELETE |
00415     META_FRAME_ALLOWS_MENU |
00416     META_FRAME_ALLOWS_MINIMIZE |
00417     META_FRAME_ALLOWS_MAXIMIZE |
00418     META_FRAME_ALLOWS_VERTICAL_RESIZE |
00419     META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
00420     META_FRAME_HAS_FOCUS |
00421     META_FRAME_ALLOWS_SHADE |
00422     META_FRAME_ALLOWS_MOVE;
00423   
00424   switch (type)
00425     {
00426     case META_FRAME_TYPE_NORMAL:
00427       break;
00428 
00429     case META_FRAME_TYPE_DIALOG:
00430     case META_FRAME_TYPE_MODAL_DIALOG:
00431       flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
00432                  META_FRAME_ALLOWS_MAXIMIZE);
00433       break;
00434 
00435     case META_FRAME_TYPE_UTILITY:
00436       flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
00437                  META_FRAME_ALLOWS_MAXIMIZE);
00438       break;
00439 
00440     case META_FRAME_TYPE_MENU:
00441       flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
00442                  META_FRAME_ALLOWS_MAXIMIZE);
00443       break;
00444 
00445     case META_FRAME_TYPE_BORDER:
00446       break;
00447       
00448     case META_FRAME_TYPE_LAST:
00449       g_assert_not_reached ();
00450       break;
00451     }  
00452   
00453   return flags;
00454 }
00455 
00456 static GtkWidget*
00457 preview_collection (int font_size,
00458                     PangoFontDescription *base_desc)
00459 {
00460   GtkWidget *box;
00461   GtkWidget *sw;
00462   GdkColor desktop_color;
00463   int i;
00464   GtkWidget *eventbox;
00465 
00466   sw = gtk_scrolled_window_new (NULL, NULL);
00467   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
00468                                   GTK_POLICY_AUTOMATIC,
00469                                   GTK_POLICY_AUTOMATIC);
00470 
00471   box = gtk_vbox_new (FALSE, 0);
00472   gtk_box_set_spacing (GTK_BOX (box), 20);
00473   gtk_container_set_border_width (GTK_CONTAINER (box), 20);
00474 
00475   eventbox = gtk_event_box_new ();
00476   gtk_container_add (GTK_CONTAINER (eventbox), box);
00477   
00478   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
00479 
00480   desktop_color.red = 0x5144;
00481   desktop_color.green = 0x75D6;
00482   desktop_color.blue = 0xA699;
00483 
00484   gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
00485 
00486   i = 0;
00487   while (i < META_FRAME_TYPE_LAST)
00488     {
00489       const char *title;
00490       GtkWidget *contents;
00491       GtkWidget *align;
00492       double xalign, yalign;
00493       GtkWidget *eventbox2;
00494       GtkWidget *preview;
00495       PangoFontDescription *font_desc;
00496       double scale;
00497       
00498       eventbox2 = gtk_event_box_new ();
00499       
00500       preview = meta_preview_new ();
00501       
00502       gtk_container_add (GTK_CONTAINER (eventbox2), preview);
00503       
00504       meta_preview_set_frame_type (META_PREVIEW (preview), i);
00505       meta_preview_set_frame_flags (META_PREVIEW (preview),
00506                                     get_window_flags (i));
00507             
00508       meta_preview_set_theme (META_PREVIEW (preview), global_theme);
00509       
00510       contents = get_window_contents (i, &title);
00511       
00512       meta_preview_set_title (META_PREVIEW (preview), title);
00513       
00514       gtk_container_add (GTK_CONTAINER (preview), contents);
00515 
00516       if (i == META_FRAME_TYPE_MENU)
00517         {
00518           xalign = 0.0;
00519           yalign = 0.0;
00520         }
00521       else
00522         {
00523           xalign = 0.5;
00524           yalign = 0.5;
00525         }
00526       
00527       align = gtk_alignment_new (0.0, 0.0, xalign, yalign);
00528       gtk_container_add (GTK_CONTAINER (align), eventbox2);
00529       
00530       gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0);
00531 
00532       switch (font_size)
00533         {
00534         case FONT_SIZE_SMALL:
00535           scale = PANGO_SCALE_XX_SMALL;
00536           break;
00537         case FONT_SIZE_LARGE:
00538           scale = PANGO_SCALE_XX_LARGE;
00539           break;
00540         default:
00541           scale = 1.0;
00542           break;
00543         }
00544 
00545       if (scale != 1.0)
00546         {
00547           font_desc = pango_font_description_new ();
00548           
00549           pango_font_description_set_size (font_desc,
00550                                            MAX (pango_font_description_get_size (base_desc) * scale, 1));
00551           
00552           gtk_widget_modify_font (preview, font_desc);
00553 
00554           pango_font_description_free (font_desc);
00555         }
00556       
00557       previews[font_size*META_FRAME_TYPE_LAST + i] = preview;
00558       
00559       ++i;
00560     }
00561 
00562   return sw;
00563 }
00564 
00565 static MetaButtonLayout different_layouts[BUTTON_LAYOUT_COMBINATIONS];
00566 
00567 static void
00568 init_layouts (void)
00569 {
00570   int i;
00571 
00572   /* Blank out all the layouts */
00573   i = 0;
00574   while (i < (int) G_N_ELEMENTS (different_layouts))
00575     {
00576       int j;
00577 
00578       j = 0;
00579       while (j < MAX_BUTTONS_PER_CORNER)
00580         {
00581           different_layouts[i].left_buttons[j] = META_BUTTON_FUNCTION_LAST;
00582           different_layouts[i].right_buttons[j] = META_BUTTON_FUNCTION_LAST;
00583           ++j;
00584         }
00585       ++i;
00586     }
00587   
00588 #ifndef ALLOW_DUPLICATE_BUTTONS
00589   i = 0;
00590   while (i <= MAX_BUTTONS_PER_CORNER)
00591     {
00592       int j;
00593       
00594       j = 0;
00595       while (j < i)
00596         {
00597           different_layouts[i].right_buttons[j] = (MetaButtonFunction) j;
00598           ++j;
00599         }
00600       while (j < MAX_BUTTONS_PER_CORNER)
00601         {
00602           different_layouts[i].left_buttons[j-i] = (MetaButtonFunction) j;
00603           ++j;
00604         }
00605       
00606       ++i;
00607     }
00608 
00609   /* Special extra case for no buttons on either side */
00610   different_layouts[i].left_buttons[0] = META_BUTTON_FUNCTION_LAST;
00611   different_layouts[i].right_buttons[0] = META_BUTTON_FUNCTION_LAST;
00612   
00613 #else
00614   /* FIXME this code is if we allow duplicate buttons,
00615    * which we currently do not
00616    */
00617   int left;
00618   int i;
00619   
00620   left = 0;
00621   i = 0;
00622 
00623   while (left < MAX_BUTTONS_PER_CORNER)
00624     {
00625       int right;
00626       
00627       right = 0;
00628       
00629       while (right < MAX_BUTTONS_PER_CORNER)
00630         {
00631           int j;
00632           
00633           static MetaButtonFunction left_functions[MAX_BUTTONS_PER_CORNER] = {
00634             META_BUTTON_FUNCTION_MENU,
00635             META_BUTTON_FUNCTION_MINIMIZE,
00636             META_BUTTON_FUNCTION_MAXIMIZE,
00637             META_BUTTON_FUNCTION_CLOSE
00638           };
00639           static MetaButtonFunction right_functions[MAX_BUTTONS_PER_CORNER] = {
00640             META_BUTTON_FUNCTION_MINIMIZE,
00641             META_BUTTON_FUNCTION_MAXIMIZE,
00642             META_BUTTON_FUNCTION_CLOSE,
00643             META_BUTTON_FUNCTION_MENU
00644           };
00645 
00646           g_assert (i < BUTTON_LAYOUT_COMBINATIONS);
00647           
00648           j = 0;
00649           while (j <= left)
00650             {
00651               different_layouts[i].left_buttons[j] = left_functions[j];
00652               ++j;
00653             }
00654 
00655           j = 0;
00656           while (j <= right)
00657             {
00658               different_layouts[i].right_buttons[j] = right_functions[j];
00659               ++j;
00660             }
00661           
00662           ++i;
00663           
00664           ++right;
00665         }
00666       
00667       ++left;
00668     }
00669 #endif
00670 }
00671 
00672 
00673 static GtkWidget*
00674 previews_of_button_layouts (void)
00675 {
00676   static gboolean initted = FALSE;
00677   GtkWidget *box;
00678   GtkWidget *sw;
00679   GdkColor desktop_color;
00680   int i;
00681   GtkWidget *eventbox;
00682   
00683   if (!initted)
00684     {
00685       init_layouts ();
00686       initted = TRUE;
00687     }
00688   
00689   sw = gtk_scrolled_window_new (NULL, NULL);
00690   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
00691                                   GTK_POLICY_AUTOMATIC,
00692                                   GTK_POLICY_AUTOMATIC);
00693 
00694   box = gtk_vbox_new (FALSE, 0);
00695   gtk_box_set_spacing (GTK_BOX (box), 20);
00696   gtk_container_set_border_width (GTK_CONTAINER (box), 20);
00697 
00698   eventbox = gtk_event_box_new ();
00699   gtk_container_add (GTK_CONTAINER (eventbox), box);
00700   
00701   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
00702 
00703   desktop_color.red = 0x5144;
00704   desktop_color.green = 0x75D6;
00705   desktop_color.blue = 0xA699;
00706 
00707   gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
00708 
00709   i = 0;
00710   while (i < BUTTON_LAYOUT_COMBINATIONS)
00711     {
00712       GtkWidget *align;
00713       double xalign, yalign;
00714       GtkWidget *eventbox2;
00715       GtkWidget *preview;
00716       char *title;
00717 
00718       eventbox2 = gtk_event_box_new ();
00719   
00720       preview = meta_preview_new ();
00721   
00722       gtk_container_add (GTK_CONTAINER (eventbox2), preview);  
00723   
00724       meta_preview_set_theme (META_PREVIEW (preview), global_theme);
00725 
00726       title = g_strdup_printf (_("Button layout test %d"), i+1);
00727       meta_preview_set_title (META_PREVIEW (preview), title);
00728       g_free (title);
00729 
00730       meta_preview_set_button_layout (META_PREVIEW (preview),
00731                                       &different_layouts[i]);
00732   
00733       xalign = 0.5;
00734       yalign = 0.5;
00735       
00736       align = gtk_alignment_new (0.0, 0.0, xalign, yalign);
00737       gtk_container_add (GTK_CONTAINER (align), eventbox2);
00738   
00739       gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0);
00740 
00741       previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + i] = preview;
00742       
00743       ++i;
00744     }
00745   
00746   return sw;
00747 }
00748 
00749 static GtkWidget*
00750 benchmark_summary (void)
00751 {
00752   char *msg;
00753   GtkWidget *label;
00754   
00755   msg = g_strdup_printf (_("%g milliseconds to draw one window frame"),
00756                          milliseconds_to_draw_frame);
00757   label = gtk_label_new (msg);
00758   g_free (msg);
00759 
00760   return label;
00761 }
00762 
00763 int
00764 main (int argc, char **argv)
00765 {
00766   GtkWidget *window;
00767   GtkWidget *collection;
00768   GError *err;
00769   clock_t start, end;
00770   GtkWidget *notebook;
00771   int i;
00772   
00773   bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR);
00774   textdomain(GETTEXT_PACKAGE);
00775   bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
00776 
00777   run_position_expression_tests ();
00778 #if 0
00779   run_position_expression_timings ();
00780 #endif
00781 
00782   gtk_init (&argc, &argv);
00783 
00784   if (g_getenv ("METACITY_DEBUG") != NULL)
00785     {
00786       meta_set_debugging (TRUE);
00787       meta_set_verbose (TRUE);
00788     }
00789   
00790   start = clock ();
00791   err = NULL;
00792   if (argc == 1)
00793     global_theme = meta_theme_load ("Atlanta", &err);
00794   else if (argc == 2)
00795     global_theme = meta_theme_load (argv[1], &err);
00796   else
00797     {
00798       g_printerr (_("Usage: metacity-theme-viewer [THEMENAME]\n"));
00799       exit (1);
00800     }
00801   end = clock ();
00802 
00803   if (global_theme == NULL)
00804     {
00805       g_printerr (_("Error loading theme: %s\n"),
00806                   err->message);
00807       g_error_free (err);
00808       exit (1);
00809     }
00810 
00811   g_print (_("Loaded theme \"%s\" in %g seconds\n"),
00812            global_theme->name,
00813            (end - start) / (double) CLOCKS_PER_SEC);
00814 
00815   run_theme_benchmark ();
00816   
00817   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
00818   gtk_window_set_default_size (GTK_WINDOW (window), 350, 350);
00819 
00820   if (strcmp (global_theme->name, global_theme->readable_name)==0)
00821     gtk_window_set_title (GTK_WINDOW (window),
00822                           global_theme->readable_name);
00823   else
00824     {
00825       /* The theme directory name is different from the name the theme
00826        * gives itself within its file.  Display both, directory name first.
00827        */
00828       gchar *title =  g_strconcat (global_theme->name, " - ",
00829                                    global_theme->readable_name,
00830                                    NULL);
00831 
00832       gtk_window_set_title (GTK_WINDOW (window),
00833                             title);
00834 
00835       g_free (title);
00836     }       
00837 
00838   g_signal_connect (G_OBJECT (window), "destroy",
00839                     G_CALLBACK (gtk_main_quit), NULL);
00840 
00841   gtk_widget_realize (window);
00842   g_assert (window->style);
00843   g_assert (window->style->font_desc);
00844   
00845   notebook = gtk_notebook_new ();
00846   gtk_container_add (GTK_CONTAINER (window), notebook);
00847 
00848   collection = preview_collection (FONT_SIZE_NORMAL,
00849                                    window->style->font_desc);
00850   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
00851                             collection,
00852                             gtk_label_new (_("Normal Title Font")));
00853   
00854   collection = preview_collection (FONT_SIZE_SMALL,
00855                                    window->style->font_desc);
00856   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
00857                             collection,
00858                             gtk_label_new (_("Small Title Font")));
00859   
00860   collection = preview_collection (FONT_SIZE_LARGE,
00861                                    window->style->font_desc);
00862   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
00863                             collection,
00864                             gtk_label_new (_("Large Title Font")));
00865 
00866   collection = previews_of_button_layouts ();
00867   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
00868                             collection,
00869                             gtk_label_new (_("Button Layouts")));
00870 
00871   collection = benchmark_summary ();
00872   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
00873                             collection,
00874                             gtk_label_new (_("Benchmark")));
00875   
00876   i = 0;
00877   while (i < (int) G_N_ELEMENTS (previews))
00878     {
00879       /* preview widget likes to be realized before its size request.
00880        * it's lame that way.
00881        */
00882       gtk_widget_realize (previews[i]);
00883 
00884       ++i;
00885     }
00886   
00887   gtk_widget_show_all (window);
00888 
00889   gtk_main ();
00890 
00891   return 0;
00892 }
00893 
00894 
00895 static MetaFrameFlags
00896 get_flags (GtkWidget *widget)
00897 {
00898   return META_FRAME_ALLOWS_DELETE |
00899     META_FRAME_ALLOWS_MENU |
00900     META_FRAME_ALLOWS_MINIMIZE |
00901     META_FRAME_ALLOWS_MAXIMIZE |
00902     META_FRAME_ALLOWS_VERTICAL_RESIZE |
00903     META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
00904     META_FRAME_HAS_FOCUS |
00905     META_FRAME_ALLOWS_SHADE |
00906     META_FRAME_ALLOWS_MOVE;
00907 }
00908 
00909 static int
00910 get_text_height (GtkWidget *widget)
00911 {
00912   return meta_pango_font_desc_get_text_height (widget->style->font_desc,
00913                                                gtk_widget_get_pango_context (widget));
00914 }
00915 
00916 static PangoLayout*
00917 create_title_layout (GtkWidget *widget)
00918 {
00919   PangoLayout *layout;
00920 
00921   layout = gtk_widget_create_pango_layout (widget, _("Window Title Goes Here"));
00922 
00923   return layout;
00924 }
00925 
00926 static void
00927 run_theme_benchmark (void)
00928 {
00929   GtkWidget* widget;
00930   GdkPixmap *pixmap;
00931   int top_height, bottom_height, left_width, right_width;
00932   MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
00933   {
00934     META_BUTTON_STATE_NORMAL,
00935     META_BUTTON_STATE_NORMAL,
00936     META_BUTTON_STATE_NORMAL,
00937     META_BUTTON_STATE_NORMAL
00938   };
00939   PangoLayout *layout;
00940   clock_t start;
00941   clock_t end;
00942   GTimer *timer;
00943   int i;
00944   MetaButtonLayout button_layout;
00945 #define ITERATIONS 100
00946   int client_width;
00947   int client_height;
00948   int inc;
00949   
00950   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
00951   gtk_widget_realize (widget);
00952   
00953   meta_theme_get_frame_borders (global_theme,
00954                                 META_FRAME_TYPE_NORMAL,
00955                                 get_text_height (widget),
00956                                 get_flags (widget),
00957                                 &top_height,
00958                                 &bottom_height,
00959                                 &left_width,
00960                                 &right_width);
00961   
00962   layout = create_title_layout (widget);
00963   
00964   i = 0;
00965   while (i < MAX_BUTTONS_PER_CORNER)
00966     {
00967       button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
00968       button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
00969       ++i;
00970     }
00971   
00972   button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
00973 
00974   button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
00975   button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
00976   button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
00977 
00978   timer = g_timer_new ();
00979   start = clock ();
00980 
00981   client_width = 50;
00982   client_height = 50;
00983   inc = 1000 / ITERATIONS; /* Increment to grow width/height,
00984                             * eliminates caching effects.
00985                             */
00986   
00987   i = 0;
00988   while (i < ITERATIONS)
00989     {
00990       /* Creating the pixmap in the loop is right, since
00991        * GDK does the same with its double buffering.
00992        */
00993       pixmap = gdk_pixmap_new (widget->window,
00994                                client_width + left_width + right_width,
00995                                client_height + top_height + bottom_height,
00996                                -1);
00997 
00998       meta_theme_draw_frame (global_theme,
00999                              widget,
01000                              pixmap,
01001                              NULL,
01002                              0, 0,
01003                              META_FRAME_TYPE_NORMAL,
01004                              get_flags (widget),
01005                              client_width, client_height,
01006                              layout,
01007                              get_text_height (widget),
01008                              &button_layout,
01009                              button_states,
01010                              meta_preview_get_mini_icon (),
01011                              meta_preview_get_icon ());
01012 
01013       g_object_unref (G_OBJECT (pixmap));
01014       
01015       ++i;
01016       client_width += inc;
01017       client_height += inc;
01018     }
01019 
01020   end = clock ();
01021   g_timer_stop (timer);
01022 
01023   milliseconds_to_draw_frame = (g_timer_elapsed (timer, NULL) / (double) ITERATIONS) * 1000;
01024   
01025   g_print (_("Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g seconds wall clock time including X server resources (%g milliseconds per frame)\n"),
01026            ITERATIONS,
01027            ((double)end - (double)start) / CLOCKS_PER_SEC,
01028            (((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS) * 1000,
01029            g_timer_elapsed (timer, NULL),
01030            milliseconds_to_draw_frame);
01031 
01032   g_timer_destroy (timer);
01033   g_object_unref (G_OBJECT (layout));
01034   gtk_widget_destroy (widget);
01035 
01036 #undef ITERATIONS
01037 }
01038 
01039 typedef struct
01040 {
01041   GdkRectangle rect;
01042   const char *expr;
01043   int expected_x;
01044   int expected_y;
01045   MetaThemeError expected_error;
01046 } PositionExpressionTest;
01047 
01048 #define NO_ERROR -1
01049 
01050 static const PositionExpressionTest position_expression_tests[] = {
01051   /* Just numbers */
01052   { { 10, 20, 40, 50 },
01053     "10", 20, 30, NO_ERROR },
01054   { { 10, 20, 40, 50 },
01055     "14.37", 24, 34, NO_ERROR },
01056   /* Binary expressions with 2 ints */
01057   { { 10, 20, 40, 50 },
01058     "14 * 10", 150, 160, NO_ERROR },
01059   { { 10, 20, 40, 50 },
01060     "14 + 10", 34, 44, NO_ERROR },
01061   { { 10, 20, 40, 50 },
01062     "14 - 10", 14, 24, NO_ERROR },
01063   { { 10, 20, 40, 50 },
01064     "8 / 2", 14, 24, NO_ERROR },
01065   { { 10, 20, 40, 50 },
01066     "8 % 3", 12, 22, NO_ERROR },
01067   /* Binary expressions with floats and mixed float/ints */
01068   { { 10, 20, 40, 50 },
01069     "7.0 / 3.5", 12, 22, NO_ERROR },
01070   { { 10, 20, 40, 50 },
01071     "12.1 / 3", 14, 24, NO_ERROR },
01072   { { 10, 20, 40, 50 },
01073     "12 / 2.95", 14, 24, NO_ERROR },
01074   /* Binary expressions without whitespace after first number */
01075   { { 10, 20, 40, 50 },
01076     "14* 10", 150, 160, NO_ERROR },
01077   { { 10, 20, 40, 50 },
01078     "14+ 10", 34, 44, NO_ERROR },
01079   { { 10, 20, 40, 50 },
01080     "14- 10", 14, 24, NO_ERROR },
01081   { { 10, 20, 40, 50 },
01082     "8/ 2", 14, 24, NO_ERROR },
01083   { { 10, 20, 40, 50 },
01084     "7.0/ 3.5", 12, 22, NO_ERROR },
01085   { { 10, 20, 40, 50 },
01086     "12.1/ 3", 14, 24, NO_ERROR },
01087   { { 10, 20, 40, 50 },
01088     "12/ 2.95", 14, 24, NO_ERROR },
01089   /* Binary expressions without whitespace before second number */
01090   { { 10, 20, 40, 50 },
01091     "14 *10", 150, 160, NO_ERROR },
01092   { { 10, 20, 40, 50 },
01093     "14 +10", 34, 44, NO_ERROR },
01094   { { 10, 20, 40, 50 },
01095     "14 -10", 14, 24, NO_ERROR },
01096   { { 10, 20, 40, 50 },
01097     "8 /2", 14, 24, NO_ERROR },
01098   { { 10, 20, 40, 50 },
01099     "7.0 /3.5", 12, 22, NO_ERROR },
01100   { { 10, 20, 40, 50 },
01101     "12.1 /3", 14, 24, NO_ERROR },
01102   { { 10, 20, 40, 50 },
01103     "12 /2.95", 14, 24, NO_ERROR },
01104   /* Binary expressions without any whitespace */
01105   { { 10, 20, 40, 50 },
01106     "14*10", 150, 160, NO_ERROR },
01107   { { 10, 20, 40, 50 },
01108     "14+10", 34, 44, NO_ERROR },
01109   { { 10, 20, 40, 50 },
01110     "14-10", 14, 24, NO_ERROR },
01111   { { 10, 20, 40, 50 },
01112     "8/2", 14, 24, NO_ERROR },
01113   { { 10, 20, 40, 50 },
01114     "7.0/3.5", 12, 22, NO_ERROR },
01115   { { 10, 20, 40, 50 },
01116     "12.1/3", 14, 24, NO_ERROR },
01117   { { 10, 20, 40, 50 },
01118     "12/2.95", 14, 24, NO_ERROR },
01119   /* Binary expressions with parentheses */
01120   { { 10, 20, 40, 50 },
01121     "(14) * (10)", 150, 160, NO_ERROR },
01122   { { 10, 20, 40, 50 },
01123     "(14) + (10)", 34, 44, NO_ERROR },
01124   { { 10, 20, 40, 50 },
01125     "(14) - (10)", 14, 24, NO_ERROR },
01126   { { 10, 20, 40, 50 },
01127     "(8) / (2)", 14, 24, NO_ERROR },
01128   { { 10, 20, 40, 50 },
01129     "(7.0) / (3.5)", 12, 22, NO_ERROR },
01130   { { 10, 20, 40, 50 },
01131     "(12.1) / (3)", 14, 24, NO_ERROR },
01132   { { 10, 20, 40, 50 },
01133     "(12) / (2.95)", 14, 24, NO_ERROR },
01134   /* Lots of extra parentheses */
01135   { { 10, 20, 40, 50 },
01136     "(((14)) * ((10)))", 150, 160, NO_ERROR },
01137   { { 10, 20, 40, 50 },
01138     "((((14)))) + ((((((((10))))))))", 34, 44, NO_ERROR },
01139   { { 10, 20, 40, 50 },
01140     "((((((((((14 - 10))))))))))", 14, 24, NO_ERROR },
01141   /* Binary expressions with variables */
01142   { { 10, 20, 40, 50 },
01143     "2 * width", 90, 100, NO_ERROR },
01144   { { 10, 20, 40, 50 },
01145     "2 * height", 110, 120, NO_ERROR },
01146   { { 10, 20, 40, 50 },
01147     "width - 10", 40, 50, NO_ERROR },
01148   { { 10, 20, 40, 50 },
01149     "height / 2", 35, 45, NO_ERROR },
01150   /* More than two operands */
01151   { { 10, 20, 40, 50 },
01152     "8 / 2 + 5", 19, 29, NO_ERROR },
01153   { { 10, 20, 40, 50 },
01154     "8 * 2 + 5", 31, 41, NO_ERROR },
01155   { { 10, 20, 40, 50 },
01156     "8 + 2 * 5", 28, 38, NO_ERROR },
01157   { { 10, 20, 40, 50 },
01158     "8 + 8 / 2", 22, 32, NO_ERROR },
01159   { { 10, 20, 40, 50 },
01160     "14 / (2 + 5)", 12, 22, NO_ERROR },
01161   { { 10, 20, 40, 50 },
01162     "8 * (2 + 5)", 66, 76, NO_ERROR },
01163   { { 10, 20, 40, 50 },
01164     "(8 + 2) * 5", 60, 70, NO_ERROR },
01165   { { 10, 20, 40, 50 },
01166     "(8 + 8) / 2", 18, 28, NO_ERROR },
01167   /* Errors */
01168   { { 10, 20, 40, 50 },
01169     "2 * foo", 0, 0, META_THEME_ERROR_UNKNOWN_VARIABLE },
01170   { { 10, 20, 40, 50 },
01171     "2 *", 0, 0, META_THEME_ERROR_FAILED },
01172   { { 10, 20, 40, 50 },
01173     "- width", 0, 0, META_THEME_ERROR_FAILED },
01174   { { 10, 20, 40, 50 },
01175     "5 % 1.0", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
01176   { { 10, 20, 40, 50 },
01177     "1.0 % 5", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
01178   { { 10, 20, 40, 50 },
01179     "! * 2", 0, 0, META_THEME_ERROR_BAD_CHARACTER },
01180   { { 10, 20, 40, 50 },
01181     "   ", 0, 0, META_THEME_ERROR_FAILED },
01182   { { 10, 20, 40, 50 },
01183     "() () (( ) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
01184   { { 10, 20, 40, 50 },
01185     "(*) () ((/) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
01186   { { 10, 20, 40, 50 },
01187     "2 * 5 /", 0, 0, META_THEME_ERROR_FAILED },
01188   { { 10, 20, 40, 50 },
01189     "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED },
01190   { { 10, 20, 40, 50 },
01191     "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED }
01192 };
01193 
01194 static void
01195 run_position_expression_tests (void)
01196 {
01197 #if 0
01198   int i;
01199   MetaPositionExprEnv env;
01200 
01201   i = 0;
01202   while (i < (int) G_N_ELEMENTS (position_expression_tests))
01203     {
01204       GError *err;
01205       gboolean retval;
01206       const PositionExpressionTest *test;
01207       PosToken *tokens;
01208       int n_tokens;
01209       int x, y;
01210 
01211       test = &position_expression_tests[i];
01212 
01213       if (g_getenv ("META_PRINT_TESTS") != NULL)
01214         g_print ("Test expression: \"%s\" expecting x = %d y = %d",
01215                  test->expr, test->expected_x, test->expected_y);
01216 
01217       err = NULL;
01218       
01219       env.rect = meta_rect (test->rect.x, test->rect.y,
01220                             test->rect.width, test->rect.height);
01221       env.object_width = -1;
01222       env.object_height = -1;
01223       env.left_width = 0;
01224       env.right_width = 0;
01225       env.top_height = 0;
01226       env.bottom_height = 0;
01227       env.title_width = 5;
01228       env.title_height = 5;
01229       env.icon_width = 32;
01230       env.icon_height = 32;
01231       env.mini_icon_width = 16;
01232       env.mini_icon_height = 16;
01233       env.theme = NULL;
01234 
01235       if (err == NULL)
01236         {
01237           retval = meta_parse_position_expression (tokens, n_tokens,
01238                                                    &env,
01239                                                    &x, &y,
01240                                                    &err);
01241         }
01242 
01243       if (retval && err)
01244         g_error (_("position expression test returned TRUE but set error"));
01245       if (!retval && err == NULL)
01246         g_error (_("position expression test returned FALSE but didn't set error"));
01247       if (((int) test->expected_error) != NO_ERROR)
01248         {
01249           if (err == NULL)
01250             g_error (_("Error was expected but none given"));
01251           if (err->code != (int) test->expected_error)
01252             g_error (_("Error %d was expected but %d given"),
01253                      test->expected_error, err->code);
01254         }
01255       else
01256         {
01257           if (err)
01258             g_error (_("Error not expected but one was returned: %s"),
01259                      err->message);
01260 
01261           if (x != test->expected_x)
01262             g_error (_("x value was %d, %d was expected"), x, test->expected_x);
01263 
01264           if (y != test->expected_y)
01265             g_error (_("y value was %d, %d was expected"), y, test->expected_y);
01266         }
01267 
01268       if (err)
01269         g_error_free (err);
01270 
01271       meta_pos_tokens_free (tokens, n_tokens);
01272       ++i;
01273     }
01274 #endif
01275 }
01276 
01277 #if 0
01278 static void
01279 run_position_expression_timings (void)
01280 {
01281   int i;
01282   int iters;
01283   clock_t start;
01284   clock_t end;
01285   MetaPositionExprEnv env;
01286 
01287 #define ITERATIONS 100000
01288 
01289   start = clock ();
01290 
01291   iters = 0;
01292   i = 0;
01293   while (iters < ITERATIONS)
01294     {
01295       const PositionExpressionTest *test;
01296       int x, y;
01297 
01298       test = &position_expression_tests[i];
01299 
01300       env.x = test->rect.x;
01301       env.y = test->rect.y;
01302       env.width = test->rect.width;
01303       env.height = test->rect.height;
01304       env.object_width = -1;
01305       env.object_height = -1;
01306       env.left_width = 0;
01307       env.right_width = 0;
01308       env.top_height = 0;
01309       env.bottom_height = 0;
01310       env.title_width = 5;
01311       env.title_height = 5;
01312       env.icon_width = 32;
01313       env.icon_height = 32;
01314       env.mini_icon_width = 16;
01315       env.mini_icon_height = 16;
01316       env.theme = NULL;
01317 
01318       meta_parse_position_expression (test->expr,
01319                                       &env,
01320                                       &x, &y, NULL);
01321 
01322       ++iters;
01323       ++i;
01324       if (i == G_N_ELEMENTS (position_expression_tests))
01325         i = 0;
01326     }
01327 
01328   end = clock ();
01329 
01330   g_print (_("%d coordinate expressions parsed in %g seconds (%g seconds average)\n"),
01331            ITERATIONS,
01332            ((double)end - (double)start) / CLOCKS_PER_SEC,
01333            ((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS);
01334 
01335 }
01336 #endif

Generated on Sat Aug 23 22:04:18 2008 for metacity by  doxygen 1.5.5