- Keep "widget prototypes" around instead of raw GtkStyles.  This way, the style retains valid GC's.
- Pass widget instances to gtk_paint_* to satisfy themes that expect this to be non-null.
- Add support for scrollbar buttons.
- Code refactoring and cleanup.

Not part of the build.
This commit is contained in:
bryner%netscape.com 2002-01-13 03:04:24 +00:00
Родитель 113dc25972
Коммит fc030b3f78
4 изменённых файлов: 147 добавлений и 106 удалений

Просмотреть файл

@ -45,6 +45,9 @@
#include <gdk/gdkprivate.h>
#include "gtkdrawing.h"
extern GtkWidget* gButtonWidget;
extern GtkWidget* gCheckboxWidget;
GtkStateType
ConvertGtkState(GtkWidgetState* aState)
{
@ -60,8 +63,8 @@ ConvertGtkState(GtkWidgetState* aState)
void
moz_gtk_button_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* buttonRect, GdkRectangle* clipRect,
GtkWidgetState* buttonState)
GdkRectangle* buttonRect, GdkRectangle* clipRect,
GtkWidgetState* buttonState)
{
GtkShadowType shadow_type;
gint default_spacing = 7; /* xxx fix me */
@ -69,13 +72,14 @@ moz_gtk_button_paint(GdkWindow* window, GtkStyle* style,
gint x = buttonRect->x, y=buttonRect->y, width=buttonRect->width, height=buttonRect->height;
if (((GdkWindowPrivate*)window)->mapped) {
gdk_window_set_back_pixmap (window, NULL, TRUE);
gdk_window_clear_area (window, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
gdk_window_set_back_pixmap(window, NULL, TRUE);
gdk_window_clear_area(window, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
}
gtk_widget_set_state(gButtonWidget, button_state);
if (buttonState->isDefault)
gtk_paint_box(style, window, GTK_STATE_NORMAL, GTK_SHADOW_IN,
clipRect, NULL, "buttondefault", x, y, width, height);
clipRect, gButtonWidget, "buttondefault", x, y, width, height);
if (buttonState->canDefault) {
x += style->klass->xthickness;
@ -93,14 +97,10 @@ moz_gtk_button_paint(GdkWindow* window, GtkStyle* style,
height -= 2;
}
if (buttonState->active)
shadow_type = GTK_SHADOW_IN;
else
shadow_type = GTK_SHADOW_OUT;
shadow_type = (buttonState->active) ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
gtk_paint_box(style, window, button_state, shadow_type, clipRect,
NULL, "button", x, y, width, height);
gButtonWidget, "button", x, y, width, height);
if (buttonState->focused) {
x -= 1;
@ -108,15 +108,15 @@ moz_gtk_button_paint(GdkWindow* window, GtkStyle* style,
width += 2;
height += 2;
gtk_paint_focus(style, window, clipRect, NULL, "button",
x, y, width - 1, height - 1);
gtk_paint_focus(style, window, clipRect, gButtonWidget, "button",
x, y, width - 1, height - 1);
}
}
void
moz_gtk_check_button_draw_indicator(GdkWindow* window, GtkStyle* style,
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState)
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState)
{
GtkStateType state_type;
GtkShadowType shadow_type;
@ -130,16 +130,17 @@ moz_gtk_check_button_draw_indicator(GdkWindow* window, GtkStyle* style,
*/
state_type = ConvertGtkState(wState);
if (state_type != GTK_STATE_NORMAL &&
state_type != GTK_STATE_PRELIGHT)
state_type = GTK_STATE_NORMAL;
/* if (state_type != GTK_STATE_NORMAL) */ /* XXX huh? */
if (state_type != GTK_STATE_NORMAL) /* this is for drawing e.g. a prelight box */
gtk_paint_flat_box (style, window, state_type,
GTK_SHADOW_ETCHED_OUT,
clipRect, NULL, "checkbutton",
boxRect->x, boxRect->y,
boxRect->width, boxRect->height);
GTK_SHADOW_ETCHED_OUT,
clipRect, gCheckboxWidget, "checkbutton",
boxRect->x, boxRect->y,
boxRect->width, boxRect->height);
x = boxRect->x + indicator_spacing;
y = boxRect->y + (boxRect->height - indicator_size) / 2;
@ -154,22 +155,37 @@ moz_gtk_check_button_draw_indicator(GdkWindow* window, GtkStyle* style,
shadow_type = GTK_SHADOW_OUT;
state_type = ConvertGtkState(wState);
}
gtk_paint_check (style, window,
state_type, shadow_type,
clipRect, NULL, "checkbutton",
x + 1, y + 1, width, height);
state_type, shadow_type,
clipRect, gCheckboxWidget, "checkbutton",
x + 1, y + 1, width, height);
}
void
moz_gtk_checkbox_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState)
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState)
{
moz_gtk_check_button_draw_indicator(window, style, boxRect, clipRect, aState);
if (((GtkWidgetState*)aState)->focused)
gtk_paint_focus (style, window,
NULL, NULL, "checkbutton",
boxRect->x, boxRect->y, boxRect->width - 1, boxRect->height - 1); /* XXX border width? */
clipRect, gCheckboxWidget, "checkbutton",
boxRect->x, boxRect->y, boxRect->width - 1, boxRect->height - 1);
}
void
moz_gtk_scrollbar_button_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* arrowRect, GdkRectangle* clipRect,
GtkWidgetState* state, GtkArrowType arrowType)
{
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = (state->active) ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
moz_gtk_button_paint(window, style, arrowRect, clipRect, state);
gtk_draw_arrow(style, window, state_type, shadow_type, arrowType, TRUE,
arrowRect->x, arrowRect->y, arrowRect->width, arrowRect->height);
}

Просмотреть файл

@ -59,17 +59,22 @@ typedef struct {
void
moz_gtk_button_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* buttonRect, GdkRectangle* clipRect,
GtkWidgetState* buttonState);
GdkRectangle* buttonRect, GdkRectangle* clipRect,
GtkWidgetState* buttonState);
void
moz_gtk_checkbox_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState);
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState);
void
moz_gtk_radio_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState);
GdkRectangle* boxRect, GdkRectangle* clipRect,
GtkToggleButtonState* aState);
void
moz_gtk_scrollbar_button_paint(GdkWindow* window, GtkStyle* style,
GdkRectangle* arrowRect, GdkRectangle* clipRect,
GtkWidgetState* state, GtkArrowType type);
#endif

Просмотреть файл

@ -57,9 +57,13 @@ extern "C" {
NS_IMPL_ISUPPORTS1(nsNativeThemeGTK, nsITheme)
GtkWidget* gButtonWidget = nsnull;
GtkWidget* gCheckboxWidget = nsnull;
GtkWidget* gScrollbarWidget = nsnull;
nsNativeThemeGTK::nsNativeThemeGTK()
: mButtonStyle(NULL),
mCheckBoxStyle(NULL)
: mProtoWindow(nsnull),
mProtoLayout(nsnull)
{
NS_INIT_ISUPPORTS();
mDisabledAtom = getter_AddRefs(NS_NewAtom("disabled"));
@ -67,10 +71,6 @@ nsNativeThemeGTK::nsNativeThemeGTK()
}
nsNativeThemeGTK::~nsNativeThemeGTK() {
if (mButtonStyle)
gtk_style_unref(mButtonStyle);
if (mCheckBoxStyle)
gtk_style_unref(mCheckBoxStyle);
}
static void GetPrimaryPresShell(nsIFrame* aFrame, nsIPresShell** aResult)
@ -225,34 +225,58 @@ nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
GdkRectangle gdk_clip = {cr.x, cr.y, cr.width, cr.height};
switch (aWidgetType) {
case NS_THEME_BUTTON:
EnsureButtonStyle();
{
EnsureButtonWidget();
GtkWidgetState buttonState;
GetGtkWidgetState(aFrame, &buttonState);
moz_gtk_button_paint(window, mButtonStyle, &gdk_rect, &gdk_clip, &buttonState);
GtkWidgetState buttonState;
GetGtkWidgetState(aFrame, &buttonState);
moz_gtk_button_paint(window, gButtonWidget->style, &gdk_rect, &gdk_clip, &buttonState);
}
break;
case NS_THEME_CHECKBOX:
EnsureCheckBoxStyle();
if (aFrame) {
// For XUL checkboxes and radio buttons, the state of the parent
// determines our state.
nsCOMPtr<nsIContent> content;
aFrame->GetContent(getter_AddRefs(content));
if (content->IsContentOfType(nsIContent::eXUL))
aFrame->GetParent(&aFrame);
{
EnsureCheckBoxWidget();
if (aFrame) {
// For XUL checkboxes and radio buttons, the state of the parent
// determines our state.
nsCOMPtr<nsIContent> content;
aFrame->GetContent(getter_AddRefs(content));
if (content->IsContentOfType(nsIContent::eXUL))
aFrame->GetParent(&aFrame);
}
GtkToggleButtonState checkBoxState;
GetGtkWidgetState(aFrame, (GtkWidgetState*)&checkBoxState);
checkBoxState.selected = CheckBooleanAttr(aFrame, mCheckedAtom);
printf("paint checkbox: gdk_rect=(%d,%d,%d,%d), gdk_clip=(%d,%d,%d,%d)\n",
gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height,
gdk_clip.y, gdk_clip.y, gdk_clip.width, gdk_clip.height);
moz_gtk_checkbox_paint(window, gCheckboxWidget->style, &gdk_rect, &gdk_clip, &checkBoxState);
}
GtkToggleButtonState checkBoxState;
GetGtkWidgetState(aFrame, (GtkWidgetState*)&checkBoxState);
checkBoxState.selected = CheckBooleanAttr(aFrame, mCheckedAtom);
moz_gtk_checkbox_paint(window, mCheckBoxStyle, &gdk_rect, &gdk_clip, &checkBoxState);
break;
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
{
EnsureScrollbarWidget();
GtkWidgetState buttonState;
GetGtkWidgetState(aFrame, &buttonState);
GtkArrowType arrowType = GtkArrowType(aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP);
moz_gtk_scrollbar_button_paint(window, gScrollbarWidget->style, &gdk_rect, &gdk_clip,
&buttonState, arrowType);
}
break;
}
return NS_OK;
@ -328,7 +352,10 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsIPresContext* aPresContext,
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_CHECKBOX:
case NS_THEME_CHECKBOX_CONTAINER:
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
return PR_TRUE;
}
@ -347,51 +374,42 @@ nsNativeThemeGTK::WidgetIsContainer(PRUint8 aWidgetType)
}
void
nsNativeThemeGTK::EnsureButtonStyle()
nsNativeThemeGTK::SetupWidgetPrototype(GtkWidget* widget)
{
if (mButtonStyle)
return;
if (!mProtoWindow) {
mProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
mProtoLayout = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(mProtoWindow), mProtoLayout);
}
GtkWidget *parent = gtk_fixed_new();
GtkWidget *button = gtk_button_new();
GtkWidget *label = gtk_label_new("M");
GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_container_add(GTK_CONTAINER(button), label);
gtk_container_add(GTK_CONTAINER(parent), button);
gtk_container_add(GTK_CONTAINER(window), parent);
gtk_widget_set_rc_style(button);
gtk_widget_set_rc_style(label);
gtk_widget_realize(button);
gtk_widget_realize(label);
mButtonStyle = gtk_widget_get_style(button);
gtk_style_ref(mButtonStyle);
gtk_widget_destroy(window);
gtk_container_add(GTK_CONTAINER(mProtoLayout), widget);
gtk_widget_set_rc_style(widget);
gtk_widget_realize(widget);
}
void
nsNativeThemeGTK::EnsureCheckBoxStyle()
nsNativeThemeGTK::EnsureButtonWidget()
{
if (mCheckBoxStyle)
return;
GtkWidget *parent = gtk_fixed_new();
GtkWidget* checkbox = gtk_check_button_new_with_label("M");
GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_container_add(GTK_CONTAINER(parent), checkbox);
gtk_container_add(GTK_CONTAINER(window), parent);
gtk_widget_set_rc_style(checkbox);
gtk_widget_realize(checkbox);
mCheckBoxStyle = gtk_widget_get_style(checkbox);
gtk_style_ref(mCheckBoxStyle);
gtk_widget_destroy(window);
if (!gButtonWidget) {
gButtonWidget = gtk_button_new_with_label("M");
SetupWidgetPrototype(gButtonWidget);
}
}
void
nsNativeThemeGTK::EnsureCheckBoxWidget()
{
if (!gCheckboxWidget) {
gCheckboxWidget = gtk_check_button_new_with_label("M");
SetupWidgetPrototype(gCheckboxWidget);
}
}
void
nsNativeThemeGTK::EnsureScrollbarWidget()
{
if (!gScrollbarWidget) {
gScrollbarWidget = gtk_vscrollbar_new(NULL);
SetupWidgetPrototype(gScrollbarWidget);
}
}

Просмотреть файл

@ -84,8 +84,10 @@ protected:
void GetGtkWidgetState(nsIFrame* aFrame, GtkWidgetState* aState);
void EnsureButtonStyle();
void EnsureCheckBoxStyle();
void SetupWidgetPrototype(GtkWidget* widget);
void EnsureButtonWidget();
void EnsureCheckBoxWidget();
void EnsureScrollbarWidget();
private:
nsCOMPtr<nsIAtom> mCheckedAtom;
@ -93,6 +95,6 @@ private:
nsCOMPtr<nsIAtom> mSelectedAtom;
nsCOMPtr<nsIAtom> mTypeAtom;
GtkStyle* mButtonStyle;
GtkStyle* mCheckBoxStyle;
GtkWidget* mProtoWindow;
GtkWidget* mProtoLayout;
};