00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00039
00040
00041
00042
00043
00044
00045
00046
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
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
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
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
00125 0, 1, 0, 1,
00126 GTK_EXPAND | GTK_FILL, 0,
00127 0, 0);
00128
00129
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);
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);
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);
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
00161 0, 1, 1, 2,
00162 GTK_EXPAND | GTK_FILL, 0,
00163 0, 0);
00164
00165
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
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
00192
00193 statusbar = gtk_statusbar_new ();
00194 gtk_table_attach (GTK_TABLE (table),
00195 statusbar,
00196
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
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
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
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
00615
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
00826
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
00880
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;
00984
00985
00986
00987 i = 0;
00988 while (i < ITERATIONS)
00989 {
00990
00991
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
01052 { { 10, 20, 40, 50 },
01053 "10", 20, 30, NO_ERROR },
01054 { { 10, 20, 40, 50 },
01055 "14.37", 24, 34, NO_ERROR },
01056
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
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
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
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
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
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
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
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
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
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