[gtk+/client-side-decorations: 1/50] work in progress
- From: Cody Russell <bratsche src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+/client-side-decorations: 1/50] work in progress
- Date: Wed, 8 Jul 2009 15:28:14 +0000 (UTC)
commit c6a3cc92bb78918e5fa2782b83673649e648a802
Author: Cody Russell <crussell canonical com>
Date: Fri May 15 14:59:01 2009 -0400
work in progress
gtk/gtkwindow-decorate.c | 499 ++++++++++++++++++++++++++++++----------------
gtk/gtkwindow-decorate.h | 1 +
gtk/gtkwindow.c | 218 ++++++++++++++++++--
gtk/gtkwindow.h | 3 +
4 files changed, 535 insertions(+), 186 deletions(-)
---
diff --git a/gtk/gtkwindow-decorate.c b/gtk/gtkwindow-decorate.c
index 5ff0612..31ad8f9 100644
--- a/gtk/gtkwindow-decorate.c
+++ b/gtk/gtkwindow-decorate.c
@@ -24,18 +24,20 @@
#include "config.h"
#include "gtkprivate.h"
#include "gtkwindow.h"
+#include "gtkhbox.h"
+#include "gtkbutton.h"
#include "gtkmain.h"
#include "gtkwindow-decorate.h"
#include "gtkintl.h"
#include "gtkalias.h"
-
-#ifdef DECORATE_WINDOWS
+#include <math.h>
typedef enum
{
GTK_WINDOW_REGION_TITLE,
GTK_WINDOW_REGION_MAXIMIZE,
+ GTK_WINDOW_REGION_MINIMIZE,
GTK_WINDOW_REGION_CLOSE,
GTK_WINDOW_REGION_BR_RESIZE
} GtkWindowRegionType;
@@ -69,29 +71,31 @@ struct _GtkWindowDecoration
gint last_x, last_y;
gint last_w, last_h;
-
+
+ gint radius;
+ gboolean round_corners;
+
PangoLayout *title_layout;
GtkWindowResizeType resize;
-
+
+ GtkWidget *hbox;
+ GtkWidget *close_button;
+ GtkWidget *max_button;
+ GtkWidget *min_button;
+
+ guint minimizing : 1;
guint moving : 1;
guint closing : 1;
guint maximizing : 1;
guint maximized : 1;
guint maximizable : 1;
+ guint minimizable : 1;
guint decorated : 1;
guint real_inner_move : 1;
guint focused : 1;
};
-#define DECORATION_BORDER_TOP 15
-#define DECORATION_BORDER_LEFT 3
-#define DECORATION_BORDER_RIGHT 3
-#define DECORATION_BORDER_BOTTOM 3
-#define DECORATION_BORDER_TOT_X (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT)
-#define DECORATION_BORDER_TOT_Y (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM)
-#define DECORATION_BUTTON_SIZE 9
-#define DECORATION_BUTTON_Y_OFFSET 2
#define DECORATION_TITLE_FONT "Sans 9"
static void gtk_decorated_window_recalculate_regions (GtkWindow *window);
@@ -122,6 +126,8 @@ gtk_decoration_free (GtkWindowDecoration *deco)
deco->regions = NULL;
deco->n_regions = 0;
+ g_object_unref (deco->hbox);
+
g_free (deco);
}
@@ -141,12 +147,22 @@ gtk_decorated_window_init (GtkWindow *window)
deco->closing = FALSE;
deco->maximizing = FALSE;
deco->maximized = FALSE;
+ deco->minimizing = FALSE;
deco->maximizable = FALSE;
deco->real_inner_move = FALSE;
-
+ deco->round_corners = TRUE;
+ deco->radius = 5;
+
+ deco->close_button = gtk_button_new_from_stock ("stock-smiley-26");
+ deco->hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (deco->hbox), deco->close_button, FALSE, FALSE, 0);
+ gtk_widget_show_all (deco->hbox);
+ gtk_widget_set_parent_window (deco->hbox, window->frame);
+ gtk_widget_set_parent (deco->hbox, GTK_WIDGET (window));
+
g_object_set_data_full (G_OBJECT (window), I_("gtk-window-decoration"), deco,
(GDestroyNotify) gtk_decoration_free);
-
+
gtk_window_set_has_frame (window, TRUE);
g_signal_connect (window,
@@ -177,35 +193,69 @@ get_decoration (GtkWindow *window)
return (GtkWindowDecoration *)g_object_get_data (G_OBJECT (window), "gtk-window-decoration");
}
+GtkWidget *
+gtk_decorated_window_get_box (GtkWindow *window)
+{
+ GtkWindowDecoration *deco;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ deco = get_decoration (window);
+
+ return deco->hbox;
+}
+
void
gtk_decorated_window_set_title (GtkWindow *window,
const gchar *title)
{
- GtkWindowDecoration *deco = get_decoration (window);
-
+ GtkWindowDecoration *deco;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ deco = get_decoration (window);
+
if (deco->title_layout)
pango_layout_set_text (deco->title_layout, title, -1);
}
-void
+void
gtk_decorated_window_calculate_frame_size (GtkWindow *window)
{
GdkWMDecoration decorations;
GtkWindowDecoration *deco = get_decoration (window);
-
- if (gdk_window_get_decorations (GTK_WIDGET (window)->window,
- &decorations))
+ gint border_left, border_top, border_right, border_bottom;
+
+ decorations = gtk_window_get_client_side_decorations (window);
+ if (!decorations)
+ {
+ gdk_window_get_decorations (GTK_WIDGET (window)->window,
+ &decorations);
+ }
+
+ if (decorations)
{
if ((decorations & GDK_DECOR_BORDER) &&
(decorations & GDK_DECOR_TITLE))
{
deco->decorated = TRUE;
+
if ((decorations & GDK_DECOR_MAXIMIZE) &&
(gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL))
- deco->maximizable = TRUE;
+ {
+ deco->maximizable = TRUE;
+ }
+
+ if ((decorations & GDK_DECOR_MINIMIZE) &&
+ (gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL))
+ {
+ deco->minimizable = TRUE;
+ }
}
else
- deco->decorated = FALSE;
+ {
+ deco->decorated = FALSE;
+ }
}
else
{
@@ -214,13 +264,24 @@ gtk_decorated_window_calculate_frame_size (GtkWindow *window)
}
if (deco->decorated)
- gtk_window_set_frame_dimensions (window,
- DECORATION_BORDER_LEFT,
- DECORATION_BORDER_TOP,
- DECORATION_BORDER_RIGHT,
- DECORATION_BORDER_BOTTOM);
+ {
+ gtk_widget_style_get (GTK_WIDGET (window),
+ "decoration-border-left", &border_left,
+ "decoration-border-top", &border_top,
+ "decoration-border-right", &border_right,
+ "decoration-border-bottom", &border_bottom,
+ NULL);
+
+ gtk_window_set_frame_dimensions (window,
+ border_left,
+ border_top,
+ border_right,
+ border_bottom);
+ }
else
- gtk_window_set_frame_dimensions (window, 0, 0, 0, 0);
+ {
+ gtk_window_set_frame_dimensions (window, 0, 0, 0, 0);
+ }
gtk_decorated_window_recalculate_regions (window);
}
@@ -261,7 +322,7 @@ gtk_decorated_window_inner_get_pos (GdkWindow *win,
GtkWindow *window = (GtkWindow *)user_data;
gdk_window_get_position (window->frame, x, y);
-
+
*x += window->frame_left;
*y += window->frame_top;
}
@@ -279,20 +340,6 @@ gtk_decorated_window_realize (GtkWindow *window)
font_desc = pango_font_description_from_string(DECORATION_TITLE_FONT);
pango_layout_set_font_description (deco->title_layout, font_desc);
pango_font_description_free (font_desc);
-
-#if 0
- /* What is this code exactly doing? I remember we were using the
- decorated windows with the DirectFB port and it did just work,
- and there was definitely no code in linux-fb involved. */
- gdk_fb_window_set_child_handler (window->frame,
- gtk_decorated_window_inner_change,
- gtk_decorated_window_inner_get_pos,
- window);
-
- /* This is a huge hack to make frames have the same shape as
- the window they wrap */
- gdk_window_shape_combine_mask (window->frame, GDK_FB_USE_CHILD_SHAPE, 0, 0);
-#endif
}
@@ -363,20 +410,28 @@ gtk_decorated_window_motion_notify (GtkWidget *widget,
GdkWindow *win;
gint x, y;
gint win_x, win_y, win_w, win_h;
-
+ gint border_top, border_left, border_right, border_bottom;
+
window = GTK_WINDOW (widget);
deco = get_decoration (window);
-
+
if (!deco->decorated)
return TRUE;
-
+
win = widget->window;
gdk_window_get_pointer (window->frame, &x, &y, &mask);
-
+
+ gtk_widget_style_get (GTK_WIDGET (window),
+ "decoration-border-left", &border_left,
+ "decoration-border-top", &border_top,
+ "decoration-border-right", &border_right,
+ "decoration-border-bottom", &border_bottom,
+ NULL);
+
gdk_window_get_position (window->frame, &win_x, &win_y);
- win_x += DECORATION_BORDER_LEFT;
- win_y += DECORATION_BORDER_TOP;
-
+ win_x += border_left;
+ win_y += border_top;
+
gdk_window_get_geometry (win, NULL, NULL, &win_w, &win_h, NULL);
if (deco->moving)
@@ -397,14 +452,14 @@ gtk_decorated_window_motion_notify (GtkWidget *widget,
switch(deco->resize) {
case RESIZE_BOTTOM_RIGHT:
- w = x - DECORATION_BORDER_TOT_X;
- h = y - DECORATION_BORDER_TOT_Y;
+ w = x - border_left + border_right;
+ h = y - border_top + border_bottom;
break;
case RESIZE_RIGHT:
- w = x - DECORATION_BORDER_TOT_X;
+ w = x - border_left + border_right;
break;
case RESIZE_BOTTOM:
- h = y - DECORATION_BORDER_TOT_Y;
+ h = y - border_top + border_bottom;
break;
case RESIZE_TOP_LEFT:
case RESIZE_TOP:
@@ -440,8 +495,11 @@ gtk_decorated_window_region_type (GtkWindow *window, gint x, gint y)
(x - deco->regions[i].rect.x < deco->regions[i].rect.width) &&
(y > deco->regions[i].rect.y) &&
(y - deco->regions[i].rect.y < deco->regions[i].rect.height))
- return deco->regions[i].type;
+ {
+ return deco->regions[i].type;
+ }
}
+
return -1;
}
@@ -452,7 +510,7 @@ gtk_decorated_window_button_press (GtkWidget *widget,
GtkWindow *window;
GtkWindowRegionType type;
GtkWindowDecoration *deco;
- gint x, y;
+ gint x, y;
window = GTK_WINDOW (widget);
deco = get_decoration (window);
@@ -462,40 +520,50 @@ gtk_decorated_window_button_press (GtkWidget *widget,
x = event->x;
y = event->y;
-
+
type = gtk_decorated_window_region_type (window, x, y);
switch (type)
{
case GTK_WINDOW_REGION_TITLE:
- if (!deco->maximized && event->state & GDK_BUTTON1_MASK)
+ if (!deco->maximized && event->button == 1)
{
- deco->last_x = x;
- deco->last_y = y;
- deco->moving = TRUE;
+ gtk_window_begin_move_drag (window,
+ event->button,
+ event->x_root,
+ event->y_root,
+ event->time);
}
break;
+#if 0
case GTK_WINDOW_REGION_MAXIMIZE:
- if (event->state & GDK_BUTTON1_MASK)
+ if (event->button == 1)
deco->maximizing = TRUE;
break;
+ case GTK_WINDOW_REGION_MINIMIZE:
+ if (event->button == 1)
+ deco->minimizing = TRUE;
+ break;
case GTK_WINDOW_REGION_CLOSE:
- if (event->state & GDK_BUTTON1_MASK)
+ if (event->button == 1)
deco->closing = TRUE;
break;
+#endif
case GTK_WINDOW_REGION_BR_RESIZE:
if (!deco->maximized)
{
- if (event->state & GDK_BUTTON1_MASK)
- deco->resize = RESIZE_BOTTOM_RIGHT;
- deco->last_x = x;
- deco->last_y = y;
+ gtk_window_begin_resize_drag (window,
+ GDK_WINDOW_EDGE_SOUTH_EAST,
+ event->button,
+ event->x_root,
+ event->y_root,
+ event->time);
}
break;
default:
break;
}
-
+
return TRUE;
}
@@ -506,13 +574,13 @@ gtk_decorated_window_button_release (GtkWidget *widget,
GtkWindow *window;
GtkWindowRegionType type;
GtkWindowDecoration *deco;
-
+
window = GTK_WINDOW (widget);
+ type = gtk_decorated_window_region_type (window, event->x, event->y);
deco = get_decoration (window);
if (deco->closing)
{
- type = gtk_decorated_window_region_type (window, event->x, event->y);
if (type == GTK_WINDOW_REGION_CLOSE)
{
GdkEvent *event = gdk_event_new (GDK_DELETE);
@@ -527,7 +595,6 @@ gtk_decorated_window_button_release (GtkWidget *widget,
}
else if (deco->maximizing)
{
- type = gtk_decorated_window_region_type (window, event->x, event->y);
if (type == GTK_WINDOW_REGION_MAXIMIZE)
{
if (deco->maximized)
@@ -536,9 +603,17 @@ gtk_decorated_window_button_release (GtkWidget *widget,
gtk_window_maximize (window);
}
}
-
+ else if (deco->minimizing)
+ {
+ if (type == GTK_WINDOW_REGION_MINIMIZE)
+ {
+ gtk_window_iconify (window);
+ }
+ }
+
deco->closing = FALSE;
deco->maximizing = FALSE;
+ deco->minimizing = FALSE;
deco->moving = FALSE;
deco->resize = RESIZE_NONE;
return TRUE;
@@ -551,11 +626,19 @@ gtk_decorated_window_window_state (GtkWidget *widget,
GtkWindow *window;
GtkWindowDecoration *deco;
GdkWindowObject *priv;
-
+ gint border_left, border_right, border_top, border_bottom;
+
window = GTK_WINDOW (widget);
deco = get_decoration (window);
priv = GDK_WINDOW_OBJECT (window->frame);
+ gtk_widget_style_get (widget,
+ "decoration-border-left", &border_left,
+ "decoration-border-top", &border_top,
+ "decoration-border-right", &border_right,
+ "decoration-border-bottom", &border_bottom,
+ NULL);
+
if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
{
if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -564,12 +647,12 @@ gtk_decorated_window_window_state (GtkWidget *widget,
gdk_window_get_geometry (widget->window, NULL, NULL,
&deco->last_w, &deco->last_h, NULL);
gdk_window_get_origin (widget->window, &deco->last_x, &deco->last_y);
- w = gdk_screen_get_width(gdk_screen_get_default()) - DECORATION_BORDER_TOT_X;
- h = gdk_screen_get_height(gdk_screen_get_default()) - DECORATION_BORDER_TOT_Y;
+ w = gdk_screen_get_width(gdk_screen_get_default()) - border_left + border_right;
+ h = gdk_screen_get_height(gdk_screen_get_default()) - border_top + border_bottom;
_gtk_window_constrain_size (window, w, h, &w, &h);
if (w != deco->last_w || h != deco->last_h)
{
- _gtk_window_reposition (window, DECORATION_BORDER_LEFT, DECORATION_BORDER_TOP);
+ _gtk_window_reposition (window, border_left, border_top);
gdk_window_resize (widget->window, w, h);
deco->maximized = TRUE;
}
@@ -594,60 +677,128 @@ gtk_decorated_window_paint (GtkWidget *widget,
GtkWindowDecoration *deco = get_decoration (window);
gint x1, y1, x2, y2;
GtkStateType border_state;
+ GdkRectangle rect;
if (deco->decorated)
{
GdkWindow *frame;
gint width, height;
+ gint border_top, border_bottom, border_left, border_right;
+ gint button_size;
+ gint y_offset;
frame = window->frame;
gdk_drawable_get_size (frame, &width, &height);
+ gtk_widget_style_get (GTK_WIDGET (window),
+ "decoration-border-left", &border_left,
+ "decoration-border-top", &border_top,
+ "decoration-border-right", &border_right,
+ "decoration-border-bottom", &border_bottom,
+ "decoration-button-size", &button_size,
+ "decoration-button-y-offset", &y_offset,
+ NULL);
+
+ height += border_top + border_bottom;
+ width += border_left + border_right;
+
+ rect.x = area->x - border_left;
+ rect.y = area->y - border_top;
+ rect.width = area->width + border_left + border_right;
+ rect.height = area->height + border_top + border_bottom;
+
+#if 1
+ /* XXX - what is this for? */
+
/* Top */
gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
GTK_SHADOW_NONE, area, widget, "base",
0, 0,
- width, DECORATION_BORDER_TOP);
+ width, border_top);
/* Bottom */
gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
GTK_SHADOW_NONE, area, widget, "base",
- 0, height - DECORATION_BORDER_BOTTOM,
- width, DECORATION_BORDER_BOTTOM);
+ 0, height - border_bottom,
+ width, border_bottom);
/* Left */
gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
GTK_SHADOW_NONE, area, widget, "base",
- 0, DECORATION_BORDER_TOP,
- DECORATION_BORDER_LEFT, height - DECORATION_BORDER_TOT_Y);
+ 0, border_top,
+ border_left, height - border_top + border_bottom);
/* Right */
gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
GTK_SHADOW_NONE, area, widget, "base",
- width - DECORATION_BORDER_RIGHT, DECORATION_BORDER_TOP,
- DECORATION_BORDER_RIGHT, height - DECORATION_BORDER_TOT_Y);
-
+ width - border_right, border_top,
+ border_right, height - border_top + border_bottom);
+#endif
+
/* Border: */
if (deco->focused)
border_state = GTK_STATE_SELECTED;
- else
+ else
border_state = GTK_STATE_PRELIGHT;
- gtk_paint_box (widget->style, frame, border_state,
- GTK_SHADOW_OUT, area, widget, "base",
- 0, 0, width, height);
-
- gtk_paint_box (widget->style, frame, border_state,
- GTK_SHADOW_IN, area, widget, "base",
- DECORATION_BORDER_LEFT - 2, DECORATION_BORDER_TOP - 2,
- width - (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT) + 3,
- height - (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM) + 3);
+ if (deco->round_corners)
+ {
+ cairo_pattern_t *gradient;
+ cairo_t *cr;
+ const int hmargin = 2, vmargin = 2, radius = 5;
+ const int width = widget->allocation.width + border_left + border_right;
+ const int height = widget->allocation.height + border_top + border_bottom;
+
+ cr = gdk_cairo_create (frame);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_arc (cr, hmargin + radius, vmargin + radius,
+ radius, M_PI, 3 * M_PI / 2);
+ cairo_line_to (cr, width - hmargin - radius, vmargin);
+ cairo_arc (cr, width - hmargin - radius, vmargin + radius,
+ radius, 3 * M_PI / 2, 2 * M_PI);
+ cairo_line_to (cr, width - hmargin, height - vmargin - radius);
+ cairo_arc (cr, width - hmargin - radius, height - vmargin - radius,
+ radius, 0, M_PI / 2);
+ cairo_line_to (cr, hmargin + radius, height - vmargin);
+ cairo_arc (cr, hmargin + radius, height - vmargin - radius,
+ radius, M_PI / 2, M_PI);
+ cairo_close_path (cr);
+
+ gradient = cairo_pattern_create_linear (width / 2 - 1, vmargin,
+ width / 2 + 1, height);
+ cairo_pattern_add_color_stop_rgba (gradient, 0, 1, 1, 1, 0.2);
+ cairo_pattern_add_color_stop_rgba (gradient, 1, 1, 1, 1, 0.9);
+ cairo_set_source (cr, gradient);
+ cairo_fill_preserve (cr);
+
+ cairo_set_source_rgba (cr, 1, 1, 1, 2);
+ cairo_set_line_width (cr, 1);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_stroke (cr);
+
+ cairo_destroy (cr);
+ }
+ else
+ {
+ gtk_paint_box (widget->style, frame, border_state,
+ GTK_SHADOW_OUT, area, widget, "base",
+ 0, 0, width, height);
+
+ gtk_paint_box (widget->style, frame, border_state,
+ GTK_SHADOW_IN, area, widget, "base",
+ border_left - 2, border_top - 2,
+ width - (border_left + border_right) + 3,
+ height - (border_top + border_bottom) + 3);
+ }
+#if 0
if (deco->maximizable)
{
/* Maximize button: */
-
- x1 = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
- y1 = DECORATION_BUTTON_Y_OFFSET;
- x2 = x1 + DECORATION_BUTTON_SIZE;
- y2 = y1 + DECORATION_BUTTON_SIZE;
+ x1 = width - (border_left * 2) - (button_size * 2);
+ y1 = y_offset;
+ x2 = x1 + button_size;
+ y2 = y1 + button_size;
if (area)
gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], area);
@@ -659,18 +810,37 @@ gtk_decorated_window_paint (GtkWidget *widget,
gdk_draw_rectangle (frame, widget->style->black_gc, FALSE,
x1 + 1, y1 + 2,
- DECORATION_BUTTON_SIZE - 3, DECORATION_BUTTON_SIZE - 4);
+ button_size - 3, button_size - 4);
if (area)
gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
}
-
+
+ if (deco->minimizable)
+ {
+ /* Minimize button */
+ x1 = width - (border_left * 2) - (button_size * 3);
+ y1 = y_offset;
+ x2 = x1 + button_size;
+ y2 = y1 + button_size;
+
+ if (area)
+ gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], area);
+
+ gdk_draw_rectangle (frame, widget->style->bg_gc[widget->state], TRUE,
+ x1, y1, x2 - x1, y2 - y1);
+
+ gdk_draw_line (frame, widget->style->black_gc, x1 + 1, y2 - 2, x2 - 2, y2 - 2);
+
+ if (area)
+ gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
+ }
+
/* Close button: */
-
- x1 = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
- y1 = DECORATION_BUTTON_Y_OFFSET;
- x2 = width - DECORATION_BORDER_LEFT;
- y2 = DECORATION_BUTTON_Y_OFFSET + DECORATION_BUTTON_SIZE;
+ x1 = width - border_left - button_size;
+ y1 = y_offset;
+ x2 = width - border_left;
+ y2 = y_offset + button_size;
if (area)
gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], area);
@@ -679,10 +849,10 @@ gtk_decorated_window_paint (GtkWidget *widget,
x1, y1, x2 - x1, y2 - y1);
if (area)
- gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], NULL);
-
- if (area)
- gdk_gc_set_clip_rectangle (widget->style->black_gc, area);
+ {
+ gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], NULL);
+ gdk_gc_set_clip_rectangle (widget->style->black_gc, area);
+ }
gdk_draw_line (frame, widget->style->black_gc, x1, y1, x2-1, y2-1);
@@ -690,9 +860,9 @@ gtk_decorated_window_paint (GtkWidget *widget,
if (area)
gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
-
-
+#endif
+#if 0
/* Title */
if (deco->title_layout)
{
@@ -701,12 +871,12 @@ gtk_decorated_window_paint (GtkWidget *widget,
gdk_draw_layout (frame,
widget->style->fg_gc [border_state],
- DECORATION_BORDER_LEFT, 1,
+ border_left, 1,
deco->title_layout);
if (area)
gdk_gc_set_clip_rectangle (widget->style->fg_gc [border_state], NULL);
}
-
+#endif
}
}
@@ -718,15 +888,20 @@ gtk_decorated_window_recalculate_regions (GtkWindow *window)
gint width, height;
GtkWindowRegion *region;
GtkWindowDecoration *deco = get_decoration (window);
-
+ gint border_left, border_right, border_top, border_bottom;
+ gint button_size;
+ gint y_offset;
+
n_regions = 0;
if (!deco->decorated)
return;
-
+
n_regions += 2; /* close, Title */
if (deco->maximizable)
n_regions += 1;
+ if (deco->minimizable)
+ n_regions += 1;
if (window->allow_shrink || window->allow_grow)
n_regions += 2;
@@ -737,51 +912,70 @@ gtk_decorated_window_recalculate_regions (GtkWindow *window)
deco->n_regions = n_regions;
}
- width = GTK_WIDGET (window)->allocation.width + DECORATION_BORDER_TOT_X;
- height = GTK_WIDGET (window)->allocation.height + DECORATION_BORDER_TOT_Y;
+ gtk_widget_style_get (GTK_WIDGET (window),
+ "decoration-border-left", &border_left,
+ "decoration-border-top", &border_top,
+ "decoration-border-right", &border_right,
+ "decoration-border-bottom", &border_bottom,
+ "decoration-button-size", &button_size,
+ "decoration-button-y-offset", &y_offset,
+ NULL);
+
+ width = GTK_WIDGET (window)->allocation.width + border_left + border_right;
+ height = GTK_WIDGET (window)->allocation.height + border_top + border_bottom;
region = deco->regions;
+ if (deco->minimizable)
+ {
+ region->rect.x = width - (border_left * 2) - (button_size * 3);
+ region->rect.y = y_offset;
+ region->rect.width = button_size;
+ region->rect.height = button_size;
+ region->type = GTK_WINDOW_REGION_MINIMIZE;
+ region++;
+ }
+
/* Maximize button */
if (deco->maximizable)
{
- region->rect.x = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
- region->rect.y = DECORATION_BUTTON_Y_OFFSET;
- region->rect.width = DECORATION_BUTTON_SIZE;
- region->rect.height = DECORATION_BUTTON_SIZE;
+ region->rect.x = width - (border_left * 2) - (button_size * 2);
+ region->rect.y = y_offset;
+ region->rect.width = button_size;
+ region->rect.height = button_size;
region->type = GTK_WINDOW_REGION_MAXIMIZE;
region++;
}
/* Close button */
- region->rect.x = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
- region->rect.y = DECORATION_BUTTON_Y_OFFSET;
- region->rect.width = DECORATION_BUTTON_SIZE;
- region->rect.height = DECORATION_BUTTON_SIZE;
+ region->rect.x = width - border_left - button_size;
+ region->rect.y = y_offset;
+ region->rect.width = button_size;
+ region->rect.height = button_size;
region->type = GTK_WINDOW_REGION_CLOSE;
region++;
-
+
/* title bar */
region->rect.x = 0;
region->rect.y = 0;
region->rect.width = width;
- region->rect.height = DECORATION_BORDER_TOP;
+ region->rect.height = border_top;
region->type = GTK_WINDOW_REGION_TITLE;
region++;
-
+
if (window->allow_shrink || window->allow_grow)
{
- region->rect.x = width - (DECORATION_BORDER_RIGHT + 10);
- region->rect.y = height - DECORATION_BORDER_BOTTOM;
- region->rect.width = DECORATION_BORDER_RIGHT + 10;
- region->rect.height = DECORATION_BORDER_BOTTOM;
+ region->rect.x = width - (border_right + 10);
+ region->rect.y = height - border_bottom;
+ region->rect.width = border_right + 10;
+ region->rect.height = border_bottom;
region->type = GTK_WINDOW_REGION_BR_RESIZE;
region++;
- region->rect.x = width - DECORATION_BORDER_RIGHT;
- region->rect.y = height - (DECORATION_BORDER_BOTTOM + 10);
- region->rect.width = DECORATION_BORDER_RIGHT;
- region->rect.height = DECORATION_BORDER_BOTTOM + 10;
+ region->rect.x = width - border_right;
+ region->rect.y = height - (border_bottom + 10);
+ region->rect.width = border_right;
+ region->rect.height = border_bottom + 10;
region->type = GTK_WINDOW_REGION_BR_RESIZE;
region++;
}
@@ -796,40 +990,11 @@ gtk_decorated_window_move_resize_window (GtkWindow *window,
{
GtkWidget *widget = GTK_WIDGET (window);
GtkWindowDecoration *deco = get_decoration (window);
-
+
deco->real_inner_move = TRUE;
gdk_window_move_resize (widget->window,
x, y, width, height);
}
-#else
-
-void
-gtk_decorated_window_init (GtkWindow *window)
-{
-}
-
-void
-gtk_decorated_window_calculate_frame_size (GtkWindow *window)
-{
-}
-
-void
-gtk_decorated_window_set_title (GtkWindow *window,
- const gchar *title)
-{
-}
-
-void
-gtk_decorated_window_move_resize_window (GtkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- gdk_window_move_resize (GTK_WIDGET (window)->window,
- x, y, width, height);
-}
-#endif
#define __GTK_WINDOW_DECORATE_C__
diff --git a/gtk/gtkwindow-decorate.h b/gtk/gtkwindow-decorate.h
index 9f182f4..bd1f2a7 100644
--- a/gtk/gtkwindow-decorate.h
+++ b/gtk/gtkwindow-decorate.h
@@ -35,6 +35,7 @@ void gtk_decorated_window_move_resize_window (GtkWindow *window,
gint y,
gint width,
gint height);
+GtkWidget *gtk_decorated_window_get_box (GtkWindow *window);
G_END_DECLS
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 1238c22..b48ac6d 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -185,6 +185,10 @@ struct _GtkWindowPrivate
guint opacity_set : 1;
guint builder_visible : 1;
+ gboolean client_side_decorated;
+ GdkWMDecoration client_side_decorations;
+ GdkWMDecoration old_decorations;
+
GdkWindowTypeHint type_hint;
gdouble opacity;
@@ -217,6 +221,8 @@ static gint gtk_window_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static gint gtk_window_key_release_event (GtkWidget *widget,
GdkEventKey *event);
+static gboolean gtk_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event);
static gint gtk_window_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event);
static gint gtk_window_leave_notify_event (GtkWidget *widget,
@@ -456,7 +462,8 @@ gtk_window_class_init (GtkWindowClass *klass)
widget_class->focus_out_event = gtk_window_focus_out_event;
widget_class->client_event = gtk_window_client_event;
widget_class->focus = gtk_window_focus;
-
+ widget_class->button_press_event = gtk_window_button_press_event;
+
widget_class->expose_event = gtk_window_expose;
container_class->check_resize = gtk_window_check_resize;
@@ -778,6 +785,50 @@ gtk_window_class_init (GtkWindowClass *klass)
1.0,
GTK_PARAM_READWRITE));
+ /* Style properties */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("client-side-decorations",
+ P_("Client-side window decorations"),
+ P_("Whether to decorate windows without the WM"),
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-border-top",
+ P_("Top border decoration size"),
+ P_("Top border decoration size"),
+ 0, G_MAXINT, 24, GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-border-left",
+ P_("Left border decoration size"),
+ P_("Left border decoration size"),
+ 0, G_MAXINT, 6, GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-border-right",
+ P_("Right border decoration size"),
+ P_("Right border decoration size"),
+ 0, G_MAXINT, 6, GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-border-bottom",
+ P_("Bottom border decoration size"),
+ P_("Bottom border decoration size"),
+ 0, G_MAXINT, 6, GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-button-size",
+ P_("Decoration button size"),
+ P_("Client-side decoration button size"),
+ 0, G_MAXINT, 12, GTK_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("decoration-button-y-offset",
+ P_("Decoration button Y offset"),
+ P_("Client-side decoration button Y offset"),
+ 0, G_MAXINT, 4, GTK_PARAM_READWRITE));
+
window_signals[SET_FOCUS] =
g_signal_new (I_("set-focus"),
G_TYPE_FROM_CLASS (gobject_class),
@@ -929,11 +980,18 @@ gtk_window_init (GtkWindow *window)
priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
priv->opacity = 1.0;
priv->startup_id = NULL;
+ priv->client_side_decorated = TRUE;
+ priv->client_side_decorations = (GDK_DECOR_BORDER |
+ GDK_DECOR_TITLE |
+ GDK_DECOR_MAXIMIZE);
+ priv->old_decorations = 0;
colormap = _gtk_widget_peek_colormap ();
- if (colormap)
- gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
-
+ //if (colormap)
+ // gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
+ gtk_widget_set_colormap (GTK_WIDGET (window),
+ gdk_screen_get_rgba_colormap (gtk_widget_get_screen (GTK_WIDGET (window))));
+
g_object_ref_sink (window);
window->has_user_ref_count = TRUE;
toplevel_list = g_slist_prepend (toplevel_list, window);
@@ -2871,29 +2929,38 @@ gtk_window_set_geometry_hints (GtkWindow *window,
*
* On Windows, this function always works, since there's no window manager
* policy involved.
- *
+ *
**/
void
gtk_window_set_decorated (GtkWindow *window,
gboolean setting)
{
+ GtkWindowPrivate *priv;
+
g_return_if_fail (GTK_IS_WINDOW (window));
+ priv = GTK_WINDOW_GET_PRIVATE (window);
setting = setting != FALSE;
if (setting == window->decorated)
return;
window->decorated = setting;
-
+
if (GTK_WIDGET (window)->window)
{
- if (window->decorated)
- gdk_window_set_decorations (GTK_WIDGET (window)->window,
- GDK_DECOR_ALL);
+ if (window->decorated && !priv->client_side_decorations)
+ {
+ g_print ("gdk_window_set_decorations (GDK_DECOR_ALL)\n");
+ gdk_window_set_decorations (GTK_WIDGET (window)->window,
+ GDK_DECOR_ALL);
+ }
else
- gdk_window_set_decorations (GTK_WIDGET (window)->window,
- 0);
+ {
+ g_print ("gdk_window_set_decorations (0)\n");
+ gdk_window_set_decorations (GTK_WIDGET (window)->window,
+ 0);
+ }
}
g_object_notify (G_OBJECT (window), "decorated");
@@ -2916,6 +2983,55 @@ gtk_window_get_decorated (GtkWindow *window)
return window->decorated;
}
+void
+gtk_window_set_client_side_decorations (GtkWindow *window,
+ GdkWMDecoration setting)
+{
+ GtkWindowPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+
+ if (setting == priv->client_side_decorations)
+ return;
+
+ priv->client_side_decorations = setting;
+
+ if (GTK_WIDGET (window)->window)
+ {
+ if (priv->client_side_decorations)
+ {
+ gdk_window_get_decorations (GTK_WIDGET (window)->window,
+ &priv->old_decorations);
+ gdk_window_set_decorations (GTK_WIDGET (window)->window, 0);
+ g_print ("gdk_window_set_decorations (0)\n");
+ }
+ else
+ {
+ if (priv->old_decorations)
+ {
+ gdk_window_set_decorations (GTK_WIDGET (window)->window,
+ priv->old_decorations);
+ g_print ("gdk_window_set_decorations (non-zero)\n");
+ priv->old_decorations = 0;
+ }
+ }
+ }
+}
+
+GdkWMDecoration
+gtk_window_get_client_side_decorations (GtkWindow *window)
+{
+ GtkWindowPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
+
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+
+ return priv->client_side_decorations;
+}
+
/**
* gtk_window_set_deletable:
* @window: a #GtkWindow
@@ -4744,7 +4860,11 @@ gtk_window_realize (GtkWidget *widget)
window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
&attributes, attributes_mask);
-
+ if (priv->client_side_decorations)
+ {
+ gdk_window_set_decorations (window->frame, 0);
+ }
+
if (priv->opacity_set)
gdk_window_set_opacity (window->frame, priv->opacity);
@@ -4779,6 +4899,8 @@ gtk_window_realize (GtkWidget *widget)
GDK_LEAVE_NOTIFY_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_STRUCTURE_MASK);
+ if (priv->client_side_decorated)
+ attributes.event_mask |= GDK_BUTTON_PRESS_MASK;
attributes.type_hint = priv->type_hint;
attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
@@ -4809,9 +4931,12 @@ gtk_window_realize (GtkWidget *widget)
if (window->wm_role)
gdk_window_set_role (widget->window, window->wm_role);
-
- if (!window->decorated)
- gdk_window_set_decorations (widget->window, 0);
+
+ if (!window->decorated || priv->client_side_decorated)
+ {
+ g_print ("gdk_window_set_decorations (0)\n");
+ gdk_window_set_decorations (widget->window, 0);
+ }
if (!priv->deletable)
gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
@@ -4899,17 +5024,18 @@ gtk_window_size_request (GtkWidget *widget,
{
GtkWindow *window;
GtkBin *bin;
+ GtkWidget *decorated_hbox;
+ GtkRequisition child_requisition;
window = GTK_WINDOW (widget);
bin = GTK_BIN (window);
-
+ decorated_hbox = gtk_decorated_window_get_box (window);
+
requisition->width = GTK_CONTAINER (window)->border_width * 2;
requisition->height = GTK_CONTAINER (window)->border_width * 2;
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
{
- GtkRequisition child_requisition;
-
gtk_widget_size_request (bin->child, &child_requisition);
requisition->width += child_requisition.width;
@@ -4923,9 +5049,14 @@ gtk_window_size_allocate (GtkWidget *widget,
{
GtkWindow *window;
GtkAllocation child_allocation;
+ GtkAllocation new_allocation;
+ GtkWidget *decorated_hbox = NULL;
+ GtkWindowPrivate *priv;
window = GTK_WINDOW (widget);
widget->allocation = *allocation;
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+ decorated_hbox = gtk_decorated_window_get_box (window);
if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
{
@@ -4939,6 +5070,25 @@ gtk_window_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (window->bin.child, &child_allocation);
}
+ if (decorated_hbox && priv->client_side_decorations)
+ {
+ GtkRequisition deco_requisition;
+ GtkAllocation deco_allocation;
+
+ gtk_widget_size_request (decorated_hbox, &deco_requisition);
+
+ deco_allocation.x = 0;
+ deco_allocation.y = 0;
+ deco_allocation.width = deco_requisition.width;
+ deco_allocation.height = deco_requisition.height;
+
+ g_print ("deco x: %d, y: %d, width: %d, height: %d\n",
+ deco_allocation.x, deco_allocation.y,
+ deco_allocation.width, deco_allocation.width);
+
+ gtk_widget_size_allocate (decorated_hbox, &deco_allocation);
+ }
+
if (GTK_WIDGET_REALIZED (widget) && window->frame)
{
gdk_window_resize (window->frame,
@@ -5196,6 +5346,26 @@ gtk_window_key_release_event (GtkWidget *widget,
return handled;
}
+static gboolean
+gtk_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
+
+ if (priv->client_side_decorated)
+ {
+ gtk_window_begin_move_drag (GTK_WINDOW (widget),
+ event->button,
+ event->x_root,
+ event->y_root,
+ event->time);
+
+ return TRUE;
+ }
+
+ return GTK_WIDGET_CLASS (gtk_window_parent_class)->button_press_event (widget, event);
+}
+
static void
gtk_window_real_activate_default (GtkWindow *window)
{
@@ -6570,9 +6740,19 @@ static gint
gtk_window_expose (GtkWidget *widget,
GdkEventExpose *event)
{
+ GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
+ GtkWidget *hbox = gtk_decorated_window_get_box (GTK_WINDOW (widget));
+
if (!GTK_WIDGET_APP_PAINTABLE (widget))
gtk_window_paint (widget, &event->area);
-
+
+ if (hbox && priv->client_side_decorations)
+ {
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ hbox,
+ event);
+ }
+
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 6918971..f8af4c1 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -271,6 +271,9 @@ void gtk_window_get_frame_dimensions (GtkWindow *window,
void gtk_window_set_decorated (GtkWindow *window,
gboolean setting);
gboolean gtk_window_get_decorated (GtkWindow *window);
+void gtk_window_set_client_side_decorations (GtkWindow *window,
+ GdkWMDecoration decoration);
+GdkWMDecoration gtk_window_get_client_side_deocrations (GtkWindow *window);
void gtk_window_set_deletable (GtkWindow *window,
gboolean setting);
gboolean gtk_window_get_deletable (GtkWindow *window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]