root/trunk/WebCore/platform/gtk/gtk2drawing.c

Revision 29824, 96.1 kB (checked in by alp@webkit.org, 6 months ago)

2008-01-27 Alp Toker <alp@atoker.com>

Reviewed by Mark Rowe.

http://bugs.webkit.org/show_bug.cgi?id=17029
Use of deprecated class function but declares GTK_DISABLE_DEPRECATED

Sync gtkdrawing.h (1.51) and gtk2drawing.c (1.71) from Mozilla
upstream.

Adapt RenderThemeGtk.cpp to track minor changes.

  • Property svn:eol-style set to native
Line 
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is mozilla.org code.
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 2002
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *  Brian Ryner <bryner@brianryner.com>  (Original Author)
24  *  Pierre Chanial <p_ch@verizon.net>
25  *  Michael Ventnor <m.ventnor@gmail.com>
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40
41 /*
42  * This file contains painting functions for each of the gtk2 widgets.
43  * Adapted from the gtkdrawing.c, and gtk+2.0 source.
44  */
45
46 #include <gtk/gtk.h>
47 #include <gdk/gdkprivate.h>
48 #include <string.h>
49 #include "gtkdrawing.h"
50
51 #include <math.h>
52
53 #define XTHICKNESS(style) (style->xthickness)
54 #define YTHICKNESS(style) (style->ythickness)
55 #define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
56
57 static GtkWidget* gProtoWindow;
58 static GtkWidget* gButtonWidget;
59 static GtkWidget* gToggleButtonWidget;
60 static GtkWidget* gCheckboxWidget;
61 static GtkWidget* gRadiobuttonWidget;
62 static GtkWidget* gHorizScrollbarWidget;
63 static GtkWidget* gVertScrollbarWidget;
64 static GtkWidget* gSpinWidget;
65 static GtkWidget* gHScaleWidget;
66 static GtkWidget* gVScaleWidget;
67 static GtkWidget* gEntryWidget;
68 static GtkWidget* gArrowWidget;
69 static GtkWidget* gOptionMenuWidget;
70 static GtkWidget* gComboBoxEntryWidget;
71 static GtkWidget* gDropdownEntryWidget;
72 static GtkWidget* gDropdownButtonWidget;
73 static GtkWidget* gHandleBoxWidget;
74 static GtkWidget* gToolbarWidget;
75 static GtkWidget* gFrameWidget;
76 static GtkWidget* gStatusbarWidget;
77 static GtkWidget* gProgressWidget;
78 static GtkWidget* gTabWidget;
79 static GtkWidget* gTooltipWidget;
80 static GtkWidget* gMenuBarWidget;
81 static GtkWidget* gMenuBarItemWidget;
82 static GtkWidget* gMenuPopupWidget;
83 static GtkWidget* gMenuItemWidget;
84 static GtkWidget* gCheckMenuItemWidget;
85 static GtkWidget* gTreeViewWidget;
86 static GtkWidget* gTreeHeaderCellWidget;
87 static GtkWidget* gTreeHeaderSortArrowWidget;
88 static GtkWidget* gExpanderWidget;
89 static GtkWidget* gToolbarSeparatorWidget;
90 static GtkWidget* gMenuSeparatorWidget;
91 static GtkWidget* gHPanedWidget;
92 static GtkWidget* gVPanedWidget;
93
94 static GtkShadowType gMenuBarShadowType;
95 static GtkShadowType gToolbarShadowType;
96
97 static style_prop_t style_prop_func;
98 static gboolean have_menu_shadow_type;
99 static gboolean is_initialized;
100
101 gint
102 moz_gtk_enable_style_props(style_prop_t styleGetProp)
103 {
104     style_prop_func = styleGetProp;
105     return MOZ_GTK_SUCCESS;
106 }
107
108 static gint
109 ensure_window_widget()
110 {
111     if (!gProtoWindow) {
112         gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
113         gtk_widget_realize(gProtoWindow);
114     }
115     return MOZ_GTK_SUCCESS;
116 }
117
118 static gint
119 setup_widget_prototype(GtkWidget* widget)
120 {
121     static GtkWidget* protoLayout;
122     ensure_window_widget();
123     if (!protoLayout) {
124         protoLayout = gtk_fixed_new();
125         gtk_container_add(GTK_CONTAINER(gProtoWindow), protoLayout);
126     }
127
128     gtk_container_add(GTK_CONTAINER(protoLayout), widget);
129     gtk_widget_realize(widget);
130     return MOZ_GTK_SUCCESS;
131 }
132
133 static gint
134 ensure_button_widget()
135 {
136     if (!gButtonWidget) {
137         gButtonWidget = gtk_button_new_with_label("M");
138         setup_widget_prototype(gButtonWidget);
139     }
140     return MOZ_GTK_SUCCESS;
141 }
142
143 static gint
144 ensure_hpaned_widget()
145 {
146     if (!gHPanedWidget) {
147         gHPanedWidget = gtk_hpaned_new();
148         setup_widget_prototype(gHPanedWidget);
149     }
150     return MOZ_GTK_SUCCESS;
151 }
152
153 static gint
154 ensure_vpaned_widget()
155 {
156     if (!gVPanedWidget) {
157         gVPanedWidget = gtk_vpaned_new();
158         setup_widget_prototype(gVPanedWidget);
159     }
160     return MOZ_GTK_SUCCESS;
161 }
162
163 static gint
164 ensure_toggle_button_widget()
165 {
166     if (!gToggleButtonWidget) {
167         gToggleButtonWidget = gtk_toggle_button_new();
168         setup_widget_prototype(gToggleButtonWidget);
169         /* toggle button must be set active to get the right style on hover. */
170         GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE;
171   }
172   return MOZ_GTK_SUCCESS;
173 }
174
175 static gint
176 ensure_checkbox_widget()
177 {
178     if (!gCheckboxWidget) {
179         gCheckboxWidget = gtk_check_button_new_with_label("M");
180         setup_widget_prototype(gCheckboxWidget);
181     }
182     return MOZ_GTK_SUCCESS;
183 }
184
185 static gint
186 ensure_radiobutton_widget()
187 {
188     if (!gRadiobuttonWidget) {
189         gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M");
190         setup_widget_prototype(gRadiobuttonWidget);
191     }
192     return MOZ_GTK_SUCCESS;
193 }
194
195 static gint
196 ensure_scrollbar_widget()
197 {
198     if (!gVertScrollbarWidget) {
199         gVertScrollbarWidget = gtk_vscrollbar_new(NULL);
200         setup_widget_prototype(gVertScrollbarWidget);
201     }
202     if (!gHorizScrollbarWidget) {
203         gHorizScrollbarWidget = gtk_hscrollbar_new(NULL);
204         setup_widget_prototype(gHorizScrollbarWidget);
205     }
206     return MOZ_GTK_SUCCESS;
207 }
208
209 static gint
210 ensure_spin_widget()
211 {
212   if (!gSpinWidget) {
213     gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
214     setup_widget_prototype(gSpinWidget);
215   }
216   return MOZ_GTK_SUCCESS;
217 }
218
219 static gint
220 ensure_scale_widget()
221 {
222   if (!gHScaleWidget) {
223     gHScaleWidget = gtk_hscale_new(NULL);
224     setup_widget_prototype(gHScaleWidget);
225   }
226   if (!gVScaleWidget) {
227     gVScaleWidget = gtk_vscale_new(NULL);
228     setup_widget_prototype(gVScaleWidget);
229   }
230   return MOZ_GTK_SUCCESS;
231 }
232
233 static gint
234 ensure_entry_widget()
235 {
236     if (!gEntryWidget) {
237         gEntryWidget = gtk_entry_new();
238         setup_widget_prototype(gEntryWidget);
239     }
240     return MOZ_GTK_SUCCESS;
241 }
242
243 static gint
244 ensure_option_menu_widget()
245 {
246     if (!gOptionMenuWidget) {
247         gOptionMenuWidget = gtk_option_menu_new();
248         setup_widget_prototype(gOptionMenuWidget);       
249     }
250     return MOZ_GTK_SUCCESS;
251 }
252
253 static gint
254 ensure_combo_box_entry_widget()
255 {
256     if (!gComboBoxEntryWidget) {
257         gComboBoxEntryWidget = gtk_combo_box_entry_new();
258         setup_widget_prototype(gComboBoxEntryWidget);
259     }
260     return MOZ_GTK_SUCCESS;
261 }
262
263 static gint
264 ensure_dropdown_entry_widget()
265 {
266     if (!gDropdownEntryWidget) {
267         ensure_combo_box_entry_widget();
268
269         gDropdownEntryWidget = GTK_BIN(gComboBoxEntryWidget)->child;
270         gtk_widget_realize(gDropdownEntryWidget);
271     }
272     return MOZ_GTK_SUCCESS;
273 }
274
275 static void
276 moz_gtk_get_dropdown_button(GtkWidget *widget,
277                             gpointer client_data)
278 {
279     if (GTK_IS_TOGGLE_BUTTON(widget))
280         gDropdownButtonWidget = widget;
281 }
282
283 static gint
284 ensure_arrow_widget()
285 {
286     if (!gArrowWidget) {
287         ensure_combo_box_entry_widget();
288
289         gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
290                              moz_gtk_get_dropdown_button,
291                              NULL);
292
293         gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
294         gtk_container_add(GTK_CONTAINER(GTK_BIN(gDropdownButtonWidget)->child),
295                           gArrowWidget);
296         gtk_widget_realize(gArrowWidget);
297     }
298     return MOZ_GTK_SUCCESS;
299 }
300
301 static gint
302 ensure_handlebox_widget()
303 {
304     if (!gHandleBoxWidget) {
305         gHandleBoxWidget = gtk_handle_box_new();
306         setup_widget_prototype(gHandleBoxWidget);
307     }
308     return MOZ_GTK_SUCCESS;
309 }
310
311 static gint
312 ensure_toolbar_widget()
313 {
314     if (!gToolbarWidget) {
315         ensure_handlebox_widget();
316         gToolbarWidget = gtk_toolbar_new();
317         gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
318         gtk_widget_realize(gToolbarWidget);
319         gtk_widget_style_get(gToolbarWidget, "shadow_type", &gToolbarShadowType,
320                              NULL);
321     }
322     return MOZ_GTK_SUCCESS;
323 }
324
325 static gint
326 ensure_toolbar_separator_widget()
327 {
328     if (!gToolbarSeparatorWidget) {
329         ensure_toolbar_widget();
330         gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
331         setup_widget_prototype(gToolbarSeparatorWidget);
332     }
333     return MOZ_GTK_SUCCESS;
334 }
335
336 static gint
337 ensure_tooltip_widget()
338 {
339     if (!gTooltipWidget) {
340         gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
341         gtk_widget_realize(gTooltipWidget);
342     }
343     return MOZ_GTK_SUCCESS;
344 }
345
346 static gint
347 ensure_tab_widget()
348 {
349     if (!gTabWidget) {
350         gTabWidget = gtk_notebook_new();
351         setup_widget_prototype(gTabWidget);
352     }
353     return MOZ_GTK_SUCCESS;
354 }
355
356 static gint
357 ensure_progress_widget()
358 {
359     if (!gProgressWidget) {
360         gProgressWidget = gtk_progress_bar_new();
361         setup_widget_prototype(gProgressWidget);
362     }
363     return MOZ_GTK_SUCCESS;
364 }
365
366 static gint
367 ensure_statusbar_widget()
368 {
369     if (!gStatusbarWidget) {
370       gStatusbarWidget = gtk_statusbar_new();
371       setup_widget_prototype(gStatusbarWidget);
372     }
373     return MOZ_GTK_SUCCESS;
374 }
375
376 static gint
377 ensure_frame_widget()
378 {
379     if (!gFrameWidget) {
380         ensure_statusbar_widget();
381         gFrameWidget = gtk_frame_new(NULL);
382         gtk_container_add(GTK_CONTAINER(gStatusbarWidget), gFrameWidget);
383         gtk_widget_realize(gFrameWidget);
384     }
385     return MOZ_GTK_SUCCESS;
386 }
387
388 static gint
389 ensure_menu_bar_widget()
390 {
391     if (!gMenuBarWidget) {
392         gMenuBarWidget = gtk_menu_bar_new();
393         setup_widget_prototype(gMenuBarWidget);
394        gtk_widget_style_get(gMenuBarWidget, "shadow_type", &gMenuBarShadowType,
395                             NULL);
396     }
397     return MOZ_GTK_SUCCESS;
398 }
399
400 static gint
401 ensure_menu_bar_item_widget()
402 {
403     if (!gMenuBarItemWidget) {
404         ensure_menu_bar_widget();
405         gMenuBarItemWidget = gtk_menu_item_new();
406         gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
407                               gMenuBarItemWidget);
408         gtk_widget_realize(gMenuBarItemWidget);
409     }
410     return MOZ_GTK_SUCCESS;
411 }
412
413 static gint
414 ensure_menu_popup_widget()
415 {
416     if (!gMenuPopupWidget) {
417         ensure_menu_bar_item_widget();
418         gMenuPopupWidget = gtk_menu_new();
419         gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget),
420                                   gMenuPopupWidget);
421         gtk_widget_realize(gMenuPopupWidget);
422     }
423     return MOZ_GTK_SUCCESS;
424 }
425
426 static gint
427 ensure_menu_item_widget()
428 {
429     if (!gMenuItemWidget) {
430         ensure_menu_popup_widget();
431         gMenuItemWidget = gtk_menu_item_new_with_label("M");
432         gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
433                               gMenuItemWidget);
434         gtk_widget_realize(gMenuItemWidget);
435     }
436     return MOZ_GTK_SUCCESS;
437 }
438
439 static gint
440 ensure_menu_separator_widget()
441 {
442     if (!gMenuSeparatorWidget) {
443         ensure_menu_popup_widget();
444         gMenuSeparatorWidget = gtk_separator_menu_item_new();
445         gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
446                               gMenuSeparatorWidget);
447         gtk_widget_realize(gMenuSeparatorWidget);
448     }
449     return MOZ_GTK_SUCCESS;
450 }
451
452 static gint
453 ensure_check_menu_item_widget()
454 {
455     if (!gCheckMenuItemWidget) {
456         ensure_menu_popup_widget();
457         gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
458         gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
459                               gCheckMenuItemWidget);
460         gtk_widget_realize(gCheckMenuItemWidget);
461     }
462     return MOZ_GTK_SUCCESS;
463 }
464
465 static gint
466 ensure_tree_view_widget()
467 {
468     if (!gTreeViewWidget) {
469         gTreeViewWidget = gtk_tree_view_new();
470         setup_widget_prototype(gTreeViewWidget);
471     }
472     return MOZ_GTK_SUCCESS;
473 }
474
475 static gint
476 ensure_tree_header_cell_widget()
477 {
478     if(!gTreeHeaderCellWidget) {
479         GtkTreeViewColumn* treeViewColumn;
480         ensure_tree_view_widget();
481
482         treeViewColumn = gtk_tree_view_column_new();
483         gtk_tree_view_column_set_title(treeViewColumn, "M");
484
485         gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), treeViewColumn);
486         gTreeHeaderCellWidget = treeViewColumn->button;
487         gtk_tree_view_column_set_sort_indicator(treeViewColumn, TRUE);
488         gTreeHeaderSortArrowWidget = treeViewColumn->arrow;
489     }
490     return MOZ_GTK_SUCCESS;
491 }
492
493 static gint
494 ensure_expander_widget()
495 {
496     if (!gExpanderWidget) {
497         gExpanderWidget = gtk_expander_new("M");
498         setup_widget_prototype(gExpanderWidget);
499     }
500     return MOZ_GTK_SUCCESS;
501 }
502
503 static GtkStateType
504 ConvertGtkState(GtkWidgetState* state)
505 {
506     if (state->disabled)
507         return GTK_STATE_INSENSITIVE;
508     else if (state->depressed)
509         return (state->inHover ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
510     else if (state->inHover)
511         return (state->active ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
512     else
513         return GTK_STATE_NORMAL;
514 }
515
516 static gint
517 TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
518 {
519     int i;
520     /* there are 5 gc's in each array, for each of the widget states */
521     for (i = 0; i < 5; ++i)
522         gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
523     return MOZ_GTK_SUCCESS;
524 }
525
526 static gint
527 TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
528 {
529     TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
530     TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
531     TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
532     TSOffsetStyleGCArray(style->dark_gc, xorigin, yorigin);
533     TSOffsetStyleGCArray(style->mid_gc, xorigin, yorigin);
534     TSOffsetStyleGCArray(style->text_gc, xorigin, yorigin);
535     TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
536     gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
537     gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
538     return MOZ_GTK_SUCCESS;
539 }
540
541 static gint
542 moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
543                      GdkRectangle* cliprect, GtkWidgetState* state,
544                      GtkReliefStyle relief, GtkWidget* widget,
545                      GtkTextDirection direction)
546 {
547     GtkShadowType shadow_type;
548     GtkStyle* style = widget->style;
549     GtkStateType button_state = ConvertGtkState(state);
550     gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
551
552     gboolean interior_focus;
553     gint focus_width, focus_pad;
554
555     moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad);
556
557     if (WINDOW_IS_MAPPED(drawable)) {
558         gdk_window_set_back_pixmap(drawable, NULL, TRUE);
559         gdk_window_clear_area(drawable, cliprect->x, cliprect->y,
560                               cliprect->width, cliprect->height);
561     }
562
563     gtk_widget_set_state(widget, button_state);
564     gtk_widget_set_direction(widget, direction);
565
566     if (state->isDefault)
567         GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT);
568
569     if (!interior_focus && state->focused) {
570         x += focus_width + focus_pad;
571         y += focus_width + focus_pad;
572         width -= 2 * (focus_width + focus_pad);
573         height -= 2 * (focus_width + focus_pad);
574     }
575
576     shadow_type = button_state == GTK_STATE_ACTIVE ||
577                       state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
578  
579     if (state->isDefault && GTK_BUTTON(widget)->relief == GTK_RELIEF_NORMAL) {
580         gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
581                       widget, "buttondefault", x, y, width, height);                   
582     }
583  
584     if (relief != GTK_RELIEF_NONE || state->depressed ||
585            (button_state != GTK_STATE_NORMAL &&
586             button_state != GTK_STATE_INSENSITIVE)) {
587         TSOffsetStyleGCs(style, x, y);
588         /* the following line can trigger an assertion (Crux theme)
589            file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area):
590            assertion `GDK_IS_WINDOW (window)' failed */
591         gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
592                       widget, "button", x, y, width, height);
593     }
594
595     if (state->focused) {
596         if (interior_focus) {
597             x += widget->style->xthickness + focus_pad;
598             y += widget->style->ythickness + focus_pad;
599             width -= 2 * (widget->style->xthickness + focus_pad);
600             height -= 2 * (widget->style->ythickness + focus_pad);
601         } else {
602             x -= focus_width + focus_pad;
603             y -= focus_width + focus_pad;
604             width += 2 * (focus_width + focus_pad);
605             height += 2 * (focus_width + focus_pad);
606         }
607
608         TSOffsetStyleGCs(style, x, y);
609         gtk_paint_focus(style, drawable, button_state, cliprect,
610                         widget, "button", x, y, width, height);
611     }
612
613     GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
614     return MOZ_GTK_SUCCESS;
615 }
616
617 gint