зеркало из https://github.com/mozilla/pjs.git
GTK theme renderer changes:
- 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:
Родитель
113dc25972
Коммит
fc030b3f78
|
@ -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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче